/* Design tokens.
 *
 * Two layers. The brand layer holds the palette exactly as briefed and never
 * changes. The semantic layer maps those to roles, and is redefined wholesale
 * inside [data-surface="dark"] -- so a component written once is correct on
 * both surfaces, and the "beam is dark-only, grape is paper-only" rule is
 * enforced by the cascade rather than by remembering it.
 *
 * Every value below was measured with lib/color.py. See docs/DESIGN.md for the
 * full table; tests/audit.py re-checks this file so nothing drifts below AA.
 */

:root {
  /* ---- Brand layer: as specified, unmodified ---- */
  --void: #120626;
  --aubergine: #1e0b3c;
  --grape: #6d28d9;
  --normify: #8b2ff8;
  --beam: #a855f7;
  --lilac: #e9d5ff;
  --paper: #f7f5fb;
  --ink: #1a1526;

  /* ---- Ramp extensions ----
   * Added because two briefed tokens fail WCAG in the roles they were given:
   *   beam  on paper = 3.66:1 -> cannot carry body text
   *   grape on void  = 2.74:1 -> fails the 3:1 non-text floor it was spec'd for
   */
  --grape-lift: #7c3aed; /* chart structure on dark      3.41:1 on void  */
  --plum: #5b21b6; /* small emphasis on paper      8.30:1 on paper */
  --quartz: #ece7f5; /* sunken surface on paper      ink 14.68:1     */
  --slate-violet: #55496e; /* muted text on paper          7.57:1          */
  --hairline: #d5cce8; /* rules on paper                               */
  --dusk: #b9a8d8; /* muted text on dark           8.94:1 on void  */
  --seam: #402868; /* rules on dark                                */

  /* ---- Semantic layer: paper (the default reading surface) ---- */
  --surface: var(--paper);
  --surface-sunken: var(--quartz);
  --surface-raised: #ffffff;
  --text: var(--ink);
  --text-muted: var(--slate-violet);
  --rule: var(--hairline);
  --rule-strong: #bfb2da;
  --accent: var(--grape); /* links, data emphasis   6.57:1 */
  --accent-strong: var(--plum); /* dense figures          8.30:1 */
  --accent-quiet: #efe9fb; /* accent wash behind text       */
  --axis: var(--grape);
  --focus: var(--normify);

  /* Series colours. Never the only carrier of meaning -- every series also
   * gets a distinct dash pattern and a direct label. */
  --series-dtc: var(--plum);
  --series-token: var(--normify);

  /* ---- Spacing, measure, radius, motion ---- */
  --measure: 66ch;
  --measure-tight: 54ch;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --radius: 3px;
  --radius-lg: 6px;

  --ease: cubic-bezier(0.2, 0, 0.1, 1);
  --dur-fast: 120ms;
  --dur: 200ms;
  --dur-slow: 380ms;
}

/* ---- Semantic layer: dark field. Reserved for the masthead, the divergence
 * moment on /model, and the concentration full-bleed on /anatomy. ---- */
[data-surface="dark"] {
  --surface: var(--void);
  --surface-sunken: #0c0418;
  --surface-raised: var(--aubergine);
  --text: var(--lilac);
  --text-muted: var(--dusk);
  --rule: var(--seam);
  --rule-strong: #573a85;
  --accent: var(--beam); /* 4.92:1 on void */
  --accent-strong: var(--beam);
  --accent-quiet: #241046;
  --axis: var(--grape-lift); /* 3.41:1 on void */
  --focus: var(--beam);

  --series-dtc: var(--dusk);
  --series-token: var(--beam);
}

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