/**
 * tokens.css — the implementation of docs/design/tokens.md.
 *
 * This file is the ONLY place a raw colour, size, shadow or easing is allowed to
 * appear. Everything else in style.css references these custom properties. The
 * markdown is the source of truth; when the two disagree, the markdown wins and
 * this file is wrong (AGENTS.md).
 *
 * Section numbers below match the markdown's, so a change can be traced both
 * ways without guessing.
 */

:root {
  /* ── 1.1 ground ─────────────────────────────────────────────────────
     There is no light mode. A white page is wrong in a dark mall and wrong
     on a phone at night. */
  --stagezero-navy: #00144b;   /* the corporate mark's own fill */
  --navy-1000: #02050f;        /* blackout / true off */
  --navy-900: #050a18;         /* app ground */
  --navy-800: #0a1226;         /* raised ground, sheet */
  --navy-700: #0f1b38;         /* panel fill (opaque fallback for glass) */
  --navy-600: #16264d;         /* hairline / inset */
  --navy-500: #1f3366;         /* disabled fill */

  /* ── 1.2 brand blue ─────────────────────────────────────────────────
     --blue-core/--blue-deep are the reference repo's true corporate blue and
     its dark stop. Reconciling them is DEFERRED post-demo (tokens.md §7.1) —
     they are recorded so nobody has to re-derive them, and deliberately unused.
     Do not reach for them until §7.1 is reopened. */
  --blue-300: #a8bcff;
  --blue-400: #7d9cff;
  --blue-500: #527eff;         /* brand blue · also the ARMS region colour */
  --blue-600: #3a5ee0;
  --blue-700: #2743a8;
  --blue-core: #204ce5;        /* UNUSED — see tokens.md §7.1 */
  --blue-deep: #001ab3;        /* UNUSED — see tokens.md §7.1 */

  /* ── 1.3 charge green — the one accent glow ─────────────────────────
     Green means charge, success, Stage Zero. It is the only colour allowed to
     glow, and only one element per screen glows. */
  --green-300: #8affd0;
  --green-400: #4dffb8;
  --green-500: #00d084;
  --green-600: #00a86a;

  /* ── 1.4 warm — pressure ────────────────────────────────────────────── */
  --amber-400: #ffc247;
  --amber-500: #f0a500;        /* warning · head region */
  --orange-400: #ff8c3d;
  --orange-500: #ff6900;       /* alarm · torso region */

  /* ── 1.4b red — the bad state ───────────────────────────────────────
     The run starts at Stage 4 and works TOWARDS good; red is what makes "bad"
     legible from three metres. Confined to the stage ladder and the Stage 4
     battery fill. NOT a general error colour — and BLACKOUT (Phase 2) is the
     absence of light, never red. */
  --red-400: #f26a6a;
  --red-500: #dd3333;
  --red-600: #8f1f1f;

  /* ── 1.5 pose regions — LOCKED ──────────────────────────────────────
     REGION_COLOR in app.js reads these same four values. If one changes, both
     change. This is the single most breakable coupling in the build. */
  --region-arms: var(--blue-500);
  --region-head: var(--amber-500);
  --region-torso: var(--orange-500);
  --region-legs: var(--green-500);

  /* ── 1.6 stage ladder — exact quarters ──────────────────────────────
     Mirrors STAGE_TONE[] in app.js verbatim as [fillTop, fillBottom, glow].
     The engine ports verbatim; these follow it, not the other way round. */
  --stage-4-top: #f26a6a;  --stage-4-bot: #8f1f1f;  --stage-4-glow: rgba(221, 51, 51, 0.5);
  --stage-3-top: #ff9248;  --stage-3-bot: #c04a00;  --stage-3-glow: rgba(255, 105, 0, 0.5);
  --stage-2-top: #ffc23d;  --stage-2-bot: #c07b00;  --stage-2-glow: rgba(240, 165, 0, 0.5);
  --stage-1-top: #2ce8a4;  --stage-1-bot: #009160;  --stage-1-glow: rgba(0, 208, 132, 0.5);
  --stage-0-top: #4dffbe;  --stage-0-bot: #00a86a;  --stage-0-glow: rgba(0, 208, 132, 0.75);

  --stage-4: var(--stage-4-top);
  --stage-3: var(--stage-3-top);
  --stage-2: var(--stage-2-top);
  --stage-1: var(--stage-1-top);
  --stage-0: var(--stage-0-top);

  /* ── 1.7 semantic surfaces ──────────────────────────────────────────── */
  --surface-ground: var(--navy-900);
  --surface-sunken: var(--navy-1000);
  --surface-raised: var(--navy-800);
  --surface-glass: rgba(255, 255, 255, 0.055);
  --surface-glass-strong: rgba(255, 255, 255, 0.1);
  --surface-card: var(--navy-700);
  --surface-inset: rgba(2, 5, 15, 0.55);
  --surface-scrim: rgba(2, 5, 15, 0.72);

  /* ── 1.7 semantic text ──────────────────────────────────────────────── */
  --text-hero: #ffffff;
  --text-body: #e6edff;
  --text-muted: rgba(230, 237, 255, 0.62);
  --text-faint: rgba(230, 237, 255, 0.38);
  --text-on-accent: var(--navy-1000);
  --text-charge: var(--green-400);
  --text-alarm: var(--orange-400);
  --text-link: var(--blue-400);
  --text-link-hover: var(--blue-300);

  /* ── 1.7 borders — white at low alpha, never grey ───────────────────
     Grey borders read as dead on navy. */
  --border-hair: rgba(255, 255, 255, 0.1);
  --border-soft: rgba(255, 255, 255, 0.16);
  --border-loud: rgba(255, 255, 255, 0.28);
  --border-charge: rgba(0, 208, 132, 0.45);
  --border-brand: rgba(82, 126, 255, 0.55);

  /* ── 1.7 status ─────────────────────────────────────────────────────── */
  --status-charge: var(--green-500);
  --status-warn: var(--amber-500);
  --status-alarm: var(--orange-500);
  --status-dead: var(--navy-600);

  /* ── 2 type ─────────────────────────────────────────────────────────
     Two families, hard split. Prose is ALWAYS Montserrat — a parent reads it
     over the kid's shoulder. Press Start 2P is numerics and score moments
     only: timers, percentages, ranks, countdowns, stage numerals, combo. */
  --font-core: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-arcade: "Press Start 2P", "Courier New", monospace;

  --fw-regular: 400;  --fw-medium: 500;  --fw-semi: 600;
  --fw-bold: 700;     --fw-heavy: 800;   --fw-black: 900;

  --fs-micro: 11px;   --fs-label: 13px;     --fs-body-sm: 15px;
  --fs-body: 17px;    --fs-body-lg: 20px;
  --fs-title-sm: 26px; --fs-title: 34px;    --fs-title-lg: 46px;
  --fs-display: 64px; --fs-display-lg: 92px; --fs-display-xl: 132px;

  /* Always smaller than it looks — Press Start 2P runs visually large. */
  --fs-num-sm: 14px;  --fs-num: 22px;  --fs-num-lg: 38px;
  --fs-num-hero: 64px; --fs-num-mega: 112px;

  --lh-tight: 1.02;  --lh-snug: 1.18;  --lh-body: 1.5;  --lh-loose: 1.62;

  /* These two tracking values do most of the brand's typographic work. */
  --ls-micro: 0.16em;
  --ls-label: 0.1em;
  --ls-display: -0.02em;
  --ls-arcade: 0.04em;
  /* Micro-labels are the one place uppercase lives, besides BLACKOUT and
     STAGE ZERO (decided 2026-09-02). This was in tokens.md §2 from the start
     and never implemented — style.css referenced it as var(--tt-micro) and
     got `none`. */
  --tt-micro: uppercase;

  /* ── 3 spacing, radii, controls ─────────────────────────────────────
     4px base. Stall screens use the top of the scale, phones the middle. */
  --space-0: 0;      --space-1: 4px;   --space-2: 8px;   --space-3: 12px;
  --space-4: 16px;   --space-5: 20px;  --space-6: 24px;  --space-8: 32px;
  --space-10: 40px;  --space-12: 48px; --space-16: 64px; --space-20: 80px;
  --space-24: 96px;

  --radius-cell: 3px;   /* battery cells read as CELLS, not lozenges */
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-xl: 32px;
  --radius-pill: 999px; /* all buttons and chips; panels are never pill */

  --control-sm: 40px;
  --control-md: 48px;
  --control-lg: 56px;   /* mall-stall / kid-thumb minimum for a primary CTA */
  --control-xl: 72px;
  --border-w: 1px;
  --border-w-loud: 2px;

  --gutter-phone: 20px;
  --gutter-stall: 64px;
  --hud-safe: 24px;
  --maxw-prose: 56ch;
  --maxw-form: 420px;

  /* ── 4 effects ──────────────────────────────────────────────────────
     Blur ONLY over the live camera feed or the dot-grid. Over a flat fill it
     costs GPU and shows nothing. */
  --blur-panel: blur(18px) saturate(140%);
  --blur-scrim: blur(6px);

  /* Near-black, not grey — they sit on navy. */
  --shadow-panel: 0 18px 48px rgba(2, 5, 15, 0.55);
  --shadow-lift: 0 8px 24px rgba(2, 5, 15, 0.45);
  --shadow-sheet: 0 -12px 40px rgba(2, 5, 15, 0.6);

  /* Wells hold anything that fills up: battery cells, inputs, the camera frame. */
  --inset-well: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 8px 20px rgba(2, 5, 15, 0.55);
  --inset-hair: inset 0 0 0 1px rgba(255, 255, 255, 0.08);

  --glow-charge: 0 0 0 1px rgba(0, 208, 132, 0.5), 0 0 24px rgba(0, 208, 132, 0.45), 0 0 64px rgba(0, 208, 132, 0.2);
  --glow-charge-hard: 0 0 0 2px rgba(77, 255, 184, 0.9), 0 0 32px rgba(0, 208, 132, 0.75), 0 0 120px rgba(0, 208, 132, 0.4);
  --glow-brand: 0 0 0 1px rgba(82, 126, 255, 0.55), 0 0 22px rgba(82, 126, 255, 0.4);
  --glow-alarm: 0 0 0 1px rgba(255, 105, 0, 0.55), 0 0 24px rgba(255, 105, 0, 0.4);
  --glow-text-charge: 0 0 12px rgba(0, 208, 132, 0.65);
  --glow-text-white: 0 0 18px rgba(255, 255, 255, 0.35);

  --ring-focus: 0 0 0 3px rgba(82, 126, 255, 0.55);

  /* The drifting dot-grid is the brand's only pattern. The mask stops it
     running into the corner rails — see tokens.md §7.4. */
  --dotgrid-color: rgba(82, 126, 255, 0.16);
  --dotgrid-size: 34px;
  --dotgrid: radial-gradient(circle at 1px 1px, var(--dotgrid-color) 1px, transparent 0);
  --dotgrid-mask: radial-gradient(85% 75% at 50% 30%, #000 40%, transparent 100%);

  /* Text on video gets a bottom-up scrim, never a translucent capsule. */
  --protect-bottom: linear-gradient(to top, rgba(2, 5, 15, 0.92) 0%, rgba(2, 5, 15, 0.55) 45%, transparent 100%);
  --protect-top: linear-gradient(to bottom, rgba(2, 5, 15, 0.85) 0%, transparent 100%);

  /* One pool of light, top-centre. No multi-stop gradients, no purple. */
  --wash-ground: radial-gradient(120% 80% at 50% -10%, rgba(82, 126, 255, 0.2) 0%, transparent 60%);
  --wash-charge: radial-gradient(80% 60% at 50% 110%, rgba(0, 208, 132, 0.22) 0%, transparent 65%);

  /* Two polarities, because the two uses genuinely disagree (tokens.md §7.5).
     --scanlines DARKENS: the default over gameplay, because white lines lift
     blacks and wash out the skeleton on a live camera feed.
     --scanlines-dead LIGHTENS: BLACKOUT only (Phase 2), where dark lines on a
     near-black dying screen would be invisible. */
  --scanlines: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.16) 0 1px, transparent 1px 3px);
  --scanlines-dead: repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 3px);

  /* ── 5 motion ───────────────────────────────────────────────────────
     Two speeds: UI is quick and confident, game juice overshoots. */
  --dur-instant: 90ms;
  --dur-fast: 160ms;
  --dur-base: 240ms;
  --dur-slow: 420ms;
  --dur-set-piece: 900ms;  /* BLACKOUT, Stage Zero — the only long animations */
  --dur-drift: 38s;        /* the only infinite loop */

  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.45, 0, 0.25, 1);
  --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);  /* score moments */
  --ease-dead: cubic-bezier(0.7, 0, 0.84, 0);     /* lights don't fade, they go */
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-drift: 0s;
    --dur-set-piece: 1ms;
  }
}
