/* ═══════════════════════════════════════════════════════════════════════════
   SwimSights — design tokens.  SINGLE SOURCE OF TRUTH for colour.
   Loaded before app.css and shell.css; nothing else may define a colour token.

   FOUR LAYERS, in order of who owns them:

     1 CORE      SwimSights' own brand (pool depth). Ours. Never club-specific.
     2 SEMANTIC  Product meaning: qualification tiers + status. MUST survive club
                 branding — a swimmer's County teal cannot become a club's colour.
     3 NEUTRAL   Surfaces, edges and type. The fill/edge/text scale, light→dark.
     4 CLUB      The only slots a club may set (--primary, --accent, --header),
                 injected at runtime from clubs/<club>/summary.json.

   RULES THAT EXIST BECAUSE THEY WERE BROKEN:
     · A club slot may NEVER be used for a fixed meaning. #157A3F became --accent
       once and the coach table's greens turned into Brompton's brand green.
       Fixed greens use --achieved. (r262)
     · Semantic tier tokens are re-ramped for the family view in body.parent-cards.
       Anything mapped to --tier-* changes colour inside that scope. (r262)
     · Club colours are chosen against WHITE. Any club slot used as text needs a
       contrast check — see pipeline/check_brand_contrast.py.
     · Print and the canvas share card must NOT follow a theme.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{

  /* ── 1 · CORE — SwimSights brand (pool depth) ── */
  --aqua:#00A6CE; --header:#1f4e79;

  /* ── 2 · SEMANTIC — qualification tiers (coach/table surfaces; re-ramped for parents) ── */
  --tier-cty:#0E7490; --tier-reg:#1E63C4; --tier-nat:#A21641; --tier-gb:#7A6100;
  --tier-cty-bg:#E7F6F9; --tier-reg-bg:#E8F0FC; --tier-nat-bg:#FBEDF2; --tier-gb-bg:#FAF3DC;

  /* ── 2 · SEMANTIC — status ── */
  --achieved:#157A3F; --danger:#c0392b; --warn:#b45309; --rank1:#d4edda;
  --rank2:#fff3cd; --rank3:#fde8d8;

  /* ── 3 · NEUTRAL — named roles ── */
  --ink:#0a2342; --ink-2:#1a2733; --ink-3:#1a3a5c; --slate:#33445c;
  --muted:#5B6B82; --muted-2:#5a6b7d; --grey:#8894a4; --grey-2:#9aa5b3;
  --deep:#0e4c73; --navy:#06263f; --current:#0F76A0;
  /* --navy/--deep also PAINT surfaces (landing gradient, coach hero, table heads).
     A fill cannot follow the same rule as type, so the fill role gets its own token. */
  --navy-fill:#06263f; --deep-fill:#0e4c73;
  --up-ink:#0B5F68; --up-strong:#0A2540; --up-chev:#0E7C86;
  /* landing: the route panels, its lede, and the gradient's shallow end */
  --path-bg:#F2F8FB; --path-edge:#D8E8F1; --lede:#555555; --shallow:#00A6CE;   /* type on the upcoming-races strip */ --panel:#eef2f7;
  --line:#e3e8ef; --line-2:#e4eaf2; --surface:var(--edge-white); --surface-2:#fff;
  --edge-white:#fff; --bg:#F5FAFC;

  /* ── 4 · CLUB — overwritten at runtime per club. Defaults are SwimSights'. ── */
  --primary:#1183B0; --accent:#157A3F;   /* == --sq-blue: one interactive colour (P1-3) */
  /* multi-select "on" state (age/stroke/distance pills). Light is unchanged from the
     hardcoded #e7f0fd it replaces; --sel-ink tracks club branding via --primary. */
  --sel-fill:#e7f0fd; --sel-ink:var(--primary);
  --tbl-shadow:rgba(10,35,60,.20);   /* right-edge cue on a table that still has more to scroll */

  /* ── 3 · NEUTRAL — consolidated scale (slice 3) ── */
  --fill-1:#fafbfd; --fill-2:#fbfaf5; --fill-3:#f5f8fb; --fill-4:#eef8f1; --fill-5:#eef7f7;
  --fill-6:#e7f5ec; --fill-7:#e7f3f5; --fill-8:#eef1f5; --fill-9:#e0f2f1; --fill-10:#e8edf5;
  --head-span:#5c6e82; --ink-15:#475569; --current-fill:#0F76A0; --ink-mute:#6B7280; --boot-sub:#5A6B82; --on-tier:#fff;
  /* the snackbar pill: dark-on-light in light, raised-surface in dark. It used to paint its
     fill with --ink, a TYPE token, so dark inverted the pill and took the white text with it. */
  /* Hero gradients (converter result, predictor card, report masthead). They were built from
     --ink -> --primary, both of which lift in dark, so the darkest thing on the page became
     the brightest. In light these resolve to exactly what the rules used before. */
  --hero-a:var(--ink); --hero-b:var(--primary);
  --hit-fill:#FFF3C4;   /* the find-a-swimmer flash; keyframes are outside the generator's reach */
  /* Canvas cannot read CSS, so the chart resolves these at draw time. Light values are exactly
     what Chart.js and the annotation plugin already produced — only the dark arm is new. */
  --chart-tick:#666666; --chart-grid:rgba(0,0,0,.1);
  --sticky-fill:rgba(255,255,255,.96);   /* near-opaque, so it is a surface not an overlay */
  --crs-lift:rgba(255,255,255,.65);      /* lifts the course chip off the pale landing hero */
  --chip-near-bg:#fff3cd; --chip-near-ink:#9a6a00;
  --chip-far-bg:#eef1f5;  --chip-far-ink:#8a94a3;
  --snack-fill:var(--ink); --snack-ink:#fff; --snack-act:rgba(255,255,255,.16); --snack-act-h:rgba(255,255,255,.28);   /* ink that sits ON a tier fill — the fills are deep in light and bright in dark, so the ink has to invert with them */   /* split out of --text-9 / --fill-15: each was painting a fill AND type, so dark could only satisfy one */
  --fill-11:#d9f0e1; --fill-12:#f0e2d8; --fill-13:#3e6796; --fill-14:#3b5e88; --fill-15:#475569;
  --fill-16:#2e4f76;
  --edge-1:#f1f4f8; --edge-2:#f1f0ea; --edge-3:#e4ebf2; --edge-4:#d3ebec; --edge-5:#e0e6ed;
  --edge-6:#dde3ea; --edge-7:#cde7ea; --edge-8:#cbe9d6; --edge-9:#e0e0e0; --edge-10:#d5dee8;
  --edge-11:#bfe3cd; --edge-12:#cdd8e6; --edge-13:#c4d6d9; --edge-14:#c5cfe8; --edge-15:#c4d0de;
  --edge-16:#556070; --edge-17:#4c56b0;
  --text-1:#c3ccd6; --text-2:#9ec2d8; --text-3:#9aa8bb; --text-4:#7fa8c4; --text-5:#90a0b4;
  --text-6:#8a94a3; --text-7:#7a8699; --text-8:#66748c; --text-9:#5c6e82; --text-10:#3f4894;
  --text-11:#3a4a5e; --text-12:#2e4057; --text-13:#1d2733; --text-14:#1a1a2e;
}

body.parent-cards{
  --pv-deep:#062A3B; --pv-deep2:#0C4C66; --pv-ink:#0A2540;
  --pv-page:#EDF3F7; --pv-line:#E4EBF2; --pv-line2:#EEF3F8;
  --pv-muted:#5C6E82; --pv-sub:#8093A5;
  --pv-accent:#0FB0C6; --pv-accent-ink:#0A7C8D;
  --pv-gold:#B7791F; --pv-gold-ink:#8A5B12; --pv-gold-bg:#FBF4E4;
  /* Gap to the next standard. NOT a warning — being 0.08s off a County time is the best news on
     the card. Coloured as the tier being chased, so it can never be read as a fault, and kept
     clear of --pv-gold-ink, which means ACHIEVED. */
  /* Amber, split in two. On a white card an amber legible as TEXT has to be dark (a bright one is
     ~3:1 and fails) — which is how it drifted to rust. The BAR needs visibility, not legibility,
     so it carries the bright amber and the text stays readable. --pv-gap-bar exists for that. */
  --pv-gap:#0E7C86; --pv-gap-bar:#0E7C86; --pv-gap-bg:#E3F3F4; --pv-gap-track:rgba(14,124,134,.20);
  --tier-cty:#0E7C86; --tier-reg:#1E63C4; --tier-gb:#B7791F;   /* re-ramp the ladder for parents */
  background:var(--pv-page);
}

/* ═══════════════════════════════════════════════════════════════════════════
   DARK — "Deep water".  Named for the pool, not for a UI convention:
     abyss   #0A1622   the page, the deep end
     deep    #122032   a card resting on it
     current #18293D   a modal above the card
     edge    #22334C   where surfaces meet

   Hue and saturation are carried over from light; only lightness moves. A parent
   who has learnt that teal means County is never re-taught.

   Applied two ways: when the phone asks for dark AND the user has not overridden
   (data-theme="auto", the default), or when they explicitly choose dark.

   NOT themed, deliberately: @media print (reports print light) and the canvas
   share card (an image sent to other people; canvas cannot read CSS variables).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ONE dark block, keyed on data-resolved — the same attribute dark.css keys on.
   It used to be four: a (prefers-color-scheme: dark) arm and an explicit [data-theme="dark"]
   arm, each duplicated for body.parent-cards. Four copies of the same ~140 tokens drift; worse,
   they disagreed with dark.css about WHEN dark applies. If JS ever failed, the media arm still
   fired here while dark.css's 207 rules did not — a half-themed hybrid. data-resolved is stamped
   by the blocking inline script in index.html before first paint (it collapses "auto" to what the
   phone actually chose), so this costs no flash, and both files now agree: no JS, no dark. */
:root[data-resolved="dark"]{
  --aqua:#3FC6E0; --header:#0E1E33; --tier-cty:#19A3AF; --tier-reg:#4C8DE8;
  --tier-nat:#EC5B85; --tier-gb:#D6A542; --tier-cty-bg:#0C2B31; --tier-reg-bg:#16233C;
  --tier-nat-bg:#2E1220; --tier-gb-bg:#2A2312; --achieved:#35C07B; --danger:#F2777A;
  --warn:#F0A93C; --rank1:#14301D; --rank2:#2E2A10; --rank3:#31200F;
  --ink:#E6EDF5; --ink-2:#D7E1EC; --ink-3:#C4D2E2; --slate:#AFC0D2;
  --muted:#9FB0C4; --muted-2:#9AACC0; --grey:#8FA2B8; --grey-2:#94A6BA;
  --deep:#7FB6D8; --navy:#8FC4E4; --navy-fill:#0A1B2B; --deep-fill:#123049; --up-ink:#7FD3C6; --up-strong:#DCE8F4; --up-chev:#19A3AF;
  --path-bg:#16253A; --path-edge:#22334C; --lede:#AFC0D2; --shallow:#0E4A63; --current:#5FB3D4; --panel:#16253A;
  --line:#22334C; --line-2:#22334C; --surface:#122032; --surface-2:#18293D;
  --edge-white:#22334C; --bg:#0A1622; --primary:#5FB3D4; --accent:#35C07B;   /* == dark --sq-blue */
  /* lifted, not darkened: 1.55:1 against the unselected pill so "on" is visible at a
     glance, with near-white ink at 8.06:1 on it. */
  --sel-fill:#264868; --sel-ink:#E6EDF5;
  --tbl-shadow:rgba(0,0,0,.55);
  --fill-1:#10141D; --fill-2:#1E1B10; --fill-3:#10171E; --fill-4:#101F15;
  --fill-5:#101F1F; --fill-6:#111F16; --fill-7:#111D1F; --fill-8:#12171E;
  --fill-9:#112020; --fill-10:#11161F; --fill-11:#122117; --fill-12:#211812;
  --head-span:#22364F; --ink-15:#C4D2E2; --current-fill:#1E6E8C; --ink-mute:#A9B2BF; --boot-sub:#A7B4C6; --on-tier:#0A1B2B;
  --hero-a:#123049; --hero-b:#1E6E8C;   /* stay a deep-water band after dark, not a light slab */
  --hit-fill:#4E4520;
  --chart-tick:#9FB0C4; --chart-grid:rgba(255,255,255,.10);
  --sticky-fill:rgba(18,32,50,.96);
  --crs-lift:rgba(255,255,255,.10);
  --chip-near-bg:#3B3218; --chip-near-ink:#E8C77A;
  --chip-far-bg:#1B2635;  --chip-far-ink:#9FB0C4;
  --snack-fill:var(--surface-2); --snack-ink:var(--ink); --snack-act:rgba(255,255,255,.10); --snack-act-h:rgba(255,255,255,.18);   /* a band white type can sit on; --current itself is now type-only */
  --fill-13:#1F2B39; --fill-14:#202C3B; --fill-15:#262D38; --fill-16:#212E3E;
  --edge-1:#10161E; --edge-2:#1D1C13; --edge-3:#111920; --edge-4:#122222;
  --edge-5:#131920; --edge-6:#141920; --edge-7:#132123; --edge-8:#132319;
  --edge-9:#1A1A1A; --edge-10:#283442; --edge-11:#294534; --edge-12:#283443;
  --edge-13:#2B4043; --edge-14:#293044; --edge-15:#293645; --edge-16:#3D4550;
  --edge-17:#323553; --text-1:#98A7B9; --text-2:#84B1CD; --text-3:#99A7BA;
  --text-4:#90B4CC; --text-5:#9EACBE; --text-6:#ABB2BD; --text-7:#B1B8C3;
  --text-8:#B9C0CC; --text-9:#BEC7D1; --text-10:#B5B9E0; --text-11:#D0D8E2;
  --text-12:#D3DCE8; --text-13:#E5EBF1; --text-14:#E8E8F2;
}
:root[data-resolved="dark"] body.parent-cards{
  --pv-deep:#08202C; --pv-deep2:#0E3A4C; --pv-ink:#E6EDF5; --pv-page:#0A1622;
  --pv-line:#22334C; --pv-line2:#1B2C42; --pv-muted:#9FB0C4; --pv-sub:#8296AF;
  --pv-accent:#3FC6E0; --pv-accent-ink:#7FE0F0; --pv-gold:#D6A542; --pv-gold-ink:#E6BD66;
  --pv-gold-bg:#2A2312; --pv-gap:#19A3AF; --pv-gap-bar:#19A3AF; --pv-gap-bg:#0C2B31; --pv-gap-track:rgba(25,163,175,.28); --tier-cty:#19A3AF;
  --tier-reg:#4C8DE8; --tier-gb:#D6A542;
}

/* Reports are printed and read on paper — never on a dark ground. */
@media print{
  :root, :root[data-theme="dark"]{
    --bg:#FFFFFF; --surface:#FFFFFF; --surface-2:#FFFFFF; --ink:#111111; --muted:#444444;
  }
}

/* Native controls — text inputs, selects, checkboxes, scrollbars — are painted by the browser,
   not by us. Without color-scheme they stay light on a dark page: .swinput sets no background,
   so the compare box rendered as a white pill on the deep end. One declaration themes them all. */
:root[data-resolved="dark"]{ color-scheme: dark; }
:root[data-resolved="light"]{ color-scheme: light; }
