/* ═══════════════════════════════════════════════════════════════════════════
   tokens.css — the token LAYER. Imported FIRST (see main.jsx).

   Ported from golfgen-dashboard. Source of truth for the values:
   docs/GolfGen_Dashboard_Design_System.html §01 (tokens), §03 (motion),
   §06 (data-viz). Registry: design/themes.js

   ── The architecture ──────────────────────────────────────────────────────
   A theme declares ONLY its contract tokens (design/themes.js CONTRACT_TOKENS):
   --acc --acc2 --up --dn --warn --t1..t3 --bg --surf --raise --line --rad
   --on-acc --fnum --flab --fbody.

   Everything else is DERIVED here, once, from that contract.

   ── Why `[data-theme]` and not a list of theme classes ────────────────────
   Custom properties resolve against THE ELEMENT'S OWN computed value. The theme
   block and this derived block both land on the theme root, so `--chart-1:
   var(--acc)` written here picks up whatever --acc that element's theme block
   won with — including a theme this file has never heard of. Adding a theme is
   therefore two steps: a block in styles/themes.css, an entry in design/themes.js.

   styles/themes.css still carries an alias block that enumerates every theme
   (`body.clarity, body.cockpit, …`). It is wrapped in :where() so it cannot
   outrank this layer; a new theme picks its aliases up from here.

   ── Precedence ────────────────────────────────────────────────────────────
   This file loads first. App.css and styles/themes.css follow, and the theme
   blocks are more specific, so a theme always wins over these defaults — it
   overrides a derived token only where it truly deviates.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Global scales — theme-independent. Identical under every theme. ──────── */
:root {
  /* Spacing — 4px base, 8-pt rhythm (§01). 24px between panels, 16px inside. */
  --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;

  /* Z-index (§01). Never hand-write a z-index; take one from this ladder. */
  --z-base:0; --z-dropdown:100; --z-sticky:200; --z-overlay:1000;
  --z-modal:1100; --z-toast:1200; --z-tooltip:1300;

  /* Motion (§03). Durations are a scale, not a free parameter. */
  --mo-fast:120ms; --mo-base:200ms; --mo-slow:320ms; --mo-enter:480ms;
  --ease-standard:cubic-bezier(.2,0,0,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);

  /* Type scale (§12) — "one ramp, no orphan sizes". Faces come from each
     theme's --fnum/--flab/--fbody; only the SCALE is shared. */
  --fs-display:48px;  --lh-display:1.0;  --tr-display:-.02em;
  --fs-h1:30px;       --lh-h1:1.1;
  --fs-h2:22px;       --lh-h2:1.25;
  --fs-h3:16px;       --lh-h3:1.35;
  --fs-kpi:31px;      --lh-kpi:1.05;
  --fs-body:14px;     --lh-body:1.6;
  --fs-label:11px;    --lh-label:1.3;   --tr-label:.1em;
  --fs-meta:11px;     --lh-meta:1.4;
  --fs-sm:12.5px;     --fs-xs:10.5px;

  /* Radius derived from each theme's --rad, so corner personality propagates. */
  --rad-tight: calc(var(--rad) * 0.4);
  --rad-card:  var(--rad);
  --rad-panel: calc(var(--rad) * 0.6);
  --rad-input: calc(var(--rad) * 0.45);
  --rad-pill:  999px;

  /* Product-color swatches — the physical color a SKU ships in (a "Green" item
     dot must read green). Theme-INDEPENDENT (a green product is green on every
     theme) but tokens, not raw hex, so there are zero hardcoded colors and the
     swatch set is defined in one place. Not semantic (never --up/--dn) and not
     chart series — they encode a real product attribute. Mirrors golfgen. */
  --product-green:  #22C55E;
  --product-red:    #EF4444;
  --product-blue:   #60A5FA;
  --product-orange: #E87830;
  --product-black:  #0B0D10;
  --product-white:  #FFFFFF;
  --product-gray:   #94A3B8;
  --product-yellow: #EAB308;
  --product-purple: #A855F7;
  --product-pink:   #EC4899;

  /* Breakpoints (px, unitless custom properties — CSS can't interpolate a
     var() into a media query, so these exist for JS/documentation reference;
     any actual @media rule must hard-code the same number). Standard 3-tier
     phone/tablet/desktop thresholds, theme-independent. */
  --bp-phone:  480;
  --bp-tablet: 768;
  --bp-desktop: 1024;
}

/* ── Derived layer ─────────────────────────────────────────────────────────
   `:root` carries the same defaults so the first paint — before ThemeContext
   stamps data-theme onto <body> — is never unstyled. */
:root,
[data-theme] {
  /* Accent states — always mixed from the theme's OWN accent, never a fixed hex. */
  --acc-hover: color-mix(in srgb, var(--acc) 82%, #000);
  --acc-soft:  color-mix(in srgb, var(--acc) 12%, transparent);
  --acc-border: color-mix(in srgb, var(--acc) 32%, transparent);

  /* Foreground for text/icons sitting ON a filled state color. Per-theme
     overrides live in themes.css (11 of these 15 combinations fail WCAG AA
     with a single global white — see the override block there); these are
     the fallback for any theme that doesn't need one. */
  --on-up:   #FFFFFF;
  --on-dn:   #FFFFFF;
  --on-warn: #FFFFFF;

  /* Theme-independent absolute white — surfaces that must stay white on every
     theme (QR quiet zones, a white glyph in a fixed brand mark). Not a
     substitute for --raise/--on-acc. */
  --white: #FFFFFF;

  /* External brand colors — fixed by the platform, identical on every theme
     (a Google button is Google-blue everywhere). Tokens, not raw hex, so they
     are named and swappable in one place — but deliberately NOT theme-derived.
     Mirrors golfgen. */
  --brand-google:    #4285F4;
  --brand-facebook:  #1877F2;
  --brand-tiktok:    #000000;
  --brand-walmart:   #0071DC;
  --brand-instagram: #E1306C;
  --brand-youtube:   #FF0000;
  --brand-linkedin:  #0A66C2;

  /* Monospace face. ESM loads no webfont mono, so use the system stack —
     always resolves, no missing-face fallback surprise. */
  --fmono: ui-monospace, SFMono-Regular, Menlo, "Cascadia Code", monospace;

  /* Surface aliases pages reference; without these a bare var() paints nothing. */
  --card-bg:  var(--raise);
  --input-bg: var(--surf);
  --hover-bg: color-mix(in srgb, var(--t1) 6%, transparent);

  /* ── Charts (§06) ────────────────────────────────────────────────────────
     Categorical: series 1 and 2 ARE the theme's accents, so every theme gets a
     coherent chart identity for free. 3-6 are brand-extension hues a theme may
     override. Cap at 6 series, then bucket the rest as "Other".

     THE HARD RULE: green and red are RESERVED for up/down meaning and must
     never appear as a categorical series color, or a reader misreads
     "category 3" as "bad". */
  --chart-1: var(--acc);
  --chart-2: var(--acc2);
  --chart-3: #4C8DFF;
  --chart-4: #A78BFA;
  --chart-5: #F4C152;
  --chart-6: #FF7AA8;

  /* Sequential (ordered magnitude, low → high): a luminance ramp through the
     theme's PRIMARY SERIES color. Derived, so a new theme gets a correct ramp
     automatically. */
  --chart-seq-1: color-mix(in srgb, var(--chart-1) 22%, #000);
  --chart-seq-2: color-mix(in srgb, var(--chart-1) 52%, #000);
  --chart-seq-3: color-mix(in srgb, var(--chart-1) 80%, #000);
  --chart-seq-4: var(--chart-1);
  --chart-seq-5: color-mix(in srgb, var(--chart-1) 55%, #fff);

  /* Diverging (under ↔ over plan): down → neutral → up. */
  --chart-div-1: var(--dn);
  --chart-div-2: color-mix(in srgb, var(--dn) 62%, var(--t3));
  --chart-div-3: var(--t3);
  --chart-div-4: color-mix(in srgb, var(--up) 62%, var(--t3));
  --chart-div-5: var(--up);

  /* Chart furniture. §06: faint gridlines in --line, axis text in --t2,
     plan/target always dashed. */
  --chart-grid: var(--line);
  --chart-axis: var(--t2);
  --chart-plan: var(--acc2);
  --chart-clearance: #F59E0B;  /* amber — semantic markdown/clearance color, all themes */
  --chart-area-opacity: .25;
  /* DECORATIVE fill under a line (above) vs DATA-BEARING fill of a stacked
     band (below). They are different jobs: a theme may want no soft gradient
     while still needing stacked bands to be solid, since there the fill IS the
     series. Constructivist is exactly that case — area-opacity 0, band 1. */
  --chart-band-opacity: .78;
  --chart-stroke: 2.25;

  /* Tooltip follows the theme's elevated surface. OTIF.jsx hardcoded a
     #1A2744 tooltip on a #E3E3E6 border — a light-theme tooltip that stayed
     light-bordered on both dark themes. */
  --chart-tip-bg:  var(--raise);
  --chart-tip-brd: var(--line);
  --chart-tip-ink: var(--t1);
}

/* Per-theme chart deviations. Everything absent is inherited from above. */
body.clarity, [data-theme="clarity"] {
  --chart-3:#FF9500; --chart-4:#AF52DE; --chart-5:#64D2FF; --chart-6:#FFD60A;
  --chart-grid:transparent;            /* §Clarity: "Kill gridlines" */
  --chart-axis:var(--t3);              /* "minimize axes" */
  --chart-plan:var(--t3);
  --chart-area-opacity:.18;
  --chart-band-opacity:.78;   /* soft, matches Clarity's restraint */
  --chart-stroke:2.5;
}
body.cockpit, [data-theme="cockpit"] {
  /* Tesla instrument panel: a MONOCHROME red-and-grey palette. The red accent
     is the hero/primary series; comparison/secondary series step down through
     greys to near-white. Because there is no green/amber "good" counterpart,
     the red primary reads as "current/highlighted", not "bad" — so it stays on
     brand without the alarm misread §06 warns about. (Data TABLES must still
     avoid red numerals — those use --t1, decoupled from this palette.) */
  --chart-1:var(--acc);  --chart-2:#9BA1AA; --chart-3:var(--acc2);
  --chart-4:#E8726F;     --chart-5:#C4C8CE; --chart-6:#3A3D44;
  --chart-clearance:#FFB340;           /* brighter amber on dark Cockpit bg */
  --chart-plan:var(--t3);              /* "grey dashed for plan/target" */
  --chart-area-opacity:.10;
  --chart-band-opacity:.85;   /* punchier on Cockpit's near-black */
  --chart-stroke:2;
}
/* Broadsheet inverts: actuals are solid blue, the claret accent is the dashed
   plan line. So --chart-1 is the SECONDARY accent here. */
body.broadsheet, [data-theme="broadsheet"] {
  --chart-1:var(--acc2);
  --chart-2:#990F3D; --chart-3:#0D7680; --chart-4:#B5731A;
  --chart-5:#593380; --chart-6:#6B635C;
  --chart-clearance:#B5731A;           /* warm ochre — on-brand for Broadsheet */
  --chart-plan:var(--acc);
  --chart-area-opacity:.08;
  --chart-band-opacity:.72;   /* lighter ink, print feel */
  --chart-stroke:2;
}
body.constructivist, [data-theme="constructivist"] {
  /* Same rule: lead with blue (its --acc2), keep the red accent for late slots
     and UI chrome, so a primary series isn't painted red. */
  --chart-1:var(--acc2); --chart-2:#F2C014; --chart-3:#5A564E;
  --chart-4:#8A8478; --chart-5:#1A1A1A; --chart-6:var(--acc);
  --chart-clearance:#F2C014;           /* constructivist gold */
  --chart-grid:transparent;            /* hard edges, no gridlines */
  --chart-axis:var(--t1);
  --chart-plan:var(--t1);
  --chart-area-opacity:0;              /* "No gradients" — flat fills only */
  --chart-band-opacity:1;   /* flat + fully opaque = "flat fills only" */
  --chart-stroke:3;                    /* "thick baselines" */
}
body.gg, [data-theme="gg"] {
  --chart-grid:#1C2430;                /* named explicitly in the spec */
  --chart-area-opacity:.35;            /* "soft area fill" */
  --chart-band-opacity:.82;   /* GG house */
  --chart-stroke:2.4;
}
/* Swiss: black is the primary series, vermilion the single accent series.
   Flat fills, no gridlines — "reduce to the essential". */
body.swiss, [data-theme="swiss"] {
  --chart-1:#0A0A0A;     --chart-2:var(--acc); --chart-3:#6B6B6B;
  --chart-4:#2F5BEA;     --chart-5:#B8B8B2;    --chart-6:#9C5200;
  --chart-clearance:#FF9A3D;
  --chart-grid:transparent;
  --chart-axis:var(--t1);
  --chart-plan:var(--acc);
  --chart-area-opacity:0;
  --chart-band-opacity:1;
  --chart-stroke:2.25;
}
/* Contrast: strongly separated, print-safe hues; thick strokes, no area fill. */
body.contrast, [data-theme="contrast"] {
  --chart-1:#0033CC; --chart-2:#000000; --chart-3:#B00020;
  --chart-4:#7A2E9E; --chart-5:#006B2D; --chart-6:#8A4B00;
  --chart-clearance:#8A4B00;
  --chart-grid:#8C8C8C; --chart-axis:#000000; --chart-plan:#000000;
  --chart-area-opacity:0; --chart-band-opacity:1; --chart-stroke:3;
}
/* Aurora: cool neon hues that glow against the violet base; soft area fills. */
body.aurora, [data-theme="aurora"] {
  --chart-1:#9B8CFF; --chart-2:#4CC9F0; --chart-3:#F472B6;
  --chart-4:#FBBF24; --chart-5:#34D399; --chart-6:#6D67A8;
  --chart-clearance:#FBBF24;
  --chart-grid:#2C2850; --chart-plan:var(--t3);
  --chart-area-opacity:.28; --chart-band-opacity:.8; --chart-stroke:2.4;
}
/* Mono: greys only, separated by lightness and value; up/down keep their colour. */
body.mono, [data-theme="mono"] {
  --chart-1:#FAFAFA; --chart-2:#A3A3A3; --chart-3:#6B6B6B;
  --chart-4:#D4D4D4; --chart-5:#525252; --chart-6:#8F8F8F;
  --chart-clearance:#FBBF24;
  --chart-grid:#1A1A1A; --chart-plan:var(--t3);
  --chart-area-opacity:.08; --chart-band-opacity:.9; --chart-stroke:1.75;
}
/* Dusk: desaturated pastels — low glare, still distinguishable. */
body.dusk, [data-theme="dusk"] {
  --chart-1:#88C0D0; --chart-2:#B48EAD; --chart-3:#EBCB8B;
  --chart-4:#D08770; --chart-5:#A3BE8C; --chart-6:#7B88A1;
  --chart-clearance:#EBCB8B;
  --chart-grid:#3E4A5E; --chart-plan:var(--t3);
  --chart-area-opacity:.2; --chart-band-opacity:.8; --chart-stroke:2.2;
}
