/* =====================================================
   CHROMA 12 — style.css
   Single source of all visual styles.
   CSS custom properties defined at :root — never duplicate these elsewhere.
   ===================================================== */

/* ── 1. CUSTOM PROPERTIES ── */
:root {
  /* Block colors — desaturated pastels, clearly distinct, never jarring */
  --color-blue:   #9ACFE8;
  --color-yellow: #F5D98A;
  --color-green:  #9ECFB5;
  --color-red:    #EEAAAA;

  /* UI colors — light theme */
  --bg:            #F5F0EB;
  --bg-card:       #FFFFFF;
  --bg-ability:    rgba(0, 0, 0, 0.055);
  --text-primary:  #2C2C2E;
  --text-secondary: #8E8E93;
  --text-on-block: rgba(45, 28, 12, 0.58);
  --border:        rgba(0, 0, 0, 0.08);
  --shadow:        rgba(0, 0, 0, 0.10);
  --color-alert:   #EE5A52;
  --color-warn:    #E8A246;

  /* Grid visual — gridlines are the grid container bg showing through gaps+padding */
  --grid-bg:       #C5BDB4;
  --grid-cell-bg:  rgba(253, 251, 249, 0.94);

  /* Layout — vertical chrome is DERIVED below (no hardcoded offset to keep in sync). */
  --hud-top-height:    104px;
  --hud-bottom-height: clamp(86px, 11vh, 110px); /* fluid: 110 on tall desktops (11vh term), shrinks toward 86 on short laptop viewports to free grid height. Touch overrides to 140 below. */
  --outer-pad-h:       34px;   /* game-area left/right padding */
  --pill-toast-bg:     rgba(44, 44, 46, 0.88); /* legacy — toasts now use --bg-card (sub-task 4) */
  /* Toast lanes — responsive. In the height-bound case these ARE the gaps above/below the grid.
     Floor ≈ today's values (small screens unchanged); grows on taller screens; capped so it
     never gets cavernous. vh (not dvh) for universal support; mismatch vs dvh total is safe. */
  --outer-pad-v-top:   clamp(82px, 13vh, 148px);   /* hud-top ↔ grid (TOP toast lane). Lower floor (was 108) frees grid height on short laptops; tall desktops sit on the 13vh term so are unchanged. Floor kept above the bottom lane's so the icon tooltip still clears the top toast. */
  --outer-pad-v-bot:   clamp(62px, 11vh, 122px);   /* grid ↔ hud-bottom (BOTTOM toast lane). Lower floor (was 88) frees grid height on short laptops; tall desktops unchanged (on 11vh term). */
  --grid-inner-pad:    8px;    /* .grid internal padding — the outer frame */
  --grid-gap:          4px;    /* gap between cells — the inner gridlines */
  --v-chrome:          56px;   /* fixed grid chrome = 2×grid-inner-pad + 5×gap + 20 misc */

  /* ── Elevation & radius scale (premium polish pass) ──
     Shadows compose from var(--shadow) so they inherit every theme + skin override.
     Radius values match the existing literals (6/12/14/18/24) — swaps are pixel-neutral. */
  --r-sm:   6px;    /* cells, blocks */
  --r-md:  12px;    /* small popovers */
  --r-lg:  14px;    /* grid frame, buttons, ability buttons */
  --r-xl:  18px;    /* dialogs (reserved) */
  --r-pill: 24px;   /* toasts, pills */
  --shadow-sm: 0 1px 2px var(--shadow);
  --shadow-md: 0 3px 12px var(--shadow);
  --shadow-lg: 0 10px 32px var(--shadow);
  --grid-shadow: 0 2px 6px var(--shadow), 0 10px 28px var(--shadow);

  /* Cell size — smaller of width-driven vs height-driven.
     Width offset 120 = 2×34 + 2×8 + 4×4 + 20.
     Height term is DERIVED from the layout vars (single source of truth): with default values it
     equals the old 378, but changing a padding now needs no manual offset edit. */
  --cell-size: min(
    calc((min(100vw, 480px) - 120px) / 5),
    calc((100vh - var(--hud-top-height) - var(--hud-bottom-height)
                - var(--outer-pad-v-top) - var(--outer-pad-v-bot) - var(--v-chrome)) / 6)
  );

  /* Typography */
  --font: 'Nunito', system-ui, -apple-system, sans-serif;
  --font-weight-normal: 600;
  --font-weight-bold:   800;
  --font-letter-spacing: normal;

  /* Animations */
  --move-duration:  130ms;
  --move-easing:    cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --merge-duration: 110ms;
  --squish-duration: 320ms;
  --power-duration: 200ms;
}

/* dvh override for browsers that support it — excludes mobile browser chrome */
@supports (height: 1dvh) {
  :root {
    --cell-size: min(
      calc((min(100vw, 480px) - 120px) / 5),
      calc((100dvh - var(--hud-top-height) - var(--hud-bottom-height)
                  - var(--outer-pad-v-top) - var(--outer-pad-v-bot) - var(--v-chrome)) / 6)
    );
  }
}

/* Dark theme overrides */
[data-theme="dark"] {
  --bg:            #1C1C1E;
  --bg-card:       #2C2C2E;
  --bg-ability:    rgba(255, 255, 255, 0.08);
  --text-primary:  #F2F2F7;
  --text-secondary: #8E8E93;
  --text-on-block: rgba(255, 255, 255, 0.78);
  --border:        rgba(255, 255, 255, 0.10);
  --shadow:        rgba(0, 0, 0, 0.40);
  --grid-bg:       rgba(255, 255, 255, 0.09);
  --grid-cell-bg:  rgba(255, 255, 255, 0.04);
  --pill-toast-bg: rgba(235, 235, 240, 0.93);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #1C1C1E;
    --bg-card:       #2C2C2E;
    --bg-ability:    rgba(255, 255, 255, 0.08);
    --text-primary:  #F2F2F7;
    --text-secondary: #8E8E93;
    --text-on-block: rgba(255, 255, 255, 0.78);
    --border:        rgba(255, 255, 255, 0.10);
    --shadow:        rgba(0, 0, 0, 0.40);
    --grid-bg:       rgba(255, 255, 255, 0.09);
    --grid-cell-bg:  rgba(255, 255, 255, 0.04);
    --pill-toast-bg: rgba(235, 235, 240, 0.93);
  }
}


/* ── R12 — SPLASH SCREEN ── */
.splash {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: var(--bg, #F5F0EB);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.splash--out {
  opacity: 0;
  transform: scale(1.03);
  pointer-events: none;
}
.splash-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
/* ── Logo images — show correct variant per theme ── */
.logo-img {
  display: block;
  width: auto;
  pointer-events: none;
  user-select: none;
}
.logo-img--dark { display: none; }

[data-theme="dark"] .logo-img--light { display: none; }
[data-theme="dark"] .logo-img--dark  { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-img--light { display: none; }
  :root:not([data-theme="light"]) .logo-img--dark  { display: block; }
}
/* Dark skin selected (Midnight, Neon, etc.) — overrides system theme preference */
[data-dark-skin] .logo-img--light { display: none; }
[data-dark-skin] .logo-img--dark  { display: block; }

.splash-logo {
  display: flex;
  align-items: center;
  justify-content: center;
}
.splash-logo .logo-img {
  height: 44px;
  width: auto;
}
.splash-tagline {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--text-secondary, #8A8580);
  text-transform: uppercase;
}
.splash-publisher {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
  opacity: 0.78;
}
.splash-by {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--text-secondary);
  text-transform: uppercase;
}
.ie-logo {
  display: block;
  height: 38px;
  width: auto;
  pointer-events: none;
  user-select: none;
}
.ie-logo--dark { display: none; }
[data-theme="dark"] .ie-logo--light { display: none; }
[data-theme="dark"] .ie-logo--dark  { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ie-logo--light { display: none; }
  :root:not([data-theme="light"]) .ie-logo--dark  { display: block; }
}
[data-dark-skin] .ie-logo--light { display: none; }
[data-dark-skin] .ie-logo--dark  { display: block; }

/* ── 2. RESET & BASE ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

body {
  height: 100%;
  height: 100dvh;
  font-family: var(--font);
  font-weight: var(--font-weight-normal);
  letter-spacing: var(--font-letter-spacing);
  background: var(--bg);
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
  touch-action: manipulation;
}


/* ── 3. TOP HUD ── */
.hud-top {
  width: 100%;
  max-width: 480px;
  height: var(--hud-top-height);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: stretch;
  padding: 28px var(--outer-pad-h) 0;
  flex-shrink: 0;
}

.score-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  min-width: 64px;
}

.score-block--right {
  align-items: flex-end;
  position: relative;
}

.score-label {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  text-transform: uppercase;
}

.score-value {
  font-size: 24px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  line-height: 1;
  letter-spacing: -0.01em;
}

/* Best score is a button — strip defaults, add subtle interactive cue */
.score-value--btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: opacity 80ms ease;
}
.score-value--btn:hover  { opacity: 0.7; }
.score-value--btn:active { opacity: 0.5; }


/* Best stats popover */
.best-stats-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 192px;
  background: rgba(28, 28, 30, 0.90);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--r-md);
  padding: 12px 14px;
  z-index: 50;
  box-shadow: var(--shadow-lg);
  animation: popover-in 120ms ease both;
}
@keyframes popover-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.best-stats-title {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  margin-bottom: 9px;
}
.best-stats-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 5px;
}
.best-stats-row:last-child { margin-bottom: 0; }
.best-stats-label {
  font-size: 11px;
  color: rgba(255,255,255,0.6);
  white-space: nowrap;
}
.best-stats-value {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  color: #fff;
  flex-shrink: 0;
}
.best-stats-divider {
  height: 1px;
  background: rgba(255,255,255,0.12);
  margin: 8px 0;
}

.title-block {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  align-self: flex-start;
}

.game-title {
  display: flex;
  align-items: center;
  justify-content: center;
}
.game-title .logo-img {
  height: 26px;
  width: auto;
}


/* ── 4. GAME AREA & GRID ── */
.game-area {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--outer-pad-v-top) var(--outer-pad-h) var(--outer-pad-v-bot) var(--outer-pad-h);
  width: 100%;
  max-width: 480px;
  overflow: hidden;
}

.grid-wrapper {
  position: relative;
}

.mode-label {
  position: absolute;
  top: var(--grid-inner-pad);
  left: calc(100% + 10px);
  writing-mode: vertical-rl;
  text-orientation: upright;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.25em;
  color: var(--text-secondary);
  opacity: 0.6;
  pointer-events: none;
  user-select: none;
}

.grid {
  display: grid;
  grid-template-columns: repeat(5, var(--cell-size));
  grid-template-rows:    repeat(6, var(--cell-size));
  gap: var(--grid-gap);
  background: var(--grid-bg);
  border-radius: var(--r-lg);
  padding: var(--grid-inner-pad);
  box-shadow: var(--grid-shadow);
  position: relative; /* required for aurora ::after pseudo-element */
  touch-action: none; /* grid can't scroll — tell the browser immediately so it skips scroll-intent detection and delivers touch events without delay */
}

/* Board danger escalation (R8) — box-shadow glow on outer grid container.
   65–75%: amber pulse · 75–85%: orange faster pulse · 85%+: red rapid pulse.
   box-shadow only — never affects cell layout or block visibility. */
@keyframes danger-pulse-1 {
  0%, 100% { box-shadow: var(--grid-shadow), 0 0  8px 2px rgba(245,185,50,0.20); }
  50%       { box-shadow: var(--grid-shadow), 0 0 18px 5px rgba(245,185,50,0.40); }
}
@keyframes danger-pulse-2 {
  0%, 100% { box-shadow: var(--grid-shadow), 0 0 10px 3px rgba(240,120,30,0.30); }
  50%       { box-shadow: var(--grid-shadow), 0 0 22px 7px rgba(240,120,30,0.55); }
}
@keyframes danger-pulse-3 {
  0%, 100% { box-shadow: var(--grid-shadow), 0 0 10px 4px rgba(220,60,60,0.40); }
  50%       { box-shadow: var(--grid-shadow), 0 0 26px 8px rgba(220,60,60,0.70); }
}
.grid--danger-1 { animation: danger-pulse-1 2.0s ease-in-out infinite; }
.grid--danger-2 { animation: danger-pulse-2 1.2s ease-in-out infinite; }
.grid--danger-3 { animation: danger-pulse-3 0.7s ease-in-out infinite; }

/* Empty cell backgrounds — 30 static divs (5×6) that form the visual grid.
   Never modified by JS (renderBoard targets only .block elements).
   Placement is made explicit so the auto-placement algorithm never displaces
   these cells when .block elements are dynamically added with explicit positions.
   Without this, auto-placement skips block-occupied cells, leaving the grey
   grid container background (#C5BDB4) exposed when blocks animate away. */
.grid-cell {
  background: var(--grid-cell-bg);
  border-radius: var(--r-sm);
  /* Dual-inset: dark-top reads on light bg, light-bottom reads on dark bg/skins. Visible only on
     empty cells (a block covers it). Keep tiny — this is a hint of depth, not a well. */
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05), inset 0 -1px 1px rgba(255, 255, 255, 0.03);
}
.grid-cell:nth-child(5n+1) { grid-column: 1; }
.grid-cell:nth-child(5n+2) { grid-column: 2; }
.grid-cell:nth-child(5n+3) { grid-column: 3; }
.grid-cell:nth-child(5n+4) { grid-column: 4; }
.grid-cell:nth-child(5n)   { grid-column: 5; }
.grid-cell:nth-child(-n+5)                  { grid-row: 1; }
.grid-cell:nth-child(n+6):nth-child(-n+10)  { grid-row: 2; }
.grid-cell:nth-child(n+11):nth-child(-n+15) { grid-row: 3; }
.grid-cell:nth-child(n+16):nth-child(-n+20) { grid-row: 4; }
.grid-cell:nth-child(n+21):nth-child(-n+25) { grid-row: 5; }
.grid-cell:nth-child(n+26):nth-child(-n+30) { grid-row: 6; }


/* ── 5. BLOCK STYLES ── */
.block {
  width: 100%;
  height: 100%;
  border-radius: var(--r-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(var(--cell-size) * 0.34);
  font-weight: var(--font-weight-bold);
  color: var(--text-on-block);
  position: relative;
  /* Faint top-lit highlight — reads on all skins' saturated colours. No drop shadow (would spill
     across the 4px gaps). Overridden during v10/v11/charge/destruction states — intended. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.30);
  transition: transform var(--move-duration) var(--move-easing);
}

/* Color fills */
.block--blue   { background: var(--color-blue); }
.block--yellow { background: var(--color-yellow); }
.block--green  { background: var(--color-green); }
.block--red    { background: var(--color-red); }

/* Value 1 — clean pastel, no number (no extra styles needed) */

/* Values 2–9 — show number, no glow */
.block--v2::after { content: '2'; }
.block--v3::after { content: '3'; }
.block--v4::after { content: '4'; }
.block--v5::after { content: '5'; }
.block--v6::after { content: '6'; }
.block--v7::after { content: '7'; }
.block--v8::after { content: '8'; }
.block--v9::after { content: '9'; }

/* Value 10 — steady inner glow (first danger signal) */
.block--v10 {
  box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.38);
}

.block--v10::after {
  content: '10';
}

/* Value 11 — pulsing glow signals "one merge to power" */
/* Per-color outer glow — matches block hue so pulse feels intrinsic */
.block--blue.block--v11   { --v11-glow: rgba(154, 207, 232, 0.55); }
.block--yellow.block--v11 { --v11-glow: rgba(245, 217, 138, 0.55); }
.block--green.block--v11  { --v11-glow: rgba(158, 207, 181, 0.55); }
.block--red.block--v11    { --v11-glow: rgba(238, 170, 170, 0.55); }

.block--v11 {
  animation: breathe 1.8s ease-in-out infinite;
  /* All box-shadow lives inside keyframes so it animates in sync with scale */
}

.block--v11::after {
  content: '11';
}

@keyframes breathe {
  0%, 100% {
    transform: scale(1.00);
    box-shadow:
      inset 0 0 10px rgba(255, 255, 255, 0.35),
      0 0 4px rgba(0, 0, 0, 0.08);
  }
  50% {
    transform: scale(1.05);
    box-shadow:
      inset 0 0 18px rgba(255, 255, 255, 0.55),
      0 0 10px var(--v11-glow),
      0 0 18px var(--v11-glow);
  }
}

/* Suppress breathe animation during JS-driven animation sequences.
   CSS animations override transitions on the same property (transform),
   so breathe must be disabled while movement/power animations are active. */
.grid.anim-active .block--v11 {
  animation: none;
}

/* Merge flash */
.block--merging {
  animation: merge-pulse var(--merge-duration) ease-out forwards;
}

@keyframes merge-pulse {
  0%   { transform: scale(1.00); }
  45%  { transform: scale(1.15); }
  100% { transform: scale(1.00); }
}

/* Squish effect — direction-aware squash-and-stretch replacing merge-pulse.
   Horizontal (left/right swipe): compress X, stretch Y, overshoot, settle.
   Vertical (up/down swipe or gravity chains): compress Y, stretch X, overshoot, settle.
   Both complete within --merge-duration (90ms) so turn pacing is unchanged. */
.block--squishing-h {
  animation: squish-h var(--squish-duration) ease-out forwards;
}
.block--squishing-v {
  animation: squish-v var(--squish-duration) ease-out forwards;
}

/* Four-oscillation gel spring — deep squish, overshoot, undershoot, settle.
   Horizontal: impact on X axis (left/right swipe). Vertical: impact on Y (up/down + gravity). */
@keyframes squish-h {
  0%   { transform: scale(1.00, 1.00); }
  18%  { transform: scale(0.58, 1.42); }
  40%  { transform: scale(1.22, 0.82); }
  60%  { transform: scale(0.90, 1.09); }
  78%  { transform: scale(1.07, 0.94); }
  90%  { transform: scale(0.97, 1.02); }
  100% { transform: scale(1.00, 1.00); }
}

@keyframes squish-v {
  0%   { transform: scale(1.00, 1.00); }
  18%  { transform: scale(1.42, 0.58); }
  40%  { transform: scale(0.82, 1.22); }
  60%  { transform: scale(1.09, 0.90); }
  78%  { transform: scale(0.94, 1.07); }
  90%  { transform: scale(1.02, 0.97); }
  100% { transform: scale(1.00, 1.00); }
}

/* Cross-fade system — old value fades out on the carrier, new value fades in on
   a transparent overlay element created at the same position.
   value-fade-out: 90ms ease-out — number exits smoothly, decelerating to zero.
   value-fade-in: 70ms spring — number enters with a scale-pop from 82%→100%.
   Both overlap with the merge-pulse scale (110ms), resolving before
   renderBoardDirect repaints at t=250ms (130ms slide + 120ms cross-fade wait). */
@keyframes value-fade-out {
  to { opacity: 0; }
}
.block--value-leaving::after {
  animation: value-fade-out 90ms ease-out forwards;
}

@keyframes value-fade-in {
  from { opacity: 0; transform: scale(0.82); }
  to   { opacity: 1; transform: scale(1.0); }
}
.block--value-entering {
  background: transparent;
  pointer-events: none;
}
.block--value-entering::after {
  opacity: 0;
  animation: value-fade-in 70ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

/* Power charge-up */
.block--charging {
  animation: charge-up var(--power-duration) ease-in-out forwards;
}

@keyframes charge-up {
  0%   { transform: scale(1.00); opacity: 1; }
  50%  { transform: scale(1.30); opacity: 1; }
  100% { transform: scale(1.00); opacity: 0; }
}

/* Power destruction */
.block--destroying {
  animation: destroy-flash 120ms ease-out forwards;
}

@keyframes destroy-flash {
  0%   { transform: scale(1.0); opacity: 1; }
  50%  { transform: scale(1.1); opacity: 0.7; }
  100% { transform: scale(0.0); opacity: 0; }
}


/* ── 5b. PER-COLOR POWER CHARGE-UP ── */

/* Blue: sharp electric pulse with blue glow ring */
.block--charging-blue {
  animation: charge-blue 180ms ease-in-out forwards;
}
@keyframes charge-blue {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: 0 0 0 0 rgba(154,207,232,0); }
  45%  { transform: scale(1.28); opacity: 1; box-shadow: 0 0 0 5px rgba(154,207,232,0.7), 0 0 20px 8px rgba(154,207,232,0.5); }
  100% { transform: scale(1.05); opacity: 0; box-shadow: 0 0 0 10px rgba(154,207,232,0); }
}

/* Red: dramatic swell with intense red glow */
.block--charging-red {
  animation: charge-red 220ms ease-in-out forwards;
}
@keyframes charge-red {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  55%  { transform: scale(1.45); opacity: 1; box-shadow: 0 0 0 5px rgba(238,170,170,0.85), 0 0 28px 12px rgba(238,170,170,0.65); }
  100% { transform: scale(1.15); opacity: 0; box-shadow: none; }
}

/* Green: soft breath, ethereal glow */
.block--charging-green {
  animation: charge-green 180ms ease-in-out forwards;
}
@keyframes charge-green {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  40%  { transform: scale(1.20); opacity: 1; box-shadow: 0 0 0 4px rgba(158,207,181,0.7), 0 0 20px 10px rgba(158,207,181,0.45); }
  100% { transform: scale(0.90); opacity: 0; box-shadow: none; }
}

/* Yellow: pulsing gold rings */
.block--charging-yellow {
  animation: charge-yellow 180ms ease-in-out forwards;
}
@keyframes charge-yellow {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  45%  { transform: scale(1.30); opacity: 1; box-shadow: 0 0 0 5px rgba(245,217,138,0.85), 0 0 22px 8px rgba(245,217,138,0.6); }
  100% { transform: scale(1.10); opacity: 0; box-shadow: none; }
}


/* ── 5c. PER-COLOR BLOCK DESTRUCTION ── */

/* Blue — horizontal wipe (swept by lightning) */
.block--shattering {
  animation: block-shatter 180ms ease-in forwards;
}
@keyframes block-shatter {
  0%   { transform: scaleX(1.00) scaleY(1.00); opacity: 1; }
  35%  { transform: scaleX(1.08) scaleY(0.85); opacity: 1; }
  100% { transform: scaleX(0.00) scaleY(0.50); opacity: 0; }
}

/* Red — scale up then collapse (explosive) */
.block--exploding {
  animation: block-explode-out 200ms ease-out forwards;
}
@keyframes block-explode-out {
  0%   { transform: scale(1.00) rotate(0deg);  opacity: 1; }
  30%  { transform: scale(1.28) rotate(4deg);  opacity: 1; }
  100% { transform: scale(0.00) rotate(-6deg); opacity: 0; }
}

/* Green — shrinks inward gracefully */
.block--dissolving {
  animation: block-dissolve-in 250ms ease-in forwards;
}
@keyframes block-dissolve-in {
  0%   { transform: scale(1.00); opacity: 1; }
  25%  { transform: scale(1.06); opacity: 0.85; }
  100% { transform: scale(0.20); opacity: 0; }
}

/* Yellow — gold glow flash on converted targets */
.block--converting {
  animation: block-convert-flash 300ms ease-out forwards;
}
@keyframes block-convert-flash {
  0%   { box-shadow: none; }
  30%  { box-shadow: 0 0 0 3px rgba(245,217,138,0.9), 0 0 14px 5px rgba(245,217,138,0.75); }
  70%  { box-shadow: 0 0 0 1px rgba(245,217,138,0.4), 0 0 8px 2px rgba(245,217,138,0.3); }
  100% { box-shadow: none; }
}


/* ── 5d. SPATIAL POWER OVERLAY EFFECTS ── */

/* Lightning: full-row horizontal flash bar */
.effect-lightning-row {
  position: fixed;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(154,207,232,0.85) 15%,
    rgba(220,240,255,0.95) 45%,
    rgba(255,255,255,1.00) 50%,
    rgba(220,240,255,0.95) 55%,
    rgba(154,207,232,0.85) 85%,
    transparent 100%
  );
  animation: lightning-row-flash 200ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
  border-radius: 3px;
}
@keyframes lightning-row-flash {
  0%   { opacity: 0; transform: scaleY(0.2); }
  15%  { opacity: 1; transform: scaleY(1.0); }
  100% { opacity: 0; transform: scaleY(0.6); }
}

/* Explosion ring: expanding circle from Red/Bomb epicentre */
.effect-explosion-ring {
  position: fixed;
  border-radius: 50%;
  border: 3px solid rgba(238,170,170,0.9);
  box-shadow: 0 0 14px 5px rgba(238,170,170,0.5), inset 0 0 8px rgba(238,170,170,0.2);
  animation: explosion-ring-expand 300ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes explosion-ring-expand {
  0%   { opacity: 0.9; transform: translate(-50%,-50%) scale(0.10); }
  55%  { opacity: 0.7; }
  100% { opacity: 0;   transform: translate(-50%,-50%) scale(1.00); }
}

/* Green shimmer: soft radial glow over the full grid */
.effect-green-shimmer {
  position: fixed;
  border-radius: var(--r-lg);
  background: radial-gradient(
    ellipse at center,
    rgba(158,207,181,0.55) 0%,
    rgba(158,207,181,0.20) 60%,
    transparent 100%
  );
  animation: green-shimmer-sweep 280ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes green-shimmer-sweep {
  0%   { opacity: 0; transform: scale(0.6); }
  35%  { opacity: 1; transform: scale(1.0); }
  100% { opacity: 0; transform: scale(1.1); }
}

/* Yellow ripple: concentric gold rings from power cell */
.effect-yellow-ripple {
  position: fixed;
  border-radius: 50%;
  border: 2px solid rgba(245,217,138,0.9);
  box-shadow: 0 0 8px rgba(245,217,138,0.5);
  animation: yellow-ripple-expand 250ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes yellow-ripple-expand {
  0%   { opacity: 0.9; transform: translate(-50%,-50%) scale(0.05); }
  100% { opacity: 0;   transform: translate(-50%,-50%) scale(1.00); }
}

/* Grid shake for Red explosion */
@keyframes grid-shake {
  0%, 100% { transform: translateX(0); }
  20%       { transform: translateX(3px); }
  45%       { transform: translateX(-3px); }
  65%       { transform: translateX(2px); }
  82%       { transform: translateX(-1px); }
}


/* ── 5e. ABILITY ANIMATIONS ── */

/* Shuffle out: blocks spin and fade away */
.block--shuffle-out {
  animation: block-shuffle-out 150ms ease-in forwards;
}
@keyframes block-shuffle-out {
  0%   { transform: scale(1.00) rotate(0deg);  opacity: 1; }
  100% { transform: scale(0.25) rotate(20deg); opacity: 0; }
}

/* Shuffle in: blocks pop in with bounce */
.block--shuffle-in {
  animation: block-shuffle-in 200ms cubic-bezier(0.34,1.56,0.64,1) both;
}
@keyframes block-shuffle-in {
  0%   { transform: scale(0.25); opacity: 0; }
  100% { transform: scale(1.00); opacity: 1; }
}

/* Color Destroy highlight: matching blocks glow before dissolving */
.block--color-highlight {
  animation: block-color-highlight 100ms ease-out forwards;
}
@keyframes block-color-highlight {
  0%   { transform: scale(1.00); box-shadow: none; }
  60%  { transform: scale(1.10); box-shadow: 0 0 0 3px rgba(255,255,255,0.7), 0 0 12px 4px rgba(255,255,255,0.3); }
  100% { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(255,255,255,0.4); }
}

/* Color Destroy dissolve: swell then vanish */
.block--color-dissolve {
  animation: block-color-dissolve 300ms ease-in forwards;
}
@keyframes block-color-dissolve {
  0%   { transform: scale(1.06); opacity: 1; }
  100% { transform: scale(0.15); opacity: 0; }
}


/* ── 6. COMBO COUNTER ── */
.combo-counter {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 36px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  pointer-events: none;
  z-index: 10;
  opacity: 0;
  text-shadow: 0 2px 8px var(--shadow);
}

/* Tier 2 (n=2–3): larger, warm yellow glow */
.combo-counter--mid {
  font-size: 52px;
  text-shadow:
    0 2px 8px var(--shadow),
    0 0 16px rgba(245, 217, 138, 0.55),
    0 0 32px rgba(245, 217, 138, 0.25);
}

/* Tier 3 (n≥4): maximum drama, intense gold glow ring */
.combo-counter--high {
  font-size: 68px;
  text-shadow:
    0 2px 8px var(--shadow),
    0 0 20px rgba(245, 217, 138, 0.80),
    0 0 48px rgba(245, 217, 138, 0.45),
    0 0 72px rgba(245, 217, 138, 0.20);
}

.combo-counter.combo-active {
  animation: combo-appear 600ms ease-out forwards;
}
.combo-counter--mid.combo-active {
  animation: combo-appear-mid 700ms ease-out forwards;
}
.combo-counter--high.combo-active {
  animation: combo-appear-high 800ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* Tier 1 — baseline pop */
@keyframes combo-appear {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.8); }
  20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.1); }
  60%  { opacity: 1; transform: translate(-50%, -60%) scale(1.0); }
  100% { opacity: 0; transform: translate(-50%, -75%) scale(0.9); }
}

/* Tier 2 — bigger bounce, rises further */
@keyframes combo-appear-mid {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.7); }
  18%  { opacity: 1; transform: translate(-50%, -50%) scale(1.18); }
  45%  { opacity: 1; transform: translate(-50%, -55%) scale(0.97); }
  65%  { opacity: 1; transform: translate(-50%, -65%) scale(1.02); }
  100% { opacity: 0; transform: translate(-50%, -85%) scale(0.88); }
}

/* Tier 3 — dramatic overshoot, high rise, longer hold */
@keyframes combo-appear-high {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.5); }
  15%  { opacity: 1; transform: translate(-50%, -50%) scale(1.28); }
  30%  { opacity: 1; transform: translate(-50%, -52%) scale(0.95); }
  48%  { opacity: 1; transform: translate(-50%, -58%) scale(1.06); }
  65%  { opacity: 1; transform: translate(-50%, -65%) scale(1.00); }
  82%  { opacity: 1; transform: translate(-50%, -80%) scale(1.00); }
  100% { opacity: 0; transform: translate(-50%, -95%) scale(0.92); }
}


/* ── 7. BOTTOM HUD (ABILITY BAR) ── */
.hud-bottom {
  width: 100%;
  max-width: 480px;
  height: var(--hud-bottom-height);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 4px var(--outer-pad-h) max(16px, env(safe-area-inset-bottom, 0px));
  flex-shrink: 0;
}

.ability-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  flex: 1;
  min-width: 0;
  max-width: 96px;
  min-height: clamp(44px, 6vh, 50px); /* fluid: 50 on tall desktops, ~44 on short laptops — pairs with the shrinking hud-bottom bar so buttons read smaller relative to the larger grid. Touch overrides to 72 below. */
  padding: 6px 4px;
  background: var(--bg-ability);
  border-radius: var(--r-lg);
  border: 1.5px solid var(--border);
  color: var(--text-primary);
  box-shadow: var(--shadow-sm);
  transition: opacity 150ms ease, transform 80ms ease, border-color 100ms ease, box-shadow 100ms ease;
  position: relative;
}

.ability-btn:active {
  transform: scale(0.94);
}

/* Desktop hover affordance — subtle lift; no-op on touch. Excludes disabled/locked/frozen. */
.ability-btn:hover:not(:disabled):not(.ability-btn--daily-disabled):not(.ability-btn--frozen) {
  background: var(--border);
  box-shadow: var(--shadow-md);
}

.ability-btn:disabled,
.ability-btn[data-charges="0"],
.ability-btn--daily-disabled {
  opacity: 0.35;
  pointer-events: none;
}

/* Freeze active: button greyed out and unclickable while grid overlay is showing */
.ability-btn--frozen {
  opacity: 0.35;
  pointer-events: none;
}

/* ── Freeze grid overlay ──────────────────────────────────────────────────────
   Sits above all grid content (z-index 5) but pointer-events: none so taps
   pass through for bomb / color-wipe cell selection.                         */
#freeze-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: transparent;
  transition: background 180ms ease;
}
#freeze-overlay[hidden] { display: none; }

/* Active hue — cold blue wash over the grid */
#freeze-overlay.freeze--active {
  background: rgba(154, 207, 232, 0.18);
}

/* Wipe bar — sweeps top-to-bottom on activation */
.freeze-wipe {
  position: absolute;
  inset: 0;
  background: rgba(154, 207, 232, 0.30);
  transform: scaleY(0);
  transform-origin: top center;
  opacity: 0;
}
#freeze-overlay.freeze--wiping .freeze-wipe {
  animation: freeze-wipe-in 400ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}
@keyframes freeze-wipe-in {
  0%   { transform: scaleY(0); opacity: 1; }
  85%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1); opacity: 0; }
}

/* Turn count — large centred number, darker blue, low opacity */
#freeze-turn-count {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(72px, 20vw, 112px);
  font-weight: var(--font-weight-bold);
  color: #3A6E8C;
  opacity: 0;
  letter-spacing: -0.02em;
  transition: opacity 200ms ease;
}
#freeze-overlay.freeze--active #freeze-turn-count {
  opacity: 0.28;
}

/* Crack lines — 4 bright rays radiating from centre, hidden until cracking */
.freeze-crack {
  position: absolute;
  top: 50%;
  left: 50%;
  height: 2px;
  width: 68%;
  background: linear-gradient(to right, rgba(255,255,255,0.95) 0%, rgba(200,235,255,0.60) 55%, rgba(255,255,255,0) 100%);
  box-shadow: 0 0 5px rgba(180, 225, 255, 0.70);
  transform-origin: 0 50%;
  opacity: 0;
}
.freeze-crack-1 { transform: translateY(-50%) rotate(-38deg); }
.freeze-crack-2 { transform: translateY(-50%) rotate(68deg); }
.freeze-crack-3 { transform: translateY(-50%) rotate(-148deg); }
.freeze-crack-4 { transform: translateY(-50%) rotate(22deg); }

#freeze-overlay.freeze--cracking .freeze-crack-1 {
  animation: crack-appear-1 140ms ease-out forwards;
}
#freeze-overlay.freeze--cracking .freeze-crack-2 {
  animation: crack-appear-2 140ms 20ms ease-out forwards;
}
#freeze-overlay.freeze--cracking .freeze-crack-3 {
  animation: crack-appear-3 140ms 40ms ease-out forwards;
}
#freeze-overlay.freeze--cracking .freeze-crack-4 {
  animation: crack-appear-4 140ms 60ms ease-out forwards;
}

@keyframes crack-appear-1 {
  from { opacity: 0; transform: translateY(-50%) rotate(-38deg)  scaleX(0); }
  to   { opacity: 1; transform: translateY(-50%) rotate(-38deg)  scaleX(1); }
}
@keyframes crack-appear-2 {
  from { opacity: 0; transform: translateY(-50%) rotate(68deg)   scaleX(0); }
  to   { opacity: 1; transform: translateY(-50%) rotate(68deg)   scaleX(1); }
}
@keyframes crack-appear-3 {
  from { opacity: 0; transform: translateY(-50%) rotate(-148deg) scaleX(0); }
  to   { opacity: 1; transform: translateY(-50%) rotate(-148deg) scaleX(1); }
}
@keyframes crack-appear-4 {
  from { opacity: 0; transform: translateY(-50%) rotate(22deg)   scaleX(0); }
  to   { opacity: 1; transform: translateY(-50%) rotate(22deg)   scaleX(1); }
}

/* Shatter-fade — brief brightness flash then pure opacity fade.
   No scale/translate: prevents the overlay from overflowing #game-grid
   which would cause the grid border to visually shift. */
#freeze-overlay.freeze--fading {
  animation: freeze-shatter-out 400ms ease-in forwards;
}
@keyframes freeze-shatter-out {
  0%   { opacity: 1; filter: brightness(1); }
  18%  { opacity: 1; filter: brightness(1.45); }
  100% { opacity: 0; filter: brightness(1); }
}

/* Reduced motion — skip wipe and crack animations; just instant show/hide */
@media (prefers-reduced-motion: reduce) {
  #freeze-overlay.freeze--wiping .freeze-wipe,
  #freeze-overlay.freeze--cracking .freeze-crack-1,
  #freeze-overlay.freeze--cracking .freeze-crack-2,
  #freeze-overlay.freeze--cracking .freeze-crack-3,
  #freeze-overlay.freeze--cracking .freeze-crack-4,
  #freeze-overlay.freeze--fading {
    animation: none;
  }
}

.ability-btn--hidden {
  display: none;
}

.ability-btn.ability-selected {
  border-color: var(--color-yellow);
  box-shadow: 0 0 0 2px var(--color-yellow);
}

.ability-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.ability-icon .btn-icon {
  width: 21px;
  height: 21px;
}


.ability-name {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.ability-charge {
  position: absolute;
  top: 6px;
  right: 8px;
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  opacity: 0.55;
}


@keyframes ability-glow {
  0%   { box-shadow: 0 0 0 3px var(--color-yellow), 0 0 20px var(--color-yellow); }
  100% { box-shadow: none; }
}

.ability-btn.ability-activated {
  animation: ability-glow 400ms ease-out forwards;
}

/* ── Score meta icon rows — 2 small icons under SCORE (left) and BEST (right) ── */
.score-meta {
  display: flex;
  flex-direction: row;
  gap: 4px;
  position: relative;
  align-self: stretch;
  justify-content: flex-start;
  width: 100%;
  /* Icons sit centred in a 28px box (20px glyph → ~4px inset). Pull the row out by that
     inset so the outer glyph reads flush with the score number's outer edge. */
  margin-left: -4px;
}

.score-meta--right {
  justify-content: flex-end;
  margin-left: 0;
  margin-right: -4px;
}

/* Unified meta button — all small utility icons in the top HUD header */
.meta-btn {
  position: relative;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-primary);
  opacity: 0.55;
  transition: opacity 80ms ease, transform 80ms ease;
  border-radius: var(--r-sm);
}
.meta-btn:hover  { opacity: 1; background: var(--bg-ability); }
.meta-btn:active { transform: scale(0.88); }

/* Tooltip — appears below button on hover (desktop only) */
.meta-btn::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(28, 28, 30, 0.82);
  color: #fff;
  font-size: 12px;
  font-family: var(--font);
  letter-spacing: 0.03em;
  padding: 4px 9px;
  border-radius: 5px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  /* Instant hide on mouse-leave — no lingering fade. The reveal delay lives on :hover only. */
  transition: opacity 0ms;
  z-index: 50;
}
.meta-btn:hover::after { opacity: 1; transition: opacity 120ms ease 200ms; }
/* Sound button tooltip */
.mute-btn::after { content: "Sound"; }
@media (hover: none) { .meta-btn::after { display: none; } }

/* SVG icon base — used in meta buttons and ability bar */
.btn-icon {
  width: 14px;
  height: 14px;
  display: block;
  flex-shrink: 0;
  pointer-events: none;
}

/* Mute icon toggle — sound-off hidden by default, swapped when .is-muted */
.mute-btn .icon--sound-off      { display: none; }
.mute-btn.is-muted .icon--sound-on  { display: none; }
.mute-btn.is-muted .icon--sound-off { display: block; }

/* ── Sound settings popover ─────────────────────────────────────────────── */
.sound-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 200;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  min-width: 158px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sound-popover[hidden] { display: none; }
#haptic-row[hidden]    { display: none; }
.sound-popover:not([hidden]) {
  animation: popover-in 120ms ease both;
}
.sound-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 10px;
  gap: 12px;
  border-radius: 8px;
}
.sound-row:hover { background: rgba(0,0,0,0.04); }
[data-theme="dark"] .sound-row:hover { background: rgba(255,255,255,0.06); }
.sound-row-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
}
.sound-toggle-btn {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 12px;
  border-radius: 20px;
  border: 1.5px solid var(--text-secondary);
  background: var(--text-secondary);
  color: var(--bg);
  cursor: pointer;
  letter-spacing: 0.05em;
  transition: background 180ms, color 180ms, border-color 180ms;
  flex-shrink: 0;
}
.sound-toggle-btn--off {
  background: transparent;
  color: var(--text-secondary);
}

/* ── Notification bell badge ─────────────────────────────────────────────── */
.notif-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 16px;
  height: 16px;
  background: var(--color-alert);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  line-height: 1;
  pointer-events: none;
}
.notif-badge[hidden] { display: none; }

/* ── Notifications overlay (z-107) ───────────────────────────────────────── */
.notif-overlay {
  position: fixed;
  inset: 0;
  z-index: 107;
  background: rgba(0,0,0,0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.notif-overlay[hidden] { display: none; }
.notif-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.notif-overlay:not([hidden]) .notif-card {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.notif-card {
  background: var(--bg-card);
  border-radius: 20px;
  width: min(320px, 100%);
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.notif-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.notif-title {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.notif-body {
  flex: 1;
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
}

.notif-item {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.notif-item:last-child { border-bottom: none; }

.notif-item--unread { background: rgba(245, 200, 80, 0.06); }

.notif-item-date {
  font-size: 10px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 4px;
}

.notif-item-title {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.notif-item-title::before {
  content: '';
  display: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-alert);
  flex-shrink: 0;
}
.notif-item--unread .notif-item-title::before { display: inline-block; }

.notif-item-body {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.notif-empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-secondary);
  font-size: 13px;
}

/* Coin (store) button in top HUD — matches tut-help-btn exactly */
.coin-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  border-radius: 50%;
  overflow: hidden;
  color: var(--text-secondary);
  font-size: 17px;
  line-height: 1;
  flex-shrink: 0;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 80ms ease;
}

.coin-btn:active {
  transform: scale(0.93);
}



/* ── 8b. BOARD CLEAR OVERLAY ── */
.board-clear-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.board-clear-overlay[hidden] {
  display: none;
}

.board-clear-number {
  font-family: var(--font);
  font-size: clamp(74px, 16.5vw, 102px);
  font-weight: 900;
  letter-spacing: 0.12em;
  white-space: nowrap;
  line-height: 1;
  background: linear-gradient(
    100deg,
    #9ACFE8  0%,
    #9ECFB5  22%,
    #F5D98A  48%,
    #EEAAAA  72%,
    #C8B3E8  90%,
    #9ACFE8 110%
  );
  background-size: 300% 100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  filter:
    drop-shadow(0 0 24px rgba(245, 217, 138, 0.50))
    drop-shadow(0 0 48px rgba(154, 207, 232, 0.30))
    drop-shadow(0 3px 12px rgba(0, 0, 0, 0.18));
  animation:
    board-clear-slam 1900ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards,
    chroma-rainbow-shift 3000ms linear infinite;
}

/* Block spawn-in: small pop with slight overshoot — 140ms, CSS-only, composited */
@keyframes spawn-in {
  0%   { transform: scale(0.35); opacity: 0.6; }
  65%  { transform: scale(1.07); opacity: 1;   }
  100% { transform: scale(1.0);  opacity: 1;   }
}
.block--spawning {
  animation: spawn-in 140ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

@keyframes board-clear-slam {
  0%   { opacity: 0; transform: scale(3.0); }
  9%   { opacity: 1; transform: scale(0.88); }
  20%  { transform: scale(1.07); }
  30%  { transform: scale(1.00); }
  62%  { opacity: 1; transform: scale(1.00); }
  100% { opacity: 0; transform: scale(1.00) translateY(-20px); }
}

@keyframes chroma-rainbow-shift {
  0%   { background-position: 0%   50%; }
  100% { background-position: 100% 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .board-clear-number {
    animation: none;
    opacity: 0;
  }
}


/* ── 8b-ii. NEAR-CLEAR COMBO OVERLAY ── */
.near-clear-overlay {
  position: fixed;
  inset: 0;
  z-index: 109;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.near-clear-overlay[hidden] {
  display: none;
}

.near-clear-text {
  font-family: var(--font);
  font-weight: 900;
  line-height: 1.1;
  text-align: center;
  letter-spacing: 0.01em;
}

/* Tier 1 — COMBO — blue, single line */
.near-clear-text--t1 {
  --nc-init-scale: 2.0;
  font-size: clamp(46px, 11vw, 66px);
  color: var(--color-blue);
  text-shadow:
    0 0 20px rgba(154, 207, 232, 0.65),
    0 3px 12px rgba(0, 0, 0, 0.12);
  animation: near-clear-slam 1400ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}

/* Tier 2 — BIG COMBO — green, two lines */
.near-clear-text--t2 {
  --nc-init-scale: 2.5;
  font-size: clamp(58px, 13vw, 84px);
  color: var(--color-green);
  text-shadow:
    0 0 24px rgba(158, 207, 181, 0.75),
    0 0 48px rgba(158, 207, 181, 0.35),
    0 4px 14px rgba(0, 0, 0, 0.12);
  animation: near-clear-slam 1700ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}

/* Tier 3 — SUPER COMBO — red, two lines */
.near-clear-text--t3 {
  --nc-init-scale: 3.0;
  font-size: clamp(70px, 16vw, 102px);
  color: var(--color-red);
  text-shadow:
    0 0 30px rgba(238, 170, 170, 0.80),
    0 0 60px rgba(238, 170, 170, 0.40),
    0 6px 20px rgba(0, 0, 0, 0.15);
  animation: near-clear-slam 2000ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}

/* Same bounce rhythm as board-clear-slam; initial scale driven by --nc-init-scale */
@keyframes near-clear-slam {
  0%   { opacity: 0; transform: scale(var(--nc-init-scale, 2.5)); }
  10%  { opacity: 1; transform: scale(0.90); }
  18%  { transform: scale(1.08); }
  26%  { transform: scale(0.96); }
  33%  { transform: scale(1.02); }
  40%  { transform: scale(1.00); }
  65%  { opacity: 1; transform: scale(1.00); }
  100% { opacity: 0; transform: scale(1.00) translateY(-20px); }
}

@media (prefers-reduced-motion: reduce) {
  .near-clear-text {
    animation: none;
    opacity: 0;
  }
}


/* ── 8b-iii. NEW PERSONAL BEST OVERLAY ── */
.new-best-overlay {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.new-best-overlay[hidden] {
  display: none;
}

.new-best-text {
  font-family: var(--font);
  font-weight: 900;
  font-size: clamp(56px, 13vw, 80px);
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--color-yellow);
  text-shadow:
    0 0 22px rgba(245, 217, 138, 0.70),
    0 0 52px rgba(245, 217, 138, 0.30),
    0 4px 16px rgba(0, 0, 0, 0.14);
  animation: new-best-text-anim 1400ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
}

/*
  Entry  (0–32%):  zoom in from scale(2.2), bounce-settle — matches near-clear rhythm
  Hold   (32–72%): fully visible, no motion
  Burst  (72–100%): scale up + blur + fade — "explodes into confetti"
*/
@keyframes new-best-text-anim {
  0%   { opacity: 0; transform: scale(2.2); filter: blur(0px); }
  10%  { opacity: 1; transform: scale(0.91); filter: blur(0px); }
  18%  { transform: scale(1.06); }
  25%  { transform: scale(0.98); }
  32%  { transform: scale(1.00); opacity: 1; }
  72%  { transform: scale(1.00); opacity: 1; filter: blur(0px); }
  86%  { transform: scale(1.22); opacity: 0.35; filter: blur(3px); }
  100% { transform: scale(1.50); opacity: 0; filter: blur(6px); }
}

@media (prefers-reduced-motion: reduce) {
  .new-best-text {
    animation: none;
    opacity: 0;
  }
}


/* ── 8c. STORE OVERLAY ── */
.store-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(0, 0, 0, 0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.store-overlay[hidden] {
  display: none;
}
.store-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.store-overlay:not([hidden]) .store-card {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.store-card {
  background: var(--bg-card);
  border-radius: 20px;
  width: min(360px, 100%);
  max-height: min(90dvh, 90vh);
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  box-shadow: var(--shadow-lg);
  padding: 0 0 8px;
}

.store-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-card);
  border-radius: 20px 20px 0 0;
}

.store-title {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.store-balance {
  font-size: 16px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.store-close-btn {
  line-height: 1;
  font-weight: 400;
  color: var(--text-secondary);
  width: 32px;
  height: 32px;
  min-width: 32px;
  min-height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-ability);
  transition: opacity 120ms ease;
  flex-shrink: 0;
}

.store-close-btn:hover {
  opacity: 0.7;
}

.store-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  transition: background 150ms ease;
}
.store-row[hidden] { display: none; }

.store-row--highlight {
  background: rgba(245, 217, 138, 0.12);
  border-left: 3px solid var(--color-yellow);
  padding-left: 17px; /* 20 - 3 border = 17 to keep content aligned */
}

.store-row-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

.store-row-icon {
  font-size: 22px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.store-row-icon svg {
  width: 22px;
  height: 22px;
  color: inherit;
}

.store-row-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.store-row-name {
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.store-row-stock {
  font-size: 11px;
  color: var(--text-secondary);
}

.store-row-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex-shrink: 0;
}

.store-row-price {
  font-size: 13px;
  color: var(--text-secondary);
}

.store-qty-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.store-qty-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  color: var(--text-primary);
  font-size: 16px;
  font-weight: var(--font-weight-bold);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: opacity 100ms ease;
}

.store-qty-btn:disabled {
  opacity: 0.3;
}

.store-qty {
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  min-width: 18px;
  text-align: center;
}

.store-buy-btn {
  padding: 7px 14px;
  background: var(--color-yellow);
  border-radius: 20px;
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  color: #000;
  transition: opacity 150ms ease, transform 80ms ease;
  white-space: nowrap;
}

.store-buy-btn:active {
  transform: scale(0.94);
}

.store-buy-btn:disabled {
  opacity: 0.35;
  pointer-events: none;
}

@keyframes store-buy-flash {
  0%   { box-shadow: 0 0 0 3px var(--color-yellow), 0 0 14px var(--color-yellow); }
  100% { box-shadow: none; }
}

.store-buy-btn.buy-flash {
  animation: store-buy-flash 350ms ease-out forwards;
}


/* ── 8d. LOADOUT OVERLAY ── */
.loadout-overlay {
  position: fixed;
  inset: 0;
  z-index: 115; /* above game-over (110), below tutorial (120) */
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.loadout-overlay[hidden] { display: none; }

.loadout-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.loadout-overlay:not([hidden]) .loadout-card {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.loadout-card {
  background: var(--bg-card);
  border-radius: 20px;
  padding: 24px 20px 20px;
  width: 100%;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.loadout-header {
  width: 100%;
  text-align: center;
}

.loadout-title {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.loadout-subtitle {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  margin: -8px 0 0;
}

.loadout-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  width: 100%;
}

.loadout-ability {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 12px 6px 10px;
  background: var(--bg-ability);
  border: 2px solid transparent;
  border-radius: var(--r-lg);
  cursor: pointer;
  transition: border-color 120ms, background 120ms, transform 80ms;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.loadout-ability:active:not(.loadout-ability--locked) {
  transform: scale(0.95);
}

.loadout-ability-icon .btn-icon {
  width: 22px;
  height: 22px;
  opacity: 0.7;
}

.loadout-ability--selected .loadout-ability-icon .btn-icon {
  opacity: 1;
}

.loadout-ability-name {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  text-transform: uppercase;
}

.loadout-ability-charge {
  font-size: 11px;
  font-weight: 800;
  color: var(--text-secondary);
  background: var(--bg-ability);
  border-radius: 8px;
  padding: 1px 6px;
  min-width: 20px;
  text-align: center;
}

.loadout-ability--selected {
  border-color: var(--color-yellow);
  background: rgba(245, 217, 138, 0.12);
}

.loadout-ability--selected .loadout-ability-charge {
  background: rgba(245, 217, 138, 0.2);
  color: var(--text-primary);
}

.loadout-ability--locked {
  opacity: 0.38;
  pointer-events: none;
}

.loadout-ability-tier {
  position: absolute;
  top: 6px;
  left: 6px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--color-yellow);
  line-height: 1;
}

.loadout-ability-tier:empty {
  display: none;
}

.loadout-ability-lock {
  display: none;
  position: absolute;
  top: 6px;
  right: 6px;
  color: var(--text-secondary);
  line-height: 1;
}

.loadout-ability--locked .loadout-ability-lock {
  display: block;
}

.loadout-count {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-secondary);
  margin: -4px 0;
}

.loadout-start-btn {
  width: 100%;
  padding: 14px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.04em;
  border-radius: var(--r-lg);
  transition: opacity 150ms;
}

.loadout-start-btn:disabled {
  opacity: 0.35;
  pointer-events: none;
}


/* ── 8. TUTORIAL OVERLAY ── */
.tutorial-overlay {
  position: fixed;
  inset: 0;
  border-radius: 0;
  background: rgba(0, 0, 0, 0.38);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  gap: 16px;
  z-index: 120; /* above store (100) and game-over (110) */
  backdrop-filter: blur(8px);
}

.tutorial-overlay[hidden] {
  display: none;
}
.tutorial-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.tutorial-overlay:not([hidden]) .tutorial-prompt {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.tutorial-prompt {
  background: var(--bg-card);
  border-radius: var(--r-xl);
  padding: 24px 28px;
  color: var(--text-primary);
  width: min(620px, 88vw);
  max-height: min(92dvh, 92vh);
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  box-shadow: var(--shadow-lg);
}

.tutorial-skip {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  color: rgba(255, 255, 255, 0.65);
  padding: 8px 16px;
  min-height: 44px;
  min-width: 72px;
  background: transparent;
}

/* ── Tutorial carousel card ── */
.tut-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Tutorial slide transitions ── */
.tut-card--exit-left  { animation: tut-exit-left  80ms ease-in  forwards; pointer-events: none; }
.tut-card--exit-right { animation: tut-exit-right 80ms ease-in  forwards; pointer-events: none; }
.tut-card--enter-right { animation: tut-enter-right 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }
.tut-card--enter-left  { animation: tut-enter-left  150ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }

@keyframes tut-exit-left  { to { opacity: 0; transform: translateX(-28px); } }
@keyframes tut-exit-right { to { opacity: 0; transform: translateX(28px);  } }
@keyframes tut-enter-right { from { opacity: 0; transform: translateX(28px);  } to { opacity: 1; transform: translateX(0); } }
@keyframes tut-enter-left  { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: translateX(0); } }

.tut-title {
  font-size: 20px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.tut-body {
  font-size: 14px;
  font-weight: var(--font-weight-normal);
  color: var(--text-secondary);
  line-height: 1.6;
  text-align: left;
}

.tut-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 4px;
}

.tut-dots {
  display: flex;
  gap: 6px;
  align-items: center;
}

.tut-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-secondary);
  opacity: 0.25;
}

.tut-dot--active {
  opacity: 1;
  background: var(--text-primary);
}

.tut-next-btn {
  background: var(--text-primary);
  color: var(--bg);
  border-radius: 8px;
  padding: 9px 22px;
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  font-family: var(--font);
  min-height: 38px;
  cursor: pointer;
  border: none;
}

.tut-next-btn:active { opacity: 0.7; }

.tut-back-btn {
  background: transparent;
  color: var(--text-primary);
  border: none;
  border-radius: 8px;
  padding: 9px 16px;
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  font-family: var(--font);
  min-height: 38px;
  cursor: pointer;
  opacity: 0.55;
}
.tut-back-btn:active { opacity: 0.3; }

/* Shared: colored block fill classes */
.tut-color-blue   { background: var(--color-blue); }
.tut-color-yellow { background: var(--color-yellow); }
.tut-color-green  { background: var(--color-green); }
.tut-color-red    { background: var(--color-red); }

/* ── Slide 1: Move ── */
.tut-move-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 4px 0;
}

.tut-mini-grid {
  display: grid;
  gap: 3px;
  background: var(--grid-bg);
  border-radius: 5px;
  padding: 3px;
}

.tut-grid-3x2 {
  grid-template-columns: repeat(3, 34px);
  grid-template-rows: repeat(2, 34px);
}

.tut-grid-1x6 {
  grid-template-columns: repeat(6, 48px);
  grid-template-rows: 48px;
}

.tut-mini-cell {
  background: var(--grid-cell-bg);
  border-radius: 3px;
}

.tut-mini-cell.tut-block {
  /* color set by tut-color-* class */
  background: var(--grid-cell-bg); /* fallback */
}

.tut-arrow-big {
  font-size: 18px;
  color: var(--text-secondary);
  line-height: 1;
}

/* ── Slide 2: Merge ── */
.tut-merge-seq {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}

.tut-merge-step {
  display: flex;
  align-items: center;
  gap: 5px;
}

.tut-iblock {
  width: 52px;
  height: 52px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: var(--font-weight-bold);
  color: var(--text-on-block);
  flex-shrink: 0;
  position: relative;
  overflow: hidden;
}

.tut-v3 {
  box-shadow: 0 0 0 2px rgba(0,0,0,0.18), 0 0 12px 4px rgba(0,0,0,0.18);
}

.tut-iblock.tut-v3 {
  animation: tut-iblock-breathe 1.8s ease-in-out infinite;
}

@keyframes tut-iblock-breathe {
  0%, 100% { transform: scale(1.00); box-shadow: 0 0 0 2px rgba(0,0,0,0.15), 0 0 10px 3px rgba(0,0,0,0.12); }
  50%       { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(0,0,0,0.20), 0 0 16px 6px rgba(0,0,0,0.20); }
}

/* Steady inner glow for the red value-10 block in slide 2 */
.tut-iblock.tut-v10-inner {
  box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.38);
}

/* Red-tinted pulsing variant for the red value-11 block in slide 2 */
.tut-iblock.tut-v11-red {
  animation: tut-iblock-breathe-red 1.8s ease-in-out infinite;
}

@keyframes tut-iblock-breathe-red {
  0%, 100% { box-shadow: 0 0 0 2px rgba(0,0,0,0.15), 0 0 10px 3px var(--color-red); }
  50%       { box-shadow: 0 0 0 2px rgba(0,0,0,0.20), 0 0 18px 6px var(--color-red); }
}

.tut-arrow-sm {
  font-size: 13px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

/* ── Slide 3: Powers ── */
.tut-power-demo {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 0;
}

.tut-power-trigger {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
}

.tut-power-flash {
  font-size: 20px;
  line-height: 1;
}

.tut-iblock.tut-cleared {
  background: rgba(0,0,0,0.06);
  border: 1.5px dashed rgba(0,0,0,0.18);
  color: transparent;
}

.tut-powers-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 10px;
}

.tut-power-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: var(--font-weight-normal);
  color: var(--text-secondary);
}

.tut-power-dot {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ── Slide 4: Structural Gravity ── */
.tut-before-after {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 8px;
  padding: 4px 0;
}

.tut-ba-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
}

.tut-ba-title {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding-left: 2px;
}

.tut-ba-sep {
  font-size: 18px;
  color: var(--text-secondary);
  align-self: center;
  margin-top: 20px; /* align with cells, not panel title */
}

.tut-grav-col {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.tut-grav-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.tut-grav-cell {
  width: 40px;
  height: 40px;
  background: var(--grid-cell-bg);
  border-radius: 5px;
  border: 1.5px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  flex-shrink: 0;
  box-sizing: border-box;
}

.tut-grav-cell.tut-block {
  border: none;
}

/* The grid-bottom row uses a dashed border to suggest it's the board edge */
.tut-grav-row--bottom .tut-grav-cell {
  border-style: dashed;
  border-color: rgba(0,0,0,0.22);
}

.tut-power-cell {
  font-size: 12px;
}

.tut-hint {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  white-space: nowrap;
  min-width: 54px;
}

.tut-hint-floor { color: var(--text-secondary); }
.tut-hint-dim   { color: var(--text-secondary); opacity: 0.55; }
.tut-hint-yes   { color: #4A9E5C; }
.tut-hint-no    { color: #C05050; }

/* ── Slide 5: Abilities ── */
.tut-abilities-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 0;
}

.tut-ability-item {
  display: flex;
  align-items: center;
  gap: 12px;
}

.tut-ability-icon {
  font-size: 20px;
  width: 30px;
  text-align: center;
  flex-shrink: 0;
}

.tut-ability-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tut-ability-name {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.tut-ability-desc {
  font-size: 11px;
  color: var(--text-secondary);
}

/* ── Tutorial ? help button ── */
.tut-help-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  color: var(--text-secondary);
  font-size: 16px;
  font-weight: var(--font-weight-bold);
  font-family: var(--font);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  line-height: 1;
  touch-action: manipulation;
}
.tut-help-btn:active { opacity: 0.6; }

/* ── Tutorial illustration area (shared) ── */
.tut-illustration {
  height: 300px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;
}

.tut-illustration-inner {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── Slide 3: Powers 2×2 grid ── */
.tut-powers-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  width: 100%;
  height: 100%;
  padding: 4px;
  box-sizing: border-box;
}

.tut-pcell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bg-ability);
  border: 1px solid var(--border);
  overflow: hidden;
}

.tut-pcell-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  min-width: 113px;
}

.tut-pcell-body {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  width: 100%;
}

.tut-pcell-header {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 5px;
  flex-shrink: 0;
  width: 100%;
}

.tut-pcell-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
}

.tut-pcell-name {
  font-size: 14px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  line-height: 1.2;
}

.tut-pcell-desc {
  font-size: 13px;
  color: var(--text-secondary);
  opacity: 0.9;
  line-height: 1.3;
  text-align: left;
  flex: 1;
  align-self: center;
}

/* Mini blocks used in power / ability demos */
.tut-mini-block {
  width: 26px;
  height: 26px;
  border-radius: 5px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tut-mini-block--charging {
  animation: tut-charge-pulse 1s ease-in-out infinite;
}

@keyframes tut-charge-pulse {
  0%, 100% { transform: scale(1.00); }
  50%       { transform: scale(1.18); }
}

@keyframes tut-bomb-ring {
  0%   { opacity: 0.85; transform: translate(-50%, -50%) scale(0.75); }
  100% { opacity: 0;    transform: translate(-50%, -50%) scale(1.5);  }
}

/* Contained variant for slide 3 bomb — stays within the 3×3 blast area */
@keyframes tut-bomb-ring-3x3 {
  0%   { opacity: 0.9; transform: translate(-50%, -50%) scale(0.45); }
  100% { opacity: 0;   transform: translate(-50%, -50%) scale(1.0);  }
}

.tut-mini-row {
  display: flex;
  gap: 3px;
  align-items: center;
}

.tut-mini-grid-3x3 {
  display: grid;
  grid-template-columns: repeat(3, 26px);
  grid-template-rows: repeat(3, 26px);
  gap: 3px;
}

.tut-mini-grid-3x4 {
  display: grid;
  grid-template-columns: repeat(4, 26px);
  grid-template-rows: repeat(3, 26px);
  gap: 3px;
}

/* ── Slide 4: Gravity cluster ── */
.tut-grav-cluster {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
}

.tut-grav-cluster-row {
  display: flex;
  gap: 3px;
  align-items: center;
}

.tut-grav-label {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  color: var(--text-secondary);
  white-space: nowrap;
  margin-left: 8px;
  transition: opacity 300ms;
}

.tut-grav-label--dim {
  opacity: 0.45;
  font-size: 9px;
}

.tut-floor-line {
  position: absolute;
  height: 2px;
  width: 0;
  left: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to right,
    var(--text-secondary) 0,
    var(--text-secondary) 5px,
    transparent 5px,
    transparent 9px
  );
  border-radius: 1px;
  transition: width 350ms ease-out;
}
.tut-floor-line.visible { width: calc(100% + 28px); }

.tut-floor-label {
  position: absolute;
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  color: var(--text-secondary);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 300ms;
  pointer-events: none;
}
.tut-floor-label.visible { opacity: 1; }

/* ── Slide 5: Abilities cycling ── */
.tut-ability-featured {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  width: 100%;
  height: 100%;
  justify-content: center;
}

.tut-ability-indicator {
  display: flex;
  gap: 6px;
  align-items: center;
}

.tut-ability-dot-ind {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-primary);
  opacity: 0.25;
  transition: opacity 250ms;
}
.tut-ability-dot-ind.active { opacity: 1; }

.tut-ability-featured-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.tut-ability-featured-icon {
  font-size: 28px;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.tut-ability-featured-icon svg {
  width: 28px;
  height: 28px;
  color: inherit;
}

.tut-ability-featured-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.tut-ability-featured-name {
  font-size: 15px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.tut-ability-featured-desc {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.4;
}

.tut-ability-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60px;
  width: 100%;
  margin-top: 16px;
}

/* ── Tutorial skin treatments ──
   Tutorial elements live outside #game-grid so skin cssClass rules don't reach them.
   body:has(#game-grid.skin-*) lets us target tutorial blocks when each skin is active.
   Skins with no cssClass (midnight, neon, forest, blush, slate, ivory, ember, lagoon)
   only change --color-* vars, which tutorial blocks already use — no extra rules needed. */

/* Aurora: inner blue glow + drifting shimmer overlay */
body:has(#game-grid.skin-aurora) .tut-iblock,
body:has(#game-grid.skin-aurora) .tut-grav-cell.tut-block {
  position: relative;
  overflow: hidden;
  box-shadow: inset 0 0 14px rgba(80, 140, 255, 0.22);
}
body:has(#game-grid.skin-aurora) .tut-mini-block {
  position: relative;
  overflow: hidden;
}
body:has(#game-grid.skin-aurora) .tut-iblock::before,
body:has(#game-grid.skin-aurora) .tut-grav-cell.tut-block::before,
body:has(#game-grid.skin-aurora) .tut-mini-block::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    135deg,
    rgba(48, 220, 130, 0.22)  0%,
    rgba(80, 160, 255, 0.18) 50%,
    rgba(168, 70, 255, 0.20) 100%
  );
  background-size: 200% 200%;
  animation: aurora-block-drift 10s ease-in-out infinite;
  pointer-events: none;
}

/* Holographic: prismatic foil surface.
   --holo-c-* animated vars live on .grid-wrapper and aren't inherited here,
   so blocks show the static --color-* holo palette. The dichroic ::before
   overlay adds the characteristic iridescent surface character. */
body:has(#game-grid.skin-holo) .tut-iblock,
body:has(#game-grid.skin-holo) .tut-grav-cell.tut-block,
body:has(#game-grid.skin-holo) .tut-mini-block {
  position: relative;
  overflow: hidden;
}
body:has(#game-grid.skin-holo) .tut-iblock::before,
body:has(#game-grid.skin-holo) .tut-grav-cell.tut-block::before,
body:has(#game-grid.skin-holo) .tut-mini-block::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(
      155deg,
      transparent 34%,
      rgba(255, 255, 255, 0.08) 46%,
      rgba(255, 255, 255, 0.12) 50%,
      rgba(255, 255, 255, 0.08) 54%,
      transparent 66%
    ),
    linear-gradient(
      115deg,
      rgba(255,  88,  88, 0.10)   0%,
      rgba(255, 195,  68, 0.10)  17%,
      rgba( 68, 230, 140, 0.10)  35%,
      rgba( 68, 182, 255, 0.10)  54%,
      rgba(172,  68, 255, 0.10)  72%,
      rgba(255,  68, 172, 0.10)  89%,
      rgba(255,  88,  88, 0.10) 100%
    );
  pointer-events: none;
}

/* ── 9. GAME OVER OVERLAY ── */
.game-over-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 110; /* above store (100), below tutorial (120) */
  backdrop-filter: blur(6px);
  animation: fade-in 200ms ease-out;
}

.game-over-overlay[hidden] {
  display: none;
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.game-over-card {
  background: var(--bg-card);
  border-radius: 20px;
  padding: 22px 20px;
  width: min(360px, 90vw);
  max-height: min(92dvh, 92vh);
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  box-shadow: var(--shadow-lg);
  animation: card-rise 250ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes card-rise {
  from { transform: translateY(20px) scale(0.96); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}

.game-over-overlay:not([hidden]) .stat {
  animation: panel-fade-in 180ms ease both;
}
.game-over-overlay:not([hidden]) .stat:nth-child(1) { animation-delay: 60ms; }
.game-over-overlay:not([hidden]) .stat:nth-child(2) { animation-delay: 120ms; }
.game-over-overlay:not([hidden]) .stat:nth-child(3) { animation-delay: 180ms; }
.game-over-overlay:not([hidden]) .stat:nth-child(4) { animation-delay: 240ms; }
.game-over-overlay:not([hidden]) .stat:nth-child(5) { animation-delay: 300ms; }

.game-over-title {
  font-size: 18px;
  font-weight: var(--font-weight-bold);
  color: var(--text-secondary);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}



.game-mode-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 4px 12px;
  margin-top: 2px;
  align-self: center;
}

.game-over-score {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

/* ── Daily challenge result overlays ── */
.daily-result-card {
  text-align: center;
  gap: 16px;
}

.daily-result-card--complete {
  border-top: 4px solid #7EC8A0;
}

.daily-result-card--failed {
  border-top: 4px solid #ccc;
}

.daily-result-icon-large {
  font-size: 40px;
  line-height: 1;
  color: #7EC8A0;
}

.daily-result-icon-large--failed {
  color: #bbb;
}

.daily-result-challenge-desc {
  font-size: 14px;
  color: var(--text-secondary);
  margin: 0;
  line-height: 1.4;
}

.daily-result-reward-row {
  font-size: 15px;
  font-weight: 700;
  color: #F5C842;
}

.new-best-badge {
  background: var(--color-yellow);
  color: var(--text-primary);
  font-size: 11px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.10em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 20px;
  animation: badge-pop 300ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

.new-best-badge[hidden] {
  display: none;
}

@keyframes badge-pop {
  from { transform: scale(0.7); opacity: 0; }
  to   { transform: scale(1.0); opacity: 1; }
}

.game-over-score-label {
  font-size: 12px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.game-over-score-value {
  font-size: 56px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  line-height: 1;
}

/* "Best: 112 — 65 turns away" shown when player didn't beat their record */
.best-distance {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-top: 2px;
}
.best-distance[hidden] { display: none; }

/* Sprint only: "in 40 turns" shown below the merge-score value */
.sprint-turns-played {
  display: block;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-top: 4px;
}
.sprint-turns-played[hidden] { display: none; }

/* ── Combo snapshot ── */
.combo-snapshot {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  padding: 10px 0 4px;
}
.combo-snapshot[hidden] { display: none; }

.combo-board-wrapper {
  position: relative;
  display: block;
  width: 100%;
  max-width: 210px;
  margin: 0 auto;
}

/* Overlay label — positioned over the mini board, styled like in-game near-clear text */
.combo-snapshot-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font);
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: 0.01em;
  text-align: center;
  pointer-events: none;
}

/* t1 — COMBO — blue */
.combo-snapshot-label--t1 {
  font-size: 28px;
  color: var(--color-blue);
  text-shadow:
    0 0 16px rgba(154, 207, 232, 0.65),
    0 2px 8px rgba(0, 0, 0, 0.12);
}

/* t2 — BIG COMBO — green */
.combo-snapshot-label--t2 {
  font-size: 32px;
  color: var(--color-green);
  text-shadow:
    0 0 20px rgba(158, 207, 181, 0.75),
    0 0 40px rgba(158, 207, 181, 0.35),
    0 3px 10px rgba(0, 0, 0, 0.12);
}

/* t3 — SUPER COMBO — red */
.combo-snapshot-label--t3 {
  font-size: 36px;
  color: var(--color-red);
  text-shadow:
    0 0 24px rgba(238, 170, 170, 0.80),
    0 0 48px rgba(238, 170, 170, 0.40),
    0 4px 14px rgba(0, 0, 0, 0.15);
}

.combo-mini-board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 3px;
  background: var(--grid-bg);
  border-radius: 10px;
  padding: 5px;
  width: 100%;
}

.combo-cell {
  aspect-ratio: 1;
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.combo-cell--empty {
  background: var(--grid-cell-bg);
}
.combo-cell--wild {
  background: linear-gradient(135deg, var(--color-blue) 0%, var(--color-green) 50%, var(--color-yellow) 100%);
  opacity: 0.85;
}
.combo-cell--multiplier {
  background: var(--text-secondary);
  opacity: 0.4;
}

.combo-cell-value {
  font-size: 14px;
  font-weight: 800;
  color: rgba(0, 0, 0, 0.5);
  line-height: 1;
  pointer-events: none;
  user-select: none;
}

/* ── Active features section ── */
.features-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 0;
}
.features-section[hidden] { display: none; }

.features-section-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.6;
}

.features-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}

.feature-chip {
  display: flex;
  align-items: center;
  gap: 5px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 3px 10px 3px 8px;
}
.feature-chip-name {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: 0.02em;
}
.feature-chip-tier {
  font-size: 9px;
  font-weight: 700;
  color: var(--text-secondary);
  background: var(--grid-cell-bg);
  border-radius: 10px;
  padding: 1px 5px;
  letter-spacing: 0.04em;
}

.game-over-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  width: 100%;
}

.stat {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--bg-ability);
  border-radius: var(--r-md);
  padding: 8px 6px;
  gap: 4px;
}

.stat-label {
  font-size: 10px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: center;
}

.stat-value {
  font-size: 20px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

/* Abilities-used stat: spans both columns, hairline top separator */
.stat--wide {
  grid-column: 1 / -1;
  border-top: 1px solid var(--border);
  flex-direction: row;
  justify-content: space-between;
  padding: 8px 14px;
}

.stat--wide.stat--pristine .stat-value {
  color: var(--text-primary);
}

/* "New record!" golden pulsing badge injected on new personal-best stats */
.stat-new-record {
  font-size: 8.5px;
  font-weight: 700;
  color: #C8993A;
  letter-spacing: 0.04em;
  white-space: nowrap;
  animation: record-pulse 1.2s ease-in-out infinite;
  pointer-events: none;
  background: rgba(200, 153, 58, 0.10);
  padding: 2px 5px;
  border-radius: 8px;
  border: 1px solid #C8993A44;
}

@keyframes record-pulse {
  0%, 100% { transform: scale(1); }
  50%       { transform: scale(1.14); }
}

/* New-best main badge: after pop-in, loop the same gentle pulse */
.new-best-badge--pulsing {
  animation: record-pulse 1.2s ease-in-out infinite;
}

/* Confetti particles — CSS custom properties set per-particle in JS */
@keyframes confetti-fall {
  0%   { transform: translate(0, 0) rotate(0deg); opacity: 1; }
  80%  { opacity: 0.85; }
  100% { transform: translate(var(--x-drift), 88vh) rotate(var(--rotation-end)); opacity: 0; }
}

/* New-best confetti: phase 1 radial burst (ease-out), phase 2 natural fall (linear).
   Vars per particle: --bx/--by (burst offset), --x-drift (fall sideways), --rot-mid/--rotation-end */
@keyframes new-best-confetti-fly {
  0%   {
    transform: translate(0, 0) rotate(0deg);
    opacity: 1;
    animation-timing-function: cubic-bezier(0.08, 0.9, 0.3, 1);
  }
  15%  {
    transform: translate(var(--bx), var(--by)) rotate(var(--rot-mid));
    opacity: 1;
    animation-timing-function: linear;
  }
  78%  { opacity: 0.9; }
  100% {
    transform: translate(calc(var(--bx) + var(--x-drift)), calc(var(--by) + 92vh)) rotate(var(--rotation-end));
    opacity: 0;
  }
}

/* Coins earned this run — shown between stats and buttons */
.game-over-coins {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 4px 0 0;
}
.game-over-coins-label {
  font-size: 11px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.game-over-coins-value {
  font-size: 15px;
  font-weight: var(--font-weight-bold);
  color: var(--color-yellow);
}

.game-over-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}
.game-over-actions-row {
  display: flex;
  gap: 8px;
  width: 100%;
}
.game-over-actions-row .btn {
  flex: 1;
}

.game-over-feedback-link {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 0.78rem;
  cursor: pointer;
  margin-top: 6px;
  padding: 4px 8px;
  opacity: 0.65;
  transition: opacity 80ms;
  font-family: inherit;
}
.game-over-feedback-link:hover { opacity: 1; }

/* Compact layout on non-touch devices (laptops/desktops) so all card content
   including action buttons fits within the viewport without scrolling. */
@media (hover: hover) {
  .game-over-card {
    padding: 14px 18px;
    gap: 7px;
    max-height: min(96dvh, 96vh);
  }
  .game-over-score-value {
    font-size: 44px;
  }
  .combo-snapshot {
    padding: 6px 0 2px;
  }
}

.btn {
  width: 100%;
  min-height: 44px;
  border-radius: var(--r-lg);
  font-family: var(--font);
  font-size: 16px;
  font-weight: var(--font-weight-bold);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px 20px;
  transition: transform 80ms ease, opacity 100ms ease, box-shadow 120ms ease;
}

.btn:active {
  transform: scale(0.97);
}

.btn--primary {
  background: var(--text-primary);
  color: var(--bg);
  box-shadow: var(--shadow-md);
}

.btn--secondary {
  background: var(--bg-ability);
  color: var(--text-primary);
  border: 1.5px solid var(--border);
  box-shadow: var(--shadow-sm);
  min-height: 36px;
  font-size: 13px;
  padding: 8px 16px;
}

.btn--danger {
  background: #C85A5A;
  color: #fff;
}

#restart-btn:disabled {
  opacity: 0.25;
  cursor: not-allowed;
  pointer-events: none;
}

/* ── Restart confirmation dialog ── */
.restart-confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 160;
  backdrop-filter: blur(6px);
  animation: fade-in 150ms ease-out;
}

.restart-confirm-overlay[hidden] { display: none; }

.restart-confirm-card {
  background: var(--bg-card);
  border-radius: var(--r-xl);
  padding: 28px 24px 20px;
  max-width: 300px;
  width: calc(100% - 48px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: var(--shadow-lg);
}

.restart-confirm-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  text-align: center;
}

.restart-confirm-body {
  font-size: 14px;
  color: var(--text-secondary);
  margin: 0;
  text-align: center;
  line-height: 1.5;
}

.restart-confirm-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.restart-confirm-actions .btn {
  flex: 1;
}

/* ── Invite modal (HUD share) — platform links + copy link ── */
.share-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 115;
  backdrop-filter: blur(6px);
  animation: fade-in 180ms ease-out;
}
.share-modal-overlay[hidden] { display: none; }
@media (min-height: 520px) {
  .share-modal-overlay { align-items: center; }
}

.share-modal-card {
  position: relative;
  background: var(--bg-card);
  border-radius: 24px 24px 0 0;
  padding: 28px 24px 32px;
  width: min(420px, 100vw);
  max-height: 90dvh;
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 -4px 40px rgba(0,0,0,0.18);
  animation: share-slide-up 240ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
@media (min-height: 520px) {
  .share-modal-card {
    border-radius: var(--r-pill);
    box-shadow: var(--shadow-lg);
    animation: card-rise 220ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
  }
}
@keyframes share-slide-up {
  from { transform: translateY(40px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

.share-modal-close {
  position: absolute;
  top: 16px; right: 16px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bg-ability);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms ease;
}
.share-modal-close:hover { background: var(--border); }

.share-modal-title {
  font-size: 17px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  text-align: center;
  margin-bottom: 0;
}
.share-modal-sub {
  font-size: 13px;
  color: var(--text-secondary);
  text-align: center;
  margin: -6px 0 0;
}

.share-platform-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.share-platform-grid--3col {
  grid-template-columns: 1fr 1fr 1fr;
}

.share-plat-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 12px 8px;
  border-radius: var(--r-lg);
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-primary);
  min-height: 64px;
  box-shadow: var(--shadow-sm);
  transition: transform 80ms ease, background 120ms ease, box-shadow 120ms ease;
}
.share-plat-btn:active { transform: scale(0.95); }
.share-plat-btn:hover  { background: var(--border); }

.share-plat-icon {
  width: 24px; height: 24px;
  flex-shrink: 0;
}

.share-copy-link-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 13px;
  border-radius: var(--r-lg);
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  transition: transform 80ms ease, background 120ms ease;
}
.share-copy-link-btn:active { transform: scale(0.97); }
.share-copy-link-btn:hover  { background: var(--border); }

/* ── Score share modal — thumbnail + caption preview ── */

.score-share-thumbnail {
  display: block;
  margin: 0 auto;
  height: 140px;
  width: auto;
  max-width: 100%;
  border-radius: 10px;
  object-fit: contain;
}

.score-share-caption-preview {
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  border-radius: var(--r-md);
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: pre-line;
  text-align: center;
}

/* ── Badge share modal — thumbnail + caption preview ── */

.badge-share-thumbnail {
  display: block;
  margin: 0 auto;
  height: 140px;
  width: auto;
  border-radius: 10px;
  object-fit: contain;
}

.badge-share-caption-preview {
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  border-radius: var(--r-md);
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: pre-line;
  text-align: center;
}

#badge-share-modal { z-index: 155; }

/* ── Referral modal — extends share-modal-card ── */

.referral-modal-card {
  gap: 16px;
}

/* Ambassador badge progress row */
.ref-ambassador-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
}

.ref-ambassador-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-secondary);
}

.ref-ambassador-dots {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ref-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--border);
  border: 2px solid var(--border);
  transition: background 200ms ease, border-color 200ms ease, transform 200ms ease;
}

.ref-dot--filled {
  background: #C8993A;
  border-color: #C8993A;
  transform: scale(1.12);
}

/* Total referral count — standalone stat below ambassador row */
.ref-total-count-row {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  padding: 10px 14px 4px;
}

.ref-total-count-number {
  font-size: 18px;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.ref-total-count-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* Ambassador unlocked banner — injected below dots row when referralCount >= 5 */
.ref-ambassador-unlocked-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background: rgba(200,153,58,0.12);
  border: 1.5px solid #C8993A;
  font-size: 13px;
  font-weight: 700;
  color: #C8993A;
  cursor: pointer;
  text-align: left;
  font-family: var(--font);
  transition: background 150ms ease;
}
.ref-ambassador-unlocked-btn:active { background: rgba(200,153,58,0.22); }
.ref-ambassador-unlocked-btn span {
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(200,153,58,0.5);
}

/* Referral link bar */
.ref-link-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 10px 14px;
  border-radius: var(--r-md);
  border: 1.5px solid var(--border);
  background: var(--bg);
  min-height: 48px;
}

.ref-link-text {
  flex: 1;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.1px;
}

.ref-link-copy-btn {
  flex-shrink: 0;
  padding: 6px 14px;
  border-radius: 8px;
  background: var(--text-primary);
  color: var(--bg-card);
  font-family: var(--font);
  font-size: 12px;
  font-weight: 800;
  transition: opacity 100ms ease;
}
.ref-link-copy-btn:active { opacity: 0.7; }

/* Platform grid — 3-column for referral modal */
.ref-platform-grid {
  grid-template-columns: 1fr 1fr 1fr;
}

.ref-subtitle {
  font-size: 13px;
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.5;
  margin-top: -4px;
}

/* ── Image share modal — shows card preview with save/copy/platforms ── */
.img-share-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.62);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 116;
  backdrop-filter: blur(6px);
  animation: fade-in 180ms ease-out;
  padding: 16px;
}
.img-share-overlay[hidden] { display: none; }

.img-share-card {
  position: relative;
  background: var(--bg-card);
  border-radius: var(--r-pill);
  padding: 28px 22px 28px;
  width: min(400px, 100%);
  max-height: 92dvh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  box-shadow: var(--shadow-lg);
  animation: card-rise 240ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

.img-share-close {
  position: absolute;
  top: 14px; right: 14px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bg-ability);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms ease;
}
.img-share-close:hover { background: var(--border); }

.img-share-preview {
  width: auto;
  max-width: 160px;
  max-height: 260px;
  border-radius: var(--r-md);
  object-fit: contain;
  box-shadow: var(--shadow-md);
  display: block;
}

.img-share-actions {
  display: flex;
  gap: 10px;
  width: 100%;
}
.img-share-actions .btn {
  flex: 1;
  font-size: 13px;
  padding: 11px 8px;
}

.img-share-platforms {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 9px;
  width: 100%;
}

.img-share-plat-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 11px 6px;
  border-radius: var(--r-md);
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  font-family: var(--font);
  font-size: 10px;
  font-weight: 700;
  color: var(--text-primary);
  min-height: 60px;
  transition: transform 80ms ease, background 120ms ease;
}
.img-share-plat-btn:active { transform: scale(0.95); }
.img-share-plat-btn:hover  { background: var(--border); }

.img-share-copy-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  padding: 12px;
  border-radius: var(--r-md);
  background: var(--bg-ability);
  border: 1.5px solid var(--border);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  transition: transform 80ms ease, background 120ms ease;
}
.img-share-copy-link:active { transform: scale(0.97); }
.img-share-copy-link:hover  { background: var(--border); }

/* ── Global share toast ── */
.share-toast {
  position: fixed;
  bottom: calc(var(--hud-bottom-height) + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  font-size: 12px;
  line-height: 1;
  font-weight: 700;
  padding: 8px 18px;
  border-radius: var(--r-pill);
  z-index: 200;
  pointer-events: none;
  white-space: nowrap;
  animation: toast-pop 200ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.share-toast[hidden] { display: none; }
@keyframes toast-pop {
  from { opacity: 0; transform: translateX(-50%) translateY(6px) scale(0.92); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0)   scale(1); }
}
.share-toast--hiding {
  animation: toast-fade-out 240ms ease forwards;
}
@keyframes toast-fade-out {
  from { opacity: 1; transform: translateX(-50%) scale(1); }
  to   { opacity: 0; transform: translateX(-50%) scale(0.94); }
}

/* ── Challenge banner — fixed top strip shown when ?beat=N URL param present ── */
.challenge-banner {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 201;
  background: #2C2C2E;
  color: #fff;
  text-align: center;
  padding: 10px 16px;
  font: 700 14px/1.4 var(--font);
  letter-spacing: 0.02em;
  pointer-events: none;
}
.challenge-banner[hidden] { display: none; }

/* ── Challenge result — shown in game-over card after ?beat= run ── */
.challenge-result {
  font: 700 13px/1.4 var(--font);
  color: var(--text-secondary, #8E8E93);
  text-align: center;
  padding: 4px 0 2px;
  margin-top: 2px;
}
.challenge-result[hidden] { display: none; }


/* ── Daily progress strip — shown below HUD during an active daily run ── */
.daily-progress-strip {
  display: flex;
  align-items: center;
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  border-radius: var(--r-pill);
  position: fixed;
  left: 50%;
  top: calc(var(--outer-pad-v-top) + var(--hud-top-height));
  transform: translateX(-50%);
  z-index: 20;
  width: auto;
  max-width: min(480px, calc(100vw - 40px));
  margin: 0;
  padding: 8px 18px;
  font-size: 12px;
  font-family: var(--font);
  line-height: 1;
  gap: 8px;
}
.daily-progress-strip[hidden] { display: none; }
.daily-progress-label {
  color: inherit;
  opacity: 0.75;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}
.daily-progress-value {
  color: inherit;
  font-weight: 700;
  white-space: nowrap;
  flex-shrink: 0;
  transition: color 200ms ease;
}
.daily-progress-value--met {
  color: var(--color-green, #9ECFB5);
}
.daily-progress-value--failed {
  color: var(--color-red, #EEAAAA);
}

/* ── Info toast — classic non-daily mode; daily CTA or nearest badge goal ── */
.info-toast {
  display: flex;
  align-items: center;
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  border-radius: var(--r-pill);
  position: fixed;
  left: 50%;
  top: calc(var(--outer-pad-v-top) + var(--hud-top-height));
  transform: translateX(-50%);
  z-index: 20;
  width: auto;
  max-width: min(480px, calc(100vw - 40px));
  margin: 0;
  padding: 8px 18px;
  gap: 8px;
  font-family: var(--font);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  overflow: hidden;
}
.info-toast[hidden] { display: none; }

/* CTA state */
.info-toast-label {
  font-weight: 700;
  color: inherit;
  white-space: nowrap;
}
.info-toast-sep {
  opacity: 0.5;
  flex-shrink: 0;
}
.info-toast-diff {
  font-size: 12px;
  opacity: 0.75;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.info-toast-action {
  font-size: 11px;
  font-weight: 700;
  color: var(--color-blue, #9ACFE8);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Badge goal state */
.info-toast-badge {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  min-width: 0;
  overflow: hidden;
}
.info-toast-badge-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.info-toast-badge-name {
  font-weight: 700;
  color: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 1;
  min-width: 0;
}
.info-toast-badge-away {
  font-size: 11px;
  opacity: 0.75;
  white-space: nowrap;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}
.info-toast-badge-reward {
  font-size: 11px;
  font-weight: 700;
  opacity: 0.75;
  text-transform: capitalize;
  white-space: nowrap;
  flex-shrink: 0;
}
.info-toast-prog {
  font-size: 11px;
  opacity: 0.60;
  white-space: nowrap;
  flex-shrink: 0;
}
.info-toast-bar-track {
  flex: 1;
  min-width: 44px;
  height: 5px;
  background: var(--border);
  border-radius: 3px;
  overflow: hidden;
}
.info-toast-bar-fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  transition: width 400ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
}


/* ── Daily challenge sheet overlay (z-109) ── */
.daily-sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 109;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: env(safe-area-inset-bottom, 0);
  background: rgba(0, 0, 0, 0.45);
}
.daily-sheet-overlay[hidden] { display: none; }
.daily-sheet-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.daily-sheet-overlay:not([hidden]) .daily-sheet-card {
  animation: share-slide-up 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.daily-sheet-card {
  background: var(--bg-card);
  border-radius: 20px 20px 0 0;
  width: 100%;
  max-width: 480px;
  padding-bottom: 24px;
  box-shadow: 0 -4px 24px rgba(0,0,0,0.14);
}
.daily-sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px 10px;
  border-bottom: 1px solid var(--border);
}
.daily-sheet-title {
  font-size: 15px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: 0.02em;
}
.daily-sheet-body {
  padding: 14px 18px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.daily-sheet-challenge {
  font-size: 18px;
  font-weight: 800;
  color: var(--text-primary);
  line-height: 1.2;
}
.daily-sheet-meta {
  font-size: 13px;
  color: var(--text-secondary);
  font-weight: 600;
}
.daily-sheet-reward {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  margin-top: 4px;
}
.daily-sheet-actions {
  padding: 4px 20px 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}
.daily-sheet-skip {
  background: none;
  border: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 6px 0;
  text-align: center;
  font-family: var(--font);
}
.daily-sheet-skip:hover { color: var(--text-primary); }
.daily-sheet-done {
  padding: 12px 20px 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.daily-sheet-done[hidden] { display: none; }
.daily-sheet-done-icon {
  font-size: 22px;
  color: var(--color-green, #9ECFB5);
}
.daily-sheet-done-text {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-green, #9ECFB5);
}

/* Daily "Try Again" button shown in game-over block when daily wasn't completed */
.daily-retry-btn {
  display: block;
  margin: 8px auto 0;
  background: none;
  border: 1.5px solid var(--color-blue, #9ACFE8);
  color: var(--color-blue, #9ACFE8);
  font: 700 13px/1 var(--font);
  padding: 7px 18px;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.daily-retry-btn:hover {
  background: rgba(154, 207, 232, 0.15);
}

/* ── R2 — Daily challenge result (game-over screen) ── */
.daily-challenge-result {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 4px 8px 0;
  font-size: 13px;
  font-weight: 600;
  border-radius: 8px;
  margin-top: 2px;
  text-align: center;
}
.daily-challenge-result[hidden] { display: none; }
.daily-challenge-result--complete {
  color: var(--color-green, #9ECFB5);
}
.daily-challenge-result--incomplete {
  color: var(--text-secondary);
  opacity: 0.72;
}
.daily-result-icon {
  font-size: 15px;
  flex-shrink: 0;
}
.daily-result-text {
  line-height: 1.3;
}

/* R2 — Daily dot: indicator on mode button when daily is not yet done */
.mode-btn {
  position: relative;
}
.daily-dot {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-alert);
  border: 1.5px solid var(--bg, #F5F0EB);
  pointer-events: none;
}
.daily-dot[hidden] { display: none; }

/* ── Daily streak screen overlay ── */
.streak-screen {
  position: fixed;
  inset: 0;
  z-index: 998;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.38);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 400ms ease;
  pointer-events: none;
}
.streak-screen--visible  { opacity: 1; pointer-events: auto; }
.streak-screen--out      { opacity: 0; }
.streak-screen[hidden]   { display: none; }

.streak-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  background: var(--bg-card);
  border-radius: var(--r-xl);
  padding: 28px 28px 24px;
  width: min(340px, 88vw);
  box-shadow: var(--shadow-lg);
}
/* Higher specificity (0,2,0) beats .streak-panel's (0,1,0) — ensures hidden attribute
   is not overridden by display:flex above. Without this, both panels render simultaneously. */
.streak-panel[hidden]  { display: none; }
.streak-panel--broken  { gap: 16px; }

/* fire icon */
.streak-fire-wrap {
  width: 64px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.streak-fire-svg { width: 100%; height: 100%; }
.streak-fire-wrap--broken { color: var(--text-secondary); filter: grayscale(1); opacity: 0.35; }

@keyframes streak-fire-flare {
  0%   { transform: scale(1)    translateY(0);    filter: drop-shadow(0 0 0px  #F5A33A); }
  30%  { transform: scale(1.24) translateY(-7px); filter: drop-shadow(0 3px 12px #F5A33A); }
  65%  { transform: scale(1.12) translateY(-3px); filter: drop-shadow(0 2px  7px #F5C842); }
  100% { transform: scale(1)    translateY(0);    filter: drop-shadow(0 0 0px  #F5C842); }
}
.streak-fire--flaring .streak-fire-svg {
  animation: streak-fire-flare 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

/* counter */
.streak-counter-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.streak-number {
  font-size: 88px;
  font-weight: 900;
  line-height: 1;
  color: var(--text-primary);
  letter-spacing: -0.04em;
}
.streak-day-label {
  font-size: 16px;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
}

@keyframes streak-number-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-28px); }
}
@keyframes streak-number-in {
  0%   { opacity: 0; transform: translateY(32px); }
  70%  { opacity: 1; transform: translateY(-6px); }
  100% { opacity: 1; transform: translateY(0); }
}
.streak-number--rolling { animation: streak-number-out 270ms ease-in  forwards; }
.streak-number--in      { animation: streak-number-in  360ms cubic-bezier(0.34, 1.56, 0.64, 1) both; }

/* reward pill */
.streak-reward-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  background: rgba(245, 200, 66, 0.15);
  border: 1px solid rgba(245, 200, 66, 0.38);
  border-radius: 999px;
  padding: 7px 18px;
}
.streak-reward-pill[hidden] { display: none; }

@keyframes streak-pill-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.streak-reward-pill--in { animation: streak-pill-in 380ms cubic-bezier(0.34, 1.56, 0.64, 1) both; }

.streak-reward-coin { font-size: 16px; line-height: 1; }
.streak-reward-text { font-size: 14px; font-weight: 600; color: #9A7000; }

/* milestone label */
@keyframes streak-text-pop {
  from { opacity: 0; transform: scale(0.82); }
  to   { opacity: 1; transform: scale(1); }
}
.streak-milestone-text {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.streak-milestone-text--in  { animation: streak-text-pop 300ms ease both; }
.streak-milestone-text[hidden] { display: none; }

/* tap-to-continue hint */
@keyframes streak-hint-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.streak-continue-hint {
  font-size: 13px;
  color: var(--text-secondary);
  opacity: 0.55;
  letter-spacing: 0.03em;
}
.streak-continue-hint--in   { animation: streak-hint-in 500ms ease both; }
.streak-continue-hint[hidden] { display: none; }

/* broken streak panel */
.streak-broken-headline {
  font-size: 26px;
  font-weight: 700;
  color: var(--text-primary);
  text-align: center;
  line-height: 1.2;
}
.streak-broken-sub {
  font-size: 14px;
  color: var(--text-secondary);
  text-align: center;
  margin-top: -8px;
}

/* restore card */
.streak-restore-card {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.streak-restore-card-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.streak-restore-cost-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.streak-restore-cost-label { font-size: 14px; color: var(--text-secondary); }
.streak-restore-cost-text  { font-size: 16px; font-weight: 700; color: #9A7000; }
.streak-restore-divider    { height: 1px; background: var(--border); }

.streak-restore-compare { display: flex; flex-direction: column; gap: 8px; }
.streak-restore-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.streak-restore-row-label     { font-size: 13px; color: var(--text-secondary); }
.streak-restore-row-val       { font-size: 14px; font-weight: 600; }
.streak-restore-row-val--gold { color: #9A7000; }
.streak-restore-row-val--dim  { color: var(--text-secondary); opacity: 0.5; }

.streak-restore-no-coins {
  font-size: 12px;
  color: var(--color-alert);
  text-align: center;
}
.streak-restore-no-coins[hidden] { display: none; }

.streak-restore-actions { display: flex; flex-direction: column; gap: 10px; width: 100%; }

.streak-btn {
  width: 100%;
  padding: 14px 20px;
  border-radius: var(--r-md);
  font-size: 15px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  letter-spacing: 0.01em;
  transition: opacity 150ms ease, transform 100ms ease;
}
.streak-btn:active           { transform: scale(0.97); }
.streak-btn:disabled         { opacity: 0.35; cursor: default; pointer-events: none; }
.streak-btn--primary         { background: #F5C842; color: #3A2800; }
.streak-btn--ghost           { background: transparent; color: var(--text-secondary); border: 1px solid var(--border); }

/* panel exit transition (broken → restored) */
@keyframes streak-panel-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-20px); }
}
.streak-panel--exit { animation: streak-panel-out 300ms ease both; }


/* ── 10. REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
  .block                  { transition: none; }
  .block--v11             { animation: none; }
  .block--value-leaving::after,
  .block--value-entering::after,
  .block--merging,
  .block--squishing-h,
  .block--squishing-v,
  .block--charging,
  .block--charging-blue,
  .block--charging-red,
  .block--charging-green,
  .block--charging-yellow,
  .block--destroying,
  .block--shattering,
  .block--exploding,
  .block--dissolving,
  .block--converting,
  .block--shuffle-out,
  .block--shuffle-in,
  .block--color-highlight,
  .block--color-dissolve,
  .block--spawning        { animation: none; }
  .effect-lightning-row,
  .effect-explosion-ring,
  .effect-green-shimmer,
  .effect-yellow-ripple   { animation: none; opacity: 0; }
  .combo-counter.combo-active { animation: none; opacity: 0; }
  .game-over-overlay      { animation: none; }
  .game-over-card         { animation: none; }
  .game-over-overlay:not([hidden]) .stat { animation: none; }
  .store-overlay:not([hidden]),
  .store-overlay:not([hidden]) .store-card,
  .notif-overlay:not([hidden]),
  .notif-overlay:not([hidden]) .notif-card,
  .mode-overlay:not([hidden]),
  .mode-overlay:not([hidden]) .mode-card,
  .collectibles-overlay:not([hidden]),
  .collectibles-overlay:not([hidden]) .collectibles-card,
  .badge-reveal-overlay:not([hidden]),
  .daily-sheet-overlay:not([hidden]),
  .daily-sheet-overlay:not([hidden]) .daily-sheet-card,
  .tutorial-overlay:not([hidden]),
  .tutorial-overlay:not([hidden]) .tutorial-prompt,
  .sound-popover:not([hidden]),
  .collectibles-panel:not([hidden]),
  .share-toast--hiding     { animation: none; }
}


/* ── 11. FOCUS RINGS (keyboard accessibility) ── */
/* Uses :focus-visible so rings only appear for keyboard nav, not mouse clicks. */
button:focus-visible {
  outline: 2px solid var(--color-yellow);
  outline-offset: 2px;
  border-radius: inherit;
}

/* ── 12. SCROLLBAR SUPPRESSION ── */
::-webkit-scrollbar { display: none; }

/* ── 13. STORE UPGRADE SYSTEM ── */
.store-section-header {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 10px 20px 2px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.store-section-rows {
  display: block;
}
.store-section-rows .store-row:last-of-type {
  border-bottom: none;
}
.store-row--placeholder {
  opacity: 0.4;
  pointer-events: none;
}
.store-row-name--dim {
  color: var(--text-secondary);
}
.store-section-note {
  font-size: 9px;
  letter-spacing: 0.06em;
  font-weight: normal;
  text-transform: none;
}
.store-section-note--warn { color: var(--color-warn); }
.store-row-subdesc {
  font-size: 10px;
  color: var(--text-secondary);
  opacity: 0.7;
  white-space: pre-line;
}
.store-buy-btn--maxed {
  background: var(--bg-ability) !important;
  color: var(--text-secondary) !important;
  pointer-events: none;
  opacity: 0.5;
}


/* ── Hint arrow overlay (shown on game grid) ── */
#hint-arrow {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 80px;
  color: rgba(255, 255, 255, 0.9);
  pointer-events: none;
  z-index: 50;
  animation: hint-appear 1.8s ease forwards;
  text-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}
#hint-arrow::before                   { content: '↑'; }
#hint-arrow[data-dir="down"]::before  { content: '↓'; }
#hint-arrow[data-dir="left"]::before  { content: '←'; }
#hint-arrow[data-dir="right"]::before { content: '→'; }
#hint-arrow[data-dir="up"]::before    { content: '↑'; }

@keyframes hint-appear {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  12%  { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
  25%  { opacity: 0.95; transform: translate(-50%, -50%) scale(1.0); }
  75%  { opacity: 0.9;  transform: translate(-50%, -50%) scale(1.0); }
  100% { opacity: 0;    transform: translate(-50%, -50%) scale(0.85); }
}

@keyframes tut-hint-bounce {
  0%   { opacity: 0;    transform: translateY(-5px); }
  18%  { opacity: 1;    transform: translateY(0);    }
  35%  { opacity: 0.9;  transform: translateY(5px);  }
  50%  { opacity: 0.9;  transform: translateY(0);    }
  65%  { opacity: 0.9;  transform: translateY(5px);  }
  80%  { opacity: 0.85; transform: translateY(1px);  }
  100% { opacity: 0;    transform: translateY(3px);  }
}


/* ── Mode selector overlay (z-108) ── */
.mode-overlay {
  position: fixed;
  inset: 0;
  z-index: 108;
  background: rgba(0, 0, 0, 0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.mode-overlay[hidden] {
  display: none;
}
.mode-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.mode-overlay:not([hidden]) .mode-card {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.mode-card {
  background: var(--bg-card);
  border-radius: 20px;
  width: min(340px, 100%);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  position: relative;
}

.mode-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}

.mode-title {
  font-size: 13px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.mode-list {
  padding: 8px 10px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mode-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--r-lg);
  border: 2px solid transparent;
  background: var(--bg-ability);
  text-align: left;
  gap: 10px;
  cursor: pointer;
  transition: background 120ms, border-color 120ms;
}

.mode-option:hover:not(.mode-locked):not(.mode-option--done):not(.mode-option--active) {
  background: rgba(0, 0, 0, 0.08);
}

[data-theme="dark"] .mode-option:hover:not(.mode-locked):not(.mode-option--done):not(.mode-option--active) {
  background: var(--border);
}

.mode-option--active {
  border-color: var(--color-yellow);
  background: rgba(245, 217, 138, 0.15);
}

[data-theme="dark"] .mode-option--active {
  background: rgba(245, 217, 138, 0.10);
}

.mode-locked {
  opacity: 0.55;
  cursor: default;
}

.mode-option--done {
  opacity: 0.45;
  cursor: default;
  pointer-events: none;
}

.mode-option-left {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.mode-option-name {
  font-size: 15px;
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.mode-option-desc {
  font-size: 12px;
  color: var(--text-secondary);
}

.mode-lock-hint {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  background: var(--bg-ability);
  border: 1px solid var(--border);
  padding: 3px 10px;
  border-radius: 8px;
  white-space: nowrap;
  flex-shrink: 0;
}

.mode-option--daily {
  border-color: var(--color-blue, #9ACFE8);
}
.mode-daily-indicator,
.mode-new-indicator {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-alert);
  flex-shrink: 0;
}
.mode-daily-indicator[hidden],
.mode-new-indicator[hidden] { display: none; }

.mode-settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px 14px;
  border-top: 1px solid rgba(0,0,0,0.07);
  margin-top: 4px;
}
[data-theme="dark"] .mode-settings-row {
  border-top-color: rgba(255,255,255,0.07);
}
.mode-settings-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.mode-bgm-btn {
  font-size: 12px;
  font-weight: 700;
  padding: 4px 14px;
  border-radius: 20px;
  border: 1.5px solid var(--text-secondary);
  background: var(--text-secondary);
  color: var(--bg);
  cursor: pointer;
  letter-spacing: 0.05em;
  transition: background 200ms, color 200ms, border-color 200ms;
}
.mode-bgm-btn--off {
  background: transparent;
  color: var(--text-secondary);
}

/* ── Badge reveal overlay (z-150) ── */
.badge-reveal-overlay {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.badge-reveal-overlay[hidden] { display: none; }
.badge-reveal-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}

.badge-reveal-card {
  background: var(--bg-card);
  border-radius: var(--r-pill);
  padding: 22px 20px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(340px, 90vw);
  box-shadow: var(--shadow-lg);
}

.badge-reveal-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--text-secondary);
  text-transform: uppercase;
}

.badge-reveal-stage {
  position: relative;
  width: 140px;
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.badge-reveal-rays {
  position: absolute;
  inset: -20px;
  animation: rays-spin 10s linear infinite;
}

.badge-ray {
  position: absolute;
  left: 50%;
  bottom: 50%;
  width: 3px;
  height: 90px;
  margin-left: -1.5px;
  border-radius: 2px;
  background: linear-gradient(to top, transparent 0%, rgba(245, 217, 138, 0.5) 100%);
  transform-origin: center bottom;
}

/* Badge container — shape and color now live inside the SVG itself */
.badge-hex {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.badge-hex--lg {
  width: 120px;
  height: 120px;
  animation: badge-scale-in 400ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
  position: relative;
  z-index: 1;
}

.badge-hex--sm {
  width: 68px;
  height: 68px;
}

.badge-hex--locked {
  filter: brightness(0) opacity(0.28);
}

.badge-icon {
  width: 100%;
  height: 100%;
  overflow: visible;
}

@keyframes badge-scale-in {
  0%   { transform: scale(0); }
  75%  { transform: scale(1.12); }
  100% { transform: scale(1.0); }
}

@keyframes rays-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.badge-reveal-name {
  font-size: 22px;
  font-weight: 800;
  color: var(--text-primary);
  text-align: center;
}

.badge-reveal-desc {
  font-size: 14px;
  color: var(--text-secondary);
  text-align: center;
  max-width: 260px;
}

.badge-reveal-reward {
  background: var(--color-yellow);
  color: rgba(45, 28, 12, 0.85);
  font-size: 13px;
  font-weight: 700;
  padding: 6px 14px;
  border-radius: 20px;
  text-align: center;
}

.badge-reveal-actions {
  display: flex;
  gap: 12px;
  margin-top: 4px;
  width: 100%;
}

/* ── Collectibles overlay (z-105) ── */
.collectibles-overlay {
  position: fixed;
  inset: 0;
  z-index: 105;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  padding: 20px 0;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.collectibles-overlay[hidden] { display: none; }
.collectibles-overlay:not([hidden]) {
  animation: fade-in 180ms ease-out both;
}
.collectibles-overlay:not([hidden]) .collectibles-card {
  animation: card-rise 260ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.collectibles-card {
  background: var(--bg-card);
  border-radius: 20px;
  width: min(380px, 94vw);
  max-height: min(90dvh, 90vh);
  flex-shrink: 0;
  margin: auto 0;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.collectibles-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px clamp(16px, 5.5%, 24px) 0;
  flex-shrink: 0;
}

.collectibles-tabs {
  display: flex;
  gap: 4px;
}

.collectibles-tab {
  background: none;
  border: none;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 800;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 6px 10px;
  border-radius: 8px;
  transition: background 100ms ease, color 100ms ease;
}
.collectibles-tab.active {
  background: var(--bg-ability);
  color: var(--text-primary);
}
.collectibles-tab[hidden] { display: none; }

.collectibles-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
  padding: 12px 18px 18px;
}

.collectibles-panel[hidden] { display: none; }
.collectibles-panel:not([hidden]) {
  animation: panel-fade-in 160ms ease both;
}
@keyframes panel-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.badge-collection-count {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  margin-bottom: 10px;
}

.badge-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.badge-cell {
  display: grid;
  grid-template-rows: auto auto 1fr auto auto;
  justify-items: center;
  row-gap: 4px;
}

/* Scroll-to highlight — added by openCollectiblesAtBadge() */
@keyframes badge-cell-highlight-pulse {
  0%, 100% { box-shadow: none; }
  30%       { box-shadow: 0 0 0 3px rgba(200,153,58,0.7); }
  70%       { box-shadow: 0 0 0 3px rgba(200,153,58,0.35); }
}
.badge-cell--highlight {
  animation: badge-cell-highlight-pulse 1.8s ease both;
  border-radius: var(--r-md);
}

.badge-cell-name {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-primary);
  text-align: center;
  line-height: 1.2;
}

.badge-progress-wrap {
  width: 56px;
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

.badge-progress-fill {
  height: 100%;
  background: var(--color-yellow);
  border-radius: 2px;
  transition: width 450ms var(--move-easing);
}

.badge-progress-label {
  font-size: 9px;
  color: var(--text-secondary);
}

.badge-progress-fill--done {
  background: var(--color-green);
}

.badge-cell-criteria {
  font-size: 9px;
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.3;
  max-width: 72px;
  align-self: center;
}

.badge-cell-reward-teaser {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.55;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}

.badge-cell--earned .badge-cell-reward-teaser {
  text-transform: none;
  letter-spacing: 0.01em;
  opacity: 0.75;
  color: var(--text-primary);
}

.badge-cell-progress {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

/* Cosmetics grid */
.cosmetics-section-label {
  font-size: 11px;
  font-weight: 800;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 10px 0 6px;
}

.cosmetics-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 8px;
}

.cosmetic-card {
  border: 2px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 10px;
  cursor: pointer;
  transition: border-color 100ms ease, box-shadow 100ms ease;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cosmetic-card:hover {
  border-color: var(--color-yellow);
}

.cosmetic-card--active {
  border-color: var(--color-yellow);
  box-shadow: 0 0 0 2px rgba(245, 217, 138, 0.4);
}

.cosmetic-card--locked {
  cursor: default;
  opacity: 0.85;
}
.cosmetic-card--locked:hover {
  border-color: var(--border);
}
.cosmetic-card--cant-afford {
  opacity: 0.5;
}

.cosmetic-buy-btn {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 20px;
  border: 1.5px solid var(--color-yellow);
  background: var(--color-yellow);
  color: rgba(45, 28, 12, 0.9);
  cursor: pointer;
  letter-spacing: 0.03em;
  transition: opacity 100ms;
  align-self: flex-start;
}
.cosmetic-buy-btn--disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: transparent;
  color: var(--text-secondary);
  border-color: var(--text-secondary);
}

.cosmetic-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
}

.cosmetic-equipped {
  font-size: 9px;
  font-weight: 800;
  background: var(--color-yellow);
  color: rgba(45, 28, 12, 0.85);
  padding: 2px 6px;
  border-radius: 8px;
  display: inline-block;
}

.cosmetic-equipped--off {
  background: transparent;
  color: var(--text-secondary);
  opacity: 0.45;
}

.effects-section-title {
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 12px 4px 4px;
}

.effects-section-hint {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-secondary);
  margin-left: 4px;
  opacity: 0.7;
}

/* ── Features panel ── */

.feature-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 4px;
  border-bottom: 1px solid var(--border);
}

.feature-row:last-child { border-bottom: none; }

.feature-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.feature-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
}

.feature-desc {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-secondary);
  opacity: 0.75;
}

.feature-toggle {
  font-size: 12px;
  font-weight: 700;
  padding: 6px 16px;
  border-radius: 20px;
  border: 2px solid var(--border);
  background: var(--bg-card);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color 100ms ease, color 100ms ease, background 100ms ease;
}

.feature-toggle--on {
  border-color: var(--color-green);
  color: var(--color-green);
  background: var(--bg-card);
}


/* ── Effect CSS classes ── */

/* ── Dynamic Powers: enhanced charge animations for all 4 colors ── */

.effect-dynamic-powers .block--charging-blue {
  animation: charge-blue-dynamic 180ms ease-in-out forwards !important;
}
@keyframes charge-blue-dynamic {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  40%  { transform: scale(1.42); opacity: 1;
         box-shadow: 0 0 0 8px rgba(154,207,232,0.95), 0 0 28px 14px rgba(154,207,232,0.75), 0 0 55px 28px rgba(154,207,232,0.35); }
  100% { transform: scale(1.10); opacity: 0; box-shadow: none; }
}

.effect-dynamic-powers .block--charging-red {
  animation: charge-red-dynamic 220ms ease-in-out forwards !important;
}
@keyframes charge-red-dynamic {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  50%  { transform: scale(1.60); opacity: 1;
         box-shadow: 0 0 0 8px rgba(238,170,170,1.0), 0 0 32px 16px rgba(238,170,170,0.8), 0 0 60px 32px rgba(238,170,170,0.4); }
  100% { transform: scale(1.20); opacity: 0; box-shadow: none; }
}

.effect-dynamic-powers .block--charging-green {
  animation: charge-green-dynamic 180ms ease-in-out forwards !important;
}
@keyframes charge-green-dynamic {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  35%  { transform: scale(1.35); opacity: 1;
         box-shadow: 0 0 0 6px rgba(158,207,181,0.95), 0 0 26px 14px rgba(158,207,181,0.7), 0 0 52px 26px rgba(158,207,181,0.35); }
  100% { transform: scale(0.75); opacity: 0; box-shadow: none; }
}

.effect-dynamic-powers .block--charging-yellow {
  animation: charge-yellow-dynamic 180ms ease-in-out forwards !important;
}
@keyframes charge-yellow-dynamic {
  0%   { transform: scale(1.00); opacity: 1; box-shadow: none; }
  42%  { transform: scale(1.48); opacity: 1;
         box-shadow: 0 0 0 8px rgba(245,217,138,1.0), 0 0 28px 14px rgba(245,217,138,0.85), 0 0 55px 28px rgba(245,217,138,0.45); }
  100% { transform: scale(1.15); opacity: 0; box-shadow: none; }
}

/* ── Dynamic Powers: per-block shimmer for Green (fires before dissolve) ── */

.block--shimmering-dynamic {
  animation: block-shimmer-dynamic 140ms ease-out forwards;
}
@keyframes block-shimmer-dynamic {
  0%   { filter: none; transform: scale(1.00); box-shadow: none; }
  40%  { filter: brightness(2.0) saturate(0.5); transform: scale(1.10);
         box-shadow: 0 0 12px 4px rgba(158,207,181,0.9); }
  100% { filter: none; transform: scale(1.00); box-shadow: none; }
}

/* ── Dynamic Powers: enhanced destruction animations ── */

.effect-dynamic-powers .block--shattering-dynamic {
  animation: block-shatter-dynamic 160ms ease-in forwards;
}
@keyframes block-shatter-dynamic {
  0%   { transform: scaleX(1.00) scaleY(1.00); opacity: 1; filter: none; }
  20%  { transform: scaleX(1.18) scaleY(0.65); opacity: 1; }
  100% { transform: scaleX(0.00) scaleY(0.25); opacity: 0; filter: blur(2px); }
}

.effect-dynamic-powers .block--exploding-dynamic {
  animation: block-explode-dynamic 190ms ease-out forwards;
}
@keyframes block-explode-dynamic {
  0%   { transform: scale(1.00) rotate(0deg);   opacity: 1; filter: none; }
  22%  { transform: scale(1.42) rotate(10deg);  opacity: 1; }
  100% { transform: scale(0.00) rotate(-14deg); opacity: 0; filter: blur(3px); }
}

.effect-dynamic-powers .block--dissolving-dynamic {
  animation: block-dissolve-dynamic 290ms ease-in forwards;
}
@keyframes block-dissolve-dynamic {
  0%   { transform: scale(1.00) rotate(0deg);   opacity: 1; filter: none; }
  18%  { transform: scale(1.10) rotate(7deg);   opacity: 0.9; }
  100% { transform: scale(0.08) rotate(-14deg); opacity: 0; filter: blur(2px); }
}

.effect-dynamic-powers .block--converting-dynamic {
  animation: block-convert-dynamic 360ms ease-out forwards;
}
@keyframes block-convert-dynamic {
  0%   { box-shadow: none; transform: scale(1.00); }
  22%  { box-shadow: 0 0 0 5px rgba(245,217,138,1.0), 0 0 20px 10px rgba(245,217,138,0.9);
         transform: scale(1.18); }
  65%  { box-shadow: 0 0 0 2px rgba(245,217,138,0.45), 0 0 10px 4px rgba(245,217,138,0.3);
         transform: scale(1.05); }
  100% { box-shadow: none; transform: scale(1.00); }
}

/* ── Dynamic Powers: new overlay element CSS ── */

.effect-lightning-row-dynamic {
  position: fixed;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(154,207,232,0.95) 8%,
    rgba(220,245,255,1.00) 35%,
    rgba(255,255,255,1.00) 50%,
    rgba(220,245,255,1.00) 65%,
    rgba(154,207,232,0.95) 92%,
    transparent 100%
  );
  animation: lightning-row-flash-dynamic 230ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
  border-radius: 2px;
}
@keyframes lightning-row-flash-dynamic {
  0%   { opacity: 0; transform: scaleY(0.08); }
  10%  { opacity: 1; transform: scaleY(1.30); }
  100% { opacity: 0; transform: scaleY(0.50); }
}

.effect-explosion-ring-dynamic {
  position: fixed;
  border-radius: 50%;
  border: 4px solid rgba(238,170,170,1.0);
  box-shadow: 0 0 22px 10px rgba(238,170,170,0.65), inset 0 0 14px rgba(238,170,170,0.3);
  animation: explosion-ring-dynamic 400ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes explosion-ring-dynamic {
  0%   { opacity: 1.0; transform: translate(-50%,-50%) scale(0.08); }
  40%  { opacity: 0.8; }
  100% { opacity: 0;   transform: translate(-50%,-50%) scale(1.00); }
}

.effect-green-shimmer-dynamic {
  position: fixed;
  border-radius: var(--r-lg);
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(158,207,181,0.75) 28%,
    rgba(200,240,218,0.90) 50%,
    rgba(158,207,181,0.75) 72%,
    transparent 100%
  );
  animation: green-sweep-dynamic 360ms ease-in-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes green-sweep-dynamic {
  0%   { opacity: 0; transform: translateY(-18%) scaleY(0.6); }
  22%  { opacity: 0.9; transform: translateY(0%) scaleY(1.0); }
  70%  { opacity: 0.75; transform: translateY(12%) scaleY(1.0); }
  100% { opacity: 0; transform: translateY(28%) scaleY(0.85); }
}

.effect-yellow-ripple-dynamic {
  position: fixed;
  border-radius: 50%;
  border: 3px solid rgba(245,217,138,1.0);
  box-shadow: 0 0 14px 4px rgba(245,217,138,0.7), 0 0 30px 10px rgba(245,217,138,0.35);
  animation: yellow-ripple-dynamic 400ms ease-out forwards;
  pointer-events: none;
  z-index: 50;
}
@keyframes yellow-ripple-dynamic {
  0%   { opacity: 1.0; transform: translate(-50%,-50%) scale(0.04); }
  18%  { opacity: 0.9; }
  100% { opacity: 0;   transform: translate(-50%,-50%) scale(1.00); }
}

@keyframes grid-shake-dynamic {
  0%, 100% { transform: translate(0, 0); }
  14%       { transform: translate(6px, 2px); }
  32%       { transform: translate(-6px, -2px); }
  50%       { transform: translate(5px, 1px); }
  68%       { transform: translate(-4px, -1px); }
  84%       { transform: translate(2px, 0); }
}

/* Shockwave ring (dynamically inserted element) */
.effect-shockwave-ring {
  position: fixed;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 200, 0.85);
  box-shadow: 0 0 20px 8px rgba(255, 255, 200, 0.4);
  pointer-events: none;
  z-index: 50;
  animation: shockwave-expand 400ms ease-out forwards;
  transform: translate(-50%, -50%);
}

@keyframes shockwave-expand {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.05); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(2.0); }
}


/* Reduced motion overrides for badge reveal */
@media (prefers-reduced-motion: reduce) {
  .badge-hex--lg,
  .badge-reveal-rays,
  .badge-reveal-card,
  .badge-reveal-overlay { animation: none !important; }
}

/* ============================================================ */
/* === WILD BLOCK                                             === */
/* Unlocked via the Chromatic badge. Rotates all 4 colors     === */
/* in a pinwheel — merges with any color on the board.        === */
/* ============================================================ */

/* overflow: hidden clips the rotating circle to the block's rounded shape */
.block--wild {
  background: none;
  overflow: hidden;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.50);
}

/* Pinwheel: a circle larger than the block rotates continuously.
   inset: -30% makes it 160% of the block size so corners are always
   covered at any rotation angle. border-radius: 50% keeps it circular. */
.block--wild::before {
  content: '';
  position: absolute;
  inset: -30%;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg at 50% 50%,
    var(--color-blue)   0deg   90deg,
    var(--color-green)  90deg  180deg,
    var(--color-yellow) 180deg 270deg,
    var(--color-red)    270deg 360deg
  );
  animation: wild-swirl 4s linear infinite;
  pointer-events: none;
}

@keyframes wild-swirl {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .block--wild::before { animation: none; }
}

/* ============================================================ */
/* === ×2 MULTIPLIER BLOCK                                   === */
/* Unlocked via the Erasure badge. Spawns at 4% rate from     === */
/* turn 30. Same-color merges multiply the run value by 2.    === */
/* ============================================================ */

/* Slightly lighter/more luminous than a standard block — feels charged.
   Double-ring box-shadow pulses gently, giving a premium halo effect. */
.block--multiplier {
  filter: brightness(1.18) saturate(0.88);
  animation: multiplier-gleam 2.5s ease-in-out infinite;
}

/* Yellow multiplier block: reduce brightness for legible white text while staying
   visibly distinct from normal yellow (more saturated, still slightly brighter). */
.block--yellow.block--multiplier {
  filter: brightness(1.08) saturate(1.12);
}

/* Diagonal glass highlight — premium gloss without visual noise */
.block--multiplier::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--r-sm);
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.28) 0%, transparent 55%);
  pointer-events: none;
}

/* '×2' label */
.block--multiplier::after {
  content: '×2';
  color: rgba(0, 0, 0, 0.75);
  font-size: 0.70em;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.22);
}

/* '×3' label override for factor-3 multiplier blocks */
.block--multiplier-x3::after {
  content: '×3';
}

/* Tight white ring + soft outer halo breathe in sync */
@keyframes multiplier-gleam {
  0%, 100% {
    box-shadow:
      0 0 0 2px rgba(255, 255, 255, 0.42),
      0 0 10px 2px rgba(255, 255, 255, 0.07),
      inset 0 0 8px  rgba(255, 255, 255, 0.13);
  }
  50% {
    box-shadow:
      0 0 0 2px rgba(255, 255, 255, 0.68),
      0 0 18px 6px rgba(255, 255, 255, 0.16),
      inset 0 0 12px rgba(255, 255, 255, 0.22);
  }
}

/* Suppress gleam during movement (same pattern as breathe suppression for v11) */
.grid.anim-active .block--multiplier {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .block--multiplier { animation: none; }
}

/* ── Block Effects ── */

/* Shared slow-sweep keyframe — used by Gilt block design and Pearl skin */
@keyframes pearl-sheen {
  0%, 18% { background-position: 260% center; }
  70%     { background-position: -60% center; }
  100%    { background-position: 260% center; }
}

/* ── Gilt (benefactor) — gold-leaf surface overlay, slow shimmer sweep ── */
.block-style-gilt .block {
  background-image:
    linear-gradient(135deg, rgba(255,228,150,0.42), rgba(190,150,70,0.30) 60%, rgba(150,112,44,0.34));
}
.block-style-gilt .block::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(105deg, transparent 30%, rgba(255,244,200,0.16) 50%, transparent 70%);
  background-size: 300% 100%;
  animation: pearl-sheen 6s ease-in-out infinite;
}

/* ── Pixel (detonator) — flat 8-bit, hard edges ── */
.block-style-pixel .block {
  border-radius: 0;
  background-image:
    linear-gradient(135deg, rgba(255,255,255,0.16) 0 50%, rgba(0,0,0,0.10) 50% 100%);
  image-rendering: pixelated;
}
.block-style-pixel .block::after {
  font-family: 'Courier New', ui-monospace, monospace;
  font-weight: 800;
  letter-spacing: 0.02em;
}

/* ── Wood (Day 7 streak) — fine horizontal grain ── */
.block-style-wood .block {
  border-radius: 3px;
  background-image:
    repeating-linear-gradient(0deg, rgba(60,38,18,0.10) 0 1px, transparent 1px 4px),
    linear-gradient(180deg, rgba(255,240,220,0.10), rgba(80,50,22,0.10));
}
.block-style-wood .block::after { font-weight: 800; }

/* ── Shard (annihilator) — fractured crystal facets ── */
.block-style-shard .block {
  background-image:
    linear-gradient(118deg, rgba(255,255,255,0.20) 0 38%, transparent 38%),
    linear-gradient(300deg, rgba(255,255,255,0.12) 0 32%, transparent 32%),
    linear-gradient(210deg, rgba(0,0,0,0.06)       0 46%, transparent 46%);
}
.block-style-shard .block::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background:
    linear-gradient(60deg,  transparent 48%, rgba(255,255,255,0.30) 49.5%, transparent 51%),
    linear-gradient(150deg, transparent 60%, rgba(255,255,255,0.18) 61%,   transparent 62%);
}

/* ── Gel (flash-mob) — glossy inflated pillow; box-shadow needs baked keyframes ──
   The breathe and multiplier-gleam animations set box-shadow in every keyframe, which
   would override the gel depth. Baked variants merge the gel insets into each frame. */
.block-style-gel .block {
  border-radius: 32%;
  background-image: radial-gradient(circle at 50% 26%, rgba(255,255,255,0.55), transparent 46%);
  box-shadow: inset 0 3px 6px rgba(255,255,255,0.45), inset 0 -5px 9px rgba(0,0,0,0.16);
}
.block-style-gel .block--v11 { animation: breathe-gel 1.8s ease-in-out infinite; }
.block-style-gel.grid.anim-active .block--v11 { animation: none; }
@keyframes breathe-gel {
  0%, 100% {
    transform: scale(1.00);
    box-shadow: inset 0 3px 6px rgba(255,255,255,0.45), inset 0 -5px 9px rgba(0,0,0,0.16),
                inset 0 0 10px rgba(255,255,255,0.35);
  }
  50% {
    transform: scale(1.05);
    box-shadow: inset 0 3px 6px rgba(255,255,255,0.55), inset 0 -5px 9px rgba(0,0,0,0.18),
                inset 0 0 18px rgba(255,255,255,0.55), 0 0 10px var(--v11-glow);
  }
}
.block-style-gel .block--multiplier { animation: multiplier-gleam-gel 2.5s ease-in-out infinite; }
.block-style-gel.grid.anim-active .block--multiplier { animation: none; }
@keyframes multiplier-gleam-gel {
  0%, 100% {
    box-shadow:
      inset 0 3px 6px rgba(255,255,255,0.45), inset 0 -5px 9px rgba(0,0,0,0.16),
      0 0 0 2px rgba(255,255,255,0.42), 0 0 10px 2px rgba(255,255,255,0.07),
      inset 0 0 8px rgba(255,255,255,0.13);
  }
  50% {
    box-shadow:
      inset 0 3px 6px rgba(255,255,255,0.45), inset 0 -5px 9px rgba(0,0,0,0.16),
      0 0 0 2px rgba(255,255,255,0.68), 0 0 18px 6px rgba(255,255,255,0.16),
      inset 0 0 12px rgba(255,255,255,0.22);
  }
}

/* ── Origami (obliterator) — colored paper square: matte wash, diagonal fold crease,
   lifted corner fold, paper-stack shadow. Flat and geometric; anti-shine, anti-gel. ── */
.block-style-origami .block {
  border-radius: 3px;
  /* White wash: desaturates block color to read as paper rather than plastic */
  background-image: linear-gradient(rgba(255,255,255,0.13), rgba(255,255,255,0.10));
  /* Paper stack: two-layer stepped offset — no blur, literal paper thickness */
  box-shadow: 2px 2px 0 rgba(0,0,0,0.10), 3px 3px 0 rgba(0,0,0,0.05);
}
.block-style-origami .block::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background:
    /* Corner fold: 13×13 white triangle at bottom-right — the lifted paper corner */
    linear-gradient(135deg, transparent 50%, rgba(255,255,255,0.42) 50%)
      bottom right / 13px 13px no-repeat,
    /* Diagonal fold crease: thin highlight + shadow line at 45° */
    linear-gradient(135deg,
      rgba(255,255,255,0.07) 0 calc(50% - 0.5px),
      rgba(255,255,255,0.32) calc(50% - 0.5px) 50%,
      rgba(0,0,0,0.07) 50% calc(50% + 0.75px),
      transparent calc(50% + 0.75px)
    );
}
/* Number: slightly lighter weight than wood/pixel — precision over heaviness */
.block-style-origami .block::after { font-weight: 600; }
/* v11 lift: shadow deepens slowly as if the block is peeling up under pressure */
.block-style-origami .block--v11 { animation: origami-lift 2.4s ease-in-out infinite; }
.block-style-origami.grid.anim-active .block--v11 { animation: none; }
@keyframes origami-lift {
  0%, 100% { box-shadow: 2px 2px 0 rgba(0,0,0,0.10), 3px 3px 0 rgba(0,0,0,0.05); }
  50%       { box-shadow: 3px 3px 0 rgba(0,0,0,0.15), 5px 5px 0 rgba(0,0,0,0.08); }
}

/* ── Laptop refinement (non-touch, short viewport) ─────────────────────────
   Desktops tall enough to clear 880px sit ABOVE this and are untouched — they
   stay on the base fluid scale (grid at the 72px width cap, full-size ability
   bar). On shorter NON-TOUCH laptop viewports the base scale has already hit
   its vh-term floor, so the only way to free more grid height / shrink the
   ability bar further WITHOUT also shrinking the desktop bar (they share one
   vh curve) is this height-gated override. Overriding the input vars is enough
   — :root's --cell-size references them via var() and re-resolves here.
   Touch devices are excluded via hover/pointer and keep their taller-bar
   layout (body.touch-device wins by specificity regardless). */
@media (hover: hover) and (pointer: fine) and (max-height: 880px) {
  :root {
    --hud-bottom-height: clamp(84px, 10vh, 104px);   /* was 110 base; floor 84 leaves room for the aspect-ratio ability buttons */
    --outer-pad-v-top:   clamp(72px, 12vh, 130px);   /* top toast/tooltip lane — kept the roomiest of the three */
    --outer-pad-v-bot:   clamp(52px, 9.5vh, 112px);  /* bottom toast lane */
  }
  /* Ability-button + HUD-icon SIZING lives in the touchscreen-laptop block below
     (gated on a coarse pointer being present) so it tracks the device, not the
     viewport height. This block only frees grid height. */
}

/* ── Landscape / Small Viewport Fix ────────────────────────────────────────
   On landscape phones (e.g. 375px tall) the height-driven cell formula yields
   microscopic cells. This override switches to a width-capped + height-limited
   formula with compressed HUD heights so the grid stays playable (~31px cells). */
@media (orientation: landscape) and (max-height: 520px) {
  :root {
    --hud-top-height:    64px;
    --hud-bottom-height: 70px;
    --outer-pad-h:       28px;
    --outer-pad-v-top:   10px;
    --outer-pad-v-bot:   10px;
    --cell-size: min(
      calc((min(100vw, 480px) - 88px) / 5),
      calc((100vh  - 188px) / 6)
    );
  }
  @supports (height: 1dvh) {
    :root {
      --cell-size: min(
        calc((min(100vw, 480px) - 88px) / 5),
        calc((100dvh - 188px) / 6)
      );
    }
  }
  body.touch-device {
    --hud-bottom-height: 86px;
    --cell-size: min(
      calc((min(100vw, 480px) - 108px) / 5),
      calc((100vh  - 206px) / 6)
    );
  }
  @supports (height: 1dvh) {
    body.touch-device {
      --cell-size: min(
        calc((min(100vw, 480px) - 108px) / 5),
        calc((100dvh - 206px) / 6)
      );
    }
  }
  .score-value        { font-size: 18px; }
  .score-label        { font-size: 9px; }
  .game-title .logo-img { height: 24px; width: auto; }
  .ability-btn        { min-height: 48px; }
  .ability-name       { font-size: 9px; }
  .info-toast              { display: none; }
  .daily-progress-strip    { display: none; }
}

/* ── Touch Optimisation ─────────────────────────────────────────────────────
   Targets body.touch-device (set by JS via isTouchDevice() in input.js),
   which uses navigator.maxTouchPoints > 0 as its primary signal — correctly
   catches iPads and hybrid devices that report pointer:fine due to Pencil/
   keyboard, which would cause @media (hover:none) and (pointer:coarse) to
   miss them entirely.
   · 44px minimum tap targets on all small interactive elements
   · Larger HUD icons, ability buttons, score fonts, and ability labels
   · Cell-size formula updated to compensate for the taller bottom HUD
     New offsets: hud-top(104) + hud-bot(140) + v-top(58) + v-bot(48) + 2×pad(16) + gaps
     Classic 6 rows: 406 (vh) / 410 (dvh)
     All modes (Classic, Sprint, Gauntlet) use the same 6-row formula
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Layout: taller bottom HUD + smaller grid to compensate ── */
body.touch-device {
  --hud-bottom-height: 140px;
  --move-duration: 100ms;
  /* Touch keeps slightly tighter lanes (the 140px hud-bottom already adds breathing room below).
     No hover tooltip on touch, so the top lane needn't clear it — kept moderate to limit grid shrink. */
  --outer-pad-v-top: clamp(72px, 9.5vh, 104px);
  --outer-pad-v-bot: clamp(62px, 8vh, 90px);
  --cell-size: min(
    calc((min(100vw, 480px) - 120px) / 5),
    calc((100vh - var(--hud-top-height) - var(--hud-bottom-height)
                - var(--outer-pad-v-top) - var(--outer-pad-v-bot) - var(--v-chrome)) / 6)
  );
}
@supports (height: 1dvh) {
  body.touch-device {
    --cell-size: min(
      calc((min(100vw, 480px) - 120px) / 5),
      calc((100dvh - var(--hud-top-height) - var(--hud-bottom-height)
                  - var(--outer-pad-v-top) - var(--outer-pad-v-bot) - var(--v-chrome)) / 6)
    );
  }
}


/* ── Score display: larger numbers and labels ── */
body.touch-device .score-label { font-size: 12px; }
body.touch-device .score-value { font-size: 28px; }

/* ── Top-bar icon buttons: 28×28 → 36×36 visual, 44×44 tap area ── */
body.touch-device .meta-btn {
  width: 36px;
  height: 36px;
  min-width: 44px;
  min-height: 44px;
}
body.touch-device .btn-icon {
  width: 22px;
  height: 22px;
}
/* Larger touch buttons (36px box, 22px glyph → ~7px inset) need a deeper pull to stay flush. */
body.touch-device .score-meta        { margin-left: -7px; }
body.touch-device .score-meta--right { margin-left: 0; margin-right: -7px; }

/* ── Best-stats popover: larger fonts for legibility ── */
body.touch-device .best-stats-popover {
  width: 216px;
  padding: 14px 16px;
}
body.touch-device .best-stats-title { font-size: 12px; }
body.touch-device .best-stats-label { font-size: 13px; }
body.touch-device .best-stats-value { font-size: 15px; }

/* ── Ability buttons: taller + larger icon + larger labels ── */
body.touch-device .ability-btn {
  min-height: 72px;
  padding: 8px 4px;
  gap: 5px;
}
body.touch-device .ability-icon .btn-icon {
  width: 23px;
  height: 23px;
}
body.touch-device .ability-name   { font-size: 11px; }
body.touch-device .ability-charge { font-size: 10px; top: 8px; right: 10px; }

/* ── Small UI elements: minimum tap targets ── */
/* Expand tap target to 44px via pseudo-element so the visual circle stays small */
body.touch-device .coin-btn,
body.touch-device .tut-help-btn    { position: relative; }
body.touch-device .coin-btn::before,
body.touch-device .tut-help-btn::before {
  content: '';
  position: absolute;
  inset: -8px;
}
body.touch-device .store-close-btn { min-width: 44px; min-height: 44px; }
body.touch-device .store-qty-btn   { min-width: 44px; min-height: 44px; }
body.touch-device .btn--secondary  { min-height: 44px; }

/* Tooltip suppression on touch (no hover state to dismiss it). */
@media (hover: none) { .meta-btn::after { display: none; } }


/* ── Touchscreen laptop: comfortable controls ──────────────────────────────
   A touch-capable device whose PRIMARY pointer is precise (trackpad/mouse) and
   that can hover = a touchscreen laptop (or touch all-in-one). It runs the
   desktop/laptop GRID layout (big grid), but desktop-size HUD icons + ability
   buttons are too small / too flat on it. Restore touch-comfortable control
   sizing here — without re-shrinking the grid.
   Excludes phones/tablets (primary pointer coarse → no match) and mouse-only
   desktops (no coarse pointer present → no match). */
@media (hover: hover) and (pointer: fine) and (any-pointer: coarse) {
  /* HUD top-bar icons — back to the size they were under the touch layout. */
  .meta-btn           { width: 36px; height: 36px; min-width: 44px; min-height: 44px; }
  .meta-btn .btn-icon { width: 22px; height: 22px; }
  .score-meta         { margin-left: -7px; }
  .score-meta--right  { margin-left: 0; margin-right: -7px; }

  /* Ability buttons — slightly smaller than the standard touch button (72px) but
     the SAME ~4:3 aspect ratio (not flattened): proportionally scaled box, glyph
     and label; max-width holds the width-to-height proportion. */
  .ability-btn            { min-height: 60px; max-width: 80px; padding: 7px 4px; gap: 4px; }
  .ability-icon .btn-icon { width: 21px; height: 21px; }
  .ability-name           { font-size: 10px; }
}

/* ── Aurora Skin ────────────────────────────────────────────────────────────
   Premium aurora borealis skin: night sky, living polar-light curtains,
   crystalline grid, iridescent blocks.

   Layer stack (back to front):
     body background      — deep space starfield (page margins + overlays)
     .skin-aurora bg      — aurora-gradient grid frame; outer halo cycles
     .grid-cell           — frosted crystal panes
     .block + ::before    — vivid iridescent block shimmer
     .skin-aurora::before — green aurora curtain across board face (z:2)
     .skin-aurora::after  — blue + violet curtain across board face (z:2)

   Outer halo excluded from danger states via :not() so danger-pulse
   box-shadow animations (same property) always win. */

/* ── Night sky: deep space starfield visible in page margins and overlays ── */
body:has(.skin-aurora) {
  background-color: #030810;
  background-image:
    /* Aurora bands near the top of the viewport */
    radial-gradient(ellipse 110% 40% at 20%  0%, rgba(40,220,130,0.13) 0%, transparent 60%),
    radial-gradient(ellipse  90% 50% at 75%  0%, rgba(60,160,255,0.10) 0%, transparent 55%),
    radial-gradient(ellipse  80% 30% at 50%  5%, rgba(150,70,255,0.08) 0%, transparent 50%),
    /* Star field — fixed-position dots scattered across the viewport */
    radial-gradient(1.5px 1.5px at  8%  10%, rgba(255,255,255,0.75) 0%, transparent 100%),
    radial-gradient(1px   1px   at 22%   6%, rgba(255,255,255,0.50) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 38%  14%, rgba(255,255,255,0.65) 0%, transparent 100%),
    radial-gradient(1px   1px   at 52%   4%, rgba(255,255,255,0.45) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 67%  11%, rgba(255,255,255,0.70) 0%, transparent 100%),
    radial-gradient(1px   1px   at 81%   7%, rgba(255,255,255,0.55) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 93%  16%, rgba(255,255,255,0.60) 0%, transparent 100%),
    radial-gradient(1px   1px   at 14%  28%, rgba(255,255,255,0.40) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 31%  35%, rgba(255,255,255,0.55) 0%, transparent 100%),
    radial-gradient(1px   1px   at 46%  22%, rgba(255,255,255,0.45) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 59%  31%, rgba(255,255,255,0.50) 0%, transparent 100%),
    radial-gradient(1px   1px   at 74%  19%, rgba(255,255,255,0.60) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 88%  40%, rgba(255,255,255,0.40) 0%, transparent 100%),
    radial-gradient(1px   1px   at  5%  55%, rgba(255,255,255,0.55) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 19%  48%, rgba(255,255,255,0.35) 0%, transparent 100%),
    radial-gradient(1px   1px   at 36%  62%, rgba(255,255,255,0.45) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 62%  57%, rgba(255,255,255,0.50) 0%, transparent 100%),
    radial-gradient(1px   1px   at 78%  68%, rgba(255,255,255,0.40) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 95%  52%, rgba(255,255,255,0.55) 0%, transparent 100%),
    radial-gradient(1px   1px   at 27%  78%, rgba(255,255,255,0.35) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 44%  85%, rgba(255,255,255,0.45) 0%, transparent 100%),
    radial-gradient(1px   1px   at 71%  82%, rgba(255,255,255,0.50) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 85%  90%, rgba(255,255,255,0.40) 0%, transparent 100%);
}

/* ── Grid: outer aurora halo — cycles green → blue → violet (2× prior intensity) ── */
.skin-aurora:not(.grid--danger-1):not(.grid--danger-2):not(.grid--danger-3) {
  animation: aurora-glow-cycle 12s ease-in-out infinite;
}

@keyframes aurora-glow-cycle {
  0%, 100% {
    box-shadow:
      0 4px 20px rgba(0,0,0,0.65),
      0 0 22px 4px rgba(48,220,130,0.44),
      0 0 38px 6px rgba(48,220,130,0.18);
  }
  33% {
    box-shadow:
      0 4px 20px rgba(0,0,0,0.65),
      0 0 22px 4px rgba(80,160,255,0.48),
      0 0 38px 6px rgba(80,160,255,0.20);
  }
  66% {
    box-shadow:
      0 4px 20px rgba(0,0,0,0.65),
      0 0 22px 4px rgba(168,70,255,0.40),
      0 0 38px 6px rgba(168,70,255,0.15);
  }
}

/* ── Grid cells: frosted crystal panes ── */
.skin-aurora .grid-cell {
  background: rgba(6,12,42,0.72);
  box-shadow: inset 0 0 0 0.5px rgba(100,180,255,0.14);
}

/* ── Aurora curtain — green band across the board face, slow breathe (14s) ──
   position: absolute + z:2 sits above blocks (position:relative, z:auto)
   and above grid cells (non-positioned). pointer-events:none ensures no
   touch/click interference. */
.skin-aurora::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 14px;
  pointer-events: none;
  z-index: 2;
  background: radial-gradient(
    ellipse 90% 65% at 18% 28%,
    rgba(48,220,130,0.30) 0%,
    rgba(40,200,150,0.10) 45%,
    transparent 70%
  );
  animation: aurora-green-pulse 14s ease-in-out infinite;
}

/* ── Aurora curtain — blue + violet bands, faster breathe (10s, −4s offset) ── */
.skin-aurora::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 14px;
  pointer-events: none;
  z-index: 2;
  background:
    radial-gradient(ellipse 75% 58% at 82% 38%,
      rgba(80,160,255,0.25) 0%,
      rgba(80,160,255,0.08) 45%,
      transparent 68%),
    radial-gradient(ellipse 65% 52% at 50% 80%,
      rgba(160,70,255,0.20) 0%,
      rgba(140,60,240,0.07) 40%,
      transparent 62%);
  animation: aurora-blue-pulse 10s ease-in-out infinite;
  animation-delay: -4s;
}

@keyframes aurora-green-pulse {
  0%, 100% { opacity: 0.40; }
  40%       { opacity: 0.88; }
  70%       { opacity: 0.55; }
}

@keyframes aurora-blue-pulse {
  0%, 100% { opacity: 0.35; }
  35%       { opacity: 0.82; }
  65%       { opacity: 0.50; }
}

/* ── Blocks: stronger iridescent depth + vivid aurora shimmer ── */
.skin-aurora .block {
  box-shadow: inset 0 0 18px rgba(80,140,255,0.22);
}

/* Block aurora shimmer: slow-drifting aurora gradient across the block face.
   On ::before so it never conflicts with any animation on .block itself. */
.skin-aurora .block::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    135deg,
    rgba(48,220,130,0.22) 0%,
    rgba(80,160,255,0.18) 50%,
    rgba(168,70,255,0.20) 100%
  );
  background-size: 200% 200%;
  animation: aurora-block-drift 10s ease-in-out infinite;
  pointer-events: none;
}

@keyframes aurora-block-drift {
  0%   { background-position: 0% 0%; }
  50%  { background-position: 100% 100%; }
  100% { background-position: 0% 0%; }
}

/* Wild block pinwheel override — restores the conic-gradient over any skin/effect ::before shimmer.
   These rules sit after every skin/effect ::before rule in source order, so they win all
   same-specificity ties. The reduced-motion animation:none rules below appear even later
   and therefore correctly suppress the wild rotation under prefers-reduced-motion. */
.skin-aurora .block--wild::before {
  background: conic-gradient(
    from 0deg at 50% 50%,
    var(--color-blue)   0deg   90deg,
    var(--color-green)  90deg  180deg,
    var(--color-yellow) 180deg 270deg,
    var(--color-red)    270deg 360deg
  );
  inset: -30%;
  border-radius: 50%;
  animation: wild-swirl 4s linear infinite;
}
/* Origami ::before sets inset:0 and border-radius:inherit — both must be
   restored here so the pinwheel circle covers the block corners correctly.
   White wash sits as the top background layer so the pinwheel colors match
   the muted paper palette of normal origami blocks. */
.block-style-origami .block--wild::before {
  background:
    linear-gradient(rgba(255,255,255,0.12), rgba(255,255,255,0.12)),
    conic-gradient(
      from 0deg at 50% 50%,
      var(--color-blue)   0deg   90deg,
      var(--color-green)  90deg  180deg,
      var(--color-yellow) 180deg 270deg,
      var(--color-red)    270deg 360deg
    );
  inset: -30%;
  border-radius: 50%;
  animation: wild-swirl 4s linear infinite;
}

/* Respect reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
  body:has(.skin-aurora) { background-image: none; }
  body.skin-cosmos-bg    { background-image: none; }
  .skin-aurora { animation: none; }
  .skin-aurora::before { animation: none; }
  .skin-aurora::after  { animation: none; }
  .skin-aurora .block::before           { animation: none; }
  .skin-pearl  .block::before           { animation: none; }
  .block-style-gilt   .block::before    { animation: none; }
  .block-style-origami .block--v11      { animation: none; }
}



/* ── Animated / Patterned Skin Backgrounds ─────────────────────────────────
   Solid skins (Ash, Obsidian, Storm, Halo) need no CSS — their SKIN_DEFS vars
   already override all colour tokens. These rules add optional body-level
   gradients/patterns for skins that have a body-level cssClass. */

/* Cosmos — faint starfield on page background */
body.skin-cosmos-bg {
  background-image:
    radial-gradient(1px 1px at 20% 30%, rgba(255,255,255,0.35), transparent),
    radial-gradient(1px 1px at 70% 65%, rgba(255,255,255,0.28), transparent),
    radial-gradient(1px 1px at 45% 80%, rgba(255,255,255,0.22), transparent),
    radial-gradient(1px 1px at 85% 20%, rgba(255,255,255,0.30), transparent);
  background-attachment: fixed;
}

/* Sunrise — soft dawn gradient, deep ember at base → pale gold at top */
body.skin-sunrise-bg {
  background-image: linear-gradient(180deg, #5A2C1C 0%, #3A2018 45%, #2A1611 100%);
  background-attachment: fixed;
}

/* Devoted — champagne woven crosshatch, extremely low contrast */
body.skin-devoted-bg {
  background-image:
    repeating-linear-gradient( 45deg, rgba(230,200,142,0.035) 0 2px, transparent 2px 7px),
    repeating-linear-gradient(-45deg, rgba(230,200,142,0.035) 0 2px, transparent 2px 7px);
  background-attachment: fixed;
}

/* Pearl — slow iridescent sheen on each block face (::before, never conflicts with
   breathe/merge/charge box-shadow on .block). Reuses pearl-sheen keyframe from §Block Designs. */
.skin-pearl .block::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(120deg,
    rgba(214,196,232,0.0) 30%, rgba(214,196,232,0.22) 45%,
    rgba(190,228,214,0.20) 52%, rgba(244,206,216,0.18) 60%, rgba(214,196,232,0.0) 75%);
  background-size: 300% 100%;
  animation: pearl-sheen 7s ease-in-out infinite;
}

/* Wild blocks: restore pinwheel (::before is overridden by pearl sheen above).
   Pearl wash sweeps across the rotating pinwheel — wild-swirl and pearl-sheen
   animate different properties (transform vs background-position) so both run. */
.skin-pearl .block--wild::before {
  background:
    linear-gradient(120deg,
      rgba(214,196,232,0.0) 30%, rgba(214,196,232,0.22) 45%,
      rgba(190,228,214,0.20) 52%, rgba(244,206,216,0.18) 60%, rgba(214,196,232,0.0) 75%),
    conic-gradient(
      from 0deg at 50% 50%,
      var(--color-blue)   0deg   90deg,
      var(--color-green)  90deg  180deg,
      var(--color-yellow) 180deg 270deg,
      var(--color-red)    270deg 360deg
    );
  background-size: 300% 100%, auto;
  inset: -30%;
  border-radius: 50%;
  animation: wild-swirl 4s linear infinite, pearl-sheen 7s ease-in-out infinite;
}


/* ── PWA install prompt ── */

#pwa-card,
#pwa-ios-guide {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--bg, #F5F0EB);
  border-radius: 20px 20px 0 0;
  padding: 24px 24px 40px;
  box-shadow: 0 -6px 32px rgba(0, 0, 0, 0.14);
  z-index: 1000;
  text-align: center;
  font-family: 'Nunito', system-ui, sans-serif;
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

#pwa-card.pwa-card--visible,
#pwa-ios-guide.pwa-card--visible {
  transform: translateY(0);
}

.pwa-card-icon {
  width: 64px;
  height: 64px;
  background: #F5C842;
  border-radius: var(--r-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 800;
  color: #fff;
  margin: 0 auto 16px;
  letter-spacing: -0.5px;
}

.pwa-card-title {
  font-size: 18px;
  font-weight: 800;
  color: var(--text, #1a1a1a);
  margin-bottom: 8px;
}

.pwa-card-body {
  font-size: 14px;
  color: var(--text-muted, #666);
  line-height: 1.5;
  margin-bottom: 24px;
  max-width: 300px;
  margin-left: auto;
  margin-right: auto;
}

.pwa-card-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 300px;
  margin: 0 auto;
}

.pwa-btn-primary {
  background: #F5C842;
  color: #1a1a1a;
  border: none;
  border-radius: var(--r-md);
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 800;
  font-family: inherit;
  cursor: pointer;
  width: 100%;
  transition: opacity 0.15s;
}

.pwa-btn-primary:active { opacity: 0.75; }

.pwa-btn-secondary {
  background: transparent;
  color: var(--text-muted, #888);
  border: none;
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  width: 100%;
  transition: opacity 0.15s;
}

.pwa-btn-secondary:active { opacity: 0.6; }

/* iOS step-by-step guide */
.pwa-ios-inner { text-align: left; max-width: 320px; margin: 0 auto; }
.pwa-ios-inner .pwa-card-title { text-align: center; margin-bottom: 20px; }

.pwa-ios-steps {
  list-style: none;
  padding: 0;
  margin: 0 0 24px;
  counter-reset: step;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.pwa-ios-steps li {
  counter-increment: step;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 14px;
  color: var(--text, #1a1a1a);
  line-height: 1.45;
}

.pwa-ios-steps li::before {
  content: counter(step);
  min-width: 24px;
  height: 24px;
  background: #F5C842;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  margin-top: 1px;
}

.pwa-ios-inner .pwa-btn-primary { margin-top: 4px; }

.pwa-share-icon {
  display: inline-block;
  font-style: normal;
  font-weight: 700;
  color: #3478f6;
}

/* Decline toast */
#pwa-toast {
  position: fixed;
  bottom: calc(var(--hud-bottom-height, 110px) + 12px);
  left: 12px;
  right: 12px;
  background: rgba(30, 30, 30, 0.93);
  color: #fff;
  border-radius: var(--r-md);
  padding: 12px 12px 12px 16px;
  font-size: 13px;
  font-family: 'Nunito', system-ui, sans-serif;
  line-height: 1.5;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  z-index: 1000;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.25s, transform 0.25s;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

#pwa-toast.pwa-toast--visible {
  opacity: 1;
  transform: translateY(0);
}

.pwa-toast-text { flex: 1; }
.pwa-toast-text strong { color: #F5C842; font-weight: 700; }

.pwa-toast-dismiss {
  background: none;
  border: none;
  color: rgba(255,255,255,0.55);
  font-size: 14px;
  cursor: pointer;
  padding: 2px 4px;
  flex-shrink: 0;
  line-height: 1;
}

/* ── Push notification first-visit prompt ── */

#push-prompt-card {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--bg, #F5F0EB);
  border-radius: 20px 20px 0 0;
  padding: 24px 24px 40px;
  box-shadow: 0 -6px 32px rgba(0, 0, 0, 0.14);
  z-index: 999;
  text-align: center;
  font-family: 'Nunito', system-ui, sans-serif;
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

#push-prompt-card.push-prompt-card--visible {
  transform: translateY(0);
}

/* Outcome toast — mirrors #pwa-toast */
#push-prompt-toast {
  position: fixed;
  bottom: calc(var(--hud-bottom-height, 110px) + 12px);
  left: 16px;
  right: 16px;
  background: #2a2a2a;
  color: #fff;
  border-radius: var(--r-md);
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.45;
  font-family: 'Nunito', system-ui, sans-serif;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  z-index: 1100;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.25s ease, transform 0.25s ease;
  pointer-events: none;
}

#push-prompt-toast.push-prompt-toast--visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

#push-prompt-toast .pwa-toast-text { flex: 1; }
#push-prompt-toast .pwa-toast-dismiss {
  background: none;
  border: none;
  color: rgba(255,255,255,0.55);
  font-size: 14px;
  cursor: pointer;
  padding: 2px 4px;
  flex-shrink: 0;
  line-height: 1;
}


/* ── Holographic skin — Dichroic Crystal (creator-exclusive) ── */

/* @property enables animating per-colour vars on the persistent #game-grid element.
   inherits: true cascades the animated value to all .block children automatically.
   Blocks read the live var via background: var(--holo-c-*), so colour shifts
   continuously even though blocks are recreated on every renderBoardDirect call. */
@property --holo-c-blue   { syntax: '<color>'; inherits: true; initial-value: #B5DBF5; }
@property --holo-c-red    { syntax: '<color>'; inherits: true; initial-value: #F5B8C8; }
@property --holo-c-green  { syntax: '<color>'; inherits: true; initial-value: #A8E0C8; }
@property --holo-c-yellow { syntax: '<color>'; inherits: true; initial-value: #F5E0A0; }

/* Shine position vars — animated on #game-grid, inherited by block ::before for automatic shimmer. */
@property --holo-shine-x  { syntax: '<number>'; inherits: true; initial-value: 0.18; }
@property --holo-shine-y  { syntax: '<number>'; inherits: true; initial-value: 0.50; }

/* Border angle var — animated on .grid-wrapper::before to spin the rainbow border. */
@property --holo-border-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }

/* Viewport canvas: warm alabaster base with 5 richly-coloured drifting blobs.
   Two selectors for reliability: body.skin-holo-bg (set by inline script on early load +
   applyAllCosmetics), and body:has(#game-grid.skin-holo) which stays truthy even during
   the brief window when applyAllCosmetics removes and re-adds the body class.
   background-size: 340% makes blobs large and soft; position drift creates slow movement. */
body.skin-holo-bg,
body:has(#game-grid.skin-holo) {
  background-color: #F5F4F2;
  background-image:
    radial-gradient(ellipse 60% 50% at 18% 18%, rgba(200, 145, 255, 0.46) 0%, transparent 68%),
    radial-gradient(ellipse 55% 45% at 84% 12%, rgba(255, 165, 195, 0.40) 0%, transparent 68%),
    radial-gradient(ellipse 58% 52% at 68% 85%, rgba(130, 230, 185, 0.40) 0%, transparent 68%),
    radial-gradient(ellipse 52% 46% at 14% 80%, rgba(120, 195, 255, 0.38) 0%, transparent 68%),
    radial-gradient(ellipse 42% 38% at 52% 46%, rgba(255, 235, 180, 0.30) 0%, transparent 60%);
  background-size: 340% 340%;
  animation: holo-bg-drift 24s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
}

@keyframes holo-bg-drift {
  0%   { background-position: 0%   0%;   }
  25%  { background-position: 100% 15%;  }
  50%  { background-position: 72%  100%; }
  75%  { background-position: 12%  78%;  }
  100% { background-position: 0%   0%;   }
}

/* Holo animations live on .grid-wrapper, not #game-grid.
   Game logic (danger pulse, power effects) adds animation classes to #game-grid,
   which would displace holo animations via the CSS cascade and snap vars to initial-value.
   .grid-wrapper never receives game-state classes, so animations run uninterrupted.
   isolation: isolate creates a stacking context so the ::before rainbow border (z-index:-1)
   sits behind #game-grid but above the body background. */
body.skin-holo-bg .grid-wrapper,
body:has(#game-grid.skin-holo) .grid-wrapper {
  isolation: isolate;
  animation:
    holo-c-blue      13s ease-in-out infinite,
    holo-c-red       17s ease-in-out infinite,
    holo-c-green     11s ease-in-out infinite,
    holo-c-yellow    19s ease-in-out infinite,
    holo-shine-drift 20s ease-in-out infinite;
}

/* Rainbow border: conic-gradient ring outside the grid only.
   inset: -5px expands the pseudo-element 5px beyond .grid-wrapper on all sides.
   padding: 5px defines the visible ring width.
   The mask XOR technique: full-element mask minus content-box mask = only the
   5px padding ring is visible; the interior is fully transparent (no rainbow bleed).
   z-index: -1 + isolation: isolate on .grid-wrapper keeps it above the body background
   but behind #game-grid. */
body.skin-holo-bg .grid-wrapper::before,
body:has(#game-grid.skin-holo) .grid-wrapper::before {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 19px;
  padding: 5px;
  background: conic-gradient(
    from var(--holo-border-angle),
    hsl(  0, 52%, 72%),
    hsl( 45, 50%, 70%),
    hsl( 90, 44%, 67%),
    hsl(135, 44%, 66%),
    hsl(180, 44%, 66%),
    hsl(225, 48%, 69%),
    hsl(270, 48%, 69%),
    hsl(315, 50%, 71%),
    hsl(360, 52%, 72%)
  );
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  z-index: -1;
  animation: holo-border-spin 12s linear infinite;
  pointer-events: none;
}

@keyframes holo-border-spin {
  from { --holo-border-angle: 0deg; }
  to   { --holo-border-angle: 360deg; }
}

/* Grid card: very light gap lines only — body blobs show through freely.
   The rainbow ::before ring replaces the old white outline box-shadow.
   Gap lines (the grid background bleeding between cells) are a faint grey-blue. */
#game-grid.skin-holo {
  background: rgba(180, 195, 215, 0.18);
  box-shadow:
    0 8px 32px rgba(70, 55, 150, 0.14),
    0 3px 10px rgba(70, 55, 150, 0.08);
}

/* Per-colour oscillations animate on .grid-wrapper and inherit to .block children.
   Prime-number durations (11/13/17/19s) keep the 4 colours drifting independently.
   Mineral-quality ranges — moderate saturation throughout, never neon/pale. Subtle hue
   drift (blue→sapphire, red→garnet, green→viridian, yellow→topaz) mirrors dichroic glass. */
@keyframes holo-c-blue {
  0%   { --holo-c-blue: #B5DBF5; }   /* soft powder blue */
  40%  { --holo-c-blue: #90C4E8; }   /* gentle cornflower */
  70%  { --holo-c-blue: #A5D0F0; }   /* light azure */
  100% { --holo-c-blue: #B5DBF5; }
}
@keyframes holo-c-red {
  0%   { --holo-c-red: #F5B8C8; }    /* soft rose */
  40%  { --holo-c-red: #E8A0B8; }    /* dusty pink */
  70%  { --holo-c-red: #F0ACB8; }    /* light blush */
  100% { --holo-c-red: #F5B8C8; }
}
@keyframes holo-c-green {
  0%   { --holo-c-green: #A8E0C8; }  /* soft mint */
  40%  { --holo-c-green: #80C8A8; }  /* gentle sage */
  70%  { --holo-c-green: #98D8B8; }  /* pale viridian */
  100% { --holo-c-green: #A8E0C8; }
}
@keyframes holo-c-yellow {
  0%   { --holo-c-yellow: #F5E0A0; }  /* soft butter */
  40%  { --holo-c-yellow: #E0C878; }  /* gentle gold */
  70%  { --holo-c-yellow: #ECD490; }  /* warm cream */
  100% { --holo-c-yellow: #F5E0A0; }
}

/* Specular hotspot drifts organically across the grid surface — automatic shimmer without
   mouse tracking. Non-symmetric keyframe times create a natural, non-mechanical rhythm. */
@keyframes holo-shine-drift {
  0%   { --holo-shine-x: 0.18; --holo-shine-y: 0.50; }
  22%  { --holo-shine-x: 0.82; --holo-shine-y: 0.28; }
  48%  { --holo-shine-x: 0.75; --holo-shine-y: 0.78; }
  72%  { --holo-shine-x: 0.22; --holo-shine-y: 0.72; }
  100% { --holo-shine-x: 0.18; --holo-shine-y: 0.50; }
}

/* Grid cells: near-transparent white tint — enough contrast vs the bare gap lines
   to keep the 4px gridlines clearly legible, while still letting the drifting body
   blob colours bleed through and tint the playing field. */
.skin-holo .grid-cell {
  background: rgba(255, 255, 255, 0.20);
  box-shadow: none; /* polish-pass: keep holo cells flat */
}

/* Holographic flat block. Colour is driven by --holo-c-* vars animated on .grid-wrapper
   and inherited here — seamless through renderBoardDirect recreations. No border or
   depth shadow — clean flat pastel surfaces with only the prismatic overlay. */
.skin-holo .block {
  overflow: hidden;
  box-shadow: none; /* polish-pass: holo blocks stay flat (only the prismatic ::before) */
}


/* Per-colour block backgrounds: read the animated grid vars so colour oscillation
   continues through block recreations (renderBoardDirect removes and re-adds .block). */
.skin-holo .block--blue   { background: var(--holo-c-blue);   }
.skin-holo .block--red    { background: var(--holo-c-red);    }
.skin-holo .block--green  { background: var(--holo-c-green);  }
.skin-holo .block--yellow { background: var(--holo-c-yellow); }

/* Holographic foil surface — 2-layer composite, no glass/3D effects:
   (1) Tilt sweep stripe: very subtle bright stripe whose angle drifts with the hotspot —
       gives a sense of light catching the foil surface without looking 3D.
   (2) Prismatic foil texture: spectral rainbow across the whole surface —
       the diffraction-grating character of real holographic material. */
.skin-holo .block::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(
      calc(20deg + var(--holo-shine-x, 0.18) * 140deg),
      transparent 34%,
      rgba(255, 255, 255, 0.08) 46%,
      rgba(255, 255, 255, 0.12) 50%,
      rgba(255, 255, 255, 0.08) 54%,
      transparent 66%
    ),
    linear-gradient(
      115deg,
      rgba(255,  88,  88, 0.10)   0%,
      rgba(255, 195,  68, 0.10)  17%,
      rgba( 68, 230, 140, 0.10)  35%,
      rgba( 68, 182, 255, 0.10)  54%,
      rgba(172,  68, 255, 0.10)  72%,
      rgba(255,  68, 172, 0.10)  89%,
      rgba(255,  88,  88, 0.10) 100%
    );
  pointer-events: none;
  z-index: 0;
}

/* Wild block inside holo skin: restore the conic-gradient pinwheel AND add the holo
   prismatic sheen so wild blocks match the holographic feel of all other blocks.
   Both effects share ::before because ::after is reserved for value numbers.
   Background layers are front-to-back: prismatic overlays sit on top of the pinwheel.
   inset:-30% is needed for the pinwheel circle to cover corners at every rotation angle;
   overflow:hidden on .block--wild clips the oversized element to the block boundary,
   so the prismatic gradients look correct within the visible area. */
.skin-holo .block--wild::before {
  background:
    linear-gradient(
      calc(20deg + var(--holo-shine-x, 0.18) * 140deg),
      transparent 34%,
      rgba(255, 255, 255, 0.08) 46%,
      rgba(255, 255, 255, 0.12) 50%,
      rgba(255, 255, 255, 0.08) 54%,
      transparent 66%
    ),
    linear-gradient(
      115deg,
      rgba(255,  88,  88, 0.10)   0%,
      rgba(255, 195,  68, 0.10)  17%,
      rgba( 68, 230, 140, 0.10)  35%,
      rgba( 68, 182, 255, 0.10)  54%,
      rgba(172,  68, 255, 0.10)  72%,
      rgba(255,  68, 172, 0.10)  89%,
      rgba(255,  88,  88, 0.10) 100%
    ),
    conic-gradient(
      from 0deg at 50% 50%,
      var(--holo-c-blue)   0deg   90deg,
      var(--holo-c-green)  90deg  180deg,
      var(--holo-c-yellow) 180deg 270deg,
      var(--holo-c-red)    270deg 360deg
    );
  inset: -30%;
  border-radius: 50%;
  animation: wild-swirl 4s linear infinite;
}

/* Value numbers: dark charcoal above gloss layers.
   Near-black hue shift under hue-rotate is negligible — readability always preserved.
   Subtle white text-shadow lifts numbers off the frosted surface. */
.skin-holo .block::after {
  position: relative;
  z-index: 1;
  color: #1C1C24;
  opacity: 1;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.60);
}

/* Ability buttons: frosted ceramic with soft prismatic edge treatment */
.skin-holo .ability-btn {
  background: rgba(255, 255, 255, 0.92);
  box-shadow:
    0 3px 14px rgba(75, 65, 170, 0.18),
    inset 0 1.5px 0 rgba(255, 255, 255, 0.96),
    0 0 0 1px rgba(155, 162, 220, 0.38),
    0 0 0 2.5px rgba(155, 162, 220, 0.10);
  border-color: rgba(0, 0, 0, 0.05);
}

/* Charge counters: dark pill badges */
.skin-holo .ability-charge {
  background: #1C1C24;
  color: #FFFFFF;
  opacity: 1;
  border-radius: 10px;
  padding: 1px 5px;
  font-size: 9px;
}

/* Sparkle burst FX: JS (_fireHoloSparkle) injects this div at merge destination center.
   8 box-shadow diamond dots expand and fade via animation in 310ms. */
.holo-sparkle-burst {
  position: fixed;
  width: 1px;
  height: 1px;
  pointer-events: none;
  z-index: 20;
  transform: scale(0.1);
  opacity: 1;
}

@keyframes holo-sparkle-expand {
  0%   { transform: scale(0.1); opacity: 1; }
  60%  { opacity: 0.85; }
  100% { transform: scale(1);   opacity: 0; }
}

.holo-sparkle-burst.expanding {
  box-shadow:
    0    -30px 0 2.5px rgba(255, 255, 255, 0.96),
    21px -21px 0 2px   rgba(200, 145, 255, 0.94),
    30px   0px 0 2.5px rgba(120, 202, 255, 0.94),
    21px  21px 0 2px   rgba(130, 232, 185, 0.94),
    0     30px 0 2.5px rgba(255, 165, 195, 0.94),
    -21px 21px 0 2px   rgba(255, 218,  82, 0.94),
    -30px  0px 0 2.5px rgba(255, 135,  82, 0.94),
    -21px -21px 0 2px  rgba(195,  82, 255, 0.94);
  animation: holo-sparkle-expand 310ms ease-out forwards;
}

/* Locked state in the skins grid */
.cosmetic-card--exclusive {
  border: 1.5px dashed rgba(130,100,200,0.4);
  background: linear-gradient(135deg, rgba(200,180,255,0.08), rgba(180,220,255,0.08));
}

.cosmetic-exclusive-label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: linear-gradient(90deg, #b060ff, #60b0ff, #60ffb0);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-top: 4px;
}

.cosmetic-exclusive-hint {
  font-size: 10px;
  color: var(--text-secondary, #888);
  margin-top: 2px;
}

/* HUD "SCORE" and "BEST" labels: full static rainbow gradient across the text.
   Muted mid-tone hues (L 34–44%) stay legible on #F5F4F2; yellow stop is darkest
   to maintain contrast. No animation — entire spectrum shows simultaneously. */
body.skin-holo-bg .score-label,
body:has(#game-grid.skin-holo) .score-label {
  background: linear-gradient(90deg,
    hsl(0,   54%, 48%),
    hsl(28,  56%, 46%),
    hsl(55,  51%, 40%),
    hsl(100, 47%, 43%),
    hsl(155, 47%, 41%),
    hsl(185, 50%, 41%),
    hsl(220, 50%, 49%),
    hsl(265, 42%, 50%),
    hsl(310, 47%, 46%),
    hsl(360, 54%, 48%)
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  body.skin-holo-bg,
  body:has(#game-grid.skin-holo)                    { animation: none; }
  body.skin-holo-bg .grid-wrapper,
  body:has(#game-grid.skin-holo) .grid-wrapper      { animation: none; }
  body.skin-holo-bg .grid-wrapper::before,
  body:has(#game-grid.skin-holo) .grid-wrapper::before { animation: none; }
  body.skin-holo-bg .score-label,
  body:has(#game-grid.skin-holo) .score-label       { /* no animation to override */ }
  .holo-sparkle-burst.expanding        { animation-duration: 1ms; }
}

/* ── Redeem code section (bottom of skins panel) ── */

.redeem-section {
  margin-top: 20px;
  padding: 16px;
  border-top: 1px solid var(--border, rgba(0,0,0,0.08));
}

.redeem-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary, #888);
  margin-bottom: 10px;
}

.redeem-row {
  display: flex;
  gap: 8px;
}

.redeem-input {
  flex: 1;
  padding: 9px 12px;
  border: 1.5px solid var(--border, rgba(0,0,0,0.12));
  border-radius: 10px;
  background: var(--bg, #F5F0EB);
  color: var(--text-primary, #1a1a1a);
  font-size: 13px;
  font-family: 'Nunito', system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: 0.05em;
  outline: none;
  text-transform: uppercase;
}

.redeem-input:focus {
  border-color: #9060cc;
}

.redeem-btn {
  padding: 9px 16px;
  background: #F5C842;
  color: #1a1a1a;
  border: none;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 800;
  font-family: 'Nunito', system-ui, sans-serif;
  cursor: pointer;
  white-space: nowrap;
  transition: opacity 0.15s;
}

.redeem-btn:active { opacity: 0.75; }
.redeem-btn:disabled { opacity: 0.4; cursor: default; }

.redeem-msg {
  margin-top: 8px;
  font-size: 12px;
  font-weight: 600;
  min-height: 16px;
}

.redeem-msg--ok      { color: #3a9e6a; }
.redeem-msg--err     { color: #c04848; }

/* ── Notification overlay: push toggle banner ── */

.notif-push-banner:not(:empty) {
  border-bottom: 1px solid var(--border, rgba(0,0,0,0.07));
}

.notif-push-row-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
}

.notif-push-label {
  font-size: 13px;
  color: var(--text-secondary, #666);
}

.notif-push-btn {
  font-size: 12px;
  font-weight: 700;
  border: none;
  border-radius: 20px;
  padding: 5px 14px;
  cursor: pointer;
  transition: opacity 0.15s;
}
.notif-push-btn:active { opacity: 0.7; }

.notif-push-btn--enable {
  background: var(--accent, #F5D98A);
  color: #1a1a1a;
}

.notif-push-btn--on {
  background: #3a9e6a;
  color: #fff;
}

.notif-push-btn--off {
  background: var(--border, rgba(0,0,0,0.1));
  color: var(--text-secondary, #888);
}

.notif-push-info {
  font-size: 12px;
  color: var(--text-secondary, #888);
  padding: 12px 20px;
  line-height: 1.5;
}

/* ── Game legal footer ── */

.game-legal-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  margin-top: -12px;
  padding: 0px 16px 16px;
  font-size: 10px;
  color: var(--text-secondary, #aaa);
  font-family: 'Nunito', system-ui, sans-serif;
  text-align: center;
  line-height: 1.4;
}

.game-legal-footer a {
  color: var(--text-secondary, #aaa);
  text-decoration: none;
}

.game-legal-footer a:hover { text-decoration: underline; }

.game-legal-links {
  display: flex;
  align-items: center;
  gap: 6px;
}

.game-legal-sep {
  opacity: 0.5;
  user-select: none;
}
