/* ============================================================
   AI BUBBLE TYCOON — DESIGN TOKENS
   Vendored from the publisher canon `games/design/tokens.css` (v1.1), reduced
   to this game's theme and extended with the unlockable skins.

   Why vendored rather than shared: this is the first game in the series to
   ship, so there is exactly one consumer. When the second one lands, the
   component steward promotes this into a shared package with a passport --
   extracting a component for a single user is the mistake the catalogue exists
   to stop.

   Dark theme only. No raster asset. No external CDN. Interface language is
   English, per canon 1.
   ============================================================ */

:root {
  /* Self-hosted only. The canon notes that mockups load fonts from a CDN; the
     shipped site never does -- that is a CSP hole and a third-party request. */
  --font-ui: "Golos Text", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-6: 24px; --sp-8: 32px; --sp-12: 48px;
  --r-xs: 4px; --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-pill: 999px;

  --ink-900: #07090C; --ink-800: #0D1117; --ink-700: #151B23;
  --ink-600: #1E2630; --ink-500: #2A3441; --ink-400: #3A4756;

  --text-hi: #E8EDF3;   /* 16.6:1 on --ink-900 */
  --text-mid: #A3AEBC;  /*  8.7:1 */
  --text-low: #7B8899;  /*  5.4:1 — the series floor, never go under */
  --text-inv: #07090C;

  --ok: #2BE08A; --warn: #FFB020; --danger: #FF5C5C; --info: #5AD7E8;

  --shadow-1: 0 1px 2px rgba(0,0,0,.6);
  --shadow-2: 0 4px 16px rgba(0,0,0,.55);
  --shadow-3: 0 16px 48px rgba(0,0,0,.65);
  /* Glow is information: the level IS the priority. --glow-3 belongs to exactly
     one element on the screen, and in this game that element is the echo board. */
  --glow-1: 0 0 8px var(--glow-color, currentColor);
  --glow-2: 0 0 14px var(--glow-color, currentColor);
  --glow-3: 0 0 16px var(--glow-color, currentColor), 0 0 40px var(--glow-color, currentColor);

  --z-bg: 0; --z-board: 10; --z-actor: 20; --z-fx: 30;
  --z-hud: 40; --z-ticker: 50; --z-modal: 60; --z-toast: 70; --z-focus: 80;

  --fs-display: clamp(34px, 9vw, 56px); --lh-display: 1.02; --tr-display: -0.03em;
  --fs-hud: clamp(28px, 7.5vw, 44px); --lh-hud: 1.0; --tr-hud: -0.02em;
  --fs-title: 20px; --lh-title: 1.25; --tr-title: -0.01em;
  --fs-body: 15px; --lh-body: 1.5;
  --fs-caption: 12px; --lh-caption: 1.35; --tr-caption: 0.02em;
  --fs-label: 12px; --lh-label: 1.2; --tr-label: 0.12em;
  --fw-reg: 400; --fw-med: 500; --fw-bold: 700; --fw-black: 800;

  --dur-1: 90ms; --dur-2: 180ms; --dur-3: 320ms; --dur-4: 600ms;
  --ease-std: cubic-bezier(.2,.6,.2,1);
  --ease-in: cubic-bezier(.5,0,.9,.3);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);

  --focus-color: var(--t-accent, var(--info));
  --focus-ring: 0 0 0 2px var(--ink-900), 0 0 0 4px var(--focus-color);
  --tap-min: 44px;

  --game-bg: #06090B;
  --game-surface: #0E1417;
  --game-accent: var(--t-accent);
  --game-accent-ink: #040A07;

  --sl-grid: #16202A;
  /* Tokens carry shape AND colour, always together (canon 11). */
  --sl-token-ext: #35D07A;   /* external — CIRCLE */
  --sl-token-cred: #FF9134;  /* credit — SQUARE */
  --sl-token-emis: #B07CFF;  /* issued — TRIANGLE */

  /* Boring Industries is deliberately boring. The only non-neon element in the
     interface, and a joke that breaks the moment somebody prettifies it. */
  --sl-boring-fill: #D9CFC0;
  --sl-boring-ink: #2C2A26;
  --sl-boring-font: ui-sans-serif, system-ui, Arial, sans-serif;

  --game-critical: var(--t-accent);
}

/* ---- PANIC TEMPERATURES: three COMPLETE sets, separable in greyscale --------
   The greyscale separator is accent lightness PLUS --t-texture-op (background
   hatch density) plus --t-scanline. Colour is never the only carrier. */

[data-panic="calm"] {
  --t-name: "CALM";
  --t-accent: #2BE08A; --t-accent-dim: #17734A; --t-ink: #04120B;
  --t-surface: #0E1417; --t-surface-tint: rgba(43,224,138,.05); --t-line: #1B2F26;
  --t-glow: 0 0 10px rgba(43,224,138,.35);
  --t-texture-op: .04; --t-texture-gap: 14px; --t-scanline: 0s;
}
[data-panic="alert"] {
  --t-name: "ALERT";
  --t-accent: #FFB020; --t-accent-dim: #8A5C05; --t-ink: #170F02;
  --t-surface: #16130D; --t-surface-tint: rgba(255,176,32,.07); --t-line: #3A2C11;
  --t-glow: 0 0 14px rgba(255,176,32,.45);
  --t-texture-op: .10; --t-texture-gap: 9px; --t-scanline: 3.2s;
}
[data-panic="panic"] {
  --t-name: "PANIC";
  --t-accent: #FF5C5C; --t-accent-dim: #7A1414; --t-ink: #1A0505;
  --t-surface: #170C0C; --t-surface-tint: rgba(255,92,92,.10); --t-line: #4A1A1A;
  --t-glow: 0 0 18px rgba(255,92,92,.55), 0 0 40px rgba(255,92,92,.25);
  --t-texture-op: .18; --t-texture-gap: 6px; --t-scanline: 1.1s;
}

/* ============================================================
   SKINS — cosmetic only, unlocked by playing.
   A skin may never make the echo board or the panic temperature harder to
   read. The critical element wins in every skin; the three panic states stay
   separable in greyscale in every skin. That is checked, not assumed.
   ============================================================ */

/* Beige Industries. The whole interface in Boring Industries' beige, system
   font, zero glow. The best joke in the game. Do not prettify it. */
[data-skin="beige"] {
  --font-ui: var(--sl-boring-font);
  --font-mono: var(--sl-boring-font);
  --game-bg: #E8E2D6;
  --game-surface: #D9CFC0;
  --text-hi: #2C2A26;
  --text-mid: #4A463E;
  --text-low: #5E594F;
  --ink-900: #E8E2D6; --ink-800: #DED7C9; --ink-700: #D9CFC0;
  --ink-600: #CFC4B2; --ink-500: #B8AC98; --ink-400: #9C907C;
  --glow-1: none; --glow-2: none;
  --glow-3: 0 0 0 2px var(--t-accent);
  --t-glow: none;
  --t-surface: #D9CFC0;
  --shadow-1: none; --shadow-2: none; --shadow-3: 0 2px 6px rgba(0,0,0,.18);
  --t-texture-op: 0;
}
[data-skin="beige"][data-panic="calm"] { --t-accent: #2F6B4A; --t-accent-dim: #7FA891; --t-line: #B8AC98; }
[data-skin="beige"][data-panic="alert"] { --t-accent: #8A5C05; --t-accent-dim: #C4A96B; --t-line: #B8AC98; }
[data-skin="beige"][data-panic="panic"] { --t-accent: #8A1414; --t-accent-dim: #C48282; --t-line: #B8AC98; }

/* Dotcom '99. Web-safe blues, bevels, and a visitor counter that lies. */
[data-skin="dotcom"] {
  --game-bg: #000080;
  --game-surface: #0000B3;
  --ink-900: #000080; --ink-800: #000099; --ink-700: #0000B3;
  --ink-600: #1A1ACC; --ink-500: #3333E6; --ink-400: #6666FF;
  --text-hi: #FFFF00; --text-mid: #C0C0FF; --text-low: #9999DD;
  --r-xs: 0; --r-sm: 0; --r-md: 0; --r-lg: 0;
  --glow-1: none; --glow-2: none; --glow-3: 0 0 0 3px #FFFF00;
}
[data-skin="dotcom"][data-panic="calm"] { --t-accent: #00FF00; }
[data-skin="dotcom"][data-panic="alert"] { --t-accent: #FFFF00; }
[data-skin="dotcom"][data-panic="panic"] { --t-accent: #FF0000; }

/* Vaporwave 2049. Magenta and cyan, and everything slightly too slow. */
[data-skin="vapor"] {
  --game-bg: #14082A;
  --game-surface: #22103F;
  --ink-900: #14082A; --ink-800: #1B0C36; --ink-700: #22103F;
  --ink-600: #301656; --ink-500: #472176; --ink-400: #6B33A8;
  --text-hi: #F5E6FF; --text-mid: #C9A6E8; --text-low: #A57FD0;
  --dur-3: 480ms; --dur-4: 900ms;
}
[data-skin="vapor"][data-panic="calm"] { --t-accent: #5AF5E8; --t-accent-dim: #1F7A73; }
[data-skin="vapor"][data-panic="alert"] { --t-accent: #FF8FE0; --t-accent-dim: #8A2E76; }
[data-skin="vapor"][data-panic="panic"] { --t-accent: #FF4D6D; --t-accent-dim: #7A1428; }

/* Receipt Printer. Monochrome dot-matrix; the whole UI as perforated paper. */
[data-skin="receipt"] {
  --font-ui: var(--font-mono);
  --game-bg: #F2EFE6;
  --game-surface: #FAF8F2;
  --ink-900: #F2EFE6; --ink-800: #EDE9DE; --ink-700: #FAF8F2;
  --ink-600: #E4DFD2; --ink-500: #C7C0AE; --ink-400: #A39B87;
  --text-hi: #1A1A1A; --text-mid: #3D3D3D; --text-low: #5C5C5C;
  --glow-1: none; --glow-2: none; --glow-3: 0 0 0 2px #1A1A1A;
  --shadow-1: none; --shadow-2: none; --shadow-3: none;
  --t-texture-op: 0;
}
[data-skin="receipt"][data-panic="calm"] { --t-accent: #2F6B4A; }
[data-skin="receipt"][data-panic="alert"] { --t-accent: #7A5200; }
[data-skin="receipt"][data-panic="panic"] { --t-accent: #8A1414; }

/* Temperature transitions smoothly, but the STATE is never ambiguous: the
   state label and the hatch density switch discretely at the midpoint. */
.scene * {
  transition: color var(--dur-4) var(--ease-std),
              background-color var(--dur-4) var(--ease-std),
              border-color var(--dur-4) var(--ease-std),
              box-shadow var(--dur-4) var(--ease-std);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--game-bg);
  color: var(--text-hi);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
.num, [data-num] {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.label {
  font-family: var(--font-mono); font-size: var(--fs-label); line-height: var(--lh-label);
  letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--text-low);
}
:where(a, button, [tabindex], input, select, summary):focus-visible {
  outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-sm);
}
a { color: var(--t-accent); text-decoration: none; border-bottom: 1px solid currentColor; }
a:hover { color: var(--text-hi); }

/* REDUCED MOTION. Series rule: movement becomes an instant state change or an
   opacity cross-fade. NO fallback is allowed to remove information. The .rm-on
   class mirrors the media query so the settings toggle works without a reload. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}
.rm-on *, .rm-on *::before, .rm-on *::after {
  animation-duration: .01ms !important; animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
}
