/* =========================================================================
   3D PROTAGON PUZZLES — DESIGN SYSTEM
   -------------------------------------------------------------------------
   Single source of truth for colour, type, space, elevation, radius and
   motion. Loaded FIRST on every page (Navigation::criticalStylesheets()).

   Webfonts live in public/css/fonts.css, emitted immediately before this file.
   They used to be pulled in with an @import from fonts.googleapis.com here;
   that made all text wait on a third-party DNS lookup + TLS handshake + two
   serial round trips before the first glyph could paint, so it was replaced
   with self-hosted, preloaded, metric-matched faces.

   ── DIRECTION: "PETROL & PARCHMENT" ─────────────────────────────────────
   A puzzle printed on good paper, with a two-family accent system that encodes
   the thing that actually makes this site different: it is both 2D and 3D.

     • Surfaces   warm parchment, low glare — kind to the eyes across the long
                  sessions that logic and jigsaw puzzles demand.
     • Ink        deep petrol rather than neutral grey, so type carries a faint
                  colour temperature and the brand reads as "depth", not "blog".
     • Ochre      2D family (word, logic) — paper-and-pencil warmth.
     • Petrol     3D family (spatial, cube, first-person) — cool, dimensional.
     • Action     a single accent colour per theme that works in BOTH roles it
                  is asked to fill: as a filled button surface (+ its contrast
                  ink) and as text on every surface. That constraint is what
                  keeps the palette from drifting into unreadable accents.

   Every colour below is verified with the WCAG 2.2 contrast maths rather than
   chosen by eye; the measured ratio for each pairing is recorded inline and the
   whole set is re-checked by tools/qa/palette.py. Light theme anchors on the
   darkest surface (--bg-2) for text, because that is the worst case.

   Strategy: the legacy token names used across the existing stylesheets
   (--bg-0, --text, --brand, --panel, --line, --ok/--warn/--danger, --radius,
   --shadow-*) are all redefined here, so those rules inherit the new system
   without a per-file rewrite.

   Zero functional change: this file is presentational only.
   ========================================================================= */

/* ───────────────────────────────────────────────────────────────────────
   1. TYPE FAMILIES  (Shared across themes — the fallback faces are
      metric-matched to the webfonts so swapping causes no layout shift.)
   ─────────────────────────────────────────────────────────────────────── */
:root {
    --font-display: 'Fraunces', 'Fraunces Fallback', 'Fraunces Serif Fallback', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
    --font-body:    'Figtree', 'Figtree Fallback', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --font-mono:    'JetBrains Mono', 'JetBrains Mono Fallback', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
}

/* ───────────────────────────────────────────────────────────────────────
   2. DARK THEME — "Ink"  (the :root default; the early inline script
      always sets data-theme, this just covers any unmapped state)
   ─────────────────────────────────────────────────────────────────────── */
:root {
    /* Surfaces */
    --bg-0: #12181A;                       /* deep petrol ink */
    --bg-1: #1A2124;                       /* raised */
    --bg-2: #232C30;                       /* higher raised / inset */
    --panel: rgba(26, 33, 36, 0.92);
    --panel-soft: rgba(35, 44, 48, 0.80);
    --line: rgba(237, 232, 220, 0.14);     /* hairline */

    /* Text — 13.6:1 / 7.6:1 / 13.9:1 against --bg-0 */
    --text: #EDE8DC;                       /* warm parchment */
    --text-strong: #F6F2E9;
    --text-muted: #A6B0AE;                 /* 7.65:1 on --bg-1 */

    /* Action. In dark mode the accent is luminous, so its ink is near-black.
       This single colour is valid as a button surface, as a link and as an
       icon colour: 9.05:1 as text on --bg-0, 9.52:1 against its own ink. */
    --accent: #5FC9C0;
    --accent-hover: #7EDBD1;
    --accent-contrast: #0D1416;
    --brand: var(--accent);
    --brand-2: #E8A24A;                    /* ochre counterpoint */
    --link: var(--accent);
    --link-hover: var(--accent-hover);

    /* Semantic — each ≥5.3:1 as text on both --bg-0 and --bg-1 */
    --ok: #74C46A;
    --warn: #E8B44A;
    --danger: #E8705C;

    /* Category identity — 2D family warm, 3D family cool */
    --cat-word: #E8A24A;                   /* 7.54:1 on --bg-1 */
    --cat-logic: #D9C08A;                  /* 9.21:1 on --bg-1 */
    --cat-spatial: #5FC9C0;                /* 8.24:1 on --bg-1 */

    /* Ink that sits on a filled accent/badge chip */
    --on-accent: var(--accent-contrast);

    /* Chrome (header / footer) — previously hard-coded inside
       Navigation::injectNavStyles(), now part of the system. */
    --nav-bg: rgba(18, 24, 26, 0.86);
    --nav-border: rgba(237, 232, 220, 0.12);
    --nav-text: var(--text);
    --nav-muted: var(--text-muted);
    --nav-hover-bg: rgba(95, 201, 192, 0.10);
    --nav-active-bg: rgba(95, 201, 192, 0.16);
    --nav-active-text: var(--accent);
    --nav-highlight: linear-gradient(96deg, #7EDBD1, #5FC9C0);

    /* Legacy aliases kept so older rules keep resolving */
    --paper: var(--text);
    --ink: var(--bg-0);
    --rule: var(--line);

    /* ── Space ──────────────────────────────────────────────────────── */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 1rem;
    --space-4: 1.5rem;
    --space-5: 2rem;
    --space-6: 3rem;
    --space-7: 4rem;

    /* ── Radius ─────────────────────────────────────────────────────── */
    --radius-xs: 6px;
    --radius-sm: 10px;
    --radius: 14px;
    --radius-lg: 20px;
    --radius-xl: 28px;
    --radius-pill: 999px;

    /* ── Elevation ──────────────────────────────────────────────────── */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25);
    --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 20px 44px rgba(0, 0, 0, 0.55);
    --surface-grad: linear-gradient(180deg, rgba(237, 232, 220, 0.03), rgba(237, 232, 220, 0));
    --edge-glow: 0 0 0 1px var(--line);

    /* ── Type scale (fluid where it earns it) ───────────────────────── */
    --fs-display: clamp(2.75rem, 6vw, 4.5rem);
    --fs-h1:      clamp(2rem, 4vw, 3rem);
    --fs-h2:      clamp(1.6rem, 3vw, 2.125rem);
    --fs-h3:      1.4rem;
    --fs-body-lg: 1.1875rem;
    --fs-body:    1.0625rem;
    --fs-sm:      0.875rem;
    --fs-eyebrow: 0.75rem;

    /* ── Motion ─────────────────────────────────────────────────────── */
    --ease-out: cubic-bezier(0.22, 0.68, 0, 1);
    --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
    --dur-fast: 0.15s;
    --dur: 0.22s;
    --dur-slow: 0.4s;

    /* Graph-paper texture — hero/atmosphere only, never behind body text. */
    --grid-texture:
        linear-gradient(var(--line) 1px, transparent 1px),
        linear-gradient(90deg, var(--line) 1px, transparent 1px);
    --grid-size: 30px;

    --focus-ring: 0 0 0 3px rgba(95, 201, 192, 0.55);
}

/* ───────────────────────────────────────────────────────────────────────
   3. LIGHT THEME — "Parchment"
   ─────────────────────────────────────────────────────────────────────── */
html[data-theme="light"] {
    /* Surfaces */
    --bg-0: #F4F1E9;                       /* parchment */
    --bg-1: #FCFAF5;                       /* raised card */
    --bg-2: #E7E2D5;                       /* inset / divider */
    --panel: rgba(252, 250, 245, 0.96);
    --panel-soft: rgba(244, 241, 233, 0.90);
    --line: #DCD5C6;

    /* Text — 12.9:1 / 6.2:1 / 5.6:1 against --bg-2 (worst case) */
    --text: #1E262A;
    --text-strong: #12181B;
    --text-muted: #5A6469;                 /* 5.32:1 on --bg-2, 6.3:1 on --bg-0 */

    /* Action. Deep petrol: 8.80:1 as text on --bg-0, 9.93:1 against white ink,
       so one value serves the filled button and the text/link role. */
    --accent: #0E4A50;
    --accent-hover: #0A383D;
    --accent-contrast: #FFFFFF;
    --brand: var(--accent);
    --brand-2: #0F6E78;                    /* petrol-teal counterpoint */
    --link: var(--accent);
    --link-hover: var(--accent-hover);

    /* Semantic — ≥5.5:1 as text on --bg-0, ≥5.9:1 on --bg-1 */
    --ok: #3E6B33;
    --warn: #7A5A22;
    --danger: #9C3A32;

    /* Category identity — 2D family warm ochre, 3D family petrol-teal */
    --cat-word: #A94D08;                   /* 4.96:1 on --bg-0 */
    --cat-logic: #6E5220;                  /* 6.44:1 on --bg-0 */
    --cat-spatial: #0F6E78;                /* 5.28:1 on --bg-0 */

    --on-accent: var(--accent-contrast);

    /* Chrome */
    --nav-bg: rgba(252, 250, 245, 0.88);
    --nav-border: rgba(30, 38, 42, 0.10);
    --nav-text: var(--text);
    --nav-muted: var(--text-muted);
    --nav-hover-bg: rgba(14, 74, 80, 0.07);
    --nav-active-bg: rgba(14, 74, 80, 0.12);
    --nav-active-text: var(--accent);
    --nav-highlight: linear-gradient(96deg, #0E4A50, #0F6E78);

    --paper: var(--text);
    --ink: var(--bg-0);
    --rule: var(--line);

    /* ── Elevation (softer, warmer in light mode) ───────────────────── */
    --shadow-sm: 0 1px 2px rgba(30, 38, 42, 0.06);
    --shadow-md: 0 6px 18px rgba(30, 38, 42, 0.08);
    --shadow-lg: 0 18px 40px rgba(30, 38, 42, 0.12);
    --surface-grad: linear-gradient(180deg, rgba(252, 250, 245, 0.6), rgba(252, 250, 245, 0));
    --edge-glow: 0 0 0 1px var(--line);

    --focus-ring: 0 0 0 3px rgba(14, 74, 80, 0.40);
}

/* ───────────────────────────────────────────────────────────────────────
   4. BASE ELEMENTS
   These deliberately match the specificity of, and load after, the legacy
   stylesheets' html/body rules so the flat parchment surface always wins
   over the old radial-gradient page background.
   ─────────────────────────────────────────────────────────────────────── */
html,
body {
    background-color: var(--bg-0);
}

html[data-theme="light"] body,
html[data-theme="dark"] body,
body {
    background-image: none;
    background-attachment: scroll;
}

body {
    font-family: var(--font-body);
    /* tnum keeps numbers from reflowing inside grids, timers and score tables */
    font-feature-settings: 'kern' 1, 'liga' 1, 'tnum' 1;
    color: var(--text);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Headings carry the editorial display face; headlines do the visual work
   rather than leaning on stock imagery. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-optical-sizing: auto;
    font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--text-strong);
    line-height: 1.08;
    text-wrap: balance;
}

p {
    text-wrap: pretty;
}

/* Anchors scroll clear of the sticky header instead of underneath it. */
html {
    scroll-padding-top: calc(var(--site-header-height, 64px) + 12px);
}

/* Tabular figures wherever numbers live in a grid, timer or score. */
.puzzle-grid,
.grid-cell,
.cell,
[class*="sudoku"],
[class*="crossword"] {
    font-variant-numeric: tabular-nums;
}

/* Links: the accent colour already clears 4.5:1 on every surface in both
   themes, so no per-theme override is needed. */
a {
    color: var(--link);
}
a:hover {
    color: var(--link-hover);
}

/* Selection echoes the accent. */
::selection {
    background: color-mix(in srgb, var(--accent) 30%, transparent);
    color: var(--text-strong);
}

/* ───────────────────────────────────────────────────────────────────────
   5. ACCESSIBILITY — focus visibility + reduced motion
   ─────────────────────────────────────────────────────────────────────── */
:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-xs);
}

/* Pause/disable all non-essential motion for users who ask for it. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}
