/**
 * tokens.css — the single source of truth for the tools site.
 *
 * WHY THIS FILE EXISTS
 * These tokens used to be copy-pasted into seven places, so changing one meant
 * editing seven files and hoping none drifted. CLAUDE.md described that as a
 * known cost; this removes it. Load this BEFORE the page's own stylesheet.
 *
 * mission-control/ does NOT use this file. It has its own kid-facing design
 * system and is deliberately exempt.
 *
 * NEUTRALS are derived, not chosen: lightness is solved for a contrast target
 * rather than picked. Identical values to the Ghost theme's custom.css, so the
 * tools match the articles they are embedded in — they render inside the same
 * viewport, so any drift is a visible seam. Verified by
 * scripts/check-contrast.mjs.
 *
 * LIGHT MODE WENT ACHROMATIC 2026-08-07. It used to carry Pink #F09984's hue
 * angle at near-zero chroma; Patrick read the result as a pink cast and asked
 * for white, so light mode is now pure white and true greys. Each grey holds
 * its predecessor's contrast ratio, so only the hue moved. Dark mode keeps its
 * warmth and is unchanged.
 *
 * ACCENT is Pom #8A153C, matching the Ghost admin accent colour, which remains
 * the source of truth. Changed from plum 2026-07-30.
 *
 * Measured against these neutrals (every light figure rose when the ground
 * went to white):
 *   accent on bg        9.32:1   accent-text    10.15:1 light · 6.22:1 dark
 *   white on accent     9.32:1   accent-2-text    5.49:1 light · 7.97:1 dark
 *   --accent-2 raw is 3.49:1 — fills and tints only, never text.
 *
 * Pom was chosen over Orange on three measures: link text at 10.0:1 against
 * Orange's 6.96 (AAA vs AA), 23° of hue separation from the paper against
 * Orange's 10° (Orange is very nearly a darker version of the background), and
 * a register that reads as considered rather than as a warning — which matters
 * on civic content. NOTE: the hue-separation leg of that argument lapsed when
 * the ground went achromatic — white separates from everything. The contrast
 * and register arguments still stand on their own, so the choice holds, but
 * don't cite hue separation as a live reason to keep it.
 *
 * DARK MODE LIFTS LIGHTNESS, IT DOES NOT MIX TOWARD WHITE. Mixing desaturates:
 * Pom at 50% white drops from chroma 50 to 25 and stops reading as Pom. A Lab
 * lightness lift to L*65 gives #F17791 at chroma 50 — the same colour, brighter.
 *
 * --accent-2 stays sea glass rather than becoming Blue 2 #15AED6. They are the
 * same hue (192-193°), but Blue 2 is too light to carry text: its 72% text mix
 * reaches only 3.91:1 against sea glass's 5.23:1. Sea glass IS Blue 2, at a
 * lightness that works.
 *
 * The accent used to sit in the paper's own hue neighbourhood (43° against
 * 32.8°); plum sat at 333.8°. The ground is achromatic now, so that adjacency
 * is gone and the accent stands clear of it. The rule it produced still holds
 * for its own reason: hover and focus states must not be "a slightly different
 * red" — move lightness or change the underline instead, because a small hue
 * step on a saturated accent reads as a rendering error rather than a state.
 */

@font-face {
  font-family: 'Geist';
  src: url('/fonts/Geist-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

:root {
  /* Brand. Keep --accent in sync with Ghost admin → Design & branding. */
  --accent: #8A153C;
  --accent-2: #2E8FA3;

  /* Indicators the eye must find against the page: keyboard focus rings and
     pressed/checked marks. Raw --accent is 1.80:1 on the dark ground —
     invisible — so this token lifts in dark mode while --accent (fills with
     white text on them) does not. WCAG 1.4.11 floor 3:1, held on both bg and
     card; asserted by scripts/check-contrast.mjs. */
  --accent-ui: var(--accent);

  /* Neutrals — light. Achromatic since 2026-08-07; see the header note. */
  --bg: #FFFFFF;
  --card: #F8F8F8;
  --line: #E5E5E5;        /* decorative hairlines */
  --line-strong: #939393; /* 3.07:1 — interactive control edges (WCAG 1.4.11) */
  --ink-mute: #767676;    /* 4.54:1 — third text tier, AA */
  --ink-soft: #585858;    /* 7.11:1 — secondary text, AAA */
  --ink: #272727;         /* 14.94:1 — headings, max emphasis */

  /* Derived. Every one of these references --bg or --ink, so they move with
     the neutrals rather than needing separate maintenance. */
  --accent-soft: color-mix(in srgb, var(--accent-2) 10%, var(--bg));
  --accent-line: color-mix(in srgb, var(--accent-2) 35%, var(--bg));
  --accent-text: color-mix(in srgb, var(--accent) 88%, var(--ink));
  --accent-2-text: color-mix(in srgb, var(--accent-2) 72%, var(--ink));

  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Dark is deliberately LOWER contrast than light (13.48 vs 14.99).
       Near-maximal light-on-dark causes halation smear for astigmatism and
       afterimages for migraine-prone readers; macOS and iOS sit near 13-15:1. */
    --bg: #231C1A;
    --card: #2E2624;
    --line: #403735;
    --line-strong: #716966; /* 3.13:1 */
    --ink-mute: #8C8380;    /* 4.53:1 */
    --ink-soft: #B1A5A3;    /* 7.01:1 */
    --ink: #ECE5E3;         /* 13.48:1 */

    /* A Lab lightness lift of the accent, NOT a mix toward white — mixing
       desaturates (chroma 50 -> 25) and the accent stops looking like itself.
       This holds chroma at 50. 6.22:1 on ground, 5.49:1 on card. */
    --accent-text: #F17791;
    --accent-ui: #F17791; /* same lift — 6.22:1 on ground, 5.49:1 on card */
    --accent-2-text: color-mix(in srgb, var(--accent-2) 60%, #fff);
  }
}
