/* public/css/tokens.css — COPY of docs/research/design-tokens.css (the design source of truth) with
   asset URLs made relative (they ride the versioned /assets/<build>/ prefix) and the Caslon latin-ext
   faces added. Change colours in BOTH files and re-run the contrast checker (design.md §3.2).
   server/test/smoke.test.js diffs the two dark blocks (they must stay identical). */
/* ==========================================================================================
   geoguess.es — design tokens ("The Chart Room", final, 2026-10-13)
   Source of truth: docs/research/design.md. Every text pair below has a computed WCAG 2.x
   contrast ratio in design.md section 3; do not change a colour without re-running the check.

   Themes
     Light = "Day watch" (default). Dark = "Night watch".
     - Follows the OS:      @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) }
     - Manual override:     <html data-theme="dark"> or <html data-theme="light">
     The two dark blocks below are IDENTICAL on purpose (CSS cannot share one block between a
     media query and an attribute selector without a build step). A unit test must diff them.

   Fonts (SIL OFL 1.1, self-hosted, never from a CDN). Paths assume /assets/fonts/.
   Starter files (already subset WOFF2, licences beside them): Website/docs/research/theme-A/mock/fonts/.
   ========================================================================================== */

@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700; font-display: swap;
  src: url(../fonts/IBMPlexSans-var-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700; font-display: swap;
  src: url(../fonts/IBMPlexSans-var-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700; font-display: swap;
  src: url(../fonts/IBMPlexSans-var-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 100 700; font-display: swap;
  src: url(../fonts/IBMPlexSans-var-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(../fonts/IBMPlexMono-500.woff2) format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(../fonts/IBMPlexMono-600.woff2) format('woff2'); }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonText-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonText-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Libre Caslon Text'; font-style: italic; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonText-400i.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Libre Caslon Text'; font-style: italic; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonText-400i-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(../fonts/LibreCaslonText-700.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(../fonts/LibreCaslonText-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Libre Caslon Display'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonDisplay-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Libre Caslon Display'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(../fonts/LibreCaslonDisplay-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
/* Caslon latin-ext subsets: instanced (wght 400/700) and subset from google/fonts ofl/librecaslontext and
   ofl/librecaslondisplay with fontTools on 2026-10-14 (Libre Caslon has no Reserved Font Name). */

:root {
  color-scheme: light;

  /* ---------- type ---------- */
  --font-ui: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --font-serif: 'Libre Caslon Text', Georgia, 'Times New Roman', serif;
  --font-display: 'Libre Caslon Display', 'Libre Caslon Text', Georgia, serif;
  --fs-11: 0.6875rem;  --fs-12: 0.75rem;  --fs-13: 0.8125rem; --fs-14: 0.875rem; --fs-15: 0.9375rem;
  --fs-16: 1rem;       --fs-18: 1.125rem; --fs-22: 1.375rem;  --fs-28: 1.75rem;  --fs-36: 2.25rem;
  --fs-48: 3rem;       --fs-56: 3.5rem;
  --lh-tight: 1.1; --lh-snug: 1.25; --lh-ui: 1.45; --lh-body: 1.55;
  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700;
  --tracking-eyebrow: 0.14em; --tracking-caps: 0.08em;

  /* ---------- space (4-pt) ---------- */
  --sp-0: 0; --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px;
  --sp-8: 32px; --sp-10: 40px; --sp-12: 48px; --sp-14: 56px; --sp-16: 64px; --sp-20: 80px;

  /* ---------- shape: machined, not pillowy ---------- */
  --r-1: 3px;   /* chips, tags, kbd, flags (2px for flags is fine) */
  --r-2: 6px;   /* buttons, inputs, avatars, tooltips */
  --r-3: 10px;  /* cards, HUD plates, menus */
  --r-4: 14px;  /* dialogs, bottom sheets (top corners) */
  --r-pill: 999px; /* status pills and quick-chat chips only */
  --bw: 1px; --bw-strong: 2px;

  /* ---------- layout ---------- */
  --rail-w: 224px; --rail-w-collapsed: 72px; --topbar-h: 56px; --tabbar-h: 60px;
  --content-max: 1240px; --side-panel-w: 340px; --hit-min: 44px;
  --z-base: 0; --z-hud: 10; --z-rail: 20; --z-dropdown: 30; --z-sheet: 40; --z-modal: 50; --z-toast: 60; --z-tooltip: 70;

  /* ---------- motion ("index arm": quick, then settles; nothing bounces) ---------- */
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --t-fast: 120ms; --t-base: 200ms; --t-panel: 300ms; --t-reveal: 700ms;

  /* ======================= DAY WATCH (light) ======================= */
  /* surfaces */
  --page: #ECEBE4;        /* the chart table: cool stone, NOT newsprint cream */
  --card: #FAF9F5;        /* a fresh sheet */
  --raised: #FFFFFF;      /* inputs, tiles that are buttons, menus */
  --sunken: #E2E0D7;      /* wells, tracks, table heads, empty bars */
  --hud: rgba(250, 249, 245, .94);   /* panels over the panorama (opacity never lower) */
  --scrim: rgba(10, 15, 22, .55);    /* behind modals */
  /* ink */
  --ink: #1A1E29;         /* indigo-black iron-gall: body text */
  --ink-2: #434855;       /* secondary */
  --ink-3: #5B606E;       /* muted, captions (>= 4.75:1 on every light surface) */
  --rule: #D8D5CB;        /* hairlines, decorative only */
  --rule-2: #B8B4A7;      /* stronger dividers, every 5th table row */
  --field: #828072;       /* borders of inputs and outline buttons (>= 3:1) */
  /* the binding: indigo rail / top bar, both modes */
  --chrome: #1B2540; --chrome-2: #26324F; --chrome-3: #30406A; --chrome-edge: #1B2540;
  --chrome-ink: #EDE6D6; --chrome-ink-2: #B6BCCB;
  /* actions */
  --accent: #2A4A7F; --accent-hover: #223D69; --accent-ink: #FFFFFF; --accent-soft: #DEE4EE;
  --cta: #D2A146; --cta-hover: #C69237; --cta-edge: #8A6416; --cta-ink: #1A1E29;  /* gilt: ONE per view */
  --brass: #B8892B;       /* decoration only, never text on light */
  --brass-ink: #7E5C17;   /* brass as text / insignia on light */
  /* status (always paired with an icon, sign or word) */
  --win: #1D6A5A;  --win-soft: #DCEBE5;    /* verdigris: win, + rating, online */
  --loss: #AD371C; --loss-soft: #F5DFD7;   /* vermilion: loss, - rating, danger, low time */
  --warn: #8A5A00; --warn-soft: #F4E7CC;   /* ochre: damage multiplier, cautions */
  --info: #2A4A7F; --info-soft: #DEE4EE;
  /* players (colour is never the only cue: side, label, pin shape) */
  --self: #2F5FA6; --self-soft: #DDE5F2;   /* you: left, circle-centred pin */
  --opp: #B23D1E;  --opp-soft: #F5E0D8;    /* rival: right, diamond-centred pin */
  --team-1: #2F5FA6; --team-2: #B23D1E; --team-3: #1D6B66; --team-4: #6A3D7A;  /* + shapes ● ◆ ▲ ■ */
  --focus: #2A4A7F;
  /* time controls (wedge of the chronometer icon, tile top rule, chart series) */
  --tc-bullet: #AD371C; --tc-blitz: #94600F; --tc-rapid: #1D6A5A; --tc-classical: #2A4A7F; --tc-daily: #6B4B2E;
  /* difficulty tiers T1-T8: bathymetric tints (T1-T4 take --ink text, T5-T8 take --depth-ink) */
  --depth-1: #E4EEEC; --depth-2: #D0E3E1; --depth-3: #B8D4D4; --depth-4: #97BEC2;
  --depth-5: #3D6D7D; --depth-6: #335F72; --depth-7: #2A5269; --depth-8: #1D3F57;
  --depth-ink: #FFFFFF; --depth-ink-2: #E3ECEF;
  /* guess map ("the chart"): vellum land on a cool table */
  --map-land: #F3EEE2; --map-water: #C9D9D6; --map-coast: #5B4A3A; --map-waterline: rgba(91, 74, 58, .22);
  --map-border: #8E7D68; --map-border-4: #C2B6A2; --map-grat: #9FB5B1; --map-label: #3E342B;
  --map-label-2: #6E6253; --map-water-label: #3B5D78; --map-grat-label: #83601A; --map-halo: #F3EEE2;
  --map-wood: #E5E6CF; --map-ice: #F7F8F6; --map-sand: #EFE3C4; --map-residential: #ECE5D4; --map-park: #DDE5CB;
  --map-road-1: #B7926A; --map-road-2: #C9AE86; --map-road-3: #D9C7A6; --map-road-4: #E2D6BF; --map-rail: #A89C88;
  --map-building: #E6DDCC; --map-river: #9DB9BB;
  /* elevation: two shadows only */
  --shadow-1: 0 1px 0 rgba(26, 30, 41, .05), 0 1px 3px rgba(26, 30, 41, .08);
  --shadow-2: 0 1px 2px rgba(26, 30, 41, .06), 0 10px 28px -6px rgba(26, 30, 41, .20);
  /* vellum grain: page background only (never cards, text wells, HUD, the game) */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .1 0 0 0 0 .12 0 0 0 0 .16 0 0 0 .06 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  /* logo files to use per theme */
  --logo-lockup-on-chrome: url(../img/brand/geoguess-lockup-reverse.svg);
}

/* ======================= NIGHT WATCH (dark): follows the OS ======================= */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --page: #0E141D; --card: #151D29; --raised: #1C2635; --sunken: #0A0F16;
    --hud: rgba(14, 20, 29, .92); --scrim: rgba(0, 0, 0, .6);
    --ink: #ECE5D6; --ink-2: #C4BCAB; --ink-3: #9C9486;
    --rule: #263142; --rule-2: #3C495D; --field: #68778E;
    --chrome: #121A2C; --chrome-2: #1C2740; --chrome-3: #26324F; --chrome-edge: #222C3B;
    --chrome-ink: #EDE6D6; --chrome-ink-2: #A9B0BF;
    --accent: #8FB2EA; --accent-hover: #A6C2EF; --accent-ink: #0E141D; --accent-soft: #1E2D45;
    --cta: #D6A64A; --cta-hover: #E2B45A; --cta-edge: #F0CE85; --cta-ink: #17120A;
    --brass: #D6A64A; --brass-ink: #DDB565;
    --win: #5CC2A6;  --win-soft: #12312B;
    --loss: #F07E60; --loss-soft: #3A1E17;
    --warn: #F2B84B; --warn-soft: #33280F;
    --info: #8FB2EA; --info-soft: #1E2D45;
    --self: #6F9BE0; --self-soft: #1A2A44;
    --opp: #E8694A;  --opp-soft: #3A1E17;
    --team-1: #6F9BE0; --team-2: #E8694A; --team-3: #5FCBBE; --team-4: #C9A0E0;
    --focus: #F2C46B;
    --tc-bullet: #F07E60; --tc-blitz: #E3A748; --tc-rapid: #5CC2A6; --tc-classical: #8FB2EA; --tc-daily: #CDA580;
    --depth-1: #172429; --depth-2: #172B33; --depth-3: #16313D; --depth-4: #153747;
    --depth-5: #143D52; --depth-6: #12435C; --depth-7: #104966; --depth-8: #0E4F71;
    --depth-ink: #ECE5D6; --depth-ink-2: #C4BCAB;
    --map-land: #1B2531; --map-water: #0C1B27; --map-coast: #B79A62; --map-waterline: rgba(183, 154, 98, .18);
    --map-border: #857A67; --map-border-4: #4A4A45; --map-grat: #24384A; --map-label: #CFC6B4;
    --map-label-2: #9A9284; --map-water-label: #7FA3BD; --map-grat-label: #C9A658; --map-halo: #1B2531;
    --map-wood: #1F2B2F; --map-ice: #253240; --map-sand: #2A2A24; --map-residential: #212B37; --map-park: #1E2B29;
    --map-road-1: #7A6F5C; --map-road-2: #6A6152; --map-road-3: #5B5446; --map-road-4: #4A463E; --map-rail: #5F6070;
    --map-building: #232D39; --map-river: #1E3A4C;
    --shadow-1: 0 1px 0 rgba(0, 0, 0, .3);
    --shadow-2: 0 12px 32px -8px rgba(0, 0, 0, .6);
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .9 0 0 0 0 .88 0 0 0 0 .8 0 0 0 .035 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  }
}

/* ======================= NIGHT WATCH (dark): manual override — keep identical to the block above ======================= */
:root[data-theme="dark"] {
  color-scheme: dark;
  --page: #0E141D; --card: #151D29; --raised: #1C2635; --sunken: #0A0F16;
  --hud: rgba(14, 20, 29, .92); --scrim: rgba(0, 0, 0, .6);
  --ink: #ECE5D6; --ink-2: #C4BCAB; --ink-3: #9C9486;
  --rule: #263142; --rule-2: #3C495D; --field: #68778E;
  --chrome: #121A2C; --chrome-2: #1C2740; --chrome-3: #26324F; --chrome-edge: #222C3B;
  --chrome-ink: #EDE6D6; --chrome-ink-2: #A9B0BF;
  --accent: #8FB2EA; --accent-hover: #A6C2EF; --accent-ink: #0E141D; --accent-soft: #1E2D45;
  --cta: #D6A64A; --cta-hover: #E2B45A; --cta-edge: #F0CE85; --cta-ink: #17120A;
  --brass: #D6A64A; --brass-ink: #DDB565;
  --win: #5CC2A6;  --win-soft: #12312B;
  --loss: #F07E60; --loss-soft: #3A1E17;
  --warn: #F2B84B; --warn-soft: #33280F;
  --info: #8FB2EA; --info-soft: #1E2D45;
  --self: #6F9BE0; --self-soft: #1A2A44;
  --opp: #E8694A;  --opp-soft: #3A1E17;
  --team-1: #6F9BE0; --team-2: #E8694A; --team-3: #5FCBBE; --team-4: #C9A0E0;
  --focus: #F2C46B;
  --tc-bullet: #F07E60; --tc-blitz: #E3A748; --tc-rapid: #5CC2A6; --tc-classical: #8FB2EA; --tc-daily: #CDA580;
  --depth-1: #172429; --depth-2: #172B33; --depth-3: #16313D; --depth-4: #153747;
  --depth-5: #143D52; --depth-6: #12435C; --depth-7: #104966; --depth-8: #0E4F71;
  --depth-ink: #ECE5D6; --depth-ink-2: #C4BCAB;
  --map-land: #1B2531; --map-water: #0C1B27; --map-coast: #B79A62; --map-waterline: rgba(183, 154, 98, .18);
  --map-border: #857A67; --map-border-4: #4A4A45; --map-grat: #24384A; --map-label: #CFC6B4;
  --map-label-2: #9A9284; --map-water-label: #7FA3BD; --map-grat-label: #C9A658; --map-halo: #1B2531;
  --map-wood: #1F2B2F; --map-ice: #253240; --map-sand: #2A2A24; --map-residential: #212B37; --map-park: #1E2B29;
  --map-road-1: #7A6F5C; --map-road-2: #6A6152; --map-road-3: #5B5446; --map-road-4: #4A463E; --map-rail: #5F6070;
  --map-building: #232D39; --map-river: #1E3A4C;
  --shadow-1: 0 1px 0 rgba(0, 0, 0, .3);
  --shadow-2: 0 12px 32px -8px rgba(0, 0, 0, .6);
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .9 0 0 0 0 .88 0 0 0 0 .8 0 0 0 .035 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- user preferences ---------- */
@media (prefers-contrast: more) {
  :root { --ink-3: var(--ink-2); --rule: var(--rule-2); --field: var(--ink-2); --grain: none; }
}
@media (prefers-reduced-motion: reduce) {
  :root { --t-fast: 0ms; --t-base: 0ms; --t-panel: 0ms; --t-reveal: 0ms; }
}
:root[data-grain="off"] { --grain: none; }
