/* WEFT design tokens — single source (Constitution §5). No magic values in components. */

/* Self-hosted fonts. Loading these from fonts.googleapis.com sent every visitor's IP to
   Google, which LG Munchen I (3 O 17493/20, 2022) found unlawful without consent for German
   visitors — and this app is aimed at German learners. Serving them ourselves also drops a
   render-blocking third-party stylesheet and lets the service worker cache them offline,
   which it could not do while they were cross-origin.
   Only the `latin` subset is shipped; it already covers a o u umlauts and eszett.
   Licence: fonts/OFL.txt. */

/* Archivo is a VARIABLE font: one file serves 400/500/600, so the browser interpolates real
   weights instead of synthesising them. Hence a weight RANGE, not three @font-face blocks. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./fonts/archivo-400-500-600.woff2") format("woff2");
}

/* IBM Plex Mono ships static instances, so each weight is its own file. */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./fonts/ibm-plex-mono-400.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./fonts/ibm-plex-mono-500.woff2") format("woff2");
}

:root {
  /* Spacing — 4px base */
  --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;

  /* Radii */
  --radius-xs: 4px;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-pill: 999px;

  /* Motion */
  --duration-fast: 120ms;
  --duration-normal: 200ms;
  --duration-slow: 300ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);

  /* Typography */
  --font: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", "SF Mono", Menlo, Consolas, monospace;
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-lg: 20px;
  --text-xl: 24px;
  --text-2xl: 32px;
  --text-3xl: 44px;

  /* Layout */
  --header-h: 56px;
  --footer-h: 56px;
  --rail-w: 240px;
  --learn-w: 380px;
  --app-max: 1440px;
  /* Legibility floor, NOT a tap-target floor. This was 48px and was enforced as a hard
     minimum, which forced a 7x7 grid wider than a 390px phone and put the last column out of
     reach entirely. A 42px cell you can touch beats a 48px cell you cannot. See fitTileSize()
     in lib/weft-core.js. */
  --tile-min: 28px;
  --touch-min: 44px;
  --shadow-raised: 0 8px 32px oklch(0% 0 0 / 0.35);

  /* Dark theme (default — Constitution: dark base retained).
     color-scheme has to be declared here, not only under [data-theme="dark"]: the toggle turns
     dark on by REMOVING the attribute, so that selector never matched in the default state and
     the browser kept painting scrollbars, form controls and the tap-highlight light-on-dark. */
  color-scheme: dark;
  --bg: oklch(14% 0.01 80);
  --surface: oklch(18% 0.01 80);
  --surface-raised: oklch(22% 0.012 80);
  --text: oklch(94% 0.02 85);
  --text-muted: oklch(72% 0.02 80);
  --line-ui: oklch(28% 0.015 80);
  --accent: oklch(78% 0.12 180);
  --accent-soft: oklch(28% 0.06 180);
  --accent-path: color-mix(in oklch, var(--accent) 22%, transparent);
  --danger: oklch(72% 0.16 25);
  --success: oklch(72% 0.12 155);
  --overlay: oklch(8% 0 0 / 0.85);
  --tile: oklch(20% 0.01 80);
  --tile-border: oklch(32% 0.015 80);
  --tile-hover: oklch(24% 0.012 80);
  --selected-ink: oklch(12% 0.01 80);
  --line: var(--accent);

  /* Word identity — OKLCH ~0.75 L */
  --word-1: oklch(75% 0.11 185);
  --word-2: oklch(75% 0.13 55);
  --word-3: oklch(75% 0.11 135);
  --word-4: oklch(75% 0.11 295);
  --word-5: oklch(75% 0.13 90);
  --word-6: oklch(75% 0.11 350);

  --chip-streak: oklch(32% 0.08 75);
  --chip-streak-ink: oklch(88% 0.12 90);

  /* Legacy aliases (Phase 1–2 migration) */
  --surface-elevated: var(--surface-raised);
  --ink: var(--text);
  --muted: var(--text-muted);
  --faint: oklch(58% 0.02 80);
  --error: var(--danger);
  --wall: transparent;
  --w1: var(--word-1);
  --w2: var(--word-2);
  --w3: var(--word-3);
  --w4: var(--word-4);
  --w5: var(--word-5);
  --w6: var(--word-6);
  --radius: var(--radius-sm);
  --radius-lg: var(--radius-md);
}

/* Hell — designed light theme (not inverted) */
[data-theme="hell"] {
  color-scheme: light;
  --bg: oklch(97% 0.02 85);
  --surface: oklch(99% 0.01 85);
  --surface-raised: oklch(100% 0 0);
  --text: oklch(22% 0.02 80);
  --text-muted: oklch(48% 0.02 80);
  --line-ui: oklch(88% 0.02 85);
  --accent: oklch(42% 0.08 200);
  --accent-soft: oklch(90% 0.04 180);
  --accent-path: color-mix(in oklch, var(--accent) 18%, transparent);
  --danger: oklch(48% 0.18 25);
  --success: oklch(42% 0.1 155);
  --overlay: oklch(18% 0 0 / 0.72);
  --tile: oklch(99% 0.01 85);
  --tile-border: oklch(88% 0.02 85);
  --tile-hover: oklch(94% 0.02 85);
  --selected-ink: oklch(99% 0.01 85);
  --faint: oklch(62% 0.02 80);
  --chip-streak: oklch(94% 0.08 90);
  --chip-streak-ink: oklch(42% 0.12 75);
  --shadow-raised: 0 8px 24px oklch(30% 0.02 80 / 0.12);

  /* Word identity has to be redefined for light, not inherited. The dark set sits at 75%
     lightness, which is legible on a 14% background and nearly invisible on a 97% one — it
     took out the wordmark (a gradient with `color: transparent`) and, worse, the colour that
     tells the player WHICH word each rail chip belongs to. Same hues, dropped to 52% so they
     read as ink rather than as highlighter. */
  --word-1: oklch(52% 0.11 185);
  --word-2: oklch(52% 0.14 55);
  --word-3: oklch(52% 0.11 135);
  --word-4: oklch(52% 0.13 295);
  --word-5: oklch(52% 0.13 90);
  --word-6: oklch(52% 0.13 350);
}

/* Legacy: previous builds used data-theme="dark" on light default */
[data-theme="dark"] {
  color-scheme: dark;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-normal: 0ms;
    --duration-slow: 0ms;
  }
}
