/* ==========================================================================
   Never Forgotten — interior sections (Faces, Stories, Voices, players)
   Companion to never-forgotten.css, which holds the tokens and the landing.

   Values here are taken from Luke's deck markup (frames 3-9), not inferred.
   Notable: the interiors are DARK throughout; only the article's reading
   column is light. Article body copy is EB Garamond, not Inter. Article
   section headings are burnt orange #8a5a1e.
   ========================================================================== */

/* A dark section ground with a photo held far back — the deck's treatment on
   Faces, Stories and Voices. --nf-section-photo is set per page. */
.nf-dark {
    flex: 1;
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--nf-ground);
    min-height: 0;
}

    .nf-dark::before {
        content: "";
        position: absolute;
        inset: 0;
        background: var(--nf-section-photo, url("/images/911/bg-memorial-field.jpg")) center/cover;
        opacity: .10;
        filter: grayscale(1);
        pointer-events: none;
    }

/* Deepest ground — the two player views sit on #111318. */
.nf-darkest {
    background: var(--nf-ink);
}

    .nf-darkest::before {
        display: none;
    }

/* The inner box for every dark view — Faces detail, Stories, Voices, the player.
   It was full-bleed with only a gutter of padding, which is why the Faces
   breadcrumb and portrait started at x=16 while the site header above them
   started at x=512.

   It is the shared page box now, and shared means the same expression the
   chrome uses rather than one that agrees with it at a single window width:
   --page-content in site.css restates Tailwind .container's real breakpoint
   steps plus its px-4/lg:px-8 padding. The old clamp() approximation landed on
   the chrome's edge at 1536px and drifted everywhere else — 52px out at 1400px.
   Derrick, 2026-09-01: "this edge, to align with this home here. That's going
   to be our sort of bounding box across the board."

   Horizontal size still comes from width + margin-inline:auto, not padding, so
   the element's own box IS the content box — .nf-back is positioned absolutely
   against it and has to be able to trust left:0. The dark ground itself is on
   .nf-dark and stays full width. */
.nf-dark-inner {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    width: var(--page-content);
    margin-inline: auto;
    padding: clamp(1.25rem, 3vw, 2.25rem) 0 clamp(1.75rem, 3vw, 3rem);
}

.nf-bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

.nf-bar-note {
    margin-left: auto;
    font: 500 11px var(--nf-sans);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--nf-muted-3);
}

/* Section label — the deck's .cnum, gold, letterspaced. */
.nf-cnum {
    font: 600 clamp(11px, 1.1vw, 13px) var(--nf-sans);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--nf-gold);
    margin: clamp(1.5rem, 3vw, 2.25rem) 0 clamp(.75rem, 1.5vw, 1rem);
}

.nf-cnum-plain {
    color: var(--nf-line);
}

.nf-cnum-row {
    display: flex;
    align-items: baseline;
    gap: .65rem;
    flex-wrap: wrap;
    margin: clamp(1.5rem, 3vw, 2.25rem) 0 clamp(.5rem, 1vw, .75rem);
}

    .nf-cnum-row .nf-cnum {
        margin: 0;
    }

    .nf-cnum-row .nf-cnum-note {
        font: 400 clamp(12px, 1.1vw, 14px) var(--nf-sans);
        color: #b7b1a4;
    }

/* Section intro used on Stories / Voices */
.nf-sec-title {
    font: 400 clamp(1.9rem, 3.6vw, 3rem)/1.05 var(--nf-serif);
    color: var(--nf-cream);
    margin: .25rem 0 .35rem;
}

.nf-sec-sub {
    font: italic 400 clamp(.95rem, 1.4vw, 1.15rem) var(--nf-serif);
    color: var(--nf-line-3);
    max-width: 62ch;
}

/* Neutral placeholder block — the deck's .ph, used wherever imagery is
   promised but not delivered. */
.nf-ph {
    background: linear-gradient(145deg, var(--nf-ground-3), var(--nf-ground-2));
    border: 1px solid rgba(245, 243, 236, .07);
}

/* ----------------------------------------------------------------- Faces   */

.nf-gallery {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
}

.nf-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: clamp(1rem, 2vw, 1.75rem) clamp(1.25rem, 2.5vw, 2.25rem);
    justify-items: center;
}

.nf-tile {
    text-align: center;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    text-decoration: none;
    display: block;
}

/* Rest values are the deck's faceIn end-state: opacity .7, brightness .9. */
/*  The tiles used to be square (width == height) with object-fit: cover, which
    cut roughly 30% off every portrait - Luke's 2026-08-13 note about the crop.
    All fourteen source images are portrait-orientation, measured between 0.68
    and 0.86 wide-to-tall and clustering at 0.70-0.78, so a 3:4 tile is the
    natural frame: the faces show full height and the remaining trim is a few
    percent at the edges rather than a third of the photograph.  */
.nf-tile-img {
    width: clamp(78px, 8.5vw, 124px);
    aspect-ratio: 3 / 4;
    height: auto;
    object-fit: cover;
    object-position: center top;
    border-radius: 2px;
    display: block;
    filter: grayscale(1) brightness(.9);
    opacity: .7;
}

/* Hover transitions are armed only once the entrance tween has finished —
   otherwise every inline write from GSAP also kicks off a CSS transition. */
.nf-grid.is-ready .nf-tile-img {
    transition: filter .3s ease, opacity .3s ease, transform .3s ease;
}

.nf-tile:hover .nf-tile-img,
.nf-tile:focus-visible .nf-tile-img {
    filter: grayscale(1) brightness(1.05);
    opacity: 1;
    transform: translateY(-2px);
}

.nf-tile-name {
    font: 600 clamp(12px, 1vw, 13px)/1.2 var(--nf-sans);
    color: var(--nf-line);
    margin-top: .45rem;
    min-height: 1.2em;
}

/*  Class year sits ON the caption line - "Burlingame ’71" - the way the Academy
    writes it. It inherits the surname's font, weight and colour deliberately: set
    quieter in the serif at --nf-muted-3 it was barely legible against the dark
    ground. nowrap is the only rule it needs, so a caption can never break between
    a person and their class.  */
.nf-tile-year {
    white-space: nowrap;
}

    .nf-tile-name.is-pending {
        color: var(--nf-muted-3);
        font-style: italic;
        font-weight: 500;
    }

.nf-detail {
    flex: 1;
    display: flex;
    gap: clamp(1.25rem, 3vw, 2.75rem);
    min-height: 0;
    align-items: center;
}

/*  Matched to the grid tile at 3:4. At 4/5 this frame was wider than thirteen
    of the fourteen source portraits, so the big memorial photograph was the one
    being trimmed hardest.  */
.nf-detail-photo {
    width: clamp(180px, 22vw, 300px);
    aspect-ratio: 3 / 4;
    object-fit: cover;
    object-position: center top;
    border-radius: 3px;
    flex: none;
    filter: grayscale(1);
}

/*  ONE measure for the whole panel, here rather than on each child.

    The bio and the pager were each given their own cap and landed 49px apart:
    `ch` is the width of the zero in THAT element's font, and the two are set at
    different sizes, so the same number is a different width in each. A cap on
    the column they share cannot disagree with itself.

    46rem, where the bio alone used to sit at 60ch. Derrick, 2026-09-09: "the
    faces the nav bar with the x of 14 is wide and the etxt is narrow and that
    makes it awkward. i fear were sticking to this narrow reading column thing
    way too hard on this site." This is a short biography beside a portrait, in a
    panel the photograph has already narrowed — an article's measure inside that
    is a column inside a column. At 1440 the panel is 873px and this holds it to
    736; below that the panel is narrower than the cap and it does nothing. */
.nf-detail-txt {
    flex: 1;
    max-width: 46rem;
    color: #dcd8cf;
    display: flex;
    flex-direction: column;
    /*  Was centred, and centring is what made the pager move. Derrick,
        2026-09-09: "i dont like the way the back to all fourteen jumps up and
        down when we flip through the faces keep it stationary."

        The bios differ by about two lines across the fourteen — 96px to 144px at
        1440 — and a centred column puts half that difference above the block and
        half below, so the pager and the back link sat at a different height on
        every portrait. Stretching the column to the row and pinning the bottom
        block to it means the only thing that moves between faces is the copy
        that actually changed. */
    align-self: stretch;
    justify-content: flex-start;
    gap: .15rem;
    min-width: 0;
}

.nf-detail-kick {
    font: 600 11px var(--nf-sans);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--nf-gold);
}

.nf-detail-name {
    font: 400 clamp(1.9rem, 3.5vw, 3rem)/1.05 var(--nf-serif);
    color: var(--nf-cream);
}

/*  No focus ring on the name. Derrick, 2026-09-09: "remove that awkward box
    highlight on the name when we hit the left and right arrow on the faces. its
    ugly."

    The pager moves focus here after each swap so a screen reader announces who
    it just landed on, and because the arrow key is a keyboard interaction the
    browser then draws its focus-visible box around a heading nobody can press.
    The focus itself is doing real work and stays; only the ring goes, and only
    on the programmatic target — the [tabindex="-1"] is what the script sets, so
    a heading that ever becomes genuinely focusable keeps its indicator. */
.nf-detail-name[tabindex="-1"]:focus {
    outline: none;
}

.nf-tag {
    display: inline-block;
    width: max-content;
    font: 500 12px var(--nf-sans);
    letter-spacing: .06em;
    color: var(--nf-line);
    border: 1px solid var(--nf-hairline);
    border-radius: 2px;
    padding: .25rem .6rem;
    margin: .6rem 0 .9rem;
}

/*  78ch, up from 60. Derrick, 2026-09-09: "the faces the nav bar with the x of
    14 is wide and the etxt is narrow and that makes it awkward. i fear were
    sticking to this narrow reading column thing way too hard on this site."

    He is describing a real mismatch rather than a preference: the text column
    here is 873px at 1440, the bio was capped at 60ch — 568px — and the pager
    under it ran the full 873. A rule that stops 300px past the paragraph above
    it reads as a mistake, because it is one.

    The measure that governs the ARTICLES is not the one to apply here. An
    article is a thousand words in a column of its own; this is a short biography
    beside a portrait, in a panel already narrowed by the photograph next to it,
    and 60ch inside that is a column inside a column. 78ch is still inside SC
    1.4.8's ceiling at this size and lets the paragraph use the space the layout
    already gave it. .nf-pager below takes the same figure so the two edges
    agree at every width. */
.nf-detail-bio {
    font: 400 clamp(13.5px, 1.15vw, 15px)/1.6 var(--nf-sans);
    color: var(--nf-line-2);
}

.nf-featured {
    margin-top: 1.4rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.nf-featured-kick {
    font: 600 10px var(--nf-sans);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--nf-muted);
}

.nf-featured-link {
    display: flex;
    align-items: center;
    gap: .6rem;
    text-decoration: none;
}

.nf-badge {
    font: 700 10px var(--nf-sans);
    letter-spacing: .08em;
    padding: .2rem .45rem;
    border-radius: 2px;
    flex: none;
}

.nf-badge-story {
    color: var(--nf-ground);
    background: var(--nf-gold);
}

.nf-badge-voices {
    color: var(--nf-chip-ink);
    background: #3a4658;
}

.nf-featured-link .nf-featured-text {
    font: 500 clamp(12px, 1.1vw, 14px) var(--nf-sans);
    color: var(--nf-chip-ink);
    transition: color .2s ease;
}

.nf-featured-link:hover .nf-featured-text {
    color: #fff;
}

/* Photo strip under the detail: the headshot currently shown (ringed in gold),
   then slots for the additional photos, with the note trailing on the right. */
/* The .nf-photo-slot strip that lived here went with its markup on 2026-09-01 —
   one portrait per person means it only ever showed the photograph already on
   the page. */

/* One of these two is displayed, chosen by pointer type, so the affordance names
   the gesture the visitor actually has. Coarse pointers win the tie. */
.nf-hint-touch { display: none; }

@media (hover: none), (pointer: coarse) {
    .nf-hint-pointer { display: none; }
    .nf-hint-touch { display: inline; }
}

.nf-pending {
    max-width: 64ch;
    margin: 0 auto clamp(1rem, 2vw, 1.75rem);
    padding: .8rem 1rem;
    border: 1px solid rgba(201, 162, 75, .35);
    border-left: 3px solid var(--nf-gold);
    border-radius: 2px;
    background: rgba(201, 162, 75, .07);
    font: 400 13px/1.55 var(--nf-sans);
    color: var(--nf-line);
}

    .nf-pending strong {
        color: var(--nf-gold);
        font-weight: 600;
    }

/* --------------------------------------------------------------- Stories   */

/*  The feature, then the rest UNDER it — not beside it.

    Luke, 2026-09-08: "is it possible, would you suggest, moving the extra
    articles under the main story so there's not a large space under the main
    story before the archived stories?"

    It was 1.25fr / 1fr: feature left, every other new story stacked in a right
    rail. That reads fine with three or four of them and breaks with nine. The
    rail grew to eight rows while the feature stayed one image tall, so the
    column under the feature was empty for most of the section's height, and the
    reader met that hole before reaching "From the archive".

    One column here, and the stack below becomes a grid of its own — so the
    articles fill the width they used to leave blank instead of running down one
    side of it. */
.nf-stories-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(1.5rem, 3.5vw, 3rem);
    align-items: start;
}

/* Feature — image on top, then chip, title, excerpt, byline. */
.nf-feature {
    display: flex;
    flex-direction: column;
    gap: .55rem;
    text-decoration: none;
    color: inherit;
}

.nf-feature-img {
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: 340px;
    object-fit: cover;
    object-position: center 40%;
    border-radius: 3px;
    display: block;
    filter: grayscale(.4);
    transition: filter .35s ease;
}

.nf-feature:hover .nf-feature-img {
    filter: grayscale(0);
}

.nf-feature-title {
    font: 400 clamp(1.4rem, 2.4vw, 2.1rem)/1.15 var(--nf-serif);
    color: var(--nf-cream-2);
    transition: color .2s ease;
}

/*  Derrick, 2026-09-01: "when we hover here, make the title gold as well."
    .nf-story-row-title already did this; the feature, the archive rows and the
    film cards did not, so within one section a hovered title changed colour or
    did not depending on which shelf it was on. The section's own gold, not the
    site's — #c9a24b on #1b1e24 measures 6.96:1. */
.nf-feature:hover .nf-feature-title {
    color: var(--nf-gold);
}

.nf-feature-excerpt {
    font: 400 clamp(13px, 1.2vw, 15px)/1.5 var(--nf-sans);
    color: var(--nf-line-2);
}

.nf-byline {
    font: 500 clamp(12px, 1vw, 12.5px) var(--nf-sans);
    color: var(--nf-muted-2);
}

/* The three announced pieces — thumb + title + skeleton rules + byline. */
/*  Two abreast under the feature. It was a single flex column because it used to
    BE a column — the right rail of the old two-up. Full width, one column would
    be eight rows of a 132px thumbnail against an ocean of empty line, so the
    rows pair up and the section closes in half the height. */
.nf-story-stack {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(1rem, 2vw, 1.5rem) clamp(1.5rem, 3.5vw, 3rem);
    align-items: start;
}

.nf-story-row {
    display: flex;
    gap: clamp(.75rem, 1.5vw, 1.1rem);
    text-decoration: none;
    color: inherit;
}

.nf-story-thumb {
    width: clamp(84px, 9vw, 132px);
    aspect-ratio: 4 / 3;
    border-radius: 2px;
    flex: none;
    overflow: hidden;
}

    .nf-story-thumb img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        filter: grayscale(1);
    }

.nf-story-row-txt {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    min-width: 0;
    flex: 1;
}

.nf-story-row-title {
    font: 400 clamp(1rem, 1.5vw, 1.35rem)/1.15 var(--nf-serif);
    color: var(--nf-cream-2);
    transition: color .2s ease;
}

.nf-story-row:hover .nf-story-row-title {
    color: var(--nf-gold);
}

/* Skeleton rules stand in for copy that has not been filed yet. */
.nf-skel {
    height: 3px;
    border-radius: 2px;
    background: var(--nf-ground-3);
}

.nf-divider {
    border-top: 1px solid var(--nf-ground-3);
    margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
}

.nf-archive-row {
    display: flex;
    align-items: center;
    gap: clamp(.75rem, 1.5vw, 1.25rem);
    padding: clamp(.7rem, 1.4vw, .95rem) 0;
    border-bottom: 1px solid var(--nf-ground-3);
    text-decoration: none;
    color: inherit;
    transition: padding-left .25s ease, background .25s ease;
}

    .nf-archive-row:hover {
        padding-left: .6rem;
        background: rgba(245, 243, 236, .03);
    }

.nf-archive-label {
    font: 600 clamp(11.5px, 1vw, 12px) var(--nf-sans);
    color: var(--nf-muted-2);
    width: clamp(9rem, 18vw, 15rem);
    flex: none;
}

.nf-archive-title {
    font: 400 clamp(1rem, 1.4vw, 1.3rem) var(--nf-serif);
    color: var(--nf-cream-2);
    flex: 1;
    transition: color .2s ease;
}

.nf-archive-row:hover .nf-archive-title {
    color: var(--nf-gold);
}

.nf-archive-arrow {
    color: var(--nf-gold);
    font: 600 clamp(12px, 1.1vw, 15px) var(--nf-sans);
    flex: none;
}

/* --------------------------------------------------- Story reading view    */

/* Dark hero with the story photo behind it, parallaxed on scroll. */
/*  Luke 2026-08-10: "reduce the header image vertically by 40-50%."
    Was clamp(280px, 42vh, 460px); each stop is cut ~45%. The floor stays high
    enough to hold the breadcrumb row plus the kicker and title without the two
    colliding on a narrow screen.  */
.nf-story-hero {
    position: relative;
    overflow: hidden;
    background: var(--nf-ground);
    min-height: clamp(200px, 32vh, 380px);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.nf-story-hero-img {
    position: absolute;
    top: -15%;
    left: 0;
    width: 100%;
    height: 130%;
    object-fit: cover;
    object-position: center 40%;
    filter: grayscale(1);
    will-change: transform;
}

/* Was .2 at the top, which left the breadcrumb and the gold kicker sitting on
   an almost bare photograph — the washed-out band across the top of every
   article. .55 holds them without darkening the image lower down, where the
   headline already had the contrast it needed. */
.nf-story-hero-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(rgba(20, 22, 28, .55), rgba(20, 22, 28, .92));
}

/* In flow rather than absolutely positioned, so it shares the measure with
   everything below it and can no longer crowd the site header above it. */
.nf-story-hero-crumb {
    position: relative;
    z-index: 2;
    width: min(100% - var(--nf-gutter) * 2, var(--nf-measure));
    margin: 0 auto;
    padding-top: clamp(1rem, 2vw, 1.5rem);
}

.nf-story-hero-body {
    position: relative;
    z-index: 1;
    width: min(100% - var(--nf-gutter) * 2, var(--nf-measure));
    margin: 0 auto;
    padding: clamp(1.25rem, 3vw, 2rem) 0 clamp(1.75rem, 3.5vw, 2.75rem);
}

.nf-read-kick {
    font: 600 clamp(11.5px, 1vw, 12px) var(--nf-sans);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--nf-gold);
    margin-bottom: .6rem;
}

.nf-read-title {
    font: 400 clamp(2.25rem, 5.5vw, 4.25rem)/1.05 var(--nf-serif);
    color: var(--nf-cream);
    max-width: 18ch;
}

.nf-read-sub {
    font: italic 400 clamp(1.05rem, 1.9vw, 1.6rem)/1.3 var(--nf-serif);
    color: var(--nf-line);
    max-width: 40ch;
    margin-top: .5rem;
}

.nf-read-byline {
    font: 500 clamp(11px, 1vw, 13px) var(--nf-sans);
    color: var(--nf-line-3);
    margin-top: .9rem;
}

/* Light reading column */
/*  The reading measure, applied to the WHOLE article rather than to the
    paragraphs inside it.

    First attempt capped each paragraph's width and left the 64rem column alone.
    That fixed the character count and looked broken: the text hugged the left of
    a box nearly twice its width, with a dead margin down the right, while the
    headline above still ran the full 64rem. Two axes on one page.

    The column itself is narrow now. Figures are unaffected: they span the grid's
    `wide` tracks, which add 140px on each side of whatever the text column is,
    so the picture still runs wider than the prose.

    32rem is chosen against both ends of the type scale, not just the desktop
    one: 512px is ~69 characters at 19px and ~79 at 16.5px, so it stays inside
    the 80 that WCAG 2.2 SC 1.4.8 sets as the ceiling at every width, and lands
    near Bringhurst's 66 where the type is largest.

    THE HERO KEEPS 64rem, deliberately, and so the headline does not share a left
    edge with the body beneath it. That is the ask, not an oversight: Derrick,
    2026-09-01, "the titles should be aligned where they were keeping the
    articles that width, i liked the titles aligned with the home icon." The
    kicker, headline, subtitle and byline stay on the site's grid where they line
    up with the nav; only the reading column narrows. A wide masthead over a
    narrow text column is the ordinary magazine arrangement, and the two share a
    centre even though they do not share an edge. */
.nf-read {
    --nf-measure: 32rem;
}

.nf-read {
    background: var(--nf-paper);
    padding: clamp(2rem, 4vw, 3.25rem) 0 clamp(3rem, 6vw, 4.5rem);
}

/* Same measure as the hero above it, so the headline and the first paragraph
   begin on the same left edge. */
.nf-read-col {
    width: min(100% - var(--nf-gutter) * 2, var(--nf-measure));
    margin: 0 auto;
}

/* ------------------------------------------------------- breakout grid

   Prose has a readable width and it is not negotiable: past roughly 80
   characters the eye loses the start of the next line, and at 19px EB Garamond
   this measure is already at 80. Widening the paragraph is the wrong answer to
   "there is too much white space".

   The right one is to stop spending the margin on nothing. The body is a grid
   whose middle track is the measure and whose outer tracks are real, addressable
   space: figures and pull quotes claim them, paragraphs do not. That is how a
   printed spread uses a page, and it is why the column can stay narrow while the
   page stops looking empty.

   Everything lands in [text] unless it asks otherwise, so a new block kind needs
   no layout work to be correct. */
.nf-read-body {
    display: grid;
    grid-template-columns:
        [full-start] minmax(var(--nf-gutter), 1fr)
        [wide-start] minmax(0, 140px)
        [text-start] min(100% - var(--nf-gutter) * 2, var(--nf-measure)) [text-end]
        minmax(0, 140px) [wide-end]
        minmax(var(--nf-gutter), 1fr) [full-end];
}

    .nf-read-body > * {
        grid-column: text;
    }

    /* Figures run wider than the prose — the standard magazine relationship, and
       what makes the column read as a deliberate measure rather than a narrow
       one. They stay centred on the same axis. */
    .nf-read-body > figure {
        grid-column: wide;
    }

        /* The caption belongs to the prose, not to the wider frame. */
        .nf-read-body > figure figcaption {
            width: min(100%, var(--nf-measure));
            margin-inline: auto;
        }

    /* A pull quote is display type; letting it break the measure is the whole
       point of one. */
    .nf-read-body > .nf-quote {
        grid-column: wide;
    }

/* The reading column is the grid now; the old wrapper would nest a second,
   narrower measure inside it. */
.nf-read > .nf-read-col {
    width: 100%;
    max-width: none;
    padding: 0;
}

    /* Its non-body children — the unwritten notice, the roster card, the back
       link — still want the measure.

       display:block is load-bearing. .nf-back is an inline-block, and auto
       inline margins do nothing on one: the link took the 760px width and then
       sat at x=0, hard against the window, while the prose it belonged to began
       at 892px. */
    .nf-read-col > :not(.nf-read-body) {
        display: block;
        width: min(100% - var(--nf-gutter) * 2, var(--nf-measure));
        margin-inline: auto;
    }

/* The editor's note that opens two of the archive reprints. It runs above the
   copy in print and does the same here — but it is not the article's first
   line, so it must not take the drop cap. Rendered as an <aside> for exactly
   that reason: p:first-of-type below then lands on the real opening
   paragraph. */
.nf-editors-note {
    font: italic 400 clamp(14.5px, 1.15vw, 16px)/1.6 var(--nf-serif);
    /*  --nf-muted-3 is tuned for the dark ground and computes to 2.45:1 here, on
        the article's near-white paper — a WCAG 1.4.3 failure on a note that
        carries the provenance of the piece. Italic, a rule down the left and the
        smaller size already mark it as an aside; it does not need to be faint as
        well. This ink clears 4.5:1 on --nf-paper. */
    color: #5f5c50;
    border-left: 2px solid var(--nf-rule);
    padding-left: clamp(.8rem, 1.8vw, 1.15rem);
    margin: 0 0 clamp(1.5rem, 3vw, 2rem);
}

.nf-read-body p {
    margin: 0 0 1.15rem;
    font: 400 clamp(16.5px, 1.4vw, 19px)/1.7 var(--nf-serif);
    color: #3a3a3a;
}

    .nf-read-body > p:first-of-type {
        color: var(--nf-ground-2);
    }

    /* Positional, so the data no longer has to carry a per-block flag that
       must be true on exactly one paragraph.

       The child combinator is load-bearing. As a descendant selector this also
       matched the <p> inside every <blockquote class="nf-quote">, since that p
       is the first of its own parent's children — so each pull quote grew a
       5rem floated drop cap. It went unnoticed while only one article had a
       pull quote; the archive reprints bring ten. .nf-read-body is a grid whose
       direct children are the blocks, so ">" is exactly the intended set. */
    .nf-read-body > p:first-of-type::first-letter {
        float: left;
        font-family: var(--nf-serif);
        font-size: 3.1em;
        line-height: .8;
        padding: .06em .18em 0 0;
        color: var(--nf-ground);
    }

/*  ------------------------------------------------- the rolls of honour

    Derrick, 2026-09-09: "the killed in action since 9/11 we should style that
    a little better like bold the names or something so doesnt look like a
    block of text on the 9/11 10 years later."

    Three lists in that article — the fourteen lost on the day, sixteen killed
    in action since, twenty-seven operational losses. Fifty-seven paragraphs of
    near-identical length, and the reader is scanning for a name.

    A hanging indent is what does the work, more than the weight: each name
    starts at the margin and its sentence is set in from it, so the eye runs
    down a single column of names instead of hunting the front of every line.
    The rhythm tightens too — an entry is one item in a list, not a paragraph
    of an argument, so 1.15rem between them was reading as prose. */
.nf-read-body p.nf-roll {
    margin-bottom: .75rem;
    padding-inline-start: 1.4rem;
    text-indent: -1.4rem;
}

.nf-roll-name {
    font-weight: 600;
    color: var(--nf-ground);
}

.nf-read-body h2 {
    font: 600 clamp(11px, 1vw, 12.5px) var(--nf-sans);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--nf-burnt);
    margin: clamp(1.75rem, 3.5vw, 2.5rem) 0 .75rem;
}

.nf-read-body figure {
    margin: clamp(1.4rem, 3vw, 2rem) 0;
}

    /* Every figure keeps its own shape.

       This used to force aspect-ratio 4/3 with object-fit:cover to reserve the
       box before decode — fine when the only figures were the deck's four
       landscape frames. The archive reprints are half portrait, and the crop
       took the top and bottom off six of them: Lisa Dolan pinning her husband's
       shoulder board, and both of the family photographs. Cropping a family out
       of its own photograph on a memorial page is not a trade worth a little
       layout stability.

       max-height keeps a tall frame from swallowing the screen; with width:auto
       and max-width:100% the image satisfies both bounds without distorting. */
    .nf-read-body figure img {
        display: block;
        /* Definite, and that is the whole point. With width:auto an image that
           has not loaded yet computes to 0x0 — the width/height attributes give
           the browser the ratio but nothing to apply it to. Zero height means a
           lazy image never intersects the viewport, so it is never fetched, so
           it stays 0x0: the figures below the fold simply never appeared. A
           definite width lets the attributes' ratio produce a real reserved
           height, which both loads them and removes the layout shift.

           The height budget is applied as a per-image max-width in the markup
           (78vh expressed as a width through that image's own ratio) rather than
           as max-height here, because clamping the height of a 100%-wide image
           squashes it. */
        width: 100%;
        height: auto;
        /* Backstop for a figure whose width/height are missing: without it such
           an image upscales to fill the 1040px track. The model and the schema
           both allow null dimensions, so this cannot be assumed away. */
        max-width: 100%;
        margin-inline: auto;
        border-radius: 3px;
    }

    .nf-read-body figure figcaption {
        font: 400 clamp(12px, 1.05vw, 13px)/1.4 var(--nf-sans);
        color: var(--nf-muted-2);
        margin-top: .45rem;
    }

.nf-quote {
    border-left: 3px solid var(--nf-gold);
    padding: .15rem 0 .15rem clamp(.9rem, 2vw, 1.35rem);
    margin: clamp(1.4rem, 3vw, 2rem) 0;
}

    .nf-quote p {
        font: italic 400 clamp(1.2rem, 2.2vw, 1.7rem)/1.4 var(--nf-serif);
        color: var(--nf-ground-2);
        margin: 0;
    }

    .nf-quote cite {
        display: block;
        font: 600 clamp(11px, 1vw, 12.5px) var(--nf-sans);
        font-style: normal;
        /* --nf-muted is a dark-ground token and computes to 3.53:1 on the light
           reading column — under 1.4.3 at this size, on the line naming the
           person being quoted. --nf-muted-3 is what this sheet already uses for
           quiet text on paper (the editor's note, the unwritten notice). */
        color: var(--nf-muted-3);
        letter-spacing: .02em;
        margin-top: .6rem;
    }

/* Dark roster card inside the light column */
.nf-roster {
    background: var(--nf-ground);
    border-radius: 5px;
    padding: clamp(1rem, 2vw, 1.4rem) clamp(1.1rem, 2.2vw, 1.6rem);
    margin-top: clamp(1.5rem, 3vw, 2.25rem);
}

.nf-roster-kick {
    font: 600 clamp(10px, .95vw, 11.5px) var(--nf-sans);
    letter-spacing: .28em;
    text-transform: uppercase;
    color: var(--nf-muted);
    margin-bottom: .8rem;
}

.nf-roster-names {
    display: flex;
    gap: .45rem;
    flex-wrap: wrap;
}

    .nf-roster-names span {
        font: 500 clamp(11.5px, 1.05vw, 13px) var(--nf-sans);
        color: var(--nf-chip-ink);
        background: var(--nf-ground-2);
        border-radius: 4px;
        padding: .35rem .6rem;
    }

.nf-roster-note {
    font: 400 clamp(11.5px, .95vw, 12px)/1.5 var(--nf-sans);
    color: var(--nf-muted-3);
    margin-top: .8rem;
}

.nf-unwritten {
    max-width: 54ch;
    font: 400 clamp(14px, 1.25vw, 16px)/1.65 var(--nf-sans);
    color: var(--nf-muted-3);
    padding: clamp(1.5rem, 3vw, 2.25rem);
    border: 1px dashed rgba(0, 0, 0, .2);
    border-radius: 3px;
}

/* --------------------------------------------------------------- Voices    */

/* Watch — a strict two-up of bare cards (no panel, no border). */
/*  Air between the standfirst and the films. Derrick, 2026-09-09: "on the voices
    page on desktop, we need more margin between the videos and the 'Film
    produced to commemorate...' section. theyre touching."

    They were: .nf-sec-sub carries no bottom margin and this grid carried no top
    one, so the first poster began immediately under the sentence. Stories does
    not show the fault because an .nf-cnum heading sits between the two there and
    brings its own margin — this page has no heading to hide behind.

    Set here rather than on .nf-sec-sub, which is shared with Stories and would
    change a gap that is already right. */
.nf-watch-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(1.25rem, 2.5vw, 2rem) clamp(1.25rem, 2.5vw, 2.25rem);
    margin-top: clamp(1.5rem, 3.2vw, 2.75rem);
}

.nf-watch-card {
    display: flex;
    flex-direction: column;
    gap: .55rem;
    text-decoration: none;
    color: inherit;
}

.nf-watch-thumb {
    aspect-ratio: 16 / 9;
    border-radius: 3px;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

    .nf-watch-thumb img {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        filter: grayscale(1);
        opacity: .7;
        transition: opacity .3s ease;
    }

.nf-watch-card:hover .nf-watch-thumb img {
    opacity: .9;
}

/* Circular play button, drawn the way the deck draws it. */
.nf-playbtn {
    position: relative;
    z-index: 2;
    width: clamp(38px, 4.5vw, 62px);
    height: clamp(38px, 4.5vw, 62px);
    border-radius: 50%;
    background: rgba(20, 22, 28, .72);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .25s ease, transform .25s ease;
}

.nf-watch-card:hover .nf-playbtn {
    background: rgba(201, 162, 75, .9);
    transform: scale(1.06);
}

.nf-playbtn::before {
    content: "";
    width: 0;
    height: 0;
    border-left: .34em solid var(--nf-cream);
    border-top: .22em solid transparent;
    border-bottom: .22em solid transparent;
    font-size: clamp(38px, 4.5vw, 62px);
    margin-left: .06em;
}

.nf-watch-card:hover .nf-playbtn::before {
    border-left-color: var(--nf-ground);
}

.nf-watch-dur {
    position: absolute;
    bottom: .45rem;
    right: .5rem;
    z-index: 2;
    font: 600 clamp(11px, .95vw, 12px) var(--nf-sans);
    color: var(--nf-cream);
    background: rgba(20, 22, 28, .72);
    padding: .12rem .35rem;
    border-radius: 2px;
}

.nf-watch-title {
    font: 400 clamp(1.05rem, 1.6vw, 1.45rem)/1.2 var(--nf-serif);
    color: var(--nf-cream-2);
    transition: color .2s ease;
}

.nf-watch-card:hover .nf-watch-title {
    color: var(--nf-gold);
}

.nf-watch-desc {
    font: 400 clamp(12.5px, 1.1vw, 14px)/1.5 var(--nf-sans);
    color: var(--nf-line-2);
}

/* Listen — chips wrapping in a centred row, not a bordered list. */
.nf-listen-wrap {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(.6rem, 1.2vw, .9rem);
    justify-content: center;
}

.nf-listen-chip {
    display: flex;
    align-items: center;
    gap: .7rem;
    background: var(--nf-ground-2);
    border-radius: 5px;
    padding: clamp(.6rem, 1.2vw, .85rem) clamp(.75rem, 1.5vw, 1.05rem);
    flex: 0 0 calc(50% - .5rem);
    max-width: 460px;
    text-decoration: none;
    color: inherit;
    transition: background .25s ease, transform .25s ease;
}

    .nf-listen-chip:hover {
        background: var(--nf-ground-3);
        transform: translateY(-1px);
    }

.nf-listen-ico {
    width: clamp(26px, 2.6vw, 34px);
    height: clamp(26px, 2.6vw, 34px);
    flex: none;
    border-radius: 50%;
    border: 1px solid rgba(201, 162, 75, .5);
    display: flex;
    align-items: center;
    justify-content: center;
}

    .nf-listen-ico::before {
        content: "";
        width: 0;
        height: 0;
        border-left: 8px solid var(--nf-gold);
        border-top: 5px solid transparent;
        border-bottom: 5px solid transparent;
        margin-left: 2px;
    }

.nf-listen-txt {
    min-width: 0;
    flex: 1;
}

.nf-listen-title {
    display: block;
    font: 500 clamp(12.5px, 1.15vw, 14.5px) var(--nf-sans);
    color: var(--nf-cream-2);
}

.nf-listen-desc {
    display: block;
    font: 400 clamp(12px, 1vw, 12.5px)/1.45 var(--nf-sans);
    color: var(--nf-muted-2);
    margin-top: .15rem;
}

.nf-listen-dur {
    font: 500 clamp(12px, 1vw, 12.5px) var(--nf-sans);
    color: var(--nf-muted);
    flex: none;
}

/* ------------------------------------------------------------- players     */

/* Fills the page box its parent already establishes. It used to cap itself at
   1080px inside a full-bleed parent, which put Stories, Voices and the player on
   a third left edge — 740px — different from both the chrome and the Faces
   detail beside them. */
.nf-player-wrap {
    width: 100%;
    margin: 0 auto;
}

.nf-stage {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 4px;
    overflow: hidden;
    background: #000;
    display: flex;
    align-items: center;
    justify-content: center;
}

    .nf-stage video {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: contain;
        background: #000;
        /* The picture is a play/pause target, as it is in every video player. */
        cursor: pointer;
    }

    .nf-stage .nf-ph {
        position: absolute;
        inset: 0;
        border-radius: 0;
    }

.nf-stage-play {
    position: relative;
    z-index: 2;
    width: clamp(44px, 5vw, 72px);
    height: clamp(44px, 5vw, 72px);
    border-radius: 50%;
    background: rgba(20, 22, 28, .62);
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .25s ease;
}

    .nf-stage-play:hover {
        background: rgba(201, 162, 75, .85);
    }

    .nf-stage-play::before {
        content: "";
        width: 0;
        height: 0;
        border-left: .33em solid var(--nf-cream);
        border-top: .22em solid transparent;
        border-bottom: .22em solid transparent;
        font-size: clamp(44px, 5vw, 72px);
        margin-left: .06em;
    }

/*  ------------------------------------------- volume and full screen, on the film

    Derrick, 2026-09-08: "move the volume and fullscreen on the video pages to on
    the video player like a normal video." They were in .nf-toolrow under the
    stage; these two are viewing controls and belong over the picture, which is
    also the only place they can be reached in full screen without the wrapper's
    whole control strip coming along.

    Bottom right, clear of .nf-stage-play — that button is centred and is the
    thing a paused film asks you to press first. z-index 3 puts these above it
    and above the picture; the play button is 2.

    The pill is not decoration. .nf-tool is --nf-muted, which is chosen against
    the deck's charcoal and would sit on whatever frame the film happens to be
    paused on — white sky, night interior, anything. The scrim gives both controls
    a fixed ground of their own, so the contrast holds against every frame rather
    than against the one the designer happened to look at. */
.nf-stage-tools {
    position: absolute;
    z-index: 3;
    right: clamp(.5rem, 1.4vw, .9rem);
    bottom: clamp(.5rem, 1.4vw, .9rem);
    display: flex;
    align-items: center;
    gap: clamp(.6rem, 1.4vw, 1rem);
    padding: .45rem clamp(.6rem, 1.2vw, .85rem);
    border-radius: 999px;
    background: rgba(20, 22, 28, .72);
    backdrop-filter: blur(6px);
    opacity: 1;
    transition: opacity .25s ease;
}

    /*  Present while paused, gone while the film runs, back on hover or focus —
        the convention every player follows. Focus-within is what keeps it usable
        from the keyboard: without it the slider would take focus inside an
        element at opacity 0 and the viewer would be dragging something invisible.

        :hover is on the STAGE, not on the pill, so the target is the picture the
        pointer is already over rather than a 40px strip it has to find. */
    .nf-stage.is-playing .nf-stage-tools {
        opacity: 0;
    }

    .nf-stage.is-playing:hover .nf-stage-tools,
    .nf-stage.is-playing:focus-within .nf-stage-tools {
        opacity: 1;
    }

    /*  A touch screen has no hover, so an auto-hiding control is a control that
        never comes back. They stay up on coarse pointers. */
    @media (hover: none), (pointer: coarse) {
        .nf-stage.is-playing .nf-stage-tools {
            opacity: 1;
        }
    }

    @media (prefers-reduced-motion: reduce) {
        .nf-stage-tools {
            transition: none;
        }
    }

    /*  Cream rather than the toolrow's grey: this pair sits on the scrim above a
        moving picture, not on the page.

        24px minimum in both directions. The full-screen glyph is a single narrow
        character and measured 14px wide as an inline button — under WCAG 2.2 SC
        2.5.8, and under the floor the rest of this release was raised to. The
        min-width is on the box rather than the glyph so the type stays the size
        the toolrow sets. */
    .nf-stage-tools .nf-tool {
        color: var(--nf-cream);
        min-width: 24px;
        min-height: 24px;
        padding: .2rem .1rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

        .nf-stage-tools .nf-tool:hover,
        .nf-stage-tools .nf-tool.is-on {
            color: var(--nf-gold);
        }

        .nf-stage-tools .nf-vol-btn.is-muted {
            color: var(--nf-line-3);
        }

/*  The speaker, and what it reports.

    The cone is filled and the waves are stroked, both in currentColor, so the
    icon inherits the cream / gold / muted-grey the button is already given and
    there is no second palette to keep in step.

    Which parts are drawn is state, and the state is the button's class — set in
    paintVolume(), the one function every volume change passes through:

      (none)     silent before the script runs   cone only
      .is-low    1-50%                           cone + inner wave
      .is-high   51-100%                         cone + both waves
      .is-muted  0% or muted                     cone + cross, no waves

    The parts are hidden with `display:none` rather than opacity: an SVG path at
    opacity 0 still takes its place in the icon's ink, and the cross would sit
    under the waves it replaces. */
/*  Sized in px on the same clamp as the full-screen mark, not in em: the button
    inherits .nf-tool's 10.5px label type, and an em-sized icon would come out at
    the size of the lettering it replaced. The two icons in the pill match. */
.nf-vol-icon {
    width: clamp(17px, 1.7vw, 21px);
    height: clamp(17px, 1.7vw, 21px);
    display: block;
    overflow: visible;
}

    .nf-vol-cone {
        fill: currentColor;
    }

    .nf-vol-wave,
    .nf-vol-cross {
        fill: none;
        stroke: currentColor;
        stroke-width: 1.9;
        stroke-linecap: round;
    }

    /* Nothing but the cone until the script reports a level. */
    .nf-vol-wave,
    .nf-vol-cross {
        display: none;
    }

    .nf-vol-btn.is-low .nf-vol-wave--1,
    .nf-vol-btn.is-high .nf-vol-wave--1,
    .nf-vol-btn.is-high .nf-vol-wave--2 {
        display: block;
    }

    .nf-vol-btn.is-muted .nf-vol-cross {
        display: block;
    }

    .nf-vol-btn.is-muted .nf-vol-wave {
        display: none;
    }

/*  The word "Vol" carried the toolrow's letter-spacing and its strike-through
    when muted. An icon wants neither — the cross says it now. */
.nf-stage-tools .nf-vol-btn {
    letter-spacing: 0;
    text-decoration: none;
    min-width: 30px;
    min-height: 30px;
}

    .nf-stage-tools .nf-vol-btn.is-muted {
        text-decoration: none;
    }

/*  The full-screen mark, drawn at icon size rather than at label size.

    Derrick, 2026-09-09: "The full screen icon in the corner needs to be bigger
    also." It inherited .nf-tool's clamp(9px, .9vw, 10.5px) — the size of the
    lettering on TRANSCRIPT and CC, which is right for a word and far too small
    for a single glyph doing the work of an icon. "Vol" beside it stays at label
    size, because that one IS a word.

    The box grows with it: 24px was the WCAG 2.2 SC 2.5.8 floor and a floor is not
    a target. At 30px the arrows have room to read as arrows. */
.nf-stage-tools .nf-full-btn {
    font-size: clamp(17px, 1.7vw, 21px);
    line-height: 1;
    min-width: 30px;
    min-height: 30px;
}

/*  The slider folds away, the way YouTube's does.

    Derrick, 2026-09-09: "I also want audio to be collapsible just like YouTube
    not taking up so much screen space all the time." At rest the pill is the mute
    button alone; the level appears when the pointer is on the volume group or
    when anything in it takes keyboard focus, and folds back when it leaves.

    width, not display or visibility. The slider has to stay in the layout and in
    the tab order for focus-within to be able to bring it back — an element set to
    display:none cannot receive the focus that would reveal it. Zero width with
    overflow clipped on the group gives the same visual result and keeps it
    reachable.

    The transition is on width and opacity only. Never on `all`: this element also
    carries --nf-vol-pct, which the player rewrites on every volumechange to paint
    the gold fill, and transitioning that would leave the level lagging the sound
    it is reporting. */
.nf-stage-tools .nf-vol {
    overflow: hidden;
}

    .nf-stage-tools .nf-vol-slider {
        width: 0;
        opacity: 0;
        margin-left: -.5rem; /* takes back the .nf-vol gap while folded */
        transition: width .22s ease, opacity .22s ease, margin-left .22s ease;
    }

    .nf-stage-tools .nf-vol:hover .nf-vol-slider,
    .nf-stage-tools .nf-vol:focus-within .nf-vol-slider {
        width: clamp(56px, 7vw, 84px);
        opacity: 1;
        margin-left: 0;
    }

    @media (prefers-reduced-motion: reduce) {
        .nf-stage-tools .nf-vol-slider {
            transition: none;
        }
    }

/* Custom transport, matching the deck's skin. */
.nf-controls {
    margin-top: clamp(.9rem, 2vw, 1.25rem);
}

.nf-scrub {
    display: flex;
    align-items: center;
    gap: .65rem;
}

.nf-time {
    font: 600 clamp(11.5px, 1vw, 12px) var(--nf-sans);
    color: var(--nf-line-3);
    flex: none;
    font-variant-numeric: tabular-nums;
}

.nf-track {
    flex: 1;
    height: 4px;
    border-radius: 2px;
    background: var(--nf-ground-3);
    position: relative;
    cursor: pointer;
}

.nf-track-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: var(--nf-gold);
    border-radius: 2px;
}

.nf-track-knob {
    position: absolute;
    left: 0;
    top: 50%;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--nf-cream);
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.nf-transport {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(1rem, 2.5vw, 1.6rem);
    margin-top: clamp(.9rem, 2vw, 1.15rem);
}

.nf-skip {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .1rem;
    background: none;
    border: 0;
    cursor: pointer;
    padding: .25rem;
}

    .nf-skip .g {
        font: 700 clamp(15px, 1.5vw, 20px) var(--nf-sans);
        color: #dcd8cf;
    }

    .nf-skip .s {
        font: 600 clamp(8px, .8vw, 9.5px) var(--nf-sans);
        color: var(--nf-muted);
    }

    .nf-skip:hover .g {
        color: var(--nf-gold);
    }

.nf-bigplay {
    width: clamp(38px, 3.6vw, 50px);
    height: clamp(38px, 3.6vw, 50px);
    border-radius: 50%;
    background: var(--nf-cream);
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    transition: transform .2s ease;
}

    .nf-bigplay:hover {
        transform: scale(1.05);
    }

    .nf-bigplay .bar {
        width: 4px;
        height: 14px;
        background: var(--nf-ink);
        border-radius: 1px;
    }

    .nf-bigplay .tri {
        width: 0;
        height: 0;
        border-left: 14px solid var(--nf-ink);
        border-top: 9px solid transparent;
        border-bottom: 9px solid transparent;
        margin-left: 3px;
    }

    /* Paused/playing swap — two bars, exactly as the deck draws the pause state. */
    .nf-bigplay .bar-pair {
        display: flex;
        gap: 3px;
    }

.nf-toolrow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(.75rem, 2vw, 1.4rem);
    margin-top: clamp(.85rem, 1.8vw, 1.15rem);
}

.nf-tool {
    font: 600 clamp(9px, .9vw, 10.5px) var(--nf-sans);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--nf-muted);
    background: none;
    border: 0;
    cursor: pointer;
    padding: .2rem;
    transition: color .2s ease;
}

    .nf-tool:hover,
    .nf-tool[aria-expanded="true"],
    .nf-tool.is-on {
        color: var(--nf-gold);
    }

/* Volume — mute toggle plus level, sharing the toolrow's type so it reads as one
   more tool rather than a browser widget dropped into the deck's chrome. */
.nf-vol {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

    .nf-vol-btn.is-muted {
        color: var(--nf-line-3);
        text-decoration: line-through;
    }

.nf-vol-slider {
    /* Set by the player on every volumechange, so the fill follows the mute
       button and the arrow keys, not just a drag of this element. */
    --nf-vol-pct: 100%;
    -webkit-appearance: none;
    appearance: none;
    box-sizing: border-box;
    width: clamp(56px, 7vw, 84px);
    /*  A 3px-tall track is a 3px-tall touch target, which fails WCAG 2.2 SC 2.5.8
        by a mile and is miserable to actually use on a phone. The element is 24px
        tall now and the padding is what gives the track back its 3px: with
        background-clip:content-box the gradient paints only inside the content
        box, so it still LOOKS like a hairline while being a real target. */
    height: 24px;
    padding: 10.5px 0;
    border-radius: 2px;
    background: linear-gradient(to right,
                var(--nf-gold) var(--nf-vol-pct),
                var(--nf-hairline) var(--nf-vol-pct));
    background-clip: content-box;
    cursor: pointer;
    outline: none;
}

    .nf-vol-slider::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 11px;
        height: 11px;
        border-radius: 50%;
        background: var(--nf-cream);
        border: 0;
        cursor: pointer;
    }

    .nf-vol-slider::-moz-range-thumb {
        width: 11px;
        height: 11px;
        border-radius: 50%;
        background: var(--nf-cream);
        border: 0;
        cursor: pointer;
    }

    .nf-vol-slider:focus-visible {
        outline: 2px solid var(--nf-gold);
        outline-offset: 3px;
    }

.nf-player-meta {
    margin-top: clamp(1rem, 2vw, 1.4rem);
}

.nf-player-title {
    font: 400 clamp(1.35rem, 2.4vw, 2rem)/1.15 var(--nf-serif);
    color: var(--nf-cream-2);
}

.nf-player-desc {
    font: 400 clamp(12px, 1.05vw, 13.5px)/1.55 var(--nf-sans);
    color: var(--nf-line-2);
    margin-top: .35rem;
}

/* Podcast — art column + transcript panel */
.nf-listen-layout {
    display: flex;
    gap: clamp(1.25rem, 3vw, 2.5rem);
    align-items: flex-start;
}

.nf-listen-side {
    flex: none;
    width: clamp(150px, 20vw, 280px);
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

.nf-listen-art {
    width: 100%;
    aspect-ratio: 1;
    border-radius: 5px;
    overflow: hidden;
}

    .nf-listen-art img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        filter: grayscale(1);
    }

.nf-listen-ep-title {
    font: 400 clamp(1.15rem, 1.9vw, 1.6rem)/1.15 var(--nf-serif);
    color: var(--nf-cream-2);
}

.nf-listen-ep-series {
    font: 500 clamp(12px, 1vw, 12.5px) var(--nf-sans);
    color: var(--nf-muted-2);
    margin-top: .2rem;
}

.nf-transcript {
    flex: 1;
    min-width: 0;
    background: #181b21;
    border-radius: 6px;
    padding: clamp(1rem, 2vw, 1.35rem) clamp(1.1rem, 2.2vw, 1.5rem);
    position: relative;
    overflow: hidden;
}

    .nf-transcript[hidden] {
        display: none;
    }

.nf-transcript-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    margin-bottom: .6rem;
}

    .nf-transcript-head .k {
        font: 600 clamp(9.5px, .95vw, 11px) var(--nf-sans);
        letter-spacing: .28em;
        text-transform: uppercase;
        color: var(--nf-gold);
    }

    .nf-transcript-head .h {
        font: 500 clamp(11.5px, .95vw, 12px) var(--nf-sans);
        color: var(--nf-muted-3);
    }

/* Top fade, as in the deck */
.nf-transcript-fade {
    position: absolute;
    left: 0;
    right: 0;
    top: clamp(2.4rem, 4vw, 3rem);
    height: 26px;
    background: linear-gradient(#181b21, transparent);
    pointer-events: none;
    z-index: 2;
}

.nf-cues {
    display: flex;
    flex-direction: column;
    gap: clamp(.65rem, 1.4vw, .95rem);
    max-height: clamp(240px, 42vh, 420px);
    overflow-y: auto;
    scrollbar-width: thin;
}

.nf-cue {
    display: flex;
    gap: .65rem;
    align-items: baseline;
    width: 100%;
    text-align: left;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

.nf-cue-time {
    font: 600 clamp(11px, .9vw, 12px) var(--nf-sans);
    color: var(--nf-hairline);
    flex: none;
    width: 2.6rem;
    font-variant-numeric: tabular-nums;
    transition: color .25s ease;
}

/* Transcript copy is EB Garamond, and the active line grows and brightens. */
.nf-cue-text {
    font: 400 clamp(14px, 1.3vw, 17px)/1.3 var(--nf-serif);
    color: #6b6f78;
    transition: color .25s ease, font-size .25s ease;
}

.nf-cue.is-past .nf-cue-text {
    color: #4e525b;
}

.nf-cue.is-current .nf-cue-text {
    font-weight: 500;
    font-size: clamp(16px, 1.6vw, 21px);
    color: var(--nf-cream);
}

.nf-cue.is-current .nf-cue-time {
    color: var(--nf-gold);
}

.nf-cue:hover .nf-cue-text {
    color: var(--nf-line);
}

/* Interior responsive */
@media (max-width: 900px) {
    /*  .nf-stories-grid is one column at every width now, so the rule that used
        to stack it here is gone. What still needs a breakpoint is the pair of
        articles under the feature: two 132px thumbnails and two excerpts do not
        fit side by side on a narrow tablet. */
    .nf-story-stack {
        grid-template-columns: 1fr;
    }

    .nf-watch-grid {
        grid-template-columns: 1fr;
    }

    .nf-listen-chip {
        flex: 0 0 100%;
    }

    .nf-listen-layout {
        flex-direction: column;
    }

    .nf-listen-side {
        width: 100%;
        max-width: 260px;
    }
}

@media (max-width: 820px) {
    .nf-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .nf-detail {
        flex-direction: column;
        align-items: flex-start;
        gap: 1.25rem;
    }

    .nf-archive-row {
        flex-wrap: wrap;
        gap: .2rem .75rem;
    }

    .nf-archive-label {
        width: auto;
    }
}

@media (max-width: 520px) {
    .nf-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (prefers-reduced-motion: reduce) {
    .nf-story-hero-img {
        transform: none !important;
    }
}

/* ------------------------------------------------ layout modifier classes

   These replace inline style= attributes that were patching one-off spacing.
   Keeping them here means the handset sheet's touch-target rules are not
   fighting an inline declaration for specificity. */

.nf-crumb--player {
    margin-bottom: 1rem;
}

.nf-kick--spaced {
    margin-top: 1rem;
}

.nf-note--spaced {
    margin-top: 1rem;
}

.nf-transcript--stacked {
    margin-top: 1.25rem;
}

/* The "Feature · New" chip sits tight under the feature image. */
.nf-tag--flag {
    margin: .15rem 0 0;
}

/* Two skeleton rules of unequal width stand in for an unwritten excerpt. */
.nf-skel {
    width: 88%;
}

.nf-skel--short {
    width: 60%;
}

/* An archive entry with no target yet is not clickable. */
.nf-archive-row.is-static {
    cursor: default;
}

    .nf-archive-row.is-static:hover {
        padding-left: 0;
        background: none;
    }

/* ------------------------------------------------ pointer target minimums

   WCAG 2.2 AA 2.5.8 sets 24x24 CSS px for pointer targets, and it applies to a
   mouse, not only to touch. These sizes lived in never-forgotten-handset.css,
   where a stray brace had been leaking them to every width for the life of the
   file. Closing that brace was right, but it silently returned desktop to base
   rules that had effectively never rendered: the scrub track dropped from a
   ~32px hit area to 4px, and the CC / Transcript / speed / fullscreen buttons to
   about 18px tall.

   They belong here, unconditionally — a comfortable target is not a phone
   concern. The handset sheet keeps only what is genuinely phone-specific. */

.nf-tool {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    padding: 0 .35rem;
}

/* Keep the 4px visual weight, give it a real hit area. */
.nf-track {
    padding: 14px 0;
    height: auto;
    background: none;
}

    .nf-track::before {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        height: 4px;
        border-radius: 2px;
        background: var(--nf-ground-3);
    }

.nf-track-fill,
.nf-track-knob {
    top: 50%;
    transform: translateY(-50%);
}

.nf-track-fill {
    height: 4px;
    bottom: auto;
    border-radius: 2px;
}

/*  ------------------------------------------------- moving between the fourteen

    Derrick, 2026-09-09: "Can we add a Next/Previous button to the faces so people
    can scroll through them without going back each time?"

    Sits above the back link on the portrait view. The two links take the back
    link's own pill shape and gold, because that is what a navigational control
    looks like on this page already — three different treatments for three links
    in the same corner would read as three different kinds of thing.

    The count between them is set in the eyebrow's muted grey rather than gold: it
    is a label, not somewhere to press, and gold on this ground means "press me".

    space-between, so Previous holds the left edge and Next the right whatever
    the names are. Two long surnames would otherwise centre themselves into one
    lump with the count squeezed between. */
/*  Same 78ch the bio is set to, so the hairline ends where the paragraph above
    it ends. It used to stretch the full width of the text column while the bio
    stopped 300px short — see the note on .nf-detail-bio. */
.nf-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    margin-top: clamp(1.75rem, 3vw, 2.5rem);
    padding-block-start: 1.1rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--nf-hairline);
}

.nf-pager-link {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    /* 24px floor, as everything tappable on this site now carries. */
    min-height: 24px;
    padding: .5rem .85rem;
    border-radius: 9999px;
    font: 500 13px var(--nf-sans);
    color: var(--nf-gold);
    text-decoration: none;
    transition: opacity .2s ease, background-color .2s ease;
}

    /* The first and last links hang into the column's margin so the ROW of type
       lines up with the bio above it, not the pill's padding. */
    .nf-pager-link {
        margin-inline-start: -.85rem;
    }

    .nf-pager-link--next {
        margin-inline-start: 0;
        margin-inline-end: -.85rem;
    }

    .nf-pager-link:hover {
        opacity: .75;
        background: rgba(245, 243, 236, .06);
    }

/*  Inside the portrait column only: auto pushes the pager and the back link to
    the floor, so they hold still while the biography above them changes length.
    An article and a film page are ordinary flow — auto would compute to zero
    there — which is why the base rule above carries a real margin. */
.nf-detail-txt .nf-pager {
    margin-top: auto;
    padding-block-start: 1.75rem;
}

.nf-pager-count {
    font: 600 clamp(9px, .9vw, 10.5px) var(--nf-sans);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--nf-muted);
    white-space: nowrap;
}

/*  A phone puts the names on top of each other before it drops the count, so the
    names go and the arrows stay: at this width the tap targets matter more than
    knowing whose portrait is next. */
@media (max-width: 420px) {
    .nf-pager-name {
        display: none;
    }
}

/*  Titles are long where surnames are short, so the pager under an article caps
    each side and lets the middle hold. Without this, "Enshrined in Memorial Hall"
    and "Forever Serving" push the count off-centre and, on a narrow window, out
    of the row entirely.

    The full title stays in the link's aria-label, so nothing is lost to a screen
    reader by the ellipsis. */
.nf-pager--article .nf-pager-name {
    display: inline-block;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

@media (max-width: 600px) {
    .nf-pager--article .nf-pager-name {
        max-width: 9ch;
    }
}
