/* ============================================================================
   Design tokens — the one source.

   Written 2026-09-11. Before this file, the same palette and type scale were
   declared three times: once in `index.html`, once in `dashboard/index.html`,
   and a divergent light-theme variant in `check-app/public/styles.css`. Two of
   those had already drifted apart in their NAMES while agreeing on their
   VALUES (`--text` / `--ink`, `--line` / `--grid` / `--border`, `--body` /
   `--body-font`), which is drift that a diff cannot catch and a reader cannot
   see.

   This repo has already paid for duplicated tables (the silent-zero roof bug)
   and duplicated prose. Duplicated design tokens are the same defect in a
   third costume, so they get the same treatment: one writer, everything else
   reads.

   WHO READS THIS FILE
     - `index.html`              — <link>s it directly
     - `dashboard/index.html`    — <link>s it directly
     - `preview/home/index.html` — <link>s it directly
     - `check-app`               — SYNCS it, via `tools/sync-specs.mjs`, into
                                   `public/vendor-tokens/tokens.css`. That copy
                                   is generated, never hand-edited, and
                                   `check-app/tools/verify.mjs` fails the build
                                   if it drifts from this file.

   WHO WRITES IT
     Only this file. If you are about to declare a colour, a font stack, a
     radius or a type size anywhere else, that is the defect starting.

   THEME
     Dark only, deliberately. The practice has one identity and theming it
     twice would mean maintaining two palettes — the problem this file exists
     to end. `color-scheme: dark` is set so form controls and scrollbars
     follow rather than rendering as light chrome on a dark page.
   ========================================================================= */

:root {
  color-scheme: dark;

  /* --- ground ------------------------------------------------------------ */
  --bg: #0a0e27;
  --bg2: #0d1230;
  --bg3: #0a1024;

  /* Raised surfaces. `--panel` and `--surface` are the same colour under two
     names because index.html and dashboard/index.html each coined one. Both
     are kept so neither page's rules had to be rewritten to adopt this file;
     new work should use `--surface`. */
  --surface: rgba(255, 255, 255, 0.045);
  --surface-2: rgba(255, 255, 255, 0.08);
  --panel: var(--surface);
  --panel-hover: var(--surface-2);

  /* --- rules and borders ------------------------------------------------- */
  --border: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.18);
  --line: var(--border);
  --line-strong: var(--border-strong);
  --grid: var(--border);

  /* --- type colour ------------------------------------------------------- */
  --ink: #e2e8f0;
  --ink-2: #94a3b8;
  --muted: #64748b;
  --text: var(--ink);
  --text2: var(--ink-2);
  --text3: var(--muted);

  /* --- brand accents ----------------------------------------------------- */
  /* Reserved meanings, not decoration. `--carbon` is results and the primary
     accent; `--model` is model/data; `--cost` is screening and warning, used
     sparingly. Do not repurpose them per-page. */
  --carbon: #00ff88;
  --model: #00d4ff;
  --cost: #fbbf24;

  --accent: var(--carbon);
  --accent-soft: rgba(0, 255, 136, 0.08);

  /* --- status ------------------------------------------------------------ */
  /* The status vocabulary is shared across every surface that renders a
     result. `not-modelled` is a real, fourth state — a system the model
     contains zero elements of — and it is NOT a pass and NOT a failure. It
     gets its own colour here precisely so no surface is tempted to map it
     onto one of the other three and overstate or understate it. */
  --good: #00ff88;
  --warning: #fbbf24;
  --critical: #f87171;
  --na: var(--muted);
  --not-modelled: var(--muted);
  /* An unrecognised status renders in this colour: visibly unhandled, never
     absent. A filter that drops what it does not recognise is how the
     silent-zero family of defects keeps recurring. */
  --unknown: #c084fc;

  /* --- EN 15978 stage palette -------------------------------------------- */
  /* Harmonized to brand on dark. Stage identity is a methodology fact, so the
     mapping lives here once rather than in whichever page draws a chart. */
  --stage-a13: #00d4ff;
  --stage-a45: #00ff88;
  --stage-b4: #a78bfa;
  --stage-c14: #fbbf24;
  --stage-d: #34d399;

  /* --- type -------------------------------------------------------------- */
  --display: 'Space Grotesk', system-ui, sans-serif;
  --body-font: 'IBM Plex Sans', system-ui, sans-serif;
  --mono-font: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  /* index.html's original spellings. */
  --body: var(--body-font);
  --mono: var(--mono-font);

  /* Type scale. Page-level sizes stay in the pages; these are the steps the
     surfaces actually share. */
  --fs-micro: 10.5px;
  --fs-small: 12px;
  --fs-body-sm: 13px;
  --fs-body: 14px;
  --fs-body-lg: 16px;
  --fs-lede: 17px;
  --fs-h3: 20px;
  --fs-h2: clamp(28px, 4vw, 38px);
  --fs-h1: clamp(34px, 6vw, 56px);

  /* --- spacing ----------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 88px;

  /* --- radius ------------------------------------------------------------ */
  --radius-sm: 4px;
  --radius: 8px;
  --radius-lg: 10px;
  --radius-xl: 14px;

  /* --- measure ----------------------------------------------------------- */
  --wrap-max: 1120px;
  --measure: 640px;
}

/* The one behaviour shipped alongside the tokens, because it is a property of
   the identity rather than of any page: the aurora drift and every transition
   stop for a reader who has asked for less motion.

   This rule was itself a fourth duplicate — `index.html`,
   `preview/home/index.html` and `dashboard/index.html` each carried their own
   copy. Verbatim from the version those pages shipped, including the reason
   the pseudo-element selectors are spelled out. */
@media (prefers-reduced-motion: reduce) {
  /* *::before/*::after needed too — bare * never matches pseudo-elements
     (the aurora lives on body::before/::after). */
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
  html {
    scroll-behavior: auto;
  }
}
