/* ══ THE DISPLAY FACE — DESIGN LAW 2, PUBLIC SURFACE (founder 2026-08-25) ══
   Measured before it was written: ZERO of the 93 headings across the eleven
   public pages carries an inline font-family, and no page declares an h1/h2
   rule at all — each sets the face on `body` and lets headings inherit. A
   direct rule beats an inherited value regardless of source order, so ONE
   declaration here reaches every heading on every page that loads this file.
   That is why the face is not a per-page migration.

   ⛔ THE SERIF DOES NOT REACH THE TERMINAL. terminal.html does not load this
   stylesheet, and TERMINAL_FACES withholds Newsreader. The site is READ; the
   terminal is SCANNED, and a serif slows a reader hunting figures.

   WEIGHT 300 IS THE MECHANISM, NOT THE DECORATION. A sans buys hierarchy
   with weight, and weight is what shouts. A light serif buys it with
   letterform contrast, so it carries size without volume. The 50px/40px
   ceilings are UNCHANGED and still gated — this makes them comfortable
   rather than contested.
   ⚠ The weight could NOT be set from here: all 87 headings carry an inline
   font-weight:600, and an inline style beats a stylesheet. Those were
   rewritten in the same change. If a new heading arrives at 600 it will
   render bold serif, which is the one ugly outcome — headline_weight and
   site_type_families are the gates that catch it.

   ⛔ No negative tracking on the serif: Newsreader's optical-size axis
   already fits spacing to size, and manual tracking on top double-corrects.
   ══════════════════════════════════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght@6..72,300;6..72,400&display=swap');
:root{
  /* ══ ONE LITERAL PER COLOUR (2026-08-23) ═══════════════════════════════
     Eight tokens repeated a hex that another token already owned:
     ground-dark · raised-2 · rule-light · ink-dark · ink-on-light ·
     ink-light-mute · and the whole --film-* block. 816 call sites read the
     aliases, so collapsing the CALL SITES is a separate, larger change — but
     the DEFECT is not the alias, it is the second LITERAL. Two literals drift
     apart silently and nothing goes red; an alias pointing at its home cannot.
     ⇒ Every alias below now RESOLVES to its home. Zero visual change, zero
     call sites touched, and the class is closed at the only place it can be.
     ⚠ --card-light and --rule-light-2 keep their own literals: they are not
     duplicates, they are their own steps on the ladder.
     ⚠ --raised-2 is #C7CDD4 — an INK value under a SURFACE name. Pointed at
     its true home rather than renamed, because 126 sites read it and a rename
     is a call-site change. The misnomer is now visible in one line.
     ══════════════════════════════════════════════════════════════════════ */
  /* GROUNDS — one ladder, blue-leaning as it rises */
  --ground:#0F1114; --ground-dark:var(--ground);
  /* ── THE SECOND GROUND (v6 GTM, 2026-08-25) ─────────────────────────
     v6 alternates two grounds section by section, separated by a 1px rule.
     --ground-dark had been aliased to --ground on 2026-08-23, so every page
     that "alternated" rendered one tone. This is the deeper step, declared
     here so the palette gate reads it as a stop; index.html is its first
     reader. ⛔ Not a card surface — cards stay on --raised. */
  --ground-deep:#080B0E;
  /* ── GOLD — VALUE, AS v6 USES IT (founder 2026-08-25: "we should use gold
     like v6"). Red is ACTION (what to do, when); gold is VALUE (money,
     attribution, proof, the cohort offer). Neither fills a large area.
     --gold on rules and borders beside money and proof; --gold-on-dk as ink
     and figures (AA on both grounds); --gold-mute for subordinate numerals.
     ⛔ This is NOT the retired orange --label (#E8A33D) coming back: that was
     a second ACCENT standing beside red on labels; this is a value colour
     with three fixed roles. */
  --gold:#E2BB4F; --gold-on-dk:var(--gold); --gold-mute:#B08F45;
  --raised:#191D21; --card-light:#20252A;
  /* RULES */
  --rule:#2A3036; --rule-light:var(--rule); --rule-light-2:var(--rule);
  /* INKS */
  --ink:#F3F5F7; --ink-2:#C3CAD1; --ink-muted:#9BA5B1; --ink-muted-2:#8E98A3;
  --raised-2:var(--ink-2);
  --ink-dark:var(--ink); --ink-on-light:var(--ink-2); --ink-light-mute:var(--ink-muted);
  /* ⛔ --ink-cool DELETED — it was #6E9BC9, the same hex as --hold, under a
     name that made a VERDICT look like a neutral. Its 36 sites were split by
     role: the acting one took fire, the held ones took --hold, and the
     copyright line and labels took ash. The sweep that did it is recorded in
     the design-lens plan under docs/, not named here — a shipped asset does
     not carry internal paths. */
  /* ── FIRE — THE ACTION, AND ONLY THE ACTION (ruling 2026-08-23) ────────
     --accent is the LINK and the ACTIVE NAV. --accent-deep is the FILL.
     ⛔ It is not an eyebrow colour any more. 18 eyebrows and 13 footer
     taglines were painted in it, which made the loudest thing on every page
     a label nobody clicks while the button sat in a dried #961212. Fire is
     emission: it marks what ACTS. The brightness budget moved to the fill.
     ⚠ #C22B2B is not a preference — it is the hottest red that still carries
     #ECEEF0 at AA. MEASURED 4.82:1; #CC3333 was rejected at 4.33:1, and
     #FF5252 as a fill needs near-black text, which could not be applied
     safely because 3 of the 41 fill sites declare no colour of their own. */
  /* ── A THIRD RUNG, NOT A SECOND ACCENT (founder, 2026-08-25) ──────────
     The homepage instrument draws TWO marks that must not be confused: the
     span the engine is releasing INTO, and the point the reader is standing
     ON. In the design they came from they were two different hues — one of
     them the orange that is now retired — so collapsing both onto --accent
     would delete a distinction the graph exists to make, while adding a
     second HUE is exactly what the ruling forbids.
     ⇒ Two rungs of the ONE red ramp. --accent stays the acting mark, this
     is the span mark, and --accent-deep stays the fill.
     ⚠ Its value is set by CONTRAST, not by taste: it is rendered as TEXT on
     the darkest ground in the system, where --accent-deep measures below AA
     and cannot carry a word. This rung clears the 4.5 floor on that ground
     and on the raised surface above it. Do not darken it to "match" the
     fill — the fill is a graphic and is not bound by that floor. */
  --accent:#FF4D3D; --accent-mid:#FF6E60; --accent-deep:#B8281C;
  /* ── GOLD — A QUANTITY, AND NOTHING ELSE ──────────────────────────────
     ⛔ --success is DELETED, not renamed. It carried three different facts
     under one name — a quantity, a HELD state, and a steady connection — and
     the held one was actively wrong: a timing hold rendered as an outcome.
     Its 20 sites were re-pointed by role. There is no success colour in this
     system, which is correct: 0 holdouts exist to measure one. */
  /* ── ONE ACCENT, NOT TWO ─────────────────────────────────────────────
     --label was #E8A33D, a GOLD second accent standing beside the red one
     across 56 sites on 10 pages. Founder ruling 2026-08-25: NO ORANGE, red
     only. That does not make label a red of its own — it removes the second
     accent entirely, so the token is now an ALIAS at its home rather than a
     duplicate hex under a second name.
     ⛔ Written as var(--accent), never as the literal. Two names on one hex
     is how a role quietly forks again: the next edit moves one and not the
     other, and nothing goes red. colour_roles §1 is the gate that caught
     exactly that here. The 56 call sites are untouched and keep their name;
     what changed is that the name no longer carries an independent value. */
  /* ★ 2026-08-25 evening (founder, in Chrome): "v6 gtm had gold not red
     headlines." The alias to the red accent made every eyebrow and label that
     reads --label an ACTION colour; v6 sets those in gold. One token, sitewide:
     labels are VALUE ink, and red stays on what acts. */
  --label:var(--gold-on-dk); --label-deep:var(--gold);
  /* ── BLUE — HELD, AND ONLY HELD ───────────────────────────────────────
     ⛔ --head is DELETED. It was --hold one shade down and it painted every
     H1 and H2 on 11 pages — so the verdict "the engine is holding this
     customer" was also the colour of the words on the marketing page. A
     state colour cannot be the display voice. All 100 sites took --ink. */
  --hold:#6E9BC9;
  /* FILM — the demo's own names, every one now RESOLVING to its home rather
     than repeating the hex. --film-sunk and --film-fire-hi are the only two
     values the film genuinely owns. */
  --film-ground:var(--ground); --film-raised:var(--raised); --film-sunk:#0A0B0C;
  --film-rule:var(--rule); --film-rule-2:var(--rule-light-2);
  --film-ink:var(--ink); --film-body:var(--ink-2); --film-muted:var(--ink-muted); --film-micro:var(--ink-muted-2);
  --film-label:var(--hold); --film-fire:var(--accent); --film-fire-hi:#F03434;
  /* ⛔ THESE THREE WERE DELETED ON 2026-08-23 AS "ZERO READERS" AND THAT WAS
     WRONG — RESTORED THE SAME DAY. The reader is the demo-film injector, which
     is a BUILD script, and the grep behind the deletion covered frontend/ only.
     The standing rule says to scan every tree INCLUDING scripts/, and not doing
     so turned a real consumer into an imaginary one. The build failed loudly
     rather than silently, which is the only reason this cost minutes.
     ★ They come back as ALIASES, not literals, so the button colour still has
     exactly one home: repointing --accent-deep now moves the film's CTA too,
     which is the behaviour their literal versions never had. */
  --cta-fill:var(--accent-deep); --cta-fill-hi:var(--accent-deep); --cta-fg:var(--ink);
}
/* A native range input paints its own track from the UA sheet; there is no
   literal to remap, so the two rules live here with the palette. */
input[type="range"]{accent-color:var(--accent);background:transparent}
input[type="range"]::-webkit-slider-runnable-track{background:var(--rule);height:4px}
input[type="range"]::-moz-range-track{background:var(--rule);height:4px}

/* THE DISPLAY ROLE — see the note at the top of this file. */
/* ⚠ 2026-08-28: this is the SECOND home of the display role — `.site--serif .h1
   /.h2` in bhasm.css is the first, and it is the one that wins wherever a
   heading carries the class. This rule catches the headings that do NOT
   (proof.html and industry.html have bare <h1>/<h2>), and while the two
   disagreed those two pages rendered a fourth family. Both now name Gambetta;
   if you change one, change the other in the same commit. */
:root{ --font-display:'Gambetta',Georgia,serif; }
/* Weight lives HERE too, not only on the 87 migrated headings. proof.html's
   three headings carry no inline style at all and inherited 600 from body —
   so a migration that only rewrote inline attributes left one page bold-serif,
   which is the single ugliest outcome of this change. The rule is the
   constructor; the inline 300s now agree with it rather than supplying it. */
h1,h2{ font-family:var(--font-display); font-weight:300; letter-spacing:-.012em; }
/* FOUNDER 2026-08-26: every section h2 is gold, sitewide. One rule; no page carries an h2 colour of its own. */
h2{ color:var(--gold-on-dk); }

/* ── MOBILE IS A SEPARATE DESIGN, NOT A COLLAPSE (founder, 2026-08-26) ──────
   On desktop the v6 hairline grid (`gap:1px` on a rule-coloured ground, no
   boxes) reads as one object. At phone width the grid goes to one column and
   the same recipe paints edge-to-edge text separated by hairlines — "a page
   with lines". THE CONSTRUCTOR, written once: below 760px every cell of a
   `.hgrid` and every `.v6row` becomes an inset, shaded card. The page files
   only tag the grid; they carry no mobile treatment of their own.
   ⚠ `!important` is deliberate — the cells are styled inline, and this is
   the one place a stylesheet must win over an inline value.
   The structure gate ratchets container counts at 380. */
@media (max-width:759px){
  .hgrid{gap:12px!important;background:transparent!important;border-top:0!important;border-bottom:0!important}
  .hgrid>*{background:var(--card-light)!important;border:1px solid var(--rule)!important;padding:20px 18px!important;min-width:0}
  .v6row{background:var(--card-light);border:1px solid var(--rule)!important;padding:18px!important;margin-bottom:10px}
  /* the ruled-row components take the same collapse: on a phone a hairline
     list is "a page with lines", which is the whole point of this block. */
  .rlist{gap:10px!important;display:flex;flex-direction:column}
  .rlist>*{background:var(--card-light)!important;border:1px solid var(--rule)!important;border-top:1px solid var(--rule)!important;padding:16px 16px!important;min-width:0}
  .rlist>*:first-child{padding-top:16px!important}
  .rrow{background:var(--card-light)!important;border:1px solid var(--rule)!important;border-top:1px solid var(--rule)!important;padding:14px 16px!important;margin-bottom:10px}
  /* tables: a 760px grid behind a scroll is not a phone design. Each row becomes
     a card; the header row is dropped and every cell names its column. */
  .mtable{overflow:visible!important;border-top:0!important}
  .mtable>div{min-width:0!important}
  .mth{display:none!important}
  .mtr{grid-template-columns:1fr!important;background:var(--card-light);border:1px solid var(--rule)!important;margin-bottom:10px;padding:4px 0 8px}
  .mtr>div{text-align:left!important;background:transparent!important;padding:8px 16px!important}
  .mtr>div:first-child{color:var(--ink)!important;padding:14px 16px 10px!important;border-bottom:1px solid var(--rule-light-2);margin-bottom:4px}
  .mtr>div[data-col]::before{content:attr(data-col);display:block;font-family:'JetBrains Mono',monospace;font-weight:600;font-size:10px;letter-spacing:.16em;color:var(--ink-muted-2);margin-bottom:4px}
  .mtr.kv>div[data-col]{display:flex;justify-content:space-between;align-items:baseline;gap:12px}
  .mtr.kv>div[data-col]::before{margin:0}
}
