/* =============================================================
   tokens.css: The HighWire layout prototype
   The single source of truth. This is the only file allowed to
   contain a literal colour value. Every other stylesheet reads
   the custom properties defined here.

   Order matters:
     1. :root                          primitives, ornament, light palette
     2. [data-brand="0|1|2|3"]         brand 0 is the greyscale baseline
     3. [data-direction="A|B|C|D|E"]   the only place the layouts differ

   There is no theme setting. The page is pinned to light and in brand 0
   every colour token resolves to a neutral grey.

   A brand direction restyles the prototype by redefining layer 1: the
   ramp, the type pair, the ornament tokens and the --brand-* accent
   tokens. Layer 2
   and layer 3 stay as they are, which is why three directions cost
   three blocks. A direction that wants to be dark inverts its own ramp.
   ============================================================= */

:root {
  /* ---- Layer 1: primitives. Never referenced outside this file. ----
     Neutral through the light stops. The three darkest stops carry a
     faint warm bias so dark grounds are warm near-black, never blue-black. */
  --g0:   #ffffff;
  --g50:  #f7f7f6;
  --g100: #efefed;
  --g200: #e2e2df;
  --g300: #cdcdc9;
  --g400: #a6a5a1;
  --g500: #706f6b;
  --g600: #5c5b57;
  --g700: #42413e;
  --g800: #2b2a27;
  --g900: #1c1b19;
  --g950: #131211;

  /* The one colour a brand direction cannot get from the ramp. Layer 2
     points --accent at this, so greyscale needs no special case. */
  --brand-accent: var(--g900);

  /* The accent's companions. Once the accent has a hue, none of these can
     be read off the ramp either, so they live at layer 1 with it. The
     workbench derives them from the accent and emits all four. Greyscale
     defaults reproduce brand 0 exactly. */
  --brand-accent-text: var(--g900);  /* the accent used as text: links in the reading view */
  --brand-on-accent: var(--g0);      /* text on an accent fill: primary button, live badge */
  --brand-accent-soft: var(--g100);  /* hover and current-page tint */
  --brand-accent-inverse: var(--brand-accent);  /* the accent on the inverted band. A deep blue that reads on white sinks into near-black; the workbench lifts it */

  /* ---- Type. Placeholder pair, both sans so neither implies a direction. ---- */
  --font-display: "Inter Tight", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Kickers, nav, buttons, chips, badges and meta. Defaults to the body face
     so brand 0 is unchanged. A direction can run a grotesk here over a serif
     body, which is how The Ken sets Archivo against Ivar. */
  --font-ui: var(--font-body);
  /* The header nav and its menus. Defaults to the UI face; a direction whose
     UI voice is a mono keeps it off the nav, where it reads as a typewriter. */
  --font-nav: var(--font-ui);

  --text-xs:  0.75rem;    /* 12  kickers, badges */
  --text-sm:  0.875rem;   /* 14  meta */
  --text-ui:  0.9375rem;  /* 15  buttons, nav, chips */
  --text-base: 1.0625rem; /* 17  body, middle of the Guardian / NPR / Free Press range */
  --text-md:  1.25rem;    /* 20  card titles */
  --text-lg:  1.5rem;     /* 24 */
  --text-xl:  2rem;       /* 32 */
  --text-2xl: 2.75rem;    /* 44 */
  --text-3xl: 3.5rem;     /* 56 */

  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-body: 1.55;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-bold: 700;

  --tracking-kicker: 0.06em;
  --tracking-display: -0.015em;

  /* ---- Long-form reading. Separate from the UI scale on purpose: the
     article body can be re-set for reading comfort without moving nav,
     cards or chips with it. ---- */
  --read-leading: var(--leading-body);
  --para-gap: var(--space-3);
  --quote-border: 3px;
  --caption-size: var(--text-sm);

  /* ---- Space. 8-point scale, one half step for chip padding. ---- */
  --space-half: 4px;
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-6: 48px;
  --space-8: 64px;
  --space-12: 96px;
  --space-16: 128px;

  /* ---- Radius. Cards 12 to 16, buttons 10 to 12, pills for functional chips only. ---- */
  --radius-sm: 6px;
  --radius-button: 10px;
  --radius-input: 10px;
  --radius-card: 12px;
  --radius-card-lg: 16px;
  --radius-pill: 999px;

  /* ---- Layout ---- */
  --container: 1280px;
  --gutter: 1.5rem;
  --measure: 65ch;
  --target: 44px;
  --icon-size: 18px;    /* drawn marks inside a 44px icon button */
  --header-h: 64px;
  /* Utility bar over the header (Tucker's top strip: socials left, account
     right). Off by default; a direction turns it on and, with it, moves Sign
     in out of the main nav and grows Donate. All three read as one decision. */
  --utility-display: none;              /* none | flex */
  --utility-h: 36px;                    /* the strip. Tucker's is 42px with 18px icons */
  --utility-icon: 16px;                 /* drawn mark inside each social target */
  --utility-icon-target: 36px;          /* wide side of the 36 by 44 social target; the row pitch */
  --utility-gap: var(--space-2);        /* between Create account and Sign in */
  --nav-signin-display: inline-flex;    /* the Sign in link in the main nav */
  --nav-donate-h: var(--target);        /* the Donate button in the main nav */
  --nav-donate-pad: var(--space-2);
  --nav-donate-size: var(--text-ui);
  --nav-donate-weight: var(--weight-medium);
  --chevron-size: 6px;   /* menu chevron: two borders of this box, turned 45 degrees */
  --chevron-stroke: 1.5px;
  --shelf-nav-size: 36px;          /* the arrow discs in a shelf's section head. Tucker's are 30px under the row */
  --shelf-nav-target: var(--target); /* the invisible hit area around each disc, so a 36px disc still holds 44px */
  --shelf-nav-chevron: 10px;       /* the chevron inside them, drawn like the menu's */
  --shelf-nav-stroke: 2px;         /* heavier than the menu's, which Chrome floors to 1px, to hold Tucker's weight */
  --chat-w: 336px;       /* live chat column beside the player */
  --transcript-h: 640px; /* transcript scroll box on the watch page */
  --search-w: 200px;     /* header search field. Tucker's is 253; this is the
                            smaller box Jeremy asked for, still wide enough
                            to read as somewhere to type. */
  --news-strip-h: 176px; /* the latest news bar in E, half the full bar and
                            the weight of D's weekly board. The band is this
                            tall; the image inside it is this height less its
                            inset, at --card-ratio. */

  /* ---- Show landing page. The hero is a slim full-bleed bar, the Tucker
     Carlson Network show header at roughly a third more height, with the key
     art's printed lockup centred in it. The art is portrait, so the bar shows
     a horizontal slice through the lockup at --show-hero-art-w wide and fades
     into the bar ground at both sides. The intro below it is centred at the
     measure, so the page reads bar, name, description, episodes. ---- */
  --show-hero-h: 272px;
  --show-hero-art-w: 720px;
  --show-hero-focus: center 51%;  /* both lockups sit just under the vertical centre of their file */
  --show-hero-fade: linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
  --show-hero-ground: var(--g950);
  --show-intro-gap: var(--space-4);  /* between the text block and the host, cadence and actions */

  /* ---- Article page. The head splits headline and byline against the
     featured image; the body runs at the measure with a related rail that
     sticks beside it. The header does not stick, so the rail offset is air
     from the viewport edge, not header height. ---- */
  --read-title-size: var(--text-2xl);  /* the headline shares its row with the image, so one step under the old 3xl */
  --read-hero-ratio: 16 / 10;         /* the featured image beside the headline. 5:4 left dead space under the headline, so a fifth shorter; the source files are 3:2 and 16:9, Jeremy's call 2026-09-11 */
  --read-hero-grow: 24px;             /* the image column takes this much more than half the head */
  --read-size: 1.1875rem;             /* 19. Body copy on the article page only, two up from --text-base, Jeremy's call 2026-09-10 */
  --read-measure: 71ch;               /* the body copy. About 14 words a line at --read-size, two fewer than the 80ch it launched with, Jeremy's call 2026-09-10 */
  --read-rail-w: 280px;               /* related articles beside the body copy */
  --read-rail-top: var(--space-3);    /* sticky offset for that rail */

  /* ---- The Protocol band at the foot of home. The five value names and
     the body copy both sit a step above where they launched (24 and 14),
     Jeremy's call 2026-09-10. The body copy has its own size so a brand
     that shrinks --text-sm for its meta, as brand 3 does for its mono,
     does not shrink this copy with it. ---- */
  --protocol-name-size: 1.75rem;  /* 28. Accuracy, Integrity and the rest */
  --protocol-name-fit: 14.5cqi;   /* but never wider than the name's column. The longest, "Accountability", needs 6.8em in brand 3's grotesk, and 14.5% of the column holds it: D's 198px columns get the full 28, C's 182px get 26, a 1024 window about 25 */
  --protocol-body-size: 1rem;     /* 16. The copy under each value and under each of the three promises */

  /* ---- Motion. Hover only, under 200ms. The one exception is the
     schedule bar in direction D, which advances on a dwell timer at
     the client's request. Reduced motion stops it. A shelf arrow
     glides the row one view on click, the browser's own smooth
     scroll; auto makes it jump, and reduced motion does that. ---- */
  --hover-duration: 150ms;
  --schedule-dwell: 6s;
  --shelf-scroll: smooth;

  /* ---- Layer 2: semantic colour. Reads layer 1, so a brand direction
     never has to touch it. ---- */
  --ground: var(--g50);
  --raised: var(--g0);
  --sunk: var(--g100);
  --overlay: color-mix(in srgb, var(--g950) 60%, transparent);

  --text: var(--g900);
  --text-2: var(--g600);
  --text-3: var(--g500);
  --text-on-accent: var(--brand-on-accent);
  --text-on-image: var(--g0);

  --border: var(--g200);
  --border-strong: var(--g400);

  /* Round controls on the ground: the shelf arrows. A soft disc with the
     chevron in ink, one step darker on hover. Once the row reaches that
     end, disc and chevron both drop back so the arrow reads as spent. */
  --control-fill: var(--g200);
  --control-fill-hover: var(--g300);
  --control-fill-off: var(--sunk);
  --control-ink-off: var(--g400);

  /* A chip on the media: the running time on a segment card. The brand's
     accent with its own ink, so the minutes are the brightest thing on the
     row, Jeremy's call 2026-09-10 (it was near-black). The same fill the
     episode badges use on the media. Brand 0's accent is ink, so there the
     chip stays dark. */
  --chip-media-fill: var(--accent);
  --chip-media-ink: var(--text-on-accent);

  /* One accent, used only for interactive and live states.
     In brand 0 the accent is ink, so states read by fill, not hue. */
  --accent: var(--brand-accent);
  --accent-text: var(--brand-accent-text);
  /* Hover colour for text links: headlines, nav, list rows. Hue instead
     of an underline, the Free Press pattern. Brand 0 has no hue to move
     to, so its block below drops the link a step on the ramp instead. */
  --link-hover: var(--accent-text);
  --accent-soft: var(--brand-accent-soft);
  --live: var(--accent);
  --focus: var(--accent);

  /* The inverted band: the Protocol statement at the foot of home. It swaps
     ends of the ramp rather than naming colours, so a dark direction flips
     it the other way on its own. The accent carries over from the brand;
     greyscale's is ink, so the brand 0 block below lifts it. */
  --inverse-ground: var(--g950);
  --inverse-raised: var(--g900);
  --inverse-text: var(--g50);
  --inverse-text-2: var(--g300);
  --inverse-text-3: var(--g400);
  --inverse-border: var(--g800);
  --inverse-accent: var(--brand-accent-inverse);
  /* The band's own accent, not --accent-text: a brand whose accent is too pale
     to carry text on the page ground (brand 1's gold) darkens it for links, and
     that darkened form would sink into the band. The pale one reads here, and
     a brand whose accent is too deep for the band (brand 3's blue) lifts it. */
  --inverse-accent-text: var(--brand-accent-inverse);

  --shadow-1: 0 1px 2px color-mix(in srgb, var(--g950) 8%, transparent);
  --shadow-2: 0 6px 20px color-mix(in srgb, var(--g950) 10%, transparent);

  /* ---- Ornament. Most of what separates one brand direction from
     another. Defaults here reproduce brand 0 exactly. ---- */
  --card-border-width: 1px;              /* 0 for borderless cards */
  --card-border-color: var(--border);    /* so a direction can tint the hairline */
  --card-shadow: none;                   /* var(--shadow-1) for a lifted card */
  --card-media-inset: 0px;               /* card edge to image: the framed look */
  --card-pad: 0px;                       /* card body padding, drives density */
  --kicker-transform: uppercase;         /* none for sentence-case kickers */
  --kicker-weight: var(--weight-medium);
  --display-weight: var(--weight-bold);  /* lets a direction run a lighter display face */
  --section-rule: 0px;                   /* rule above every section head */
  --section-rule-color: var(--border);   /* var(--text) runs it in ink, the newspaper section rule */
  --section-rule-gap: 0px;               /* rule to heading; only meaningful with a rule */
  --card-body-gap: 0px;                  /* image to title on a stacked card */
  --card-rule: 0px;                      /* rule along the top of every card: rule, image, title */
  --card-rule-color: var(--border);
  --frame-rule: 1px;                     /* the line under the header and over the footer */
  --frame-rule-color: var(--border);
  --kicker-color: var(--text-3);         /* var(--accent-text) puts the brand's one hue on every kicker */
  --btn-border-width: 1px;               /* secondary button outline */

  /* Where an episode card carries its number and duration. The comps put both
     on the thumbnail; the prototype has always put them under the card. Both
     readings are reachable so Del can compare them in one brand direction.
     meta is the default because a badge on the media sits on the face of
     whoever is on screen. Set data-badges="media" on <html> to switch. */
  --badge-on-media: none;
  --badge-in-meta: inline;

  /* Applied to every photograph. Brand 0 holds it at greyscale; the
     three brand directions release it below. */
  --media-filter: grayscale(1);

  /* ---- Hero wash. A tinted, grainy overlay on the lead-story and hero
     photograph only, never the cards. Lifted from the Colby College hero
     (a blue duotone with visible grain). Off in brand 0: opacity 0 and the
     photo carries the ordinary media filter. ---- */
  --hero-wash-color: transparent;
  --hero-wash-blend: multiply;             /* multiply | color | screen | soft-light */
  --hero-wash-opacity: 0;
  --hero-media-filter: var(--media-filter); /* the photo under the wash; grayscale(1) makes it a duotone */
  --hero-grain: none;                      /* var(--grain-image) switches the grain on */
  --grain-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 .38 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");

  /* ---- Layer 3 defaults: direction A applies until JS sets data-direction. ---- */
  --column: 1280px;
  --section-gap: var(--space-12);
  --theatre-gap: var(--space-4);     /* player to the episode head, one step off the frame */
  --grid-cols: 4;
  --card-ratio: 16 / 9;
  --card-gap: var(--space-3);
  --headline-size: var(--text-2xl);
  --hero-h: 440px;
  --shelf-cols: var(--grid-cols);
  --topic-cols: 4;
  --film-cols: 3;
  --film-ratio: 16 / 9;

  /* Pinned, and it has to stay pinned. Without it a visitor on a
     dark-mode OS gets dark form controls and scrollbars on a light page. */
  color-scheme: light;
}

@media (prefers-reduced-motion: reduce) {
  :root { --hover-duration: 0ms; --schedule-dwell: 0s; --shelf-scroll: auto; }
}

/* ---- 2. Brand tokens. A direction redefines layer 1 here and nowhere
        else. Brand 0 is the greyscale baseline and must stay reachable. ---- */

/* The one place the badge reading differs. No selector below this file. */
[data-badges="media"] { --badge-on-media: flex; --badge-in-meta: none; }

/* Photography comes up in colour the moment a direction is selected. */
/* Greyscale has no hue to shift to. Two steps down the ramp, so links that
   rest at --text-2 (More, footer) still move on hover. */
[data-brand="0"] { --media-filter: grayscale(1); --link-hover: var(--text-3); }
[data-brand="1"],
[data-brand="2"],
[data-brand="3"] { --media-filter: none; }
/* Greyscale's accent is ink, which on the inverted band is nearly the ground
   itself: the Protocol's kicker, wire and link all vanish. Lift it to the
   band's own ink. Branded directions keep their accent untouched. */
[data-brand="0"] { --inverse-accent: var(--inverse-text); --inverse-accent-text: var(--inverse-text); }

/* Brand 1. Generated from the workbench 2026-09-10.
   Layer 1 only. Nothing here touches the semantic tokens, so the
   whole prototype restyles off this ramp. */
[data-brand="1"] {
  --g0: #fefefe;
  --g50: #f5f6f7;
  --g100: #edeef0;
  --g200: #dee0e5;
  --g300: #c6c9d1;
  --g400: #9da2b0;
  --g500: #656c80;
  --g600: #4f576e;
  --g700: #353d56;
  --g800: #1d2541;
  --g900: #0f1633;
  --g950: #080e2b;

  --brand-accent: #fbc374;
  --brand-accent-text: #8d6830;   /* the accent as text: hover and reading links. Bronze, rgb(141 104 48), Jeremy's pick 2026-09-10 (was slate #2c3f58). The gold itself is 1.5:1 on the ground; this is 4.7:1, 5.0 on cards */
  --brand-on-accent: #080e2b;
  --brand-accent-soft: #f6efe6;

  --font-display: "Newsreader", Georgia, serif;
  --font-body: "Geist", system-ui, sans-serif;   /* Jeremy's pick 2026-09-11 (was Figtree). The UI face follows it */
  --font-ui: var(--font-body);
  --display-weight: 600;
  --tracking-display: -0.012em;
  --text-base: 17px;
  --kicker-transform: uppercase;

  --radius-sm: 2px;
  --radius-card: 4px;
  --radius-card-lg: 8px;
  --radius-button: 28px;
  --radius-input: 28px;
  --radius-pill: 999px;
  --card-border-width: 0px;
  --card-shadow: none;
  --card-media-inset: 0px;
  --section-rule: 1px;
  --section-rule-gap: var(--space-3);
  --card-body-gap: var(--space-2);
  --media-filter: none;

  --hero-wash-color: transparent;
  --hero-wash-blend: multiply;
  --hero-wash-opacity: 0;
  --hero-media-filter: var(--media-filter);
  --hero-grain: none;
}

/* Brand 2. Generated from the workbench 2026-09-10.
   Layer 1 only. Nothing here touches the semantic tokens, so the
   whole prototype restyles off this ramp. */
[data-brand="2"] {
  --g0: #fefefe;
  --g50: #f6f6f6;
  --g100: #eeeeee;
  --g200: #e0e0e0;
  --g300: #c9c9c9;
  --g400: #a2a2a2;
  --g500: #6c6c6c;
  --g600: #585858;
  --g700: #3e3e3e;
  --g800: #272727;
  --g900: #191919;
  --g950: #111111;

  --brand-accent: #d33c3c;
  --brand-accent-text: #d33c3c;
  --brand-on-accent: #fefefe;
  --brand-accent-soft: #f5dedb;

  --font-display: "Instrument Sans", system-ui, sans-serif;
  --font-body: "Source Serif 4", Georgia, serif;
  --font-ui: var(--font-body);
  --display-weight: 600;
  --tracking-display: -0.01em;
  --text-base: 17px;
  --kicker-transform: uppercase;

  --radius-sm: 0px;
  --radius-card: 0px;
  --radius-card-lg: 4px;
  --radius-button: 2px;
  --radius-input: 2px;
  --radius-pill: 999px;
  --card-border-width: 0px;
  --card-shadow: none;
  --card-media-inset: 5px;
  --section-rule: 1px;
  --section-rule-gap: var(--space-2);  /* to the top of the heading row, where the shelf arrows start. The capitals land 22px under the rule, one cap height; 0 set the arrows on the rule. Measured 2026-09-10, see layout-decisions.md */
  --card-body-gap: 0px;
  --media-filter: none;

  --hero-wash-color: transparent;
  --hero-wash-blend: multiply;
  --hero-wash-opacity: 0;
  --hero-media-filter: var(--media-filter);
  --hero-grain: none;
}

/* Brand 3. Generated from the workbench 2026-09-10, ground pinned to white.
   Layer 1 only. Nothing here touches the semantic tokens, so the
   whole prototype restyles off this ramp.
   The ruled edition: pure white, one black, one blue. Everything is
   square, nothing is filled or shadowed, and structure is drawn with
   lines instead of boxes: a 2px ink rule under the header and over every
   section head, a hairline over every card, and the blue held to kickers,
   the primary button, the live state and hover. Type is one grotesk for
   display, body and the nav, with Geist for kickers, buttons and meta (a
   mono voice until 2026-09-11). Photography is full colour everywhere,
   the lead included: the blue wash was tried and dropped, Jeremy's call
   2026-09-10. */
[data-brand="3"] {
  --g0: #ffffff;
  --g50: #ffffff;
  --g100: #efefef;
  --g200: #e1e1e1;
  --g300: #c9c9c9;
  --g400: #a2a2a2;
  --g500: #6c6c6c;
  --g600: #585858;
  --g700: #3e3e3e;
  --g800: #272727;
  --g900: #191919;
  --g950: #111111;

  --brand-accent: #0646c3;
  --brand-accent-text: #0646c3;
  --brand-on-accent: #ffffff;
  --brand-accent-soft: #dbe6f9;
  --brand-accent-inverse: #447ae6;

  --font-display: "Schibsted Grotesk", system-ui, sans-serif;
  --font-body: "Schibsted Grotesk", system-ui, sans-serif;
  --font-ui: "Geist", system-ui, sans-serif;   /* Jeremy's pick 2026-09-11 (was the mono, Source Code Pro): buttons, chips, kickers and meta. The nav stays on the body face */
  --font-nav: var(--font-body);
  --display-weight: 700;
  --tracking-display: -0.03em;
  --text-base: 17px;
  --text-sm: 0.8125rem;   /* 13. Meta, dates, the schedule cells. Set a size down for the mono; kept when the UI face went to Geist */
  --text-ui: 0.875rem;    /* 14. Nav, buttons and chips, Thrillist's nav is 12 */
  --kicker-transform: uppercase;
  --kicker-color: var(--accent-text);

  --radius-sm: 0px;
  --radius-card: 0px;
  --radius-card-lg: 0px;
  --radius-button: 0px;
  --radius-input: 0px;
  --radius-pill: 0px;
  --card-border-width: 0px;
  --card-shadow: none;
  --card-media-inset: 0px;
  --section-rule: 2px;
  --section-rule-color: var(--text);
  --section-rule-gap: var(--space-2);
  --card-body-gap: var(--space-2);
  --card-rule: 1px;
  --card-rule-color: var(--border);
  --frame-rule: 2px;
  --frame-rule-color: var(--text);
  --media-filter: none;

  --hero-wash-color: transparent;
  --hero-wash-blend: multiply;
  --hero-wash-opacity: 0;
  --hero-media-filter: var(--media-filter);
  --hero-grain: none;
}

/* ---- 3. Direction tokens. The only place A, B, C, D and E differ in CSS.
        If a per-direction selector is ever needed below this block,
        stop and move the difference up here as a token. ---- */

/* A: Tucker. Wide and cinematic. Shelves at full container width. */
[data-direction="A"] {
  --column: 1280px;
  --section-gap: var(--space-12);
  --grid-cols: 4;
  --card-ratio: 16 / 9;
  --card-gap: var(--space-3);
  --headline-size: var(--text-2xl);
  --hero-h: 440px;
}

/* B: NPR. Contained column, generous measure, calm rhythm. */
[data-direction="B"] {
  --column: 1120px;
  --section-gap: var(--space-8);
  --grid-cols: 3;
  --card-ratio: 3 / 2;
  --card-gap: var(--space-4);
  --headline-size: var(--text-xl);
  --hero-h: 0px;
}

/* C: Puck. Tighter editorial width, dense stacked lists. */
[data-direction="C"] {
  --column: 1040px;
  --section-gap: var(--space-6);
  --grid-cols: 2;
  --card-ratio: 16 / 9;
  --card-gap: var(--space-2);
  --headline-size: var(--text-lg);
  --hero-h: 0px;
}

/* D: the combination. B's frame and nav, A's latest-episodes shelf,
   the weekly schedule block, films at 16:9 three across, image-led articles. */
[data-direction="D"] {
  --column: 1120px;
  --section-gap: var(--space-8);
  --grid-cols: 3;
  --card-ratio: 16 / 9;
  --card-gap: var(--space-3);
  --headline-size: var(--text-xl);
  --hero-h: 0px;
  --shelf-cols: 4;
  --topic-cols: 5;
  --film-cols: 3;
  --film-ratio: 16 / 9;
}

/* E: D's tokens exactly. D and E differ only in section order, which lives in
   the markup: E leads with the latest news bar, D with the weekly schedule. */
[data-direction="E"] {
  --column: 1120px;
  --utility-display: flex;              /* 2026-09-11, Jeremy: Tucker's top strip on E */
  --nav-signin-display: none;           /* Sign in lives in the strip, so the nav drops it */
  --nav-donate-h: 48px;                 /* and Donate takes the room: one step taller and wider, same weight as D's */
  --nav-donate-pad: var(--space-3);
  --nav-donate-size: var(--text-base);
  --section-gap: var(--space-8);
  --grid-cols: 3;
  --card-ratio: 16 / 9;
  --card-gap: var(--space-3);
  --headline-size: var(--text-xl);
  --hero-h: 0px;
  --shelf-cols: 4;
  --topic-cols: 5;
  --film-cols: 3;
  --film-ratio: 16 / 9;
}
