/* BackstagePass design tokens — the WIRE round (2026-08-19 overnight).
   Source: design-imports/WIRE-Directions.html ("The Wire with live room"),
   which supersedes the 08-19 Marquee/Gilt pair where they conflict
   (DESIGN-FEATURE-RECONCILIATION.md §0). Three moods, one component
   vocabulary:

     body            HOUSE LIGHTS — the product. Studio, rooms, replays,
                     receipts, clips, the roster: warm near-black #0b0a09,
                     tungsten #ffd9a3 as the house light (not brand gold),
                     IBM Plex Mono for every number, live-red only when
                     something is live or cut.
     body.door       THE DOOR — public/sales/auth/fan-facing brand surfaces:
                     #030303 canvas, the gold family from
                     BRAND-ANCHOR-OVERSKILL.md, graduated gold hairlines,
                     gold fills only on the one CTA per screen.
     body.paper      PAPER — the covenant and the fine print (/trust, legal,
                     the ownership-proof band): #F1F2F4, ink #202123, deep
                     gold #b8860b for the accent only.

   One display voice everywhere: Big Shoulders Display (condensed marquee
   caps) over Archivo body and IBM Plex Mono numbers. Components are defined
   once in application.css against these variables — a mood is a token flip,
   never a parallel stylesheet. */

@font-face {
  font-family: "Big Shoulders Display";
  src: url("/fonts/design/big-shoulders-display-var.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/design/archivo.woff2") format("woff2");
  font-weight: 400 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/design/plex-mono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/design/plex-mono-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/design/plex-mono-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}

/* Ben's Choice type (Maaz 2026-09-16), self-hosted like every other face so it
   loads deterministically in CI and production rather than depending on a
   third-party fetch. Variable woff2, latin subset. */
@font-face {
  font-family: "Outfit";
  src: url("/fonts/design/outfit-var.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  /* Outfit carries a taller line box than the Archivo it replaces (hhea
     1000/-260 vs 878/-210). Left alone that grows every control, card and
     textarea that sizes to the line box and reflows the layout the product's
     tests were tuned to. These overrides pin Outfit's used ascent/descent to
     Archivo's so the vertical rhythm is unchanged; only the letterforms move. */
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/fonts/design/playfair-display-var.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/fonts/design/playfair-display-italic-var.woff2") format("woff2");
  font-weight: 400 900; font-style: italic; font-display: swap;
}

:root {
  /* type voices — shared by all three moods.
     Ben's Choice (Maaz 2026-09-16): Playfair Display for ceremony and
     numerals, Outfit for everything functional. Loaded via Google Fonts in
     layouts/application.html.erb; the stacks fall back to the platform serif
     and sans so nothing flashes if the network is slow. */
  --display: "Playfair Display", Georgia, "Times New Roman", serif;
  --sans: "Outfit", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  /* motion — the brand curve everywhere (BRAND-ANCHOR) */
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --dur: 500ms;

  /* print geometry — hairlines, not boxes; WIRE radii: 6 controls, 10 cards */
  --radius: 10px;
  --radius-sm: 6px;

  /* THE CHANNEL HEADER'S CROP (Maaz 2026-09-17). He sent a YouTube channel art
     as "THE height" and it measures 2276×376 — YouTube's own VISIBLE crop, not
     the 2560×1440 file it is cut from. The public band wore 21/7 and the
     account card's preview 3/1; both took a third of the first screen before
     the creator's name.

     ONE TOKEN, TWO HOSTS (`.prof-banner` and `body.studio .acct-header__pick`),
     because the preview a creator frames their picture in has to be the crop a
     stranger reads — two numbers is how one starts lying about the other. */
  --banner-crop: 2560 / 423;

  /* THE WHOLE-PIXEL RULE (r8, 2026-09-03) — why hairlines looked "rough".
     Chrome pixel-snaps a SQUARE 1px border but antialiases a ROUNDED one as a
     path. So a pill (radius 999px) whose border box lands on a fractional y
     gets its 1px hairline painted as TWO rows at ~50% coverage each — and at
     0.3 alpha over a near-black canvas that is 48/255 instead of 84/255: the
     top edge of the pill reads as grit while the bottom edge reads as a line.
     Measured on /studio/lives at dPR 1 and 2 (r8 PR body has the crops).

     Nothing here was fractional on purpose. The type scale is fractional rem
     (0.95rem = 15.2px) times a unitless line-height (1.55), so EVERY line box
     is fractional (23.56px) and every block below it sits on a fraction — 430
     of the 444 boxes on the Lives board did.

     So: a line-height is now a RATIO in `--lh` (it inherits exactly as a
     unitless line-height does), and `--lh-snap` turns that ratio into a
     WHOLE-PIXEL length against the element's own font-size. `1em` and
     `var(--lh)` both resolve at the point of USE, so one token snaps every
     element. application.css applies it universally; every rule that carries
     its own leading writes `--lh: N; line-height: var(--lh-snap)`.

     Rules that follow from it, for anything new:
       * a ratio goes in `--lh`, never in `line-height` — a bare
         `line-height: 1.05` computes to a LENGTH and its children inherit that
         length instead of the ratio;
       * one stroke mechanism per element (a border OR an inset shadow OR an
         outline — never two, and never a control's box under another one:
         that is what made the masthead avatar a wobbly polygon);
       * give a stroked pill/avatar an INTEGER height, so the box it snaps to
         is the box it was drawn as. */
  --lh-snap: round(calc(1em * var(--lh, 1.55)), 1px);

  /* THE ROUND HAIRLINE IS TWO DEVICE PIXELS (r9, 2026-09-03) — the other half
     of "why do the pills still look rough", measured after r8 had already
     landed every box on a whole pixel.

     r8 fixed the STRAIGHT runs: Chrome snaps an axis-aligned 1px border to one
     device row at full strength, and it does that at dPR 1 and 2 alike
     (verified: one row at 84/255 on an 11/255 canvas, both edges equal). What
     it cannot snap is the ARC. On a 999px-radius pill the whole left and right
     end IS arc, and where that arc runs diagonally a 1-device-pixel stroke is
     split across two pixels at roughly half coverage each — so the line's peak
     luminance HALVES as it goes round the corner. Measured around the
     perimeter of the Lives board's pills:

       dPR 1, 1px:  peak 30..75  (sd 10.6 on a mean of 64 — 16%)
       dPR 2, 1px:  peak 61..75  (sd  1.3 on a mean of 75 —  2%)

     A line whose weight changes as it turns is what the eye calls hand-drawn,
     and it is worse than either number suggests on a SCALED Retina display
     ("More Space"), where macOS renders at 2x and resamples the framebuffer
     down — the owner's own r9-ref-1 is ~1.77x, and reproducing that resample
     over our own render gives 55..87 (sd 6.2) plus Lanczos ringing that dips a
     pixel BELOW the canvas beside the line. That ring is the grit.

     Two device pixels is the cure, because then every point on the arc always
     contains one fully-covered pixel. So the hairline's WIDTH is a token: 1px
     where a device pixel is a CSS pixel, 1.5px (three device rows) once there
     are two to spend. Resampled at 1.77x that measures 55..61, sd 1.3 — a 4.8x
     improvement in the one number that means "rough".

     It is spent on the FULLY-ROUND strokes only (the pills, the chips, the
     circles, the avatar's ring). A 6px or 10px radius is straight run almost
     everywhere and Chrome snaps all of it; paying for those would thicken half
     the product to fix four corners nobody can see. */
  --hair-w: 1px;

  /* THE HOUSE'S OWN ACCENT, NAMED SO THE DOOR CAN BORROW IT (2026-09-19).
     Two rules in the door mood deliberately pin the HOUSE's light rather than
     the door's gold — the identity panel and the fan rail's current row, both
     so a navigation row is not painted in the money colour. They spelled
     #ffd9a3 inline, which under a look where the house accent is champagne
     made those two the only tungsten left on the platform: one gold
     everywhere except the two controls that exist to match. It is a token
     now, so the pin follows the look instead of freezing one. */
  --house-accent: #ffd9a3;

  /* the one loud color: live-red means live or cut, nowhere else */
  --live: #e5484d;
}

@media (min-resolution: 1.5dppx) {
  :root { --hair-w: 1.5px; }
}

/* ---- HOUSE LIGHTS (default): the product, lights down ---------------------- */
body {
  color-scheme: dark;
  --bg: #0b0a09;             /* the house, warm near-black */
  --surface: #17130e;        /* the raised booth */
  --surface-2: #1c1712;
  --surface-3: #221c15;
  --frame-mat: #0d0c0a;
  /* OPAQUE HAIRLINES (r9). A hairline was tungsten at an alpha, which means
     its painted colour was a function of whatever it happened to sit on AND
     of the antialiasing coverage — the two multiply, so a half-covered pixel
     on an arc came out at half of an already-thin 0.14. Every hairline token
     is now the composite it used to resolve to over THIS mood's canvas, laid
     down opaque, so coverage is the only variable left. (A hairline on a
     raised card is a few levels dimmer than it was; on the canvas, where
     nearly all of them are, it is identical.) The old alphas are kept in the
     comments — they are the recipe if a canvas ever moves. */
  --border: #2d271f;         /* was tungsten @ 0.14 */
  --border-strong: #544837;  /* was tungsten @ 0.30 */
  --text: #f4ede1;           /* stage paper */
  --muted: rgb(244 237 225 / 0.62);
  --dim: rgb(244 237 225 / 0.45);
  --accent: #ffd9a3;         /* the house light — tungsten, not brand gold
                                (pinned: identity menu offer row, fan lit row) */
  --accent-soft: #ffe6c2;
  --accent-deep: #b8860b;
  --gold: #d4a84b;           /* Ben's Choice champagne — money and the Pass */
  --gold-bright: #e3bc66;
  --gold-ink: #15110a;
  --ok: #8fb5a0;             /* "connected" */
  --warn: #d5a13d;
  /* Ben's Choice control grammar (Maaz 2026-09-17): controls are pills and icon
     buttons are circles, sentence case not marquee caps — the proto SHAPE, on
     top of #730's colour/font retoken. The FILL is untouched: the house's one
     filled primary stays warm tungsten (Todd's ruling 2026-09-15; drop_card /
     live_drops_tray system tests enforce it) — gold means money and the Pass. */
  --btn-bg: #ffd9a3;         /* the primary action is a tungsten block (Todd 2026-09-15) */
  --btn-fg: #0b0a09;
  --btn-hover: #ffe6c2;
  --radius-control: 999px;   /* CTAs are pills */
  --radius-icon: 999px;      /* share / kebab / close are circles */
  --btn-family: var(--sans); /* the proto binds the button's face on a token */
  --btn-transform: none;     /* sentence case, never SHOUTED */
  --input-bg: rgb(255 217 163 / 0.05);
  --hair-25: #2d271f;        /* tungsten @ 0.14 */
  --hair-35: #3c3328;        /* @ 0.20 */
  --hair-48: #544837;        /* @ 0.30 */
  --hair-60: #71614a;        /* @ 0.42 */
  /* the coloured hairlines, same rule: a chip's stroke is its own colour at
     55% over the canvas, laid down opaque. */
  --hair-gold: #79612d;      /* champagne @ 0.55 over the house canvas */
  --hair-ok: #54685c;
  --hair-warn: #7a5d26;
  --hair-live: #832c2e;
  /* the screen you are standing on: a subtle warm lift and a gold LEFT marker
     (Ben's Choice --rail-on-*, Maaz 2026-09-16). The row wears the whole
     hairline ring plus a 3px gold inset on its leading edge — not a ::before
     square, and the row is never `overflow: hidden` (it would clip the mark). */
  --rail-on-bg: #241e19;
  --rail-on-fg: #f5f0e8;
  --rail-on-ring: #40372f;
  --rail-on-glyph: #f5f0e8;
  --rail-on-rule: 3px;
  --rail-on-marker: #e3b341;
}

/* ---- THE DOOR: the brand anchor, now in Ben's Choice warm charcoal --------- */
body.door {
  color-scheme: dark;
  --bg: #0b0a09;             /* warm charcoal — the same dark ground as the house */
  --surface: #151311;
  --surface-2: #1d1a17;
  --surface-3: #252119;
  --frame-mat: #0d0c0a;
  --border: #2a2621;
  --border-strong: #3b352d;
  --text: #f3eee4;
  --muted: rgb(244 237 225 / 0.62);
  --dim: rgb(244 237 225 / 0.45);
  --accent: #d4a84b;         /* at the door, the gold IS the accent — champagne */
  --accent-soft: #e3bc66;
  --accent-deep: #b68f39;
  --gold: #d4a84b;
  --gold-bright: #e3bc66;
  --gold-ink: #15110a;
  --ok: #4caf72;
  --warn: #d9932e;
  --btn-bg: var(--gold);     /* gold fills only on the one CTA */
  --btn-fg: #15110a;
  --btn-hover: #e3bc66;
  --input-bg: #151311;
  /* the graduated hairline over the warm charcoal canvas */
  --hair-25: #2d271f;
  --hair-35: #3c3328;
  --hair-48: #544837;
  --hair-60: #71614a;
  --hair-gold: #79612d;
  --hair-ok: #54685c;
  --hair-warn: #7a5d26;
  --hair-live: #832c2e;
}

/* ---- PAPER: the covenant and the fine print -------------------------------- */
/* Maaz 2026-09-16: dark only, everywhere. Paper joins the house and the door
   in Ben's Choice warm charcoal rather than keeping a light second look. */
body.paper {
  color-scheme: dark;
  --bg: #0b0a09;
  --surface: #151311;
  --surface-2: #1d1a17;
  --surface-3: #252119;
  --frame-mat: #0d0c0a;
  --border: #2a2621;
  --border-strong: #3b352d;
  --text: #f3eee4;
  --muted: rgb(244 237 225 / 0.62);
  --dim: rgb(244 237 225 / 0.45);
  --accent: #d4a84b;         /* champagne reads on the dark ground */
  --accent-soft: #e3bc66;
  --accent-deep: #b68f39;
  --gold: #d4a84b;
  --gold-bright: #e3bc66;
  --gold-ink: #15110a;
  --ok: #4caf72;
  --warn: #d9932e;
  --btn-bg: var(--gold);     /* the one CTA is champagne, like the other moods */
  --btn-fg: #15110a;
  --btn-hover: #e3bc66;
  --input-bg: #151311;
  --hair-25: #2d271f;
  --hair-35: #3c3328;
  --hair-48: #544837;
  --hair-60: #71614a;
  --hair-gold: #79612d;
  --hair-ok: #54685c;
  --hair-warn: #7a5d26;
  --hair-live: #832c2e;
}

/* ==========================================================================
   BEN'S CHOICE — THE LOOK, AS A TOKEN FLIP (Maaz 2026-09-19)
   ==========================================================================

   The proto (bsp-proto/studio/themes/bens-choice.css) absorbed onto bsp.live
   as a SWITCHABLE look, because Maaz's condition for taking it was a revert
   he can make in thirty minutes: `BSP_THEME=classic` on web + worker, deploy.

   CLASSIC IS NOT WRITTEN DOWN, AND THAT IS THE WHOLE SAFETY ARGUMENT. There
   is no `body.theme-classic { … }` block here or anywhere, and there must
   never be one. Classic is this sheet WITHOUT the block below — the same
   `:root`, the same three moods, byte for byte — so it restores today's
   computed look by CONSTRUCTION rather than by somebody having transcribed
   it correctly. The moment Classic is a set of rules, it is a third look that
   can drift from the thing it exists to restore.

   The same rule downstream: every component value this look moves is written
   in application.css as `var(--token, <today's value>)`. The FALLBACK is the
   Classic snapshot, inline, at the point of use — so a page with no theme
   token set computes exactly what it computed before, and the diff of this
   round is readable as "what Ben's Choice changes" rather than as a rewrite.

   IT COMPOSES WITH THE MOOD, IT DOES NOT REPLACE IT. `body.theme-bens-choice`
   is (0,2,0), the same as `body.door` / `body.paper` and one step above the
   bare `body`, and it ships AFTER all three — so it wins the ties it needs on
   source order and the moods keep every token it does not name. A theme is
   which values the three moods resolve to; it is never a fourth mood.

   WHAT IT MOVES is the list Maaz enumerated and nothing else: Playfair 400 in
   sentence case for ceremony and figures, Outfit for everything functional,
   champagne #d4a84b as the ONE gold, live-red #d93025 for on-air only, 999px
   pill controls and 16px cards. (It moved the chrome's GO pill to live-red
   too, in every state; Maaz reversed that on 2026-09-20 — see the `--go-*`
   note below — so the IDLE pill is the house gold in both looks and only the
   session's own words are red.) Ink
   alphas, surface ladders and the hairline scale are deliberately NOT here:
   they are invisible at these deltas, and `--dim`'s 45% carries a measured
   contrast ceiling (r9, tokens above) that is nobody's to move in a look
   round. */
body.theme-bens-choice {
  /* ONE GOLD. This is the change with the largest blast radius and the one
     Maaz named twice: the house lit its accent with tungsten #ffd9a3 while
     the door and the money lit theirs with champagne, so a creator crossing
     from /studio to their own page crossed two golds. Under this look there
     is one. (Todd's 2026-09-15 ruling that the filled primary is tungsten is
     what CLASSIC restores, and it is exactly why Classic is still a switch
     away rather than a memory.) */
  --accent: #d4a84b;
  --accent-soft: #e3bc66;
  --accent-deep: #b68f39;
  /* …and the two door-mood rules that pin the house's light move with it, or
     they are the only tungsten left on a one-gold platform. */
  --house-accent: #d4a84b;
  --btn-bg: #d4a84b;
  --btn-fg: #15110a;
  --btn-hover: #e3bc66;

  /* LIVE-RED IS THE BROADCAST HUE, AND ONLY THAT. #e5484d reads as an error
     colour beside champagne; the proto's #d93025 is a broadcast red. The
     bright is its hover and the ink on it is the proto's own. */
  --live: #d93025;
  --live-bright: #e8453a;
  --on-live: #fff5f4;
  /* the coloured hairline, by this sheet's own rule: the stroke is its own
     colour at 55% over the canvas, laid down OPAQUE (r9) — #d93025 at 0.55
     over #0b0a09. Recomputed rather than carried over, or the chip's stroke
     would still be the old hue's composite. */
  --hair-live: #7c1f18;

  /* SHAPE. 16px cards and 999px controls are the proto's; `--radius-control`
     and `--radius-icon` are already pills on this plane (#756), so the only
     moves are the card and the small radius. */
  --radius: 16px;
  --radius-sm: 8px;
  /* the landing's one CTA joins the house's control grammar. It is its OWN
     token rather than a read of `--radius-control`, because that one is
     already 999px in the base sheet and reading it would make the landing a
     pill under CLASSIC as well — a regression wearing a fallback. */
  --lp-control-radius: var(--radius-control);

  /* TYPE — the tokens application.css now reads. Playfair is already the
     `--display` face on this plane (#730); what was still Classic was the
     WEIGHT and the CASE, which is why the new look read as Playfair being
     shouted. 400 and sentence case is the whole of it. */
  --headline-transform: none;
  --headline-spacing: -0.01em;
  --h1-weight: 400;
  --h2-weight: 400;
  --headline-weight: 400;
  --figure-weight: 400;
  /* the studio's own heading face. Classic swaps h1/h2/.headline to the sans
     at the desk; the proto binds them to the display face at 400 in both
     halves of the product, which is the "one type stack everywhere" law. */
  --studio-heading-family: var(--display);
  --studio-heading-weight: 400;

  /* CONTROLS. Outfit 500 in sentence case — the button's face and transform
     are already tokens (#756); the weight was the last Classic value in the
     base rule, and 700 is what made a pill read as a slab. */
  --btn-weight: 500;
  /* the on-air stamp is a LABEL, not a serif shout: the proto sets
     `--pill-live-*` to the sans at 500 with the label's own tracking. */
  --pill-live-family: var(--sans);
  --pill-live-weight: 500;
  --pill-live-spacing: 0.14em;

  /* THE CHROME'S GO IS GOLD WHEN IT IS IDLE, AND THE FOUR `--go-*` COLOUR
     TOKENS WENT WITH THAT RULING (Maaz 2026-09-20 — this REVERSES the four
     declarations that stood here, `--go-bg: var(--live)` and its three
     siblings, written on the reading that the masthead pill is always about
     the broadcast). His own screenshot is the other half of that reading:
     a live-red GO LIVE in the chrome over
     a gold "Start a new live" and a gold hero GO LIVE on the same page —
     three names for one act, in two colours, eight inches apart. Idle GO LIVE
     is the house gold in BOTH looks now and live-red is the SESSION's alone
     (Join now / Start now / Join Again), which application.css paints through
     `.topbar__go--live` off `--live` — a token every mood already defines, so
     there is nothing left here for a theme to move. The reads in
     application.css are COLLAPSED back to their literals rather than left as
     seams for a value nobody chose (rule 15 of this look's own ruling). The
     GO LIVE BLOCK's grammar below is a different control and is untouched. */
  /* and the GO LIVE BLOCK's own grammar (the /d gallery's composer is its one
     host today, so this costs nothing now and is right the day it returns).
     The FACE moves with the rest of it: a button word is UI, so it is Outfit
     under this look even though the word beside it on the same screen is
     ceremony. */
  --go-family: var(--sans);
  --go-radius: 999px;
  --go-weight: 500;
  --go-transform: none;
  --go-spacing: 0.01em;
}
