/* tokens.css — the design token layer. Change the look here, nowhere else.
 *
 * The "Tape" system (light). Everything visual derives from here: no component stylesheet may hold
 * a raw hex, a raw px font size or a raw spacing number. Restyling the whole product should mean
 * editing this file and nothing else — which is also what lets the UI be thrown away and rebuilt
 * without touching js/room.js or any function.
 *
 * ACCESSIBILITY CONTRACT: every text/background pair below is >= 7:1 (WCAG 2.2 AAA, 1.4.6).
 * Measured ratios are recorded next to each token. Non-text UI borders are held to >= 3:1 (1.4.11).
 * Run `npm run test:contrast` after any change here.
 */

/* ── Fonts — SELF-HOSTED, deliberately ───────────────────────────────────────────────
 * These used to load from fonts.googleapis.com. That put a third-party request on the one page
 * that must not fail: a host is 45 minutes into an interview and Google is not a dependency we
 * chose. Served from our own origin, the fonts fail exactly when the app itself fails, and not
 * one moment sooner. It also drops two DNS lookups and a TLS handshake from first paint.
 *
 * Both faces are SIL Open Font License 1.1 — see fonts/LICENSE.md for attribution.
 *
 * Instrument Sans is a VARIABLE font: one file covers 400-600, so the whole interface costs a
 * single 30KB download instead of three static weights.
 *
 * font-display: swap is not decoration. If a font is slow, text must appear immediately in the
 * fallback rather than leaving someone staring at an invisible status pill.
 *
 * The latin-ext files exist for guests' names — "Zoë", "Łukasz". A browser only fetches them if
 * the page actually uses those codepoints, so the common path is latin only (~45KB total).
 *
 * NOTE: build.js content-stamps .css and .js only, so these filenames are the cache key. If you
 * ever replace a font file, RENAME it — netlify.toml caches /fonts/* for a year.
 */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/fonts/instrument-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/fonts/instrument-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ── Type ─────────────────────────────────────────────────────────────────────────
   * One family for the interface, one for numbers. Instrument Sans is slightly narrow and
   * slightly technical and holds up at 15px in a control bar. IBM Plex Mono is used ONLY for
   * values a person might read aloud or check twice — timecode, room codes, part counts,
   * latency, file sizes — so digits never shift under a glance.
   *
   * Self-hosted — see the @font-face block above. The fallback stack is not decoration either:
   * if a woff2 fails to load the product stays entirely usable in the system UI font, because
   * nothing here encodes meaning in a letterform.
   */
  --font-display: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  --font-body: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --text-base: 18px;
  --text-scale: 1.2;

  --text-xs: calc(var(--text-base) / var(--text-scale) / var(--text-scale));  /* 12.5px */
  --text-sm: calc(var(--text-base) / var(--text-scale));                      /* 15px   */
  --text-md: var(--text-base);                                                /* 18px   */
  --text-lg: calc(var(--text-base) * var(--text-scale));                      /* 21.6px */
  --text-xl: calc(var(--text-base) * var(--text-scale) * var(--text-scale));  /* 25.9px */
  --text-2xl: calc(var(--text-base) * var(--text-scale) * var(--text-scale) * var(--text-scale));
  --text-display: clamp(calc(var(--text-2xl) * 1.05), 5.4vw, calc(var(--text-2xl) * 2));

  --leading-body: 1.6;
  --leading-tight: 1.05;
  --measure: 60ch;

  /* The redesign leans on tight tracking at display sizes — it is what makes the headline read
     as equipment rather than a magazine. Apply to h1/h2 only. */
  --tracking-display: -0.035em;
  --tracking-heading: -0.02em;
  --tracking-wide: 0.01em;
  --tracking-wordmark: 0.15em;

  --weight-normal: 400;
  --weight-medium: 500;
  --weight-bold: 600;

  /* ── Space — 8px scale ────────────────────────────────────────────────────────── */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 88px;

  /* ── Shape — tighter than the old system; instrument, not card ────────────────── */
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  --border-width: 1px;

  /* ── Colour ───────────────────────────────────────────────────────────────────────
   * Three signals and nothing else. A colour in this product always means exactly one of:
   * safe (the server has it) / rec (rolling) / pending (still on this device).
   * Everything else is ink on paper. Ratios measured against --bg unless noted.
   *
   * Each signal clears 7:1 as TEXT on --bg and carries white text at 7:1 as a FILL, so a single
   * token stays honest in both directions.
   */
  --bg: #f7f7f5;
  --surface: #ffffff;
  --surface-sunken: #edede9;
  --surface-inverse: #1b1d1f;   /* video panes only — faces read wrong on grey */

  --ink: #16181a;          /* 16.6:1 on --bg · 17.7:1 on --surface */
  --ink-muted: #4a4e52;    /*  7.8:1 on --bg ·  8.3:1 on --surface */
  --ink-placeholder: #545454; /* 7.1:1 on --bg · 7.6:1 on --surface */
  --ink-inverse: #ffffff;
  --ink-on-dark: #c4c8cb;  /* 10.0:1 on --surface-inverse */
  --ink-on-dark-dim: #a7abae; /* 7.3:1 on --surface-inverse */

  --border: #e4e4e0;        /* decorative hairlines only — NOT a control outline */
  --border-strong: #8a8a83; /* 3.3:1 on --bg — the minimum for an interactive control edge */

  --accent: #0e5a3d;   /* SAFE    · 7.7:1 on --bg · white on it 8.2:1 */
  --danger: #a00f06;   /* ROLLING · 7.6:1 on --bg · white on it 8.2:1 */
  --pending: #6e4e05;  /* IN FLIGHT · 7.1:1 on --bg · white on it 7.6:1 */
  --safe: var(--accent);
  --neutral-deep: var(--ink);

  /* Notices are drawn as a rule + a coloured left edge, not a filled box. Kept as tokens for
     any surface that still needs a tinted panel. */
  --notice-bg: var(--bg);
  --notice-border: var(--pending);
  --notice-ink: var(--pending);

  /* ── The part ledger ──────────────────────────────────────────────────────────────
   * The one new component. A strip of segments, one per chunk.
   *   confirmed  → --ledger-safe fill
   *   in flight  → --ledger-flight fill, gentle opacity pulse
   *   not yet    → transparent with a --ledger-empty OUTLINE (never a pale fill: at 1.2:1 the
   *                empty state disappears, and the empty finish screen is made entirely of it)
   *   gap        → --ledger-gap fill
   */
  --ledger-safe: var(--accent);
  --ledger-flight: var(--pending);
  --ledger-gap: var(--danger);
  --ledger-empty: var(--border-strong);  /* 3.3:1 — an outline you can actually see */
  --ledger-height: 14px;
  --ledger-height-sm: 10px;
  --ledger-gap-x: 4px;
  --ledger-radius: 3px;

  --focus-ring: var(--ink);
  --focus-width: 3px;
  --focus-offset: 2px;

  /* ── Motion ───────────────────────────────────────────────────────────────────── */
  --motion-fast: 80ms;
  --motion-base: 200ms;
  --motion-ease: cubic-bezier(.2, .7, .3, 1);

  /* ── Controls ─────────────────────────────────────────────────────────────────── */
  --tap-min: 44px;
  --control-h: 52px;   /* inputs, secondary buttons */
  --control-h-lg: 58px; /* primary actions */
  --content-max: 720px;
  --card-max: 560px;
  --card-narrow-max: 480px;
}

:root[data-text-size="large"]  { --text-base: 20px; }
:root[data-text-size="xlarge"] { --text-base: 23px; --leading-body: 1.75; }

@media (prefers-reduced-motion: reduce) {
  :root { --motion-fast: 0ms; --motion-base: 0ms; }
}

@media (forced-colors: active) {
  :root {
    --border: CanvasText;
    --border-strong: CanvasText;
    --focus-ring: Highlight;
  }
}
