/* ===========================================================================
   Number Merge — design tokens
   The single source of truth. See DESIGN.md for the reasoning behind each
   decision. Nothing below should be overridden ad hoc in component files;
   add a token instead.
   =========================================================================== */

/* --- Self-hosted faces. Both subset to latin, both precached by the SW. --- */

@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/CabinetGrotesk-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/CabinetGrotesk-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/CabinetGrotesk-800.woff2') format('woff2');
  font-weight: 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Spline Sans Mono';
  src: url('../assets/fonts/SplineSansMono-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Spline Sans Mono';
  src: url('../assets/fonts/SplineSansMono-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Spline Sans Mono';
  src: url('../assets/fonts/SplineSansMono-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  /* --- Surfaces -------------------------------------------------------- */
  /* Deep cool slate. Tinted (not chroma-0) because the scene is a lit room. */
  --room:        oklch(0.185 0.014 265);
  --room-deep:   oklch(0.150 0.014 265);   /* vignette floor */
  --tray:        oklch(0.145 0.016 265);
  --tray-edge:   oklch(0.115 0.016 265);
  --surface-cell:        oklch(0.215 0.012 265);
  --surface-cell-alt:    oklch(0.235 0.012 265);
  --raised:      oklch(0.245 0.014 265);
  --raised-hi:   oklch(0.295 0.014 265);
  --hairline:    oklch(1 0 0 / 0.08);
  --glow:        oklch(0.30 0.030 265 / 0.55);  /* pool of light behind the board */

  /* --- Ink -------------------------------------------------------------- */
  --ink:         oklch(0.980 0.005 265);
  --ink-dim:     oklch(0.760 0.012 265);   /* 4.5:1+ on --raised */
  --ink-faint:   oklch(0.600 0.012 265);   /* decorative / disabled only */

  /* --- Accents ---------------------------------------------------------- */
  --accent:      oklch(0.820 0.140 172);   /* teal — best score, positive */
  --accent-ink:  oklch(0.300 0.070 172);
  --accent-warm: oklch(0.820 0.160 78);    /* amber — undo, hold, resources */
  --accent-warm-ink: oklch(0.320 0.090 70);
  --danger:      oklch(0.630 0.200 25);
  --danger-soft: oklch(0.630 0.200 25 / 0.16);

  /* --- Block palette ----------------------------------------------------
     2–64 are the source game's own hues (verified twice: sampled from the
     reference screenshot and re-sampled from a texture inside the APK).
     128+ are ours — they are generated in code in the original and are not
     recoverable. Each tier carries a matching dark shade used for the
     numeral shadow and the block's lower inner edge.                       */
  --t2:      oklch(0.710 0.160 20);    --t2-dk:    oklch(0.420 0.150 20);
  --t4:      oklch(0.630 0.200 300);   --t4-dk:    oklch(0.360 0.170 300);
  --t8:      oklch(0.830 0.170 85);    --t8-dk:    oklch(0.520 0.150 75);
  --t16:     oklch(0.760 0.160 138);   --t16-dk:   oklch(0.450 0.130 138);
  --t32:     oklch(0.770 0.130 235);   --t32-dk:   oklch(0.450 0.140 245);
  --t64:     oklch(0.800 0.110 60);    --t64-dk:   oklch(0.500 0.130 50);
  --t128:    oklch(0.680 0.210 350);   --t128-dk:  oklch(0.400 0.180 350);
  --t256:    oklch(0.790 0.130 195);   --t256-dk:  oklch(0.460 0.120 200);
  --t512:    oklch(0.600 0.190 278);   --t512-dk:  oklch(0.340 0.160 278);
  --t1024:   oklch(0.780 0.180 65);    --t1024-dk: oklch(0.470 0.160 58);
  --t2048:   oklch(0.930 0.100 175);   --t2048-dk: oklch(0.420 0.120 180);
  --t4096:   oklch(0.600 0.220 22);    --t4096-dk: oklch(0.340 0.180 22);
  --t8192:   oklch(0.870 0.210 128);   --t8192-dk: oklch(0.450 0.160 130);
  --tmax:    oklch(0.960 0.040 265);   --tmax-dk:  oklch(0.400 0.060 265);

  /* --- Special blocks (Loaded mode) --------------------------------------
     Deliberately outside the numeric hue cycle so they can never be mistaken
     for a value. Each one telegraphs its job before you read anything: the
     wild is bright and precious, the bomb is dark and hot, the stone is dead
     matte with no highlight at all.                                        */
  --t-wild:  oklch(0.930 0.075 305);   --t-wild-dk:  oklch(0.520 0.140 300);
  --t-bomb:  oklch(0.330 0.030 20);    --t-bomb-dk:  oklch(0.200 0.030 20);
  --t-stone: oklch(0.480 0.006 265);   --t-stone-dk: oklch(0.330 0.006 265);

  /* --- Type ------------------------------------------------------------- */
  --font-display: 'Cabinet Grotesk', ui-rounded, 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'Spline Sans Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.375rem;
  --text-2xl:  1.75rem;
  --text-3xl:  2.25rem;
  --text-4xl:  3rem;

  --tracking-tight: -0.02em;
  --tracking-wide:   0.06em;

  /* --- Space (4px base) -------------------------------------------------- */
  --s-1: 0.125rem; --s-2: 0.25rem;  --s-3: 0.375rem; --s-4: 0.5rem;
  --s-6: 0.75rem;  --s-8: 1rem;     --s-10: 1.25rem; --s-12: 1.5rem;
  --s-16: 2rem;    --s-20: 2.5rem;  --s-24: 3rem;    --s-32: 4rem;

  /* --- Radius ----------------------------------------------------------- */
  /* Block radius is a percentage so it scales correctly at any board size. */
  --radius-block: 22%;
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-tray: 26px;
  --radius-pill: 999px;

  /* --- Depth ------------------------------------------------------------ */
  --shadow-block: 0 3px 0 0 var(--block-dk, oklch(0 0 0 / 0.4)),
                  0 6px 14px -4px oklch(0 0 0 / 0.55);
  --shadow-panel: 0 2px 4px oklch(0 0 0 / 0.3), 0 16px 40px -12px oklch(0 0 0 / 0.6);
  --shadow-pill:  inset 0 1px 0 oklch(1 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.4);
  --inset-tray:   inset 0 3px 10px oklch(0 0 0 / 0.55), inset 0 -1px 0 oklch(1 0 0 / 0.05);

  /* --- Motion ----------------------------------------------------------- */
  /* Gravity accelerates: the one place the ease-out rule is inverted. */
  --ease-fall:       cubic-bezier(0.42, 0, 0.70, 0.42);  /* quadratic-in = constant acceleration */
  --ease-out-quint:  cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo:   cubic-bezier(0.16, 1, 0.30, 1);

  --dur-fast: 95ms;
  --dur:      150ms;
  --dur-slow: 260ms;
  --dur-fall-base: 85ms;      /* render.js: fall = 85ms x sqrt(rows), floor 75ms */

  /* --- Z scale ---------------------------------------------------------- */
  --z-board: 1; --z-block: 2; --z-fx: 3; --z-hud: 10;
  --z-backdrop: 40; --z-dialog: 50; --z-toast: 60;

  /* --- Board geometry (JS may override --cols/--rows) -------------------- */
  --cols: 5;
  --rows: 5;
  --gap: clamp(4px, 1.1vmin, 8px);
  color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   Alternate block themes. The shell never changes — only the block hues do,
   so the room always reads the same and only the "lit" objects re-skin.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Alternate block palettes.

   These are three genuinely different SYSTEMS, not one palette with the
   saturation knob turned. Arcade encodes value as HUE (a designed cycle, the
   source game's own identity — no ordering information, you learn it). Ember
   and Tide encode value as LIGHTNESS along a single temperature ramp, so a
   brighter block is always a bigger block and you can read the state of the
   board without reading a single numeral. That is a different way to play, not
   a different tint.

   The special blocks deliberately do NOT re-skin. They are functional, not
   decorative, and a Bomb must look like a Bomb in every theme.
   --------------------------------------------------------------------------- */

/* Ember — a heat ramp. Cold dark oxblood at the bottom, white-hot at the top. */
[data-theme='ember'] {
  --room:      oklch(0.170 0.014 30);
  --room-deep: oklch(0.130 0.014 30);
  --tray:      oklch(0.135 0.016 30);
  --tray-edge: oklch(0.105 0.016 30);
  --surface-cell:     oklch(0.205 0.012 30);
  --surface-cell-alt: oklch(0.228 0.012 30);
  --raised:    oklch(0.240 0.014 30);
  --raised-hi: oklch(0.290 0.014 30);
  --glow:      oklch(0.34 0.070 35 / 0.55);

  --t2:      oklch(0.395 0.120 15);   --t2-dk:    oklch(0.235 0.085 15);
  --t4:      oklch(0.455 0.160 22);   --t4-dk:    oklch(0.275 0.115 22);
  --t8:      oklch(0.480 0.180 25);   --t8-dk:    oklch(0.290 0.130 25);
  --t16:     oklch(0.560 0.200 32);   --t16-dk:   oklch(0.340 0.150 32);
  --t32:     oklch(0.640 0.200 42);   --t32-dk:   oklch(0.400 0.160 42);
  --t64:     oklch(0.710 0.190 55);   --t64-dk:   oklch(0.450 0.160 55);
  --t128:    oklch(0.780 0.180 68);   --t128-dk:  oklch(0.500 0.150 68);
  --t256:    oklch(0.840 0.170 80);   --t256-dk:  oklch(0.540 0.145 80);
  --t512:    oklch(0.890 0.150 90);   --t512-dk:  oklch(0.570 0.130 90);
  --t1024:   oklch(0.930 0.130 96);   --t1024-dk: oklch(0.600 0.115 96);
  --t2048:   oklch(0.965 0.080 100);  --t2048-dk: oklch(0.620 0.090 100);
  --t4096:   oklch(0.985 0.040 100);  --t4096-dk: oklch(0.640 0.060 100);
  --t8192:   oklch(0.995 0.015 100);  --t8192-dk: oklch(0.660 0.030 100);
  --tmax:    oklch(1.000 0.000 0);    --tmax-dk:  oklch(0.680 0.010 100);
}

/* Tide — the cold mirror. Deep indigo at the bottom, pale mint at the top. */
[data-theme='tide'] {
  --room:      oklch(0.170 0.016 255);
  --room-deep: oklch(0.130 0.016 255);
  --tray:      oklch(0.135 0.018 255);
  --tray-edge: oklch(0.105 0.018 255);
  --surface-cell:     oklch(0.205 0.014 255);
  --surface-cell-alt: oklch(0.228 0.014 255);
  --raised:    oklch(0.240 0.016 255);
  --raised-hi: oklch(0.290 0.016 255);
  --glow:      oklch(0.32 0.060 245 / 0.55);

  --t2:      oklch(0.405 0.110 278);  --t2-dk:    oklch(0.240 0.080 278);
  --t4:      oklch(0.470 0.145 272);  --t4-dk:    oklch(0.285 0.105 272);
  --t8:      oklch(0.500 0.150 262);  --t8-dk:    oklch(0.300 0.115 262);
  --t16:     oklch(0.580 0.150 248);  --t16-dk:   oklch(0.350 0.115 248);
  --t32:     oklch(0.650 0.140 232);  --t32-dk:   oklch(0.400 0.110 232);
  --t64:     oklch(0.720 0.130 214);  --t64-dk:   oklch(0.450 0.105 214);
  --t128:    oklch(0.780 0.130 196);  --t128-dk:  oklch(0.490 0.105 196);
  --t256:    oklch(0.830 0.130 182);  --t256-dk:  oklch(0.530 0.110 182);
  --t512:    oklch(0.880 0.120 170);  --t512-dk:  oklch(0.560 0.105 170);
  --t1024:   oklch(0.920 0.110 160);  --t1024-dk: oklch(0.590 0.095 160);
  --t2048:   oklch(0.960 0.070 155);  --t2048-dk: oklch(0.610 0.075 155);
  --t4096:   oklch(0.980 0.040 150);  --t4096-dk: oklch(0.630 0.050 150);
  --t8192:   oklch(0.995 0.015 150);  --t8192-dk: oklch(0.650 0.025 150);
  --tmax:    oklch(1.000 0.000 0);    --tmax-dk:  oklch(0.670 0.010 150);
}

/* On both ramps the top half of the scale is too light to carry white text,
   so those tiers take dark ink drawn from their own shade. */
[data-theme='ember'] .block[data-tier="256"]  .block__num,
[data-theme='ember'] .block[data-tier="512"]  .block__num,
[data-theme='ember'] .block[data-tier="1024"] .block__num,
[data-theme='ember'] .block[data-tier="4096"] .block__num,
[data-theme='ember'] .block[data-tier="8192"] .block__num,
[data-theme='tide']  .block[data-tier="256"]  .block__num,
[data-theme='tide']  .block[data-tier="512"]  .block__num,
[data-theme='tide']  .block[data-tier="1024"] .block__num,
[data-theme='tide']  .block[data-tier="4096"] .block__num,
[data-theme='tide']  .block[data-tier="8192"] .block__num {
  color: var(--block-dk);
  text-shadow: 0 calc(var(--cell) * 0.02) 0 oklch(1 0 0 / 0.3);
}

/* --- Reduced motion: collapse, never remove ------------------------------ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --ease-fall: linear;
    --dur-fast: 1ms;
    --dur: 90ms;
    --dur-slow: 90ms;
  }
}
