@import url("https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@500;600;700;800;900&display=swap");

:root {
  --color-bg: #eef5fb;
  --color-bg-soft: #f8fbfe;
  --color-surface: rgba(255, 255, 255, 0.8);
  --color-surface-strong: rgba(255, 255, 255, 0.98);
  --color-border: rgba(17, 77, 134, 0.08);
  --color-text: #0f2742;
  --color-text-soft: #607e9f;
  --color-accent: #1f7dff;
  --color-accent-soft: rgba(31, 125, 255, 0.12);
  --color-track: rgba(15, 39, 66, 0.08);
  --color-shadow: 0 28px 64px rgba(24, 76, 126, 0.12);
  --radius-sm: 14px;
  --radius-md: 22px;
  --radius-lg: 30px;
  --ease-slow: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ui-font: "Nunito Sans", "Nunito", system-ui, sans-serif;

  /* BluKit shared palette (cyan / cream / pink) — reused by glows, bursts, auras. */
  --accent-cyan: #5ce8ff;
  --accent-cream: #fff0a8;
  --accent-pink: #ff9be8;

  /* "Ready" look shared with the Enter Run button — the reroll button swaps to
     this pastel fill (+ rainbow border) the moment a charge is banked. */
  --reroll-ready-fill:
    linear-gradient(110deg, rgba(255, 255, 255, 0.98), rgba(232, 250, 255, 0.9), rgba(255, 245, 188, 0.86) 48%, rgba(255, 224, 250, 0.86) 68%, rgba(235, 249, 255, 0.9));
  --reroll-ready-border:
    linear-gradient(100deg, #5ce8ff, #fff0a8, #ff9be8, #6fcfff, #5ce8ff);

  /* BluKit's exact sky: a soft top highlight over a 4-stop blue→white fall-off. */
  --blupets-sky-background:
    radial-gradient(circle at 50% 22%, rgba(255, 255, 255, 0.34), transparent 34%),
    linear-gradient(180deg, #078ee8 0%, #20b7f2 42%, #dff7ff 76%, #ffffff 100%);

  /* BluKit branded pixel cursors (40x40 PNG, hotspots 4 4 / 3 3). */
  --blupets-cursor-default: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAdVJREFUeJztmq9Pw0AUx78lGLak/wAG/PRmgIHAIRBLlikkYuFPQE2iEZglqIVkEs9+GYIAgWeZmiYB5BC3R9LSa69ps/ba78c0u3vvZcn79K67DiDlxgmZW8WItZatrL9A1gR1dQUAnesvAMBBuwIA6NacsBxroQEBYx4DVnvKAGf+DQAY9KphudZRegO2owIOG+o6hTJBzBj0qrJLWG0CDYibIGvC7bsSoFtzrDaBBugmfvYroYnTZ3W13QQakLSA7SbQgLQK2WoCDUi7oG0m0IC0C961PgEAZ80jwAITaEDcBH+Hd6/ePPMy/jierEdUPHJqAg0wDfR3Xjp8OQyOl7jJqzIkr7sDDTANdF3X81m3BkSRNxNoQNoF/UZ0+sFxYkLWZ4ylN0D7XuC8rxpyWleD0jFT5DTZj65OVu8dSm+A8RoQt6OmxvzVbagzyOViBAB4uj/eyJpAA0wDTTsq97Ips7m6LhcvsfLSggYkLSD38Ozh3yqeFO4Cm0BrwM7H+l6uB78hCul8Ln7nm0ID4iYUpfMCDYgKkP2/aJ0XaIBuQp7MWu0mAGB4MwbUM7qEWN15ofQGaM8DTi5GnsGidV6gASFz/Lc4IYQQQgghhBBSTH4BSU6ZlyBUcEYAAAAASUVORK5CYII=) 4 4;
  --blupets-cursor-pointer: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAcxJREFUeJztmT1Ow0AQhZ8RdS5AiSUKoHBDSaTUaZAoEBegoqLKCVxxADhAlAKJJnWkUNIEKVBESi6RC5hiPSTrrJ1NvOvI+H2Nf2bWsjzPz7NrgDSboCCW7DGmdhwd+gYOjamaCQC8TpUARp/p2bnaDOKgaGztaLwCjq0zQ7W56yllDOJAPKLWSqAC8gKjvtp27tNj8YJUCWddZQqzYVhrJVABeYHJdAEA6ODUGI9u5PyGElxRiaIar4CtnaC4/oYXZJi8L7Tj6NKsHFuq6jeogIJYgjW3f4pVRfMU4JyKOk8qwCJnJy94uV0CALrtawDAyeNXqTzfSmi8AqznAtIXoJ+6e6jHsxUdjj8AAA9v5utl84Blmt/a5f5LQwXYJs6GUnL1Ukah/p1vtfTKbX23M3krJVQLFVAQ09xf+POCf0LjFeBsLuAN9gF+sV8TzKFzZT5vq5Sy48tCBRTEAmirv2YvKFupyj0lAxVgm5idC/j+Kog3jOZ+ri80XgG7fFO1FSJBVopc89zTO87VXIR9gFP2eZpGJfjCV+UFKqDE2AQAzi/G7u5mjZ/vtuzyv4BPXDxd1/8EBf4bJIQQQgghhBBCCCGEEEIIcckv5K+BK8+A/okAAAAASUVORK5CYII=) 3 3;
}

/* ============================================================================
   DESIGN SYSTEM — semantic token layer (v2 elevation)
   Maps the verified blupix.app palette onto named roles. Base tokens above are
   kept as aliases so nothing breaks; new work should reference these.
   ========================================================================== */
:root {
  /* Ink (text) */
  --ink: #0a2140;
  --ink-strong: #074882;
  --ink-soft: #356684;
  --ink-faint: #6b8aa0;

  /* Action / brand */
  --action: #1d6fe8;
  --action-strong: #1568d6;
  --action-ink: #075faf;
  --action-soft: rgba(29, 111, 232, 0.12);

  /* Accents (holographic family) */
  --acc-cyan: #5ce8ff;
  --acc-cyan-deep: #68d8ff;
  --acc-pink: #ff9be8;
  --acc-yellow: #fff0a8;
  --alert: #d9233f;

  /* Surfaces */
  --surface-glass: rgba(255, 255, 255, 0.82);
  --surface-frost: rgba(255, 255, 255, 0.96);
  --surface-icy: #ebf9ff;
  --hairline: rgba(53, 102, 132, 0.16);
  --hairline-soft: rgba(255, 255, 255, 0.7);

  /* Radii (pill-forward) */
  --r-pill: 999px;
  --r-card: 26px;
  --r-md: 18px;
  --r-sm: 12px;

  /* Elevation + glow scale */
  --glow-sm: 0 8px 22px rgba(20, 70, 120, 0.16);
  --glow-md: 0 16px 38px rgba(20, 70, 120, 0.22);
  --glow-lg: 0 26px 60px rgba(20, 70, 120, 0.26);
  --glow-halo: 0 0 0 5px rgba(255, 255, 255, 0.36), 0 0 26px rgba(255, 235, 128, 0.42), 0 0 44px rgba(104, 216, 255, 0.24);
  --ring-inset: inset 0 1px 0 rgba(255, 255, 255, 0.9);

  /* Reusable gradient fills */
  --holo-border: linear-gradient(100deg, #5ce8ff, #fff0a8, #ff9be8, #6fcfff, #5ce8ff);
  --glass-fill: linear-gradient(150deg, rgba(255, 255, 255, 0.96), rgba(232, 250, 255, 0.86) 52%, rgba(255, 255, 255, 0.9));
  --sheen-fill: linear-gradient(110deg, transparent 28%, rgba(255, 255, 255, 0.82) 46%, transparent 64%);

  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.2, 0.8, 0.2, 1);
  --t-fast: 160ms;
  --t-med: 320ms;
}

/* ---- Reusable helper classes (apply in HTML alongside existing classes) ---- */

/* Frosted glass surface with iridescent holographic edge. */
.glass-card {
  position: relative;
  background: var(--glass-fill) padding-box, var(--holo-border) border-box;
  border: 1.5px solid transparent;
  border-radius: var(--r-card);
  box-shadow: var(--glow-md), var(--ring-inset);
  backdrop-filter: blur(14px);
}

/* Plain frosted surface (no rainbow edge) for nested/secondary panels. */
.frost {
  background: var(--surface-glass);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  box-shadow: var(--glow-sm);
  backdrop-filter: blur(10px);
}

/* One-shot / looping glossy sheen sweep — add to .sheen elements. */
.sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--sheen-fill);
  background-size: 220% 100%;
  background-position: 180% 0;
  mix-blend-mode: screen;
  pointer-events: none;
  opacity: 0;
}
.sheen:hover::after,
.sheen.is-active::after {
  opacity: 1;
  animation: sheen-sweep 900ms var(--ease-out);
}

@keyframes sheen-sweep {
  from { background-position: 180% 0; }
  to   { background-position: -80% 0; }
}

/* Holographic text wash for hero numerals / accents. */
.holo-text {
  background: linear-gradient(100deg, #1d6fe8, #5ce8ff 40%, #ff9be8 70%, #1d6fe8);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
  /* Kill the browser rubber-band: dragging tiles must not scroll/overscroll the
     page, otherwise it springs back at the bottom edge — the «отскок внизу поля». */
  overscroll-behavior: none;
}

body {
  font-family: var(--ui-font);
  color: var(--color-text);
  position: fixed;
  inset: 0;
  overflow: hidden;
  touch-action: none;
  /* BluKit's sky, with the original sparkle highlights layered on top. */
  background:
    radial-gradient(circle at 18% 14%, rgba(255, 255, 255, 0.92), transparent 18%),
    radial-gradient(circle at 82% 22%, rgba(255, 240, 168, 0.34), transparent 16%),
    radial-gradient(circle at 68% 10%, rgba(92, 232, 255, 0.28), transparent 16%),
    var(--blupets-sky-background);
}

/* BluKit branded cursors — desktop pointer only; touch devices ignore them. */
@media (hover: hover) and (pointer: fine) {
  body {
    cursor: var(--blupets-cursor-default), auto;
  }

  button:not(:disabled),
  .tile:not(.tile--empty),
  a,
  [role="button"] {
    cursor: var(--blupets-cursor-pointer), pointer;
  }

  .tile:not(.tile--empty):active {
    cursor: var(--blupets-cursor-pointer), grabbing;
  }
}

button,
input {
  font: inherit;
}

button {
  color: inherit;
}

.app-shell {
  position: relative;
  height: 100dvh;
  display: grid;
  place-items: center;
  /* Expand beyond 12px on devices with notch / Dynamic Island / home bar so the
     card never slides under an unsafe zone. env() falls back to 12px on
     non-notched hardware. */
  padding: max(12px, env(safe-area-inset-top, 12px))
           max(12px, env(safe-area-inset-right, 12px))
           max(12px, env(safe-area-inset-bottom, 12px))
           max(12px, env(safe-area-inset-left, 12px));
}

.screen {
  /* Centered by the .app-shell grid (place-items: center). Using absolute
     positioning with inset + width together over-constrained the box and pushed
     it sideways on mobile, so stay in flow and let the grid center it. */
  position: relative;
  width: min(100%, 480px);
  /* Subtract the safe-area-aware padding from both ends of the viewport so the
     card never bleeds under the notch or home bar. env() falls back to 12px. */
  height: min(
    100dvh
      - max(12px, env(safe-area-inset-top, 12px))
      - max(12px, env(safe-area-inset-bottom, 12px)),
    920px
  );
  margin: auto;
}

.screen[hidden] {
  display: none !important;
}

[hidden] {
  display: none !important;
}

.start-card,
.game-frame,
.leaderboard-card {
  height: 100%;
  /* Holographic iridescent edge — the signature DNA, now on every hero card
     (was a plain navy hairline; the rainbow only lived on modals/buttons). */
  border: 1.5px solid transparent;
  border-radius: var(--radius-lg);
  box-shadow: var(--color-shadow);
  backdrop-filter: blur(20px);
}

.start-card,
.game-frame,
.leaderboard-card,
.victory-card {
  background:
    radial-gradient(circle at 50% 18%, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.16) 42%, transparent 62%) padding-box,
    linear-gradient(180deg, #109de8 0%, #42c4ee 38%, #d9f6ff 62%, #ffffff 82%, #ffffff 100%) padding-box,
    var(--holo-border) border-box;
}

.start-card,
.leaderboard-card {
  padding: 26px;
}

.game-frame {
  position: relative;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto auto;
  gap: 10px;
  padding: 10px;
  overflow: hidden;
}

.game-frame::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(42% - 76px);
  width: min(188vw, 1260px);
  height: min(118vw, 820px);
  background:
    radial-gradient(ellipse at 50% 76%, rgba(255, 255, 255, 0.32) 0%, rgba(255, 255, 255, 0.15) 18%, transparent 40%),
    repeating-conic-gradient(
      from -22deg at 50% 76%,
      transparent 0deg 4.4deg,
      rgba(255, 255, 255, 0.14) 5.4deg 8.2deg,
      rgba(255, 255, 255, 0.42) 8.2deg 11.8deg,
      rgba(255, 255, 255, 0.12) 11.8deg 14.4deg,
      transparent 14.4deg 24deg
    );
  opacity: 0.72;
  transform: translate(-50%, -45%) scale(0.96, 0.92);
  transform-origin: 50% 76%;
  animation: entry-rays-breathe 4.2s ease-in-out infinite;
  mask-image: radial-gradient(ellipse at 50% 76%, #000 0%, rgba(0, 0, 0, 0.95) 48%, transparent 78%);
  pointer-events: none;
  z-index: 0;
}

/* Mobile explicit ordering: board (row 3) above vibe-status (row 4).
   DOM order is vibe-status → board-shell, so we must override. */
.game-frame .topbar     { grid-row: 1; }
.game-frame .roster-row { grid-row: 2; }
.game-frame .board-shell { grid-row: 3; }
.game-frame .vibe-status { grid-row: 4; }
.game-frame .game-footer { grid-row: 5; }

/* Mobile: mute lives in the topbar, not the footer. */
.game-frame .game-footer { display: none; }

/* Mobile profile chip: icon + "Profile" text, no count. */
.profile-chip-label { display: inline; }
.profile-chip-count { display: none; }
.profile-chip { min-width: 0; padding: 0 14px 0 10px; gap: 6px; }
.profile-chip .profile-chip-icon { width: 2.4rem; height: 2.4rem; }

.victory-screen {
  display: grid;
  place-items: center;
}

.victory-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
  padding: 26px 24px 22px;
  border: 1.5px solid transparent;
  border-radius: var(--radius-lg);
  box-shadow: var(--color-shadow);
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 16px;
  text-align: center;
  animation: card-pop-in 460ms cubic-bezier(0.2, 1, 0.3, 1) both;
}

.victory-card::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(42% - 76px);
  width: min(188vw, 1260px);
  height: min(118vw, 820px);
  background:
    radial-gradient(ellipse at 50% 76%, rgba(255, 255, 255, 0.32) 0%, rgba(255, 255, 255, 0.15) 18%, transparent 40%),
    repeating-conic-gradient(
      from -22deg at 50% 76%,
      transparent 0deg 4.4deg,
      rgba(255, 255, 255, 0.14) 5.4deg 8.2deg,
      rgba(255, 255, 255, 0.42) 8.2deg 11.8deg,
      rgba(255, 255, 255, 0.12) 11.8deg 14.4deg,
      transparent 14.4deg 24deg
    );
  opacity: 0.72;
  transform: translate(-50%, -45%) scale(0.96, 0.92);
  transform-origin: 50% 76%;
  animation: entry-rays-breathe 4.2s ease-in-out infinite;
  mask-image: radial-gradient(ellipse at 50% 76%, #000 0%, rgba(0, 0, 0, 0.95) 48%, transparent 78%);
  pointer-events: none;
}

.victory-card .entry-rays {
  position: absolute;
  inset: -10%;
  opacity: 0.64;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.78) 0 10%, rgba(92, 232, 255, 0.2) 28%, rgba(255, 155, 232, 0.12) 46%, transparent 72%);
  filter: blur(18px);
  animation: entry-aura-pulse 3.2s ease-in-out infinite;
}

.victory-card .entry-aura {
  position: absolute;
  inset: 10%;
  background:
    radial-gradient(circle at 35% 35%, rgba(92, 232, 255, 0.52), transparent 34%),
    radial-gradient(circle at 68% 58%, rgba(255, 240, 168, 0.46), transparent 32%),
    radial-gradient(circle at 50% 50%, rgba(255, 155, 232, 0.28), transparent 52%);
  filter: blur(18px);
  animation: entry-aura-liquid 6.4s ease-in-out infinite;
  pointer-events: none;
}

.victory-copy {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 16px;
  align-content: center;
  justify-items: center;
  width: min(100%, 420px);
}

/* The single, self-contained share card — its on-screen look is the 1:1 twin of
   the PNG that the Share button generates. */
.victory-share-card {
  position: relative;
  width: 100%;
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 22px 22px 20px;
  border-radius: 26px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  background:
    radial-gradient(circle at 50% 14%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.5) 46%, rgba(255, 255, 255, 0.32) 100%);
  box-shadow:
    0 22px 48px rgba(20, 70, 120, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(6px);
}

.victory-brand {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--color-text);
  font-weight: 900;
  letter-spacing: 0.22em;
  font-size: 12px;
  text-transform: uppercase;
}

.victory-brand-mark {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  object-fit: contain;
  image-rendering: pixelated;
}

.victory-art-wrap {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  place-items: center;
}

/* D9 — one-shot ray burst behind the winning Blupet on reveal. */
.victory-ray-burst {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  z-index: -1;
  pointer-events: none;
}

.victory-ray-burst i {
  position: absolute;
  left: 0;
  top: -3px;
  width: 72px;
  height: 6px;
  border-radius: 3px;
  transform-origin: 0 50%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.92), rgba(255, 247, 176, 0.6) 38%, rgba(255, 155, 232, 0.12) 70%, transparent);
  opacity: 0;
  animation: victory-ray-burst 1100ms cubic-bezier(0.14, 0.86, 0.22, 1) both;
}

.victory-ray-burst i:nth-child(1)  { --ray: 0;  animation-delay: 20ms; }
.victory-ray-burst i:nth-child(2)  { --ray: 1;  animation-delay: 60ms; }
.victory-ray-burst i:nth-child(3)  { --ray: 2;  animation-delay: 40ms; }
.victory-ray-burst i:nth-child(4)  { --ray: 3;  animation-delay: 90ms; }
.victory-ray-burst i:nth-child(5)  { --ray: 4;  animation-delay: 30ms; }
.victory-ray-burst i:nth-child(6)  { --ray: 5;  animation-delay: 70ms; }
.victory-ray-burst i:nth-child(7)  { --ray: 6;  animation-delay: 50ms; }
.victory-ray-burst i:nth-child(8)  { --ray: 7;  animation-delay: 100ms; }
.victory-ray-burst i:nth-child(9)  { --ray: 8;  animation-delay: 35ms; }
.victory-ray-burst i:nth-child(10) { --ray: 9;  animation-delay: 80ms; }
.victory-ray-burst i:nth-child(11) { --ray: 10; animation-delay: 45ms; }
.victory-ray-burst i:nth-child(12) { --ray: 11; animation-delay: 65ms; }

.victory-art {
  width: min(72%, 208px);
  height: auto;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 16px 22px rgba(25, 63, 103, 0.22));
  animation: victory-art-float 5.8s ease-in-out infinite;
}

.victory-screen .start-mark {
  width: fit-content;
}

.victory-screen h2 {
  margin: 0;
  font-size: clamp(2.2rem, 7vw, 3.1rem);
  line-height: 0.92;
  letter-spacing: -0.05em;
}

.victory-detail {
  color: var(--color-text-soft);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
}

/* Score / Place / Forms — the three numbers shown on the card and the PNG. */
.victory-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  width: 100%;
  padding-top: 12px;
  border-top: 1px solid rgba(120, 160, 200, 0.28);
}

.victory-stat {
  display: grid;
  gap: 3px;
  justify-items: center;
  text-align: center;
}

.victory-stat span {
  color: var(--color-text-soft);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.victory-stat strong {
  font-size: clamp(1.15rem, 4.4vw, 1.55rem);
  line-height: 1;
  letter-spacing: -0.03em;
}

.victory-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}

@keyframes victory-art-float {
  0%, 100% {
    transform: translateY(0) scale(1);
  }
  50% {
    transform: translateY(-6px) scale(1.01);
  }
}

.start-card {
  position: relative;
  overflow: hidden;
  display: grid;
  /* Pin the column to the full card width. Without this the auto column shrinks
     to the widest intrinsic child (the 220px cube), so the wider Enter Run button
     could only overflow that narrow column to the right — it appeared shoved off
     the right edge on wider phones (~420px). minmax(0,1fr) keeps it full-width. */
  grid-template-columns: minmax(0, 1fr);
  /* Hero gets the flexible top row so it sits large and centered; the two
     action rows are pushed to the bottom of the card. */
  grid-template-rows: 1fr auto auto auto;
  gap: 10px;
  padding: 18px 20px 30px;
  align-items: center;
  justify-items: center;
  text-align: center;
}

.start-card::before,
.leaderboard-card::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(42% - 76px);
  width: min(188vw, 1260px);
  height: min(118vw, 820px);
  background:
    radial-gradient(ellipse at 50% 76%, rgba(255, 255, 255, 0.32) 0%, rgba(255, 255, 255, 0.15) 18%, transparent 40%),
    repeating-conic-gradient(
      from -22deg at 50% 76%,
      transparent 0deg 4.4deg,
      rgba(255, 255, 255, 0.14) 5.4deg 8.2deg,
      rgba(255, 255, 255, 0.42) 8.2deg 11.8deg,
      rgba(255, 255, 255, 0.12) 11.8deg 14.4deg,
      transparent 14.4deg 24deg
    );
  opacity: 0.72;
  transform: translate(-50%, -45%) scale(0.96, 0.92);
  transform-origin: 50% 76%;
  animation: entry-rays-breathe 4.2s ease-in-out infinite;
  mask-image: radial-gradient(ellipse at 50% 76%, #000 0%, rgba(0, 0, 0, 0.95) 48%, transparent 78%);
  pointer-events: none;
}

.hud-btn.start-mute-btn {
  --hud-h: 58px;
  width: 108px;
  height: var(--hud-h);
  position: absolute;
  left: calc(14px + env(safe-area-inset-left, 0px));
  top: calc(14px + env(safe-area-inset-top, 0px));
  border-radius: 999px;
  z-index: 20;
  border: 2px solid #2f80ff;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(238, 245, 255, 0.96));
  box-shadow:
    0 0 0 4px rgba(47, 128, 255, 0.12),
    0 14px 28px rgba(48, 98, 168, 0.16);
  color: #2f80ff;
}

.entry-hero {
  position: relative;
  width: min(72vw, 320px);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  /* Drop the cube to the bottom of its flexible row instead of centering it,
     so it sits low (near the CTA) on tall windows rather than floating up. */
  align-self: end;
  margin-bottom: 0;
  z-index: 2;
}

.entry-echoes {
  display: none;
}

.entry-platform {
  position: relative;
  z-index: 3;
  width: min(122%, 560px);
  height: clamp(150px, 28vw, 220px);
  margin-top: clamp(-188px, -25vw, -132px);
  margin-bottom: clamp(-100px, -14vw, -66px);
  display: grid;
  place-items: center;
  pointer-events: none;
}

.entry-platform img {
  width: 118%;
  height: auto;
  object-fit: contain;
  image-rendering: pixelated;
  transform: translateY(-34%);
  filter: drop-shadow(0 14px 18px rgba(15, 39, 66, 0.16));
}

.entry-rays {
  position: absolute;
  inset: -12%;
  border-radius: 50%;
  opacity: 0.64;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.78) 0 10%, rgba(92, 232, 255, 0.2) 28%, rgba(255, 155, 232, 0.12) 46%, transparent 72%);
  filter: blur(18px);
  animation: entry-aura-pulse 3.2s ease-in-out infinite;
  pointer-events: none;
}

.entry-aura {
  position: absolute;
  inset: 10%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 35%, rgba(92, 232, 255, 0.52), transparent 34%),
    radial-gradient(circle at 68% 58%, rgba(255, 240, 168, 0.46), transparent 32%),
    radial-gradient(circle at 50% 50%, rgba(255, 155, 232, 0.28), transparent 52%);
  filter: blur(18px);
  animation: entry-aura-liquid 6.4s ease-in-out infinite;
  pointer-events: none;
}

.entry-particles,
.entry-sparks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.entry-particles i,
.entry-sparks i {
  position: absolute;
  display: block;
  image-rendering: pixelated;
}

.entry-particles i {
  width: var(--size, 8px);
  height: var(--size, 8px);
  left: var(--x, 50%);
  top: var(--y, 50%);
  background: var(--color, rgba(255, 255, 255, 0.58));
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
  opacity: 0;
  transform: translate(0) scale(0.72);
  animation: entry-particle-drift var(--duration, 7s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}

.entry-sparks i {
  width: var(--spark-size, 5px);
  height: var(--spark-size, 5px);
  left: var(--spark-x, 50%);
  top: var(--spark-y, 50%);
  border-radius: 1px;
  background: var(--spark-color, rgba(255, 255, 255, 0.82));
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.18),
    0 0 10px color-mix(in srgb, var(--spark-color, #7df7ff), transparent 24%);
  opacity: 0;
  transform: translate(-50%, -50%) rotate(var(--spark-rot, 0deg)) scale(0.42);
  animation: entry-hover-spark var(--spark-duration, 3.8s) ease-in-out infinite;
  animation-delay: var(--spark-delay, 0s);
}

.entry-particles i:nth-child(1) { --x: 12%; --y: 20%; --size: 8px; --color: rgba(255,255,255,.6); --duration: 8.4s; --delay: -.4s; }
.entry-particles i:nth-child(2) { --x: 24%; --y: 62%; --size: 6px; --color: rgba(202,246,255,.72); --duration: 7.6s; --delay: -2.1s; }
.entry-particles i:nth-child(3) { --x: 34%; --y: 16%; --size: 5px; --color: rgba(255,247,176,.68); --duration: 7.2s; --delay: -1.6s; }
.entry-particles i:nth-child(4) { --x: 50%; --y: 76%; --size: 7px; --color: rgba(255,141,241,.46); --duration: 8.6s; --delay: -3.2s; }
.entry-particles i:nth-child(5) { --x: 62%; --y: 18%; --size: 6px; --color: rgba(255,255,255,.72); --duration: 7.8s; --delay: -1.1s; }
.entry-particles i:nth-child(6) { --x: 74%; --y: 64%; --size: 9px; --color: rgba(125,247,255,.5); --duration: 8.2s; --delay: -4.2s; }
.entry-particles i:nth-child(7) { --x: 84%; --y: 28%; --size: 7px; --color: rgba(255,240,168,.52); --duration: 7.4s; --delay: -.8s; }
.entry-particles i:nth-child(8) { --x: 18%; --y: 84%; --size: 5px; --color: rgba(255,255,255,.52); --duration: 8.1s; --delay: -5.2s; }
.entry-particles i:nth-child(9) { --x: 42%; --y: 32%; --size: 8px; --color: rgba(104,216,255,.42); --duration: 7.9s; --delay: -2.8s; }
.entry-particles i:nth-child(10) { --x: 58%; --y: 54%; --size: 6px; --color: rgba(255,255,255,.68); --duration: 8.8s; --delay: -1.7s; }
.entry-particles i:nth-child(11) { --x: 70%; --y: 86%; --size: 5px; --color: rgba(255,141,241,.44); --duration: 7.1s; --delay: -3.7s; }
.entry-particles i:nth-child(12) { --x: 90%; --y: 52%; --size: 7px; --color: rgba(255,247,176,.48); --duration: 8.3s; --delay: -4.8s; }

.entry-sparks i:nth-child(1) { --spark-x: 20%; --spark-y: 38%; --spark-size: 5px; --spark-color: #ffffff; --spark-rot: -12deg; --spark-duration: 3.4s; --spark-delay: -.7s; }
.entry-sparks i:nth-child(2) { --spark-x: 35%; --spark-y: 78%; --spark-size: 6px; --spark-color: #7df7ff; --spark-rot: 12deg; --spark-duration: 4s; --spark-delay: -2.2s; }
.entry-sparks i:nth-child(3) { --spark-x: 49%; --spark-y: 20%; --spark-size: 4px; --spark-color: #fff7b0; --spark-rot: 8deg; --spark-duration: 3.8s; --spark-delay: -1.5s; }
.entry-sparks i:nth-child(4) { --spark-x: 64%; --spark-y: 76%; --spark-size: 5px; --spark-color: #ff9be8; --spark-rot: -6deg; --spark-duration: 4.1s; --spark-delay: -2.9s; }
.entry-sparks i:nth-child(5) { --spark-x: 77%; --spark-y: 30%; --spark-size: 6px; --spark-color: #ffffff; --spark-rot: 16deg; --spark-duration: 3.7s; --spark-delay: -.9s; }
.entry-sparks i:nth-child(6) { --spark-x: 86%; --spark-y: 58%; --spark-size: 5px; --spark-color: #7df7ff; --spark-rot: -14deg; --spark-duration: 4.2s; --spark-delay: -3.1s; }

.entry-art {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  width: min(120vw, 528px);
  /* hero-block.svg has ~74px of transparent space below the cube (content ends
     at y=154 of the 228-tall image). Crop the box to the cube's actual height
     and show only the top so the visible cube bottom == the layout box bottom,
     otherwise the cube floats high above the CTA. 154/248 = 0.621. */
  height: calc(min(120vw, 528px) * 0.621);
  object-fit: cover;
  object-position: top center;
  image-rendering: pixelated;
  filter: drop-shadow(0 20px 32px rgba(0, 78, 147, 0.22));
  animation:
    entry-artwork-in 520ms cubic-bezier(0.16, 1, 0.3, 1) both,
    block-hover-float 8.2s cubic-bezier(0.46, 0, 0.24, 1) 520ms infinite;
}

h1,
h2 {
  margin: 10px 0 0;
  font-size: clamp(2rem, 6vw, 3.2rem);
  line-height: 0.96;
}

h2 {
  font-size: clamp(1.4rem, 4vw, 2rem);
}

.game-screen .game-frame > *,
.leaderboard-card > * {
  position: relative;
  z-index: 1;
}

.entry-btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  max-width: 360px;
  min-height: 72px;
  padding: 0 42px;
  border: 2px solid rgba(255, 255, 255, 0.92);
  border-radius: 999px;
  background:
    linear-gradient(110deg, rgba(255, 255, 255, 0.98), rgba(232, 250, 255, 0.9), rgba(255, 245, 188, 0.86) 48%, rgba(255, 224, 250, 0.86) 68%, rgba(235, 249, 255, 0.9)) padding-box,
    linear-gradient(100deg, #5ce8ff, #fff0a8, #ff9be8, #6fcfff, #5ce8ff) border-box;
  box-shadow:
    inset 0 0 0 1px rgba(12, 101, 184, 0.1),
    0 0 0 5px rgba(255, 255, 255, 0.36),
    0 0 26px rgba(255, 235, 128, 0.42),
    0 0 44px rgba(104, 216, 255, 0.24);
  color: #075faf;
  font-size: clamp(28px, 6vw, 38px);
  font-weight: 900;
  letter-spacing: 0;
  cursor: pointer;
  transition:
    transform 820ms cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 420ms ease,
    filter 420ms ease,
    background-position 420ms ease;
  animation: entry-btn-colorflow 5.2s ease-in-out infinite;
}

.entry-btn::before {
  content: "";
  position: absolute;
  inset: -30%;
  background: linear-gradient(115deg, transparent 30%, rgba(104, 216, 255, 0.12) 40%, rgba(255, 246, 164, 0.52) 49%, rgba(255, 128, 226, 0.22) 58%, transparent 69%);
  opacity: 0.82;
  transform: translateX(-62%);
  animation: entry-btn-shine 2.2s linear infinite;
  pointer-events: none;
}

.entry-btn:hover {
  transform: translateY(-3px) scale(1.04);
  filter: saturate(1.08) brightness(1.02);
}

.start-actions,
.end-actions,
.leaderboard-head {
  display: flex;
  gap: 10px;
  align-items: center;
}

.start-actions {
  position: relative;
  z-index: 4;
  justify-content: center;
  flex-wrap: wrap;
}

.start-actions--primary {
  width: 100%;
  margin-bottom: 0;
  display: grid;
  /* Explicit full-width column: without it the implicit auto column shrinks to
     the button's text width, leaving the pill narrow instead of stretching. */
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  /* center so the max-width-capped pill stays centered on wide screens */
  justify-items: center;
}

/* Secondary row under Enter Run: Guide + Leaderboard share the width evenly. */
.start-actions--secondary {
  width: 100%;
  max-width: 360px;
  margin: 10px auto 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.start-actions--secondary .btn {
  width: 100%;
}

.btn,
.icon-btn {
  border: 1px solid var(--color-border);
  background: var(--color-surface-strong);
  color: var(--color-text);
  transition:
    transform 360ms var(--ease-slow),
    background 360ms var(--ease-slow),
    border-color 360ms var(--ease-slow),
    opacity 360ms var(--ease-slow);
}

.btn {
  border-radius: 999px;
  padding: 12px 18px;
  font-weight: 800;
  cursor: pointer;
}

.btn:hover,
.icon-btn:hover {
  transform: translateY(-1px);
}

/* Tactile press feedback — shared by every interactive control so the whole
   app feels physical. Kept short + spring-eased; honoured app-wide. */
.btn:active,
.icon-btn:active,
.hud-btn:active,
.profile-chip:active {
  transform: translateY(1px) scale(0.97);
  transition-duration: var(--t-fast);
}

.entry-btn:active,
.btn--primary:active {
  transform: translateY(-1px) scale(0.985);
  filter: saturate(1.12) brightness(1.04);
  transition-duration: var(--t-fast);
}

.btn:focus-visible,
.icon-btn:focus-visible,
.entry-btn:focus-visible,
.hud-btn:focus-visible,
.auth-btn:focus-visible,
.profile-chip:focus-visible,
.tile:focus-visible,
.partner-card:focus-visible,
.form-card:focus-visible {
  outline: 3px solid rgba(31, 125, 255, 0.3);
  outline-offset: 2px;
}

.btn:disabled,
.icon-btn:disabled {
  opacity: 0.45;
  cursor: default;
  transform: none;
}

/* Primary CTAs (Play Again / Try Again / New Run) borrow the entry button's
   glassy pastel-rainbow shell + a slow light sweep so they feel alive. */
.btn--primary {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.9);
  background:
    linear-gradient(110deg, rgba(255, 255, 255, 0.98), rgba(232, 250, 255, 0.9), rgba(255, 245, 188, 0.86) 48%, rgba(255, 224, 250, 0.86) 68%, rgba(235, 249, 255, 0.9)) padding-box,
    linear-gradient(100deg, var(--accent-cyan), var(--accent-cream), var(--accent-pink), #6fcfff, var(--accent-cyan)) border-box;
  color: #075faf;
  font-weight: 900;
  box-shadow:
    inset 0 0 0 1px rgba(12, 101, 184, 0.1),
    0 0 0 3px rgba(255, 255, 255, 0.3),
    0 0 18px rgba(255, 235, 128, 0.32),
    0 0 30px rgba(104, 216, 255, 0.2);
}

.btn--primary::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 36%, rgba(104, 216, 255, 0.12) 44%, rgba(255, 246, 164, 0.5) 50%, rgba(255, 128, 226, 0.2) 58%, transparent 66%);
  transform: translateX(-72%);
  animation: cta-shine 3.6s ease-in-out infinite;
  pointer-events: none;
}

.btn--primary:hover {
  filter: saturate(1.08) brightness(1.02);
}

/* Ghost CTAs share the glassy white treatment of the HUD buttons. */
.btn--ghost {
  border: 1px solid rgba(255, 255, 255, 0.9);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.72) 60%),
    var(--color-surface-strong);
  color: var(--color-accent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 22px rgba(40, 92, 150, 0.1);
}

.icon-btn {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: 18px;
}

.topbar {
  --hud-h: 52px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}

.topbar-right {
  display: flex;
  align-items: center;
}

/* Mobile reroll button — mini card analog of the desktop reroll button */
.reroll-hud-btn {
  position: relative;
  width: var(--hud-h);
  height: var(--hud-h);
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 14px;
  border: 1.5px solid var(--color-border);
  /* Neutral while the meter fills — no progress overlay. */
  background: var(--color-surface-strong);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(15, 39, 66, 0.1);
  transition:
    transform 320ms var(--ease-slow),
    box-shadow 320ms var(--ease-slow),
    background 460ms var(--ease-slow);
}
.reroll-hud-btn.has-charge {
  /* Charge ready: light up with the Enter-Run pastel fill + rainbow border. */
  border: 1.5px solid transparent;
  background: var(--reroll-ready-fill) padding-box, var(--reroll-ready-border) border-box;
  box-shadow:
    0 4px 14px rgba(15, 39, 66, 0.1),
    0 0 16px rgba(255, 235, 128, 0.4),
    0 0 22px rgba(104, 216, 255, 0.28);
}
.reroll-hud-btn.has-charge .reroll-hud-icon { color: #075faf; }
/* A slow breathing glow says "ready — spend me" without nagging. */
.reroll-hud-btn.has-charge { animation: reroll-ready-pulse 2.4s var(--ease-out) infinite; }
@keyframes reroll-ready-pulse {
  0%, 100% {
    box-shadow:
      0 4px 14px rgba(15, 39, 66, 0.1),
      0 0 16px rgba(255, 235, 128, 0.4),
      0 0 22px rgba(104, 216, 255, 0.28);
  }
  50% {
    box-shadow:
      0 4px 14px rgba(15, 39, 66, 0.1),
      0 0 24px rgba(255, 235, 128, 0.62),
      0 0 32px rgba(104, 216, 255, 0.48);
  }
}
@media (prefers-reduced-motion: reduce) {
  .reroll-hud-btn.has-charge { animation: none; }
}
.reroll-hud-btn:hover { transform: translateY(-1px); }
.reroll-hud-btn:active { transform: scale(0.95); }
.reroll-hud-btn:disabled { opacity: 0.4; cursor: default; transform: none; box-shadow: none; }

.reroll-hud-icon {
  position: relative;
  z-index: 1;
  font-size: 1.6rem;
  font-weight: 900;
  line-height: 1;
  color: var(--color-text);
  display: block;
}

.reroll-hud-badge {
  /* Reroll is always a single charge — the count badge adds no information. */
  display: none;
  position: absolute;
  top: -4px;
  right: -4px;
  z-index: 2;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--accent-cyan, #36c6ef), #0a8faf);
  color: #fff;
  font-size: 11px;
  font-weight: 900;
  line-height: 18px;
  text-align: center;
  border: 1.5px solid #fff;
  pointer-events: none;
}

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

.topbar-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* Back + Reroll share one identical look, parked on opposite edges of the HUD. */
.hud-btn {
  width: var(--hud-h);
  height: var(--hud-h);
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.7) 60%),
    var(--color-surface-strong);
  color: var(--color-accent);
  font-size: 24px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 22px rgba(40, 92, 150, 0.12);
  transition:
    transform 320ms var(--ease-slow),
    box-shadow 320ms var(--ease-slow),
    filter 320ms var(--ease-slow);
}

.hud-btn:hover {
  transform: translateY(-1px);
  filter: saturate(1.06) brightness(1.02);
}

.hud-btn:active {
  transform: translateY(0) scale(0.96);
}

.hud-btn:disabled {
  opacity: 0.45;
  cursor: default;
  transform: none;
  filter: none;
}

/* Reroll dock: medallion icon on the left, fill track on the right, charge
   pips outside the track. Tap to spend a charge and reshuffle the board. */
.reroll-dock {
  /* hidden on mobile — only shown in the desktop sidebar column */
  display: none;
}

.reroll-bar {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  border: 1.5px solid var(--color-border);
  border-radius: 50px;
  background: var(--color-surface-strong);
  cursor: pointer;
  font: inherit;
  color: var(--color-text);
  transition: background 0.3s var(--ease-slow), border-color 0.25s, box-shadow 0.25s, transform 0.18s;
}

/* Left: circular icon medallion */
.reroll-medallion {
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--color-bg);
  border: 1.5px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  transition: border-color 0.25s, box-shadow 0.25s;
}

.reroll-medallion-icon {
  width: 78%;
  height: 78%;
  image-rendering: pixelated;
  object-fit: contain;
  display: block;
}

/* Middle: progress track */
.reroll-track {
  flex: 1;
  height: 24px;
  border-radius: 20px;
  background: var(--color-track);
  position: relative;
  overflow: hidden;
}

.reroll-track-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: calc(var(--pct, 0) * 1%);
  background: var(--accent-cyan);
  border-radius: inherit;
  pointer-events: none;
}

/* Right: vertical stack of charge pips */
.reroll-pips {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
}

.reroll-pip {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--color-border);
  background: transparent;
  transition: background 0.22s, border-color 0.22s, box-shadow 0.22s;
}

.reroll-pip.is-active {
  background: var(--accent-cyan);
  border-color: var(--accent-cyan);
}

.reroll-bar.has-charge {
  border-color: var(--accent-cyan, #5ce8ff);
  box-shadow: 0 0 0 2px rgba(92, 232, 255, 0.18), var(--color-shadow);
}

.reroll-bar.has-charge .reroll-medallion {
  border-color: var(--accent-cyan, #5ce8ff);
  box-shadow: 0 0 10px rgba(92, 232, 255, 0.28);
}

.reroll-bar.has-charge .reroll-pip.is-active {
  background: var(--accent-cyan, #5ce8ff);
  border-color: var(--accent-cyan, #5ce8ff);
  box-shadow: 0 0 6px rgba(92, 232, 255, 0.65);
}

.reroll-bar.is-hatched { animation: hatch-pop 640ms var(--ease-slow); }
.reroll-bar:not(:disabled):hover { transform: translateY(-1px); }
.reroll-bar:not(:disabled):active { transform: scale(0.99); }
.reroll-bar:disabled { opacity: 0.4; cursor: default; transform: none; box-shadow: none; }

@keyframes hatch-pop {
  0% {
    transform: scale(1);
  }
  35% {
    transform: scale(1.2);
    filter: drop-shadow(0 0 8px rgba(92, 232, 255, 0.7));
  }
  100% {
    transform: scale(1);
  }
}

.stat-pill,
.leaderboard-row {
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.18)),
    var(--color-surface-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 4px 14px rgba(20, 50, 74, 0.08);
  transition:
    transform var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out);
}

.leaderboard-row:has(.leaderboard-user-btn:hover) {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--action) 34%, var(--hairline));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    var(--glow-md);
}

.leaderboard-row:has(.leaderboard-user-btn:active) {
  transform: translateY(0) scale(0.992);
  transition-duration: 90ms;
}

.stat-pill {
  position: relative;
  overflow: hidden;
  border-radius: 18px;
  padding: 8px 12px;
  text-align: center;
  height: var(--hud-h);
  min-width: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 2px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.82),
    inset 0 -1px 0 rgba(72, 132, 189, 0.08);
}

.stat-pill::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.5), transparent 58%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.2), transparent 55%);
  pointer-events: none;
}

.stat-pill--moves {
  background:
    radial-gradient(circle at 50% 0%, rgba(125, 247, 255, 0.1), transparent 54%),
    var(--color-surface-strong);
}

.stat-pill--score {
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 214, 136, 0.16), transparent 54%),
    var(--color-surface-strong);
}

.stat-kicker {
  display: block;
  color: var(--color-text-soft);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  position: relative;
  z-index: 1;
}

.stat-pill strong {
  display: block;
  margin-top: 0;
  font-size: 24px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.04em;
  position: relative;
  z-index: 1;
  white-space: nowrap;
}

/* Give each counter its own identity colour (warning/danger on Moves are more
   specific selectors below, so they still win when moves run low). */
.stat-pill--moves strong {
  color: var(--action);
}
.stat-pill--score strong {
  color: #d98214;
}

/* Score punches up for a beat whenever it climbs (toggled from JS). */
.stat-pill--score.is-bump strong {
  animation: score-bump 420ms var(--ease-out);
}
@keyframes score-bump {
  0% { transform: scale(1); }
  32% { transform: scale(1.22); color: #ffae2e; }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .stat-pill--score.is-bump strong { animation: none; }
}

/* Scale the score number down as it grows so big totals stay inside the pill
   instead of clipping. ID specificity intentionally beats the small-screen
   `.stat-pill strong` size override below. `data-len` is the digit count. */
#scoreValue[data-len="4"] {
  font-size: 21px;
  letter-spacing: -0.05em;
}
#scoreValue[data-len="5"] {
  font-size: 17px;
  letter-spacing: -0.05em;
}
#scoreValue[data-len="6"] {
  font-size: 15px;
  letter-spacing: -0.05em;
}
#scoreValue[data-len="7"] {
  font-size: 14px;
  letter-spacing: -0.06em;
}
#scoreValue[data-len="8"],
#scoreValue[data-len="9"],
#scoreValue[data-len="10"] {
  font-size: 12px;
  letter-spacing: -0.06em;
}

/* ── All-color progress roster ──────────────────────────────────────────
   One "activity ring" per color: a conic fill = % to next tier wrapped around
   that color's current form SVG, the leading color enlarged + glowing.
   @property makes the fill sweep smoothly, so you watch the others drop when
   a fusion decays them. */
@property --pct {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

.roster-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.roster-row .color-roster {
  flex: 1;
  min-width: 0;
}

.color-roster {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 16px 16px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--r-md);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.6), transparent 62%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.24));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 8px 20px rgba(40, 92, 150, 0.07);
}

.roster-item {
  display: grid;
  place-items: center;
  flex: 1 1 0;
  min-width: 0;
}

.roster-ring {
  --pct: 0;
  /* Fluid, not fixed: the ring fills its flex slot and caps at 52px. On a
     narrow phone 8 rings shrink to fit instead of forcing the whole frame
     wider than the viewport (which slid the board off to the right). */
  width: 100%;
  max-width: 52px;
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  background: conic-gradient(
    var(--ring-color, var(--color-accent)) calc(var(--pct) * 1%),
    var(--color-track) 0
  );
  transition: --pct 460ms var(--ease-slow);
}

.roster-ring::before {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: linear-gradient(180deg, #ffffff, #eef5ff);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.9);
}

/* Form SVG sits ON TOP of the ring, large enough to read, overlapping the
   thin progress band so it reads as a chip held inside the ring. */
.roster-art {
  position: relative;
  z-index: 2;
  width: 84%;
  height: 84%;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(40, 92, 150, 0.22));
}

.roster-tier {
  position: absolute;
  right: -3px;
  bottom: -3px;
  z-index: 3;
  min-width: 22px;
  height: 16px;
  padding: 1px 5px 0;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.72);
  background: color-mix(in srgb, var(--ring-color, var(--color-accent)) 54%, #173555);
  color: #fff;
  font-size: 9px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0;
  box-shadow:
    0 2px 5px rgba(15, 39, 66, 0.24),
    inset 0 1px 0 rgba(255, 255, 255, 0.32);
  pointer-events: none;
}

.roster-item.is-evolved .roster-tier {
  display: inline-flex;
}

/* Leader emphasis is glow only — every ring stays the same size so the row
   reads uniform. */
.roster-item.is-leader .roster-ring {
  box-shadow:
    0 0 0 2px rgba(255, 255, 255, 0.85),
    0 4px 14px color-mix(in srgb, var(--roster-color, var(--color-accent)) 55%, transparent);
}

/* Evolve-ready cue (moved off the old leader chip): a slow liquid rainbow
   aura glows around the whole roster while a fusion pick is pending. */
.color-roster.is-evolve {
  position: relative;
  isolation: isolate;
  border-color: rgba(80, 164, 255, 0.4);
}

.color-roster.is-evolve::before {
  content: "";
  position: absolute;
  inset: -6px;
  z-index: -1;
  border-radius: 20px;
  background:
    radial-gradient(circle at 28% 50%, var(--accent-cyan), transparent 52%),
    radial-gradient(circle at 72% 50%, var(--accent-pink), transparent 52%),
    radial-gradient(circle at 50% 50%, var(--accent-cream), transparent 58%);
  opacity: 0.5;
  animation: tile-aura-liquid 6s ease-in-out infinite;
  pointer-events: none;
}

.board-shell {
  position: relative;
  justify-self: stretch;
  align-self: stretch;
  width: 100%;
  height: 100%;
  min-height: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: 6px;
  border-radius: 30px;
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.74), rgba(255, 255, 255, 0.18) 50%, rgba(255, 255, 255, 0.06) 80%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.12));
  border: 1px solid rgba(255, 255, 255, 0.46);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 16px 34px rgba(53, 138, 204, 0.14);
  transition:
    box-shadow 280ms var(--ease-slow),
    border-color 280ms var(--ease-slow),
    transform 280ms var(--ease-slow);
}

.board-shell::before,
.board-shell::after {
  content: "";
  position: absolute;
  border-radius: inherit;
  pointer-events: none;
  transition:
    opacity 280ms var(--ease-slow),
    transform 280ms var(--ease-slow),
    box-shadow 280ms var(--ease-slow),
    filter 280ms var(--ease-slow);
}

.board-shell::before {
  inset: -18px;
  background:
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--glow-color, #7fdcff) 30%, transparent) 0%, transparent 64%),
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--glow-color, #7fdcff) 12%, transparent) 0%, transparent 72%);
  filter: blur(18px);
  opacity: 0.2;
  transform: scale(0.98);
}

.board-shell::after {
  inset: 0;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.46),
    inset 0 0 18px rgba(255, 255, 255, 0.08);
  opacity: 0.95;
}

/* C6 — a quick flinch each time a match clears. */
.board-shell.is-impact {
  animation: board-platform-impact 420ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.board-shell.is-cascade-active {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.96),
    0 24px 46px rgba(53, 138, 204, 0.22),
    0 0 0 1px color-mix(in srgb, var(--glow-color, #7fdcff) 30%, transparent),
    0 0 42px color-mix(in srgb, var(--glow-color, #7fdcff) 22%, transparent);
}

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 2px;
  padding: 0;
  border-radius: 0;
  background: transparent;
  border: none;
  touch-action: none;
}

.board.blocked {
  pointer-events: none;
}

.tile {
  position: relative;
  aspect-ratio: 1;
  border: none;
  border-radius: 12px;
  overflow: hidden;
  cursor: grab;
  background: transparent;
  isolation: isolate;
  transition:
    transform 420ms var(--ease-slow),
    box-shadow 420ms var(--ease-slow),
    filter 420ms var(--ease-slow),
    opacity 420ms var(--ease-slow);
}

.tile.is-swapping,
.tile.is-falling,
.tile.is-reshuffling,
.tile.is-settling,
.tile.clearing {
  will-change: transform, opacity, filter;
}

.tile--empty {
  pointer-events: none;
  cursor: default;
  opacity: 0.18;
}

.tile--empty::before,
.tile--empty::after {
  inset: 7px;
  border-radius: 12px;
}

.tile--empty::before {
  background:
    radial-gradient(circle at 50% 30%, rgba(255, 255, 255, 0.16), transparent 58%),
    rgba(255, 255, 255, 0.08);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.26),
    inset 0 -1px 0 rgba(123, 177, 226, 0.08);
}

.tile--empty::after {
  border: 1px dashed rgba(255, 255, 255, 0.28);
  opacity: 0.55;
}

.tile::before {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.2)),
    radial-gradient(circle at 32% 22%, rgba(255, 255, 255, 0.92), transparent 40%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    inset 0 -1px 0 rgba(123, 177, 226, 0.18),
    0 10px 24px rgba(71, 146, 214, 0.12);
  z-index: 0;
}

.tile::after {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.88);
  opacity: 0.96;
  z-index: 1;
  pointer-events: none;
}

.tile:hover {
  transform: scale(1.02);
}

.tile.is-swapping {
  z-index: 4;
  /* Both swapped tiles must travel together, so ignore the positional stagger. */
  animation: tile-swap-slide 210ms cubic-bezier(0.22, 0.9, 0.3, 1) both;
  animation-delay: 0ms;
}

.tile.is-rejecting {
  z-index: 4;
  animation: tile-swap-reject 300ms cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

.tile.is-falling {
  z-index: 3;
  /* Gentle ease-out so tiles decelerate into place instead of slamming. */
  animation: tile-fall-in 360ms cubic-bezier(0.25, 0.6, 0.3, 1) both;
  animation-delay: var(--tile-delay, 0ms);
}

.tile.is-reshuffling {
  animation: tile-reshuffle-in 320ms cubic-bezier(0.2, 0.9, 0.22, 1) both;
  animation-delay: var(--tile-delay, 0ms);
}

.tile.is-settling {
  /* No landing rebound — the scale dip-and-recover read as a jarring bounce
     on every tile after it fell. Tiles now just rest where they land. */
  z-index: 3;
}

/* Idle hint — a small, quick wobble on the tiles of one available move. The JS
   loop adds this to one move at a time, so the board never shakes all at once. */
.tile.hint-jitter {
  z-index: 2;
  animation: tile-hint-jitter 680ms ease-in-out both;
}

.tile--ghost {
  pointer-events: none;
  cursor: default;
  z-index: 5;
  /* Let the crystal shards fly past the tile bounds instead of being clipped. */
  overflow: visible;
}

/* D8 — crystal shard burst fired from a clearing tile. */
.tile-burst {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: visible;
}

.tile-burst i {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.98), var(--crystal-color, var(--accent-cyan)));
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.32),
    0 0 10px var(--crystal-color, var(--accent-cyan));
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.3);
  animation: tile-crystal-burst 280ms cubic-bezier(0.14, 0.86, 0.22, 1) both;
}

.tile-burst i:nth-child(1) { --crystal-angle: 8deg;   --crystal-distance: 26px; --crystal-color: var(--accent-cyan); }
.tile-burst i:nth-child(2) { --crystal-angle: 52deg;  --crystal-distance: 30px; --crystal-color: var(--accent-cream); }
.tile-burst i:nth-child(3) { --crystal-angle: 96deg;  --crystal-distance: 24px; --crystal-color: #ffffff; }
.tile-burst i:nth-child(4) { --crystal-angle: 140deg; --crystal-distance: 28px; --crystal-color: var(--accent-pink); }
.tile-burst i:nth-child(5) { --crystal-angle: 188deg; --crystal-distance: 26px; --crystal-color: var(--accent-cyan); }
.tile-burst i:nth-child(6) { --crystal-angle: 232deg; --crystal-distance: 30px; --crystal-color: var(--accent-cream); }
.tile-burst i:nth-child(7) { --crystal-angle: 278deg; --crystal-distance: 23px; --crystal-color: #ffffff; }
.tile-burst i:nth-child(8) { --crystal-angle: 322deg; --crystal-distance: 28px; --crystal-color: var(--accent-pink); }

.tile.selected,
.tile.drag-target {
  transform: scale(1.08);
  filter: brightness(1.08) saturate(1.1);
  z-index: 2;
}

.tile.selected::after,
.tile.drag-target::after {
  border-color: color-mix(in srgb, var(--tile-accent, #1f7dff) 85%, white);
  box-shadow:
    inset 0 0 0 2.5px color-mix(in srgb, var(--tile-accent, #1f7dff) 70%, white),
    inset 0 0 16px color-mix(in srgb, var(--tile-accent, #1f7dff) 52%, transparent);
  opacity: 1;
}

.tile.evolved .tile-art {
  filter:
    drop-shadow(0 3px 6px rgba(0, 0, 0, 0.14))
    drop-shadow(0 0 8px var(--tile-accent));
}

.tile.clearing {
  animation: tile-clear-shell 280ms cubic-bezier(0.18, 0.9, 0.22, 1) forwards;
}

.tile.clearing::before {
  animation: tile-clear-glass 280ms cubic-bezier(0.18, 0.9, 0.22, 1) forwards;
}

.tile.clearing::after {
  animation: tile-clear-outline 280ms cubic-bezier(0.18, 0.9, 0.22, 1) forwards;
}

.tile-art {
  position: absolute;
  inset: 12%;
  width: 76%;
  height: 76%;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.14));
  transform: scale(1.04);
  transform-origin: center;
  pointer-events: none;
  z-index: 2;
}

.tile.clearing .tile-art {
  animation: tile-clear-art 280ms cubic-bezier(0.18, 0.9, 0.22, 1) forwards;
}

.vibe-status {
  display: grid;
  gap: 8px;
}

.game-footer {
  display: flex;
  align-items: center;
  align-self: end;
}

.game-footer .mute-btn {
  --hud-h: 52px;
}

/* Compact per-run vibe readout: the rolled bonus that used to live on the old
   leader chip, restored as a slim glassy strip above the status line. */
.vibe-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 13px;
  /* The per-run "vibe" is the run's identity — give it the holographic-glass
     treatment so it reads as a special, earned readout rather than a plain note. */
  border: 1.5px solid transparent;
  border-radius: 16px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(255, 255, 255, 0.74)) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 0 18px rgba(92, 232, 255, 0.18),
    0 10px 22px rgba(40, 92, 150, 0.08);
}

.vibe-strip-badge {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  overflow: hidden;
  background: linear-gradient(180deg, #ffffff, #eef5ff);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 0 12px rgba(92, 232, 255, 0.4);
}

.vibe-strip-badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}

.vibe-strip-text {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.vibe-strip-name {
  font-size: 14px;
  font-weight: 900;
  letter-spacing: 0.02em;
  color: var(--color-text, #14324f);
  text-transform: uppercase;
  white-space: normal;
  line-height: 1.1;
}

.vibe-strip-perks {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-text-soft);
  white-space: normal;
}

.status-line {
  min-height: 40px;
  padding: 9px 14px;
  border-radius: 14px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.72)),
    rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(15, 39, 66, 0.06);
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  display: flex;
  align-items: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 10px 22px rgba(40, 92, 150, 0.06);
}

.leaderboard-card {
  position: relative;
  overflow: hidden;
  display: grid;
  /* Two children (header + #leaderboard-content): the content must be the final
     minmax(0,1fr) track so its overflow-y:auto actually scrolls. A stray third
     `auto` track parked the content in an auto row, so long lists clipped. */
  grid-template-rows: auto minmax(0, 1fr);
}

.modal-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  backdrop-filter: blur(12px);
  animation: modal-backdrop-in 180ms ease-out both;
  background: rgba(14, 32, 53, 0.18);
}

.modal-card {
  width: min(320px, calc(100% - 24px));
  padding: 22px 18px;
  border-radius: var(--r-card);
  border: 1px solid var(--color-border);
  background: var(--color-surface-strong);
  text-align: center;
  box-shadow: var(--color-shadow);
  animation: card-pop-in 320ms cubic-bezier(0.2, 1, 0.3, 1) both;
}

.gameover-screen {
  display: grid;
  place-items: center;
}

.gameover-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 24px 22px 22px;
  border-radius: 30px;
  border: 1.5px solid transparent;
  background:
    radial-gradient(circle at 50% 18%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.14) 42%, transparent 62%),
    linear-gradient(180deg, #4f86c4 0%, #7aaed7 38%, #d7ebf6 62%, #ffffff 82%, #ffffff 100%) padding-box,
    var(--holo-border) border-box;
  box-shadow: var(--glow-lg), 0 0 30px rgba(118, 158, 198, 0.22), var(--ring-inset);
  animation: card-pop-in 460ms cubic-bezier(0.2, 1, 0.3, 1) both;
}

.gameover-card::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(42% - 76px);
  width: min(188vw, 1260px);
  height: min(118vw, 820px);
  background:
    radial-gradient(ellipse at 50% 76%, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0.12) 18%, transparent 40%),
    repeating-conic-gradient(
      from -22deg at 50% 76%,
      transparent 0deg 4.4deg,
      rgba(214, 240, 255, 0.12) 5.4deg 8.2deg,
      rgba(255, 255, 255, 0.34) 8.2deg 11.8deg,
      rgba(214, 240, 255, 0.1) 11.8deg 14.4deg,
      transparent 14.4deg 24deg
    );
  opacity: 0.26;
  transform: translate(-50%, -45%) scale(0.96, 0.92);
  transform-origin: 50% 76%;
  animation: entry-rays-breathe 5.2s ease-in-out infinite;
  mask-image: radial-gradient(ellipse at 50% 76%, #000 0%, rgba(0, 0, 0, 0.95) 48%, transparent 78%);
  pointer-events: none;
}

.gameover-card .entry-rays {
  position: absolute;
  inset: -10%;
  opacity: 0.38;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.5) 0 10%, rgba(150, 185, 215, 0.2) 28%, rgba(120, 160, 195, 0.12) 48%, transparent 72%);
  filter: blur(18px);
  animation: entry-aura-pulse 3.6s ease-in-out infinite;
}

.gameover-card .entry-aura {
  position: absolute;
  inset: 10%;
  background:
    radial-gradient(circle at 38% 36%, rgba(140, 180, 215, 0.3), transparent 38%),
    radial-gradient(circle at 66% 60%, rgba(150, 185, 215, 0.22), transparent 42%),
    radial-gradient(circle at 50% 50%, rgba(120, 165, 205, 0.18), transparent 52%);
  filter: blur(20px);
  opacity: 0.55;
  animation: entry-aura-liquid 7s ease-in-out infinite;
  pointer-events: none;
}

.gameover-copy {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 12px;
  width: min(100%, 420px);
  margin: 0 auto;
}

.gameover-mark {
  color: rgba(15, 39, 66, 0.72);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.gameover-title {
  margin: 0;
  font-size: clamp(2.4rem, 7vw, 3.6rem);
  line-height: 0.94;
  letter-spacing: -0.06em;
}

.gameover-art {
  width: min(100%, 220px);
  height: auto;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 20px 28px rgba(25, 63, 103, 0.22));
  animation: victory-art-float 5.8s ease-in-out infinite;
}

.gameover-detail {
  color: var(--color-text-soft);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
}

.gameover-score-wrap {
  display: grid;
  gap: 4px;
  justify-items: center;
  margin-top: 4px;
  padding: 12px 30px 14px;
  border-radius: var(--r-md, 18px);
  border: 1px solid rgba(255, 255, 255, 0.85);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.75), transparent 60%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.42));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 22px rgba(40, 92, 150, 0.12);
}

.gameover-score-label {
  color: rgba(15, 39, 66, 0.56);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.gameover-score {
  font-size: clamp(2.1rem, 7vw, 3rem);
  line-height: 1;
  font-weight: 900;
  letter-spacing: -0.05em;
}

.gameover-screen .end-actions {
  justify-content: center;
  width: 100%;
}

.gameover-screen .end-actions .btn {
  min-width: 192px;
}

.modal-label,
.modal-sub {
  color: var(--color-text-soft);
}

.modal-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.modal-headline {
  margin-top: 8px;
  font-size: 22px;
  font-weight: 900;
}

.modal-sub {
  margin-top: 6px;
  font-size: 13px;
}

.modal-options {
  margin-top: 16px;
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}

.partner-card,
.form-card {
  min-width: 84px;
  padding: 12px 10px;
  border-radius: var(--r-md);
  border: 1px solid var(--color-border);
  background: var(--color-bg-soft);
  cursor: pointer;
  transition:
    transform 360ms var(--ease-slow),
    background 360ms var(--ease-slow),
    border-color 360ms var(--ease-slow);
}

.partner-dot {
  width: 24px;
  height: 24px;
  margin: 0 auto 8px;
}

.partner-name,
.partner-pts,
.form-name {
  display: block;
}

.partner-name,
.form-name {
  font-size: 11px;
  font-weight: 800;
}

.partner-pts {
  margin-top: 4px;
  color: var(--color-text-soft);
  font-size: 10px;
}

.form-img {
  width: 40px;
  height: 40px;
  display: block;
  margin: 0 auto 8px;
  object-fit: contain;
  image-rendering: pixelated;
}

.end-actions {
  justify-content: center;
  flex-wrap: wrap;
}

.leaderboard-head {
  justify-content: flex-start;
}

.leaderboard-head h2 {
  margin: 0;
}

.leaderboard-content {
  margin-top: 18px;
  display: grid;
  gap: 10px;
  /* Allow the grid item to shrink below its content height so it scrolls inside
     its 1fr track instead of overflowing the card. */
  min-height: 0;
  /* Keep rows their natural height instead of ballooning to fill the card
     (grid align-content defaults to stretch), and let long lists / the form
     gallery scroll within the card so everything fits. */
  align-content: start;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Standard scrollbar styling — no layout impact, stays overlay on all platforms. */
.leaderboard-content {
  scrollbar-width: thin;
  scrollbar-color: var(--color-accent-soft) transparent;
}

.leaderboard-columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  align-items: stretch;
}

.leaderboard-column {
  display: grid;
  gap: 10px;
}

/* Category switcher — only shown on mobile, where the two columns collapse into
   a single tabbed view (see the max-width: 520px block). On wider screens both
   columns sit side-by-side and these tabs stay hidden. */
/* The leaderboard card now has three children: header + tabs host + scrolling
   content. Give it a third track so the content stays the final minmax(0,1fr)
   scroll row (profile cards keep their own grid via .profile-card). */
#leaderboardScreen .leaderboard-card {
  grid-template-rows: auto auto minmax(0, 1fr);
}

/* A real third grid child. On desktop its only child (.leaderboard-tabs) is
   display:none, so this track collapses to 0; on mobile it holds the switcher. */
.leaderboard-tabs-host:empty {
  display: none;
}

.leaderboard-tabs {
  display: none;
}

.leaderboard-tab {
  appearance: none;
  border: 1.5px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.2)),
    var(--color-surface-strong);
  color: var(--ink-soft);
  font: inherit;
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.01em;
  padding: 11px 10px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition:
    background var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    transform var(--t-fast) var(--ease-out);
}

.leaderboard-tab.is-active {
  background: linear-gradient(180deg, var(--action) 0%, var(--action-strong) 100%);
  border-color: var(--action-strong);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    var(--glow-md);
}

.leaderboard-column-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Desktop: pin the column heading to the top of the scroll area so it stays
     put while the rows scroll under it (on mobile the head is display:none and
     the pinned tabs host stands in instead). */
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 11px 16px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, 0.9);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.72) 60%),
    var(--color-surface-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 22px rgba(40, 92, 150, 0.1);
  margin-bottom: 2px;
}

.leaderboard-column-head h3 {
  margin: 0;
  color: var(--action);
  font-size: 16px;
  font-weight: 900;
  letter-spacing: 0.01em;
}

.leaderboard-list {
  display: grid;
  gap: 8px;
}

.leaderboard-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-radius: 20px;
}

.leaderboard-row .leaderboard-meta {
  display: block;
  margin-top: 2px;
}

.leaderboard-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.leaderboard-avatar--placeholder {
  background: var(--color-surface-raised, #e8edf4);
  display: block;
}

.leaderboard-user {
  flex: 1;
  min-width: 0;
}

.leaderboard-rank {
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 800;
  flex-shrink: 0;
}

.leaderboard-title {
  display: block;
  font-size: 18px;
  font-weight: 800;
}

.leaderboard-meta,
.leaderboard-empty {
  color: var(--color-text-soft);
  font-size: 12px;
}

.leaderboard-value {
  font-size: 20px;
  font-weight: 900;
  flex-shrink: 0;
  text-align: right;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.leaderboard-medal {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-size: 15px;
  font-weight: 900;
  color: #fff;
  background: var(--medal-grad, linear-gradient(145deg, #d8dde3, #9aa7b4));
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.8),
    0 2px 6px rgba(20, 50, 74, 0.28);
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.28);
}

/* Top 10 sit in a highlighted band; the podium (top 3) gets a metallic tint
   plus a colored rail so the ranking reads at a glance. */
.leaderboard-row.is-top10 {
  border-color: color-mix(in srgb, var(--color-accent, #16a7e8) 38%, var(--color-border));
  background:
    linear-gradient(
      90deg,
      color-mix(in srgb, var(--color-accent, #16a7e8) 9%, var(--color-surface-strong)),
      var(--color-surface-strong) 60%
    );
}

.leaderboard-row.is-top3 {
  position: relative;
  overflow: hidden;
}

.leaderboard-row.is-top3::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--medal, #c9a227);
}

.leaderboard-row.is-rank1 {
  --medal: #e8b923;
  --medal-grad: linear-gradient(145deg, #ffe79a, #e8b923 52%, #b07d10);
  border-color: color-mix(in srgb, #e8b923 55%, var(--color-border));
  background: linear-gradient(90deg, rgba(232, 185, 35, 0.16), var(--color-surface-strong) 64%);
}

.leaderboard-row.is-rank2 {
  --medal: #9aa7b4;
  --medal-grad: linear-gradient(145deg, #f4f7fa, #9aa7b4 52%, #6b7785);
  border-color: color-mix(in srgb, #9aa7b4 50%, var(--color-border));
  background: linear-gradient(90deg, rgba(154, 167, 180, 0.16), var(--color-surface-strong) 64%);
}

.leaderboard-row.is-rank3 {
  --medal: #c77b3b;
  --medal-grad: linear-gradient(145deg, #f3c692, #c77b3b 52%, #8a4f24);
  border-color: color-mix(in srgb, #c77b3b 50%, var(--color-border));
  background: linear-gradient(90deg, rgba(199, 123, 59, 0.16), var(--color-surface-strong) 64%);
}

.leaderboard-row.is-top3 .leaderboard-value {
  color: var(--medal);
}

@keyframes tile-swap-slide {
  0% {
    transform: translate(
      calc(var(--swap-dx, 0) * (100% + 2px)),
      calc(var(--swap-dy, 0) * (100% + 2px))
    );
    filter: brightness(1);
  }

  /* Clean glide into place — no scale pop. The earlier grow-to-1.05-then-shrink
     read as a bounce on the swapped tiles. A brief brightness shine keeps the
     feedback without any rebound. */
  60% {
    filter:
      brightness(1.07)
      drop-shadow(0 0 8px color-mix(in srgb, var(--tile-accent), white 22%));
  }

  100% {
    transform: translate(0, 0);
    filter: brightness(1);
  }
}

@keyframes tile-swap-reject {
  0% {
    transform: translate(0, 0);
  }

  /* Nudge toward the attempted swap, then return straight to rest. The old
     keyframe overshot to -10% PAST the origin before settling, which read as a
     bounce/rebound on every invalid swap — that was the remaining «подскок». */
  45% {
    transform: translate(
      calc(var(--swap-dx, 0) * 28%),
      calc(var(--swap-dy, 0) * 28%)
    );
    filter: brightness(1.05);
  }

  100% {
    transform: translate(0, 0);
  }
}

@keyframes tile-hint-jitter {
  0%,
  100% {
    transform: translate(0, 0) rotate(0deg);
  }

  12% {
    transform: translate(-1.6px, 0.6px) rotate(-2.4deg);
  }

  28% {
    transform: translate(1.6px, -0.6px) rotate(2.4deg);
  }

  44% {
    transform: translate(-1.2px, 0.4px) rotate(-1.8deg);
  }

  60% {
    transform: translate(1.2px, -0.4px) rotate(1.8deg);
  }

  76% {
    transform: translate(-0.6px, 0.2px) rotate(-0.9deg);
  }
}

@keyframes tile-fall-in {
  0% {
    opacity: 0;
    transform: translate3d(0, -42%, 0);
  }

  55% {
    opacity: 1;
  }

  /* Gentle gravity bounce (BluKit block-gravity-drop, scaled way down): a small
     overshoot past the cell, then settle. Kept tiny so 64 tiles don't slam. */
  78% {
    opacity: 1;
    transform: translate3d(0, 7%, 0);
  }

  90% {
    transform: translate3d(0, -2%, 0);
  }

  100% {
    opacity: 1;
    transform: translateZ(0);
  }
}

@keyframes tile-reshuffle-in {
  0% {
    opacity: 0;
    transform: scale(0.88);
    filter: blur(3px) saturate(0.9);
  }

  100% {
    opacity: 1;
    transform: scale(1);
    filter: blur(0) saturate(1);
  }
}

@keyframes tile-clear-shell {
  0% {
    opacity: 1;
    transform: scale(1);
    filter: brightness(1);
  }

  32% {
    opacity: 1;
    transform: scale(1);
    filter: brightness(1.22) saturate(1.1);
  }

  100% {
    opacity: 0;
    transform: scale(0.68);
    filter: brightness(1.08);
  }
}

@keyframes tile-clear-glass {
  0% {
    opacity: 1;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.92),
      inset 0 -1px 0 rgba(123, 177, 226, 0.18),
      0 10px 24px rgba(71, 146, 214, 0.12);
  }

  45% {
    opacity: 1;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 1),
      0 0 0 1px rgba(255, 255, 255, 0.78),
      0 0 18px color-mix(in srgb, var(--tile-accent), transparent 28%);
  }

  100% {
    opacity: 0;
    box-shadow: 0 0 24px color-mix(in srgb, var(--tile-accent), transparent 16%);
  }
}

@keyframes tile-clear-outline {
  0% {
    opacity: 0.96;
    transform: scale(1);
  }

  48% {
    opacity: 1;
    transform: scale(1);
  }

  100% {
    opacity: 0;
    transform: scale(0.9);
  }
}

@keyframes tile-clear-art {
  0% {
    opacity: 1;
    transform: scale(1);
    filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.14));
  }

  38% {
    opacity: 1;
    transform: scale(1);
    filter:
      brightness(1.32)
      saturate(1.16)
      drop-shadow(0 0 14px color-mix(in srgb, var(--tile-accent), white 28%));
  }

  100% {
    opacity: 0;
    transform: scale(0.58);
    filter:
      brightness(1.12)
      drop-shadow(0 0 18px color-mix(in srgb, var(--tile-accent), white 36%));
  }
}


@keyframes modal-backdrop-in {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes modal-panel-in {
  0% {
    opacity: 0;
    filter: blur(4px);
    transform: translate3d(0, 18px, 0) scale(0.965);
  }

  100% {
    opacity: 1;
    filter: blur(0);
    transform: translateZ(0) scale(1);
  }
}

@keyframes hatch-button-shine {
  0% {
    transform: translateX(-62%);
  }

  50% {
    transform: translateX(10%);
  }

  100% {
    transform: translateX(62%);
  }
}

@keyframes hatch-button-breathe {
  0%,
  100% {
    transform: translateY(0) scale(1);
    filter: saturate(1);
  }

  50% {
    transform: translateY(-1px) scale(1.03);
    filter: saturate(1.08) brightness(1.04);
  }
}

@keyframes hatch-bar-flow {
  0%,
  100% {
    background-position: 0% 50%;
  }

  50% {
    background-position: 100% 50%;
  }
}

@keyframes entry-btn-shine {
  0% {
    transform: translateX(-62%);
  }

  100% {
    transform: translateX(62%);
  }
}

/* B4 — light sweep across primary CTAs (from BluKit wallet-connect-shine). */
@keyframes cta-shine {
  0%, 16% {
    transform: translateX(-72%);
    opacity: 0;
  }
  42% {
    opacity: 0.9;
  }
  70%, 100% {
    transform: translateX(72%);
    opacity: 0;
  }
}

/* C6 — board flinch when a match clears (from BluKit platform-impact). */
@keyframes board-platform-impact {
  0% { transform: translateY(0) rotate(0) skew(0); }
  22% { transform: translateY(2px) rotate(-0.4deg) skew(-0.24deg); }
  46% { transform: translateY(0) rotate(0.32deg) skew(0.18deg); }
  68% { transform: translateY(0) rotate(-0.14deg) skew(-0.1deg); }
  100% { transform: translateY(0) rotate(0) skew(0); }
}

/* C7 — liquid morphing aura behind evolve-ready elements (BluKit block-aura-liquid). */
@keyframes tile-aura-liquid {
  0%, 100% {
    border-radius: 44% 56% 48% 52% / 36% 42% 58% 64%;
    filter: blur(14px) saturate(1.3);
    transform: scale(1.04) rotate(-1deg);
  }
  45% {
    border-radius: 56% 44% 42% 58% / 46% 34% 66% 54%;
    filter: blur(16px) saturate(1.46) hue-rotate(74deg);
    transform: scale(1.16) rotate(1.2deg);
  }
  72% {
    border-radius: 48% 52% 62% 38% / 38% 52% 48% 62%;
    filter: blur(15px) saturate(1.38) hue-rotate(190deg);
    transform: scale(1.1) rotate(-0.4deg);
  }
}

/* D8 — crystal shard burst on a cleared tile (from BluKit reveal-crystal-burst). */
@keyframes tile-crystal-burst {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(var(--crystal-angle, 0deg)) translate(0) scale(0.22);
  }
  16% {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(var(--crystal-angle, 0deg)) translate(calc(var(--crystal-distance, 30px) * 0.6)) scale(1.04);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(var(--crystal-angle, 0deg)) translate(var(--crystal-distance, 30px)) scale(0.4);
  }
}

/* D9 — one-shot rotating ray burst behind reveal art (from BluKit hatch-ray-burst). */
@keyframes victory-ray-burst {
  0% {
    opacity: 0;
    transform: rotate(calc(var(--ray) * 30deg)) translate(14px) scaleX(0.12);
  }
  20% { opacity: 1; }
  72% {
    opacity: 0.7;
    transform: rotate(calc(var(--ray) * 30deg)) translate(58px) scaleX(1);
  }
  100% {
    opacity: 0;
    transform: rotate(calc(var(--ray) * 30deg)) translate(104px) scaleX(0.18);
  }
}

/* E10 — card entrance with a small overshoot (from BluKit reveal-card-pop-in). */
@keyframes card-pop-in {
  0% {
    opacity: 0;
    transform: translateY(26px) scale(0.92);
  }
  60% {
    opacity: 1;
    transform: translateY(-5px) scale(1.015);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes entry-artwork-in {
  0% {
    opacity: 0;
    filter: blur(6px) saturate(0.92);
    transform: translate3d(0, 14px, 0) scale(0.985);
  }

  100% {
    opacity: 1;
    filter: blur(0) saturate(1);
    transform: translateZ(0) scale(1);
  }
}

@keyframes entry-rays-breathe {
  0%,
  100% {
    transform: translate(-50%, -45%) scale(0.96, 0.92);
    opacity: 0.62;
  }

  50% {
    transform: translate(-50%, -44%) scale(1.04, 0.98);
    opacity: 0.84;
  }
}

@keyframes entry-aura-pulse {
  0%,
  100% {
    opacity: 0.58;
    transform: scale(0.94);
  }

  50% {
    opacity: 0.88;
    transform: scale(1.02);
  }
}

@keyframes entry-aura-liquid {
  0%,
  100% {
    border-radius: 44% 56% 48% 52% / 36% 42% 58% 64%;
    transform: scale(0.96) rotate(-1deg);
    opacity: 0.92;
  }

  50% {
    border-radius: 54% 46% 58% 42% / 42% 36% 64% 58%;
    transform: scale(1.08) rotate(2deg);
    opacity: 1;
  }
}

@keyframes block-hover-float {
  0%,
  100% {
    transform: translateY(0) rotate(0deg);
  }

  25% {
    transform: translateY(-6px) rotate(-1.2deg);
  }

  50% {
    transform: translateY(-11px) rotate(0.4deg);
  }

  75% {
    transform: translateY(-4px) rotate(1.2deg);
  }
}

@keyframes entry-echo-float-left {
  0%,
  100% {
    transform: translateY(8%) scale(0.72) rotate(0deg);
  }

  25% {
    transform: translateY(6%) scale(0.72) rotate(-1deg);
  }

  50% {
    transform: translateY(4%) scale(0.72) rotate(0.4deg);
  }

  75% {
    transform: translateY(7%) scale(0.72) rotate(1deg);
  }
}

@keyframes entry-echo-float-right {
  0%,
  100% {
    transform: translateY(9%) scale(0.72) rotate(0deg);
  }

  25% {
    transform: translateY(7%) scale(0.72) rotate(1deg);
  }

  50% {
    transform: translateY(5%) scale(0.72) rotate(-0.4deg);
  }

  75% {
    transform: translateY(8%) scale(0.72) rotate(-1deg);
  }
}

@keyframes entry-particle-drift {
  0%,
  100% {
    opacity: 0;
    transform: translate(0, 0) scale(0.6);
  }

  20% {
    opacity: 0.78;
  }

  50% {
    opacity: 1;
    transform: translate(8px, -12px) scale(1);
  }

  80% {
    opacity: 0.38;
  }
}

@keyframes entry-hover-spark {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(var(--spark-rot, 0deg)) scale(0.36);
  }

  16% {
    opacity: 0.92;
  }

  54% {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(calc(var(--spark-rot, 0deg) + 12deg)) scale(1);
  }

  100% {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(calc(var(--spark-rot, 0deg) + 22deg)) scale(0.52);
  }
}

@keyframes entry-btn-colorflow {
  0%,
  100% {
    background-position: 0% 50%, 0% 50%;
  }

  50% {
    background-position: 100% 50%, 100% 50%;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Silence the looping decorative motion (rays, auras, drifting particles,
     button shine, floating art) that can bother motion-sensitive players. */
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* But keep the one-shot gameplay feedback: a match-3 board is unreadable if
     tiles teleport instead of sliding, falling and clearing. These re-assert the
     real durations (animation-name stays set above, only duration was zeroed). */
  .tile.is-swapping {
    animation-duration: 210ms !important;
  }
  .tile.is-rejecting {
    animation-duration: 300ms !important;
  }
  .tile.is-falling {
    animation-duration: 360ms !important;
  }
  .tile.is-reshuffling {
    animation-duration: 320ms !important;
  }
  .tile.hint-jitter {
    animation-duration: 680ms !important;
  }
  .tile.clearing,
  .tile.clearing::before,
  .tile.clearing::after {
    animation-duration: 280ms !important;
  }
}

@media (max-width: 520px) {
  .screen {
    width: 100%;
  }

  .start-card,
  .leaderboard-card {
    padding: 20px;
  }

  .game-frame {
    padding: 10px;
  }

  .entry-hero {
    width: min(82vw, 300px);
  }

  .entry-art {
    width: min(140vw, 504px);
    height: calc(min(140vw, 504px) * 0.621);
  }

  .entry-btn {
    min-height: 74px;
    font-size: clamp(24px, 7vw, 32px);
  }

  .topbar {
    --hud-h: 64px;
  }

  .topbar-stats {
    gap: 8px;
  }

  .stat-pill {
    padding: 10px 10px 9px;
  }

  .stat-pill strong {
    font-size: 24px;
  }

  .board-shell {
    padding: 6px;
    border-radius: 24px;
  }

  .victory-card {
    padding: 14px;
  }

  .victory-art {
    width: min(64%, 180px);
  }

  .gameover-card {
    padding: 18px 16px;
  }

  .gameover-art {
    width: min(100%, 180px);
  }

  .gameover-screen .end-actions .btn {
    min-width: 148px;
  }

  .board {
    width: min(100%, calc(100dvh - 240px));
  }

  .leaderboard-columns {
    grid-template-columns: 1fr;
  }

  /* Mobile: replace the stacked columns with a tab switcher pinned above the
     scrolling list (the host sits outside #leaderboard-content). */
  .leaderboard-tabs-host {
    margin-top: 14px;
  }
  .leaderboard-tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  /* The tab labels stand in for the per-column headings on mobile. */
  .leaderboard-columns .leaderboard-column-head {
    display: none;
  }

  /* Show only the active category; the other stays mounted but hidden so the
     scroll position and DOM are preserved across taps. */
  .leaderboard-columns .leaderboard-column {
    display: none;
  }
  .leaderboard-columns[data-active="score"] .leaderboard-column[data-col="score"],
  .leaderboard-columns[data-active="speed"] .leaderboard-column[data-col="speed"] {
    display: grid;
  }
}

/* Vibe intro overlay — shown once at the start of each run to reveal the rolled
   perks before play begins. */
/* Coachmark guide: a full-screen capture layer freezes the board, a spotlight
   box dims everything except the highlighted element, and a glass tip explains
   it. The spotlight's big box-shadow is the dimmer; the layer itself catches
   pointer events so the live board stays frozen until the tour ends. */
.coach-layer {
  position: fixed;
  inset: 0;
  z-index: 70;
  pointer-events: auto;
  animation: vibe-intro-fade 200ms ease both;
}

.coach-layer--centered {
  background: radial-gradient(circle at 50% 40%, rgba(20, 24, 38, 0.5), rgba(8, 10, 18, 0.8));
  backdrop-filter: blur(4px);
}

.coach-spotlight {
  position: fixed;
  border-radius: 16px;
  box-shadow:
    0 0 0 9999px rgba(10, 14, 26, 0.62),
    inset 0 0 0 2px rgba(255, 255, 255, 0.85),
    0 0 22px rgba(104, 216, 255, 0.45);
  pointer-events: none;
  transition:
    top 280ms cubic-bezier(0.2, 0.9, 0.3, 1),
    left 280ms cubic-bezier(0.2, 0.9, 0.3, 1),
    width 280ms cubic-bezier(0.2, 0.9, 0.3, 1),
    height 280ms cubic-bezier(0.2, 0.9, 0.3, 1);
}

.coach-tip {
  position: fixed;
  width: min(300px, calc(100vw - 24px));
  padding: 16px 18px 14px;
  border-radius: var(--r-md);
  border: 1.5px solid transparent;
  background:
    linear-gradient(180deg, #ffffff, #eef6ff) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    var(--glow-md),
    0 0 28px rgba(92, 232, 255, 0.2),
    var(--ring-inset);
  animation: vibe-intro-pop 260ms cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}

.coach-tip-step {
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--action-ink);
}

.coach-tip-title {
  margin: 4px 0 6px;
  font-size: 1.18rem;
  font-weight: 800;
  color: var(--color-text);
}

.coach-tip-body {
  font-size: 0.95rem;
  line-height: 1.4;
  color: #4a5575;
}

.coach-tip-actions {
  margin-top: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.coach-skip {
  border: none;
  background: none;
  padding: 8px 6px;
  font-weight: 700;
  font-size: 0.9rem;
  color: #8a96b8;
  cursor: pointer;
}

.coach-skip:hover {
  color: var(--color-text);
}

.coach-next {
  padding: 10px 22px;
  border-radius: 999px;
  font-size: 0.95rem;
  cursor: pointer;
}

.vibe-intro {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(circle at 50% 32%, rgba(29, 111, 232, 0.3), transparent 58%),
    rgba(7, 24, 48, 0.62);
  backdrop-filter: blur(8px);
  animation: vibe-intro-fade 220ms ease both;
}

.vibe-intro[hidden] {
  display: none;
}

.vibe-intro-card {
  position: relative;
  width: min(360px, 100%);
  padding: 28px 26px 24px;
  border-radius: var(--r-card);
  text-align: center;
  border: 1.5px solid transparent;
  background:
    linear-gradient(180deg, #ffffff, #eef6ff) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    var(--glow-lg),
    0 0 40px rgba(92, 232, 255, 0.26),
    var(--ring-inset);
  animation: vibe-intro-pop 280ms cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}

.vibe-intro-kicker {
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--action-ink);
}

.vibe-intro-name {
  margin: 10px 0 12px;
  font-size: 1.7rem;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.vibe-intro-blurb {
  margin: 0 0 22px;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

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

@keyframes vibe-intro-pop {
  from { opacity: 0; transform: translateY(12px) scale(0.94); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* ============================================================
   Feature pack: move meter, mute, combo FX, toast, collection
   ============================================================ */

/* --- Mute toggle (topbar HUD button) --- */
.mute-btn {
  font-size: 16px;
  line-height: 1;
}
.mute-btn.is-muted {
  opacity: 0.55;
}

/* --- Move meter: thin fill under the Moves pill --- */
/* The meter is pinned to the bottom edge of the pill so it doesn't add to the
   pill's height — that keeps every HUD control the same height. */
/* Low-moves warning is conveyed by the number's colour now (no meter bar). */
.stat-pill--moves strong {
  transition: color 0.3s ease;
}
.stat-pill--moves.is-warning strong {
  color: #f59e0b;
}
.stat-pill--moves.is-danger strong {
  color: #e23b3b;
  animation: moves-danger-pulse 0.9s ease-in-out infinite;
}
@keyframes moves-danger-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

/* --- Cascade combo / score floaters over the board --- */
.fx-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
  z-index: 30;
}
.fx-combo,
.fx-score {
  position: absolute;
  left: var(--fx-x, 50%);
  top: var(--fx-y, 50%);
  transform: translate(-50%, -50%);
  font-weight: 900;
  letter-spacing: -0.02em;
  white-space: nowrap;
  pointer-events: none;
  text-shadow:
    0 2px 0 rgba(255, 255, 255, 0.9),
    0 6px 18px rgba(24, 76, 126, 0.35);
}
.fx-combo {
  font-size: clamp(22px, 7vw, 38px);
  color: hsl(var(--fx-hue, 40) 95% 52%);
  animation: fx-combo-pop 0.92s cubic-bezier(0.18, 0.9, 0.3, 1) forwards;
}
.fx-score {
  font-size: calc(clamp(18px, 5vw, 26px) * var(--fx-scale, 1));
  color: #1f7dff;
  animation: fx-score-rise 0.98s ease-out forwards;
}
.fx-score.is-big-cascade {
  color: #ff7a1f;
}
@keyframes fx-combo-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(-6deg); }
  28% { opacity: 1; transform: translate(-50%, -50%) scale(1.18) rotate(2deg); }
  55% { transform: translate(-50%, -58%) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(-50%, -96%) scale(0.92); }
}
@keyframes fx-score-rise {
  0% { opacity: 0; transform: translate(-50%, -40%) scale(0.7); }
  25% { opacity: 1; transform: translate(-50%, -52%) scale(1.05); }
  100% { opacity: 0; transform: translate(-50%, -118%) scale(1); }
}

/* --- Toast (share fallback) --- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 12px);
  max-width: min(86vw, 360px);
  padding: 12px 18px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(20, 52, 88, 0.96), rgba(10, 33, 64, 0.96));
  border: 1px solid rgba(92, 232, 255, 0.28);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 14px 34px rgba(10, 33, 64, 0.4),
    0 0 22px rgba(92, 232, 255, 0.18);
  opacity: 0;
  transition: opacity 0.24s ease, transform 0.24s var(--ease-slow);
  z-index: 200;
}
.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* --- Start-screen profile chip (non-intrusive overlay) --- */
.profile-chip {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top, 0px));
  right: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 170px;
  height: 58px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-surface-strong);
  color: var(--color-text);
  font: inherit;
  font-weight: 800;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--color-shadow);
  z-index: 20;
  transition: transform 0.18s var(--ease-slow);
}
.profile-chip:hover { transform: translateY(-1px); }
.profile-chip:active { transform: translateY(0) scale(0.97); }
.profile-chip-icon {
  display: grid;
  place-items: center;
  width: 25px;
  height: 25px;
  flex: 0 0 auto;
}
.profile-chip-icon img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: contain;
  image-rendering: pixelated;
}
.profile-chip-label {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0;
}
.profile-chip-count {
  margin-left: auto;
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 900;
}
.profile-chip.is-signed-in .profile-chip-label {
  color: var(--color-accent);
}

/* --- Social auth panel (Supabase OAuth) --- */
.auth-panel {
  display: grid;
  gap: 8px;
  width: 100%;
  padding: 10px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.58);
  background: rgba(255, 255, 255, 0.62);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.75),
    0 14px 34px rgba(40, 92, 150, 0.12);
  backdrop-filter: blur(10px);
}

.auth-modal {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: grid;
  place-items: center;
  padding: 20px;
  /* Sky-tinted scrim instead of flat black — keeps the brand mood behind the modal. */
  background:
    radial-gradient(circle at 50% 30%, rgba(29, 111, 232, 0.28), transparent 60%),
    rgba(7, 24, 48, 0.52);
  backdrop-filter: blur(8px);
  animation: modal-backdrop-in 260ms var(--ease-out) both;
}

.auth-modal[hidden] {
  display: none;
}

.auth-modal-card {
  position: relative;
  width: min(420px, 100%);
  padding: 20px;
  border-radius: var(--r-card);
  /* Holographic iridescent edge to match the hero cards. */
  border: 1.5px solid transparent;
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.97), rgba(255, 255, 255, 0.78) 46%, rgba(235, 249, 255, 0.7) 100%) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    var(--glow-lg),
    0 0 38px rgba(104, 216, 255, 0.22),
    var(--ring-inset);
  animation: modal-panel-in 360ms var(--ease-out) both;
}

.auth-modal-head {
  display: flex;
  gap: 16px;
  align-items: start;
  justify-content: space-between;
}

.auth-modal-kicker {
  color: var(--color-text-soft);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.auth-modal-title {
  margin: 4px 0 0;
  font-size: 24px;
  line-height: 1.08;
  color: var(--color-text);
}

.auth-modal-copy {
  margin: 12px 0 14px;
  color: var(--color-text-soft);
  font-size: 14px;
  line-height: 1.5;
}

.auth-modal-skip {
  border: none;
  background: transparent;
  color: var(--color-text-soft);
  font-weight: 900;
  cursor: pointer;
  padding: 6px 2px;
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
}
.auth-modal-skip:hover {
  color: var(--color-text);
}
/* No focus box on the skip text button — it should read as plain text, not a framed control. */
.auth-modal-skip:focus,
.auth-modal-skip:focus-visible {
  outline: none;
  box-shadow: none;
}

.auth-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.auth-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 46px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.72) 60%),
    var(--color-surface-strong);
  color: var(--color-accent);
  font: inherit;
  font-size: 14px;
  font-weight: 900;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 10px 22px rgba(40, 92, 150, 0.1);
  transition:
    transform 240ms var(--ease-slow),
    box-shadow 240ms var(--ease-slow),
    opacity 240ms var(--ease-slow);
}

.auth-btn-icon {
  flex: 0 0 auto;
  display: block;
}

.auth-btn:hover {
  transform: translateY(-1px);
}

.auth-btn:active {
  transform: translateY(0) scale(0.98);
}

.auth-btn:disabled {
  cursor: default;
  opacity: 0.5;
  transform: none;
}

/* Provider identity — recognizable sign-in buttons rather than generic pills. */
.auth-btn--google {
  color: #1f2733;
}
.auth-btn--google:hover {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    0 12px 26px rgba(40, 92, 150, 0.16);
}

.auth-btn--x {
  border-color: rgba(255, 255, 255, 0.16);
  background:
    radial-gradient(circle at 50% 0%, rgba(70, 78, 90, 0.55), transparent 60%),
    linear-gradient(180deg, #20242b, #0d0f13);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 10px 22px rgba(8, 12, 20, 0.34);
}
.auth-btn--x:hover {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 12px 26px rgba(8, 12, 20, 0.42);
}

.auth-btn--ghost {
  width: 100%;
}

.auth-user {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 4px 8px 4px 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.76);
}

.auth-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background:
    url("./assets/blu-logo.png") center / contain no-repeat,
    linear-gradient(180deg, #ffffff, #eef5ff);
  image-rendering: pixelated;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.auth-name {
  min-width: 0;
  overflow: hidden;
  color: var(--color-text);
  font-size: 14px;
  font-weight: 900;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.auth-status {
  color: var(--color-text-soft);
  font-size: 11px;
  font-weight: 800;
  text-align: center;
}

.auth-panel.has-error .auth-status {
  color: #e23b3b;
}

.profile-card {
  display: grid;
  /* Four children: summary (now carries the inline back button), empty
     section-head anchor, the JS-injected .profile-stats (pills +
     collection-progress, inserted via stats.after()/sectionHead.before()),
     then #profile-content. The gallery must land in the final minmax(0,1fr)
     track so the 36-card grid scrolls, not clips. */
  grid-template-rows: auto auto auto minmax(0, 1fr);
  gap: 8px;
}

.profile-head {
  align-items: center;
}

.profile-subtitle {
  margin: 3px 0 0;
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 700;
}


.profile-summary {
  display: grid;
  /* back button | avatar | name+status | actions. Back button lives inline at
     the card's left edge — there's no separate page header anymore. */
  grid-template-columns: auto 44px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.2)),
    var(--color-surface-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.75),
    0 6px 18px rgba(20, 50, 74, 0.08);
}

.profile-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background:
    url("./assets/blu-logo.png") center / contain no-repeat,
    linear-gradient(180deg, #ffffff, #eef5ff);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 10px 20px rgba(38, 93, 142, 0.12);
  image-rendering: pixelated;
}

.profile-meta {
  min-width: 0;
}

.profile-name {
  color: var(--color-text);
  font-size: 16px;
  font-weight: 900;
  line-height: 1.1;
}

.profile-status {
  margin-top: 2px;
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.25;
}

.profile-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.profile-section-head {
  margin-top: 0;
  color: var(--color-text-soft);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.profile-stats {
  display: grid;
  margin-top: -2px;
}

.profile-stats .lifetime-stats {
  gap: 8px;
  margin-bottom: 6px;
}

.profile-stats .lifetime-stat {
  min-width: 0;
  padding: 13px 8px;
  border-radius: 16px;
}

.profile-stats .lifetime-stat span {
  font-size: 10px;
}

.profile-stats .lifetime-stat strong {
  font-size: 24px;
}

/* --- Collection progress hero (own + public profile) --- */
.collection-progress {
  padding: 13px 15px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.18)),
    var(--color-surface-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 8px 20px rgba(20, 50, 74, 0.09);
  margin-bottom: 10px;
}
.cp-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}
.cp-label {
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cp-count {
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-faint);
  white-space: nowrap;
}
.cp-count strong {
  font-size: 22px;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: var(--action);
}
.cp-total {
  margin-left: 3px;
}
.cp-track {
  position: relative;
  height: 13px;
  border-radius: var(--r-pill);
  background: rgba(20, 50, 74, 0.1);
  box-shadow:
    inset 0 1px 3px rgba(20, 50, 74, 0.18),
    inset 0 -1px 0 rgba(255, 255, 255, 0.5);
  overflow: hidden;
}
.cp-fill {
  position: absolute;
  inset: 0 auto 0 0;
  min-width: 13px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, #5ce8ff 0%, #1d6fe8 58%, #6fcfff 100%);
  box-shadow: 0 0 14px rgba(92, 232, 255, 0.6);
  transition: width 720ms var(--ease-out);
}
/* glossy top sheen on the fill */
.cp-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 58%);
}
/* full collection = full holographic rainbow */
.collection-progress.is-complete .cp-fill {
  background: var(--holo-border);
  box-shadow: 0 0 16px rgba(255, 155, 232, 0.45), 0 0 14px rgba(92, 232, 255, 0.5);
}
@media (prefers-reduced-motion: reduce) {
  .cp-fill { transition: none; }
}

/* --- Lifetime stats banner (leaderboard) --- */
.lifetime-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.lifetime-stat {
  flex: 1 1 0;
  min-width: 64px;
  padding: 8px 6px;
  border-radius: 14px;
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.18)),
    var(--color-surface-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.72),
    0 4px 12px rgba(20, 50, 74, 0.07);
  text-align: center;
}
.lifetime-stat span {
  display: block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.lifetime-stat strong {
  display: block;
  margin-top: 3px;
  font-size: 18px;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink-strong);
}

/* --- Collection gallery (persistent apex forms) --- */
.collection-head {
  font-size: 13px;
  font-weight: 800;
  color: var(--color-text-soft);
  margin: 4px 2px 12px;
}
.collection-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 5px;
}
.collection-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  padding: 4px;
  border-radius: 12px;
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.12)),
    var(--color-surface-strong);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
  transition:
    transform var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out);
}
/* Discovered apex forms read as earned trophies: iridescent holographic edge
   (border-box gradient — stays inside the card, never clips) + cyan inner glow.
   The outer glow on hover is kept tight (≤3px) and the container has padding
   headroom, so nothing gets clipped by the scroll/overflow gallery wrapper. */
.collection-card.is-owned {
  border: 1.5px solid transparent;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.66), rgba(255, 255, 255, 0.22)) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 0 14px rgba(92, 232, 255, 0.24);
}
.collection-card.is-owned:hover {
  transform: translateY(-2px) scale(1.06);
  z-index: 2;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 0 20px rgba(92, 232, 255, 0.4),
    0 0 0 2px rgba(92, 232, 255, 0.55),
    0 6px 16px rgba(40, 92, 150, 0.18);
}
.collection-card.is-owned:active {
  transform: translateY(0) scale(1.0);
  transition-duration: 90ms;
}
/* Locked forms recede: muted, desaturated, low contrast — so each discovery is
   a visible jump up the holographic ladder. */
.collection-card.is-locked {
  opacity: 0.72;
  filter: saturate(0.65);
}
.collection-art {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 8px;
}
.collection-art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}
/* Locked forms tease the real art, blurred — instead of a flat "?" block. */
.collection-art-blurred {
  filter: blur(2.5px) saturate(0.9) brightness(1.02);
  transform: scale(1.08);
  opacity: 0.92;
}
.collection-lock {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 22px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 1px 4px rgba(14, 32, 53, 0.45);
  opacity: 0.85;
}
.collection-name {
  display: none;
  font-size: 11px;
  font-weight: 700;
  text-align: center;
  line-height: 1.15;
  color: var(--color-text);
}
.collection-card.is-locked .collection-name {
  color: var(--color-text-soft);
}
.collection-card[data-form-key] {
  cursor: pointer;
}
.collection-card[data-form-key]:focus-visible {
  outline: 2px solid rgba(92, 232, 255, 0.7);
  outline-offset: 2px;
}
/* Even locked cards are tappable (they open the tree with a spoiler-safe apex),
   so give them the same lift-on-hover affordance as owned cards. */
.collection-card.is-locked:hover {
  transform: translateY(-2px) scale(1.04);
  opacity: 0.85;
}

/* ── Evolution-tree popup ─────────────────────────────────────────────────
   Opened by tapping a form card in either profile gallery. Mirrors the auth
   modal's sky scrim + holographic card. The tree is a vertical stack of tier
   rows (apex on top → base color pair at the bottom) joined by thin links. */
.evo-modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 18px;
}
.evo-modal[hidden] {
  display: none;
}
.evo-modal-backdrop {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 30%, rgba(29, 111, 232, 0.28), transparent 60%),
    rgba(7, 24, 48, 0.52);
  backdrop-filter: blur(8px);
  animation: modal-backdrop-in 260ms var(--ease-out) both;
}
.evo-modal-card {
  position: relative;
  width: min(440px, 100%);
  max-height: min(88vh, 760px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 22px 18px 24px;
  border-radius: var(--r-card);
  border: 1.5px solid transparent;
  background:
    radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.97), rgba(255, 255, 255, 0.78) 46%, rgba(235, 249, 255, 0.7) 100%) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    var(--glow-lg),
    0 0 38px rgba(104, 216, 255, 0.22),
    var(--ring-inset);
  animation: modal-panel-in 360ms var(--ease-out) both;
}
.evo-modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 999px;
  background: rgba(14, 32, 53, 0.06);
  color: var(--color-text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}
.evo-modal-close:hover {
  background: rgba(14, 32, 53, 0.12);
}
.evo-tree {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.evo-kicker {
  color: var(--color-text-soft);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.evo-title {
  margin: 2px 0 8px;
  font-size: 22px;
  line-height: 1.1;
  text-align: center;
  color: var(--color-text);
}
.evo-tier {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: nowrap;
  gap: 6px;
  width: 100%;
}
.evo-link {
  width: 2px;
  height: 18px;
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(120, 170, 220, 0.55), rgba(120, 170, 220, 0.22));
}
.evo-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  /* Size every node so the 5-wide T2 tier fits one row even on the narrowest
     phone: (row width − 4 gaps) / 5, capped so wider screens don't balloon.
     T3/T1 tiers reuse the same width and just center, keeping nodes uniform. */
  width: min(72px, calc((100% - 24px) / 5));
  min-width: 0;
}
.evo-tier--apex .evo-node {
  width: clamp(66px, 22vw, 96px);
}
.evo-tier-tag {
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.08em;
  color: var(--color-text-soft);
}
.evo-node-art {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 10px;
  border: 1px solid var(--hairline);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.12)),
    var(--color-surface-strong);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.evo-node-art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}
.evo-node--base .evo-node-art {
  border-color: color-mix(in srgb, var(--evo-base) 55%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 0 12px color-mix(in srgb, var(--evo-base) 24%, transparent);
}
.evo-tier--apex .evo-node-art {
  border: 1.5px solid transparent;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.66), rgba(255, 255, 255, 0.22)) padding-box,
    var(--holo-border) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 0 14px rgba(92, 232, 255, 0.24);
}
.evo-node.is-locked {
  opacity: 0.82;
  filter: saturate(0.7);
}
.evo-node-name {
  font-size: 10px;
  font-weight: 700;
  text-align: center;
  line-height: 1.1;
  color: var(--color-text);
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* Desktop: widen the card and force each tier onto a single row, so the 5-wide
   T2 tier reads as one clean row (mobile keeps the wrapping fallback). */
@media (min-width: 700px) {
  .evo-modal-card {
    width: min(560px, 100%);
  }
  .evo-tier {
    flex-wrap: nowrap;
  }
  .evo-node {
    width: 80px;
  }
  .evo-tier--apex .evo-node {
    width: 104px;
  }
}

.profile-content {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Cancel the inherited .leaderboard-content margin-top — the profile grid gap
     already spaces this from the section head, so 18px+gap doubled the gap. */
  margin-top: 0;
  /* Headroom so the gallery cards' hover lift/glow isn't clipped at the edges. */
  padding: 6px;
}

/* ── Leaderboard: clickable user row ───────────────────────────────────── */
.leaderboard-user-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
  border-radius: 0.5rem;
}
.leaderboard-user-btn:hover .leaderboard-title,
.leaderboard-user-btn:focus-visible .leaderboard-title {
  text-decoration: underline;
}


/* ── Audit fixes: scroll-lock, tap delay, tap targets, landscape phone ──────
   These are DEFAULT (mobile-first) rules — placed before the desktop media
   query so they apply at all widths unless overridden below.        ──────── */

/* U1: lock background scroll while a blocking modal is open. */
body.modal-open {
  overflow: hidden;
}

/* U5: remove the 300ms tap delay / double-tap zoom on controls (zoom still
   works on the page, since the viewport meta keeps user-scalable enabled). */
button,
.btn,
.icon-btn,
.hud-btn,
.partner-card,
.form-card,
.entry-btn,
.profile-chip {
  touch-action: manipulation;
}

/* U6: meet the 44px minimum hit target on small text buttons. */
.auth-modal-skip,
.coach-skip,
.icon-btn {
  min-height: 44px;
}

/* Portrait lock: the game is portrait-only on phones. The rotate overlay is
   hidden by default and only covers the screen when a small viewport is held
   in landscape. Desktop (≥700px) never triggers it. */
.rotate-lock {
  display: none;
}

@media (orientation: landscape) and (max-width: 932px) and (max-height: 600px) {
  .rotate-lock {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    overflow: hidden;
    font-family: var(--ui-font);
    color: var(--color-text, #0f2742);
    text-align: center;
    /* BluKit sky — same backdrop as the start screen. */
    background: var(--blupets-sky-background);
  }

  /* Soft cyan/cream/pink aura drifting behind the card, echoing the entry hero. */
  .rotate-lock-glow {
    position: absolute;
    width: 120vmax;
    height: 120vmax;
    border-radius: 50%;
    background:
      radial-gradient(circle at 32% 42%, rgba(92, 232, 255, 0.55), transparent 46%),
      radial-gradient(circle at 68% 58%, rgba(255, 155, 232, 0.45), transparent 46%),
      radial-gradient(circle at 50% 50%, rgba(255, 240, 168, 0.4), transparent 52%);
    filter: blur(28px);
    opacity: 0.85;
    animation: rotate-lock-aura 7s ease-in-out infinite;
  }

  .rotate-lock-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    max-width: 380px;
    padding: 24px 30px 26px;
    border-radius: var(--radius-lg, 30px);
    background: var(--color-surface-strong, rgba(255, 255, 255, 0.98));
    border: 1px solid rgba(255, 255, 255, 0.9);
    box-shadow:
      0 24px 60px rgba(24, 76, 126, 0.22),
      inset 0 0 0 1px rgba(92, 232, 255, 0.25);
  }

  /* Rounded "ready" medallion holding the phone glyph — matches the reroll/enter look. */
  .rotate-lock-phone {
    display: grid;
    place-items: center;
    width: 116px;
    height: 116px;
    border-radius: 50%;
    color: #0a8faf;
    background: var(--reroll-ready-fill);
    box-shadow:
      0 12px 28px rgba(24, 76, 126, 0.18),
      inset 0 0 0 2px rgba(92, 232, 255, 0.5);
    animation: rotate-lock-nudge 2.4s var(--ease-slow, ease-in-out) infinite;
  }

  .rotate-lock-text {
    margin: 0;
    font-size: 1.32rem;
    font-weight: 800;
    letter-spacing: 0.2px;
    color: var(--color-text, #0f2742);
  }

  .rotate-lock-sub {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--color-text-soft, #607e9f);
  }

  /* Stop the underlying game from animating/playing behind the overlay. */
  .app-shell {
    visibility: hidden;
  }
}

@keyframes rotate-lock-nudge {
  0%, 55%, 100% { transform: rotate(0deg); }
  25%, 35% { transform: rotate(-90deg); }
}

@keyframes rotate-lock-aura {
  0%, 100% { transform: scale(1) rotate(0deg); }
  50% { transform: scale(1.08) rotate(8deg); }
}

@media (prefers-reduced-motion: reduce) {
  .rotate-lock-phone,
  .rotate-lock-glow {
    animation: none;
  }
}

/* ── Desktop layout (≥700px) ──────────────────────────────────────────────
   Mobile (< 700px) is completely unaffected — these rules are dead to narrow
   viewports because they live inside the media query.               ──────── */
@media (min-width: 700px) {
  :root {
    --desktop-aspect: 16 / 9;
  }

  .app-shell {
    /* Increase padding so the card never clips browser chrome edges. */
    padding: 20px;
  }

  .screen {
    /* Desktop uses a browser-native wide canvas. Width is constrained by both
       viewport axes, so the 16:9 card always fits without page scrolling. */
    width: min(
      calc(100vw - 40px),
      calc((100dvh - 40px - max(0px, env(safe-area-inset-top, 0px)) - max(0px, env(safe-area-inset-bottom, 0px))) * 16 / 9)
    );
    height: auto;
    max-height: none;
    aspect-ratio: var(--desktop-aspect);
    /* At narrow desktop widths (700-900px) 16:9 collapses the card to ~370px —
       not tall enough for the game content. Floor the height so the board and
       left-column controls always fit. */
    min-height: min(560px, calc(100dvh - 40px));
  }

  .start-card,
  .leaderboard-card {
    padding: clamp(24px, 3dvh, 36px);
  }

  .start-screen .start-card {
    grid-template-rows: minmax(0, 1fr) auto;
    padding-top: clamp(78px, 9dvh, 110px);
  }

  .start-screen .hud-btn.start-mute-btn {
    left: clamp(24px, 3dvh, 36px);
    top: auto;
    bottom: clamp(18px, 2.2dvh, 26px);
  }

  .start-screen .profile-chip {
    right: clamp(24px, 3dvh, 36px);
    top: clamp(18px, 2.2dvh, 26px);
  }

  .profile-card {
    /* 4 children incl. JS-injected .profile-stats — see default block above. */
    grid-template-rows: auto auto auto minmax(0, 1fr);
    gap: 10px;
  }

  .profile-content {
    overflow-y: auto;
    padding: 6px;
  }

  .profile-content .collection-grid {
    grid-template-columns: repeat(9, minmax(0, 1fr));
    gap: 6px;
  }

  .profile-content .collection-card {
    min-height: 104px;
    padding: 6px 4px;
    border-radius: 16px;
    gap: 4px;
  }

  .profile-content .collection-art {
    width: 68px;
    height: 68px;
    border-radius: 14px;
  }

  .profile-content .collection-name {
    display: block;
    font-size: 10px;
  }

  .leaderboard-columns {
    gap: 12px;
  }

  .start-screen .start-actions--secondary {
    position: absolute;
    left: clamp(24px, 3dvh, 36px);
    top: clamp(18px, 2.2dvh, 26px);
    width: min(330px, 25dvw);
    max-width: none;
    margin: 0;
    z-index: 22;
  }

  .start-screen .start-actions--secondary .btn {
    min-height: clamp(48px, 5.6dvh, 62px);
    padding: 10px 18px;
    font-size: clamp(16px, 1.8dvh, 20px);
  }

  .entry-hero {
    width: min(34dvw, 42dvh, 380px);
  }

  .entry-echoes {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
  }

  .entry-echo {
    position: absolute;
    width: 150%;
    height: calc(150% * 0.621);
    object-fit: cover;
    object-position: top center;
    image-rendering: pixelated;
    opacity: 0.72;
    filter:
      saturate(0.96)
      brightness(1.02)
      drop-shadow(0 18px 24px rgba(0, 78, 147, 0.18));
    transform-origin: center bottom;
    will-change: transform;
  }

  .entry-echo--left {
    left: -82%;
    top: 10%;
    animation: entry-echo-float-left 8.8s cubic-bezier(0.46, 0, 0.24, 1) infinite;
  }

  .entry-echo--right {
    right: -82%;
    top: 10%;
    animation: entry-echo-float-right 9.2s cubic-bezier(0.46, 0, 0.24, 1) -2.6s infinite;
  }

  .entry-art {
    position: relative;
    z-index: 3;
    width: min(58dvw, 72dvh, 620px);
    height: calc(min(58dvw, 72dvh, 620px) * 0.621);
  }

  .entry-platform {
    width: min(52dvw, 760px);
    height: clamp(150px, 25dvh, 240px);
    margin-top: clamp(-188px, -22dvh, -128px);
    margin-bottom: clamp(-98px, -12dvh, -62px);
  }

  .entry-btn {
    max-width: min(420px, 38dvw);
    min-height: clamp(64px, 8dvh, 82px);
    font-size: clamp(28px, 4dvh, 40px);
    opacity: 0;
    transform: translateY(28px) scale(0.94);
    pointer-events: none;
    transition:
      opacity 220ms ease,
      transform 360ms cubic-bezier(0.16, 1, 0.3, 1),
      box-shadow 420ms ease,
      filter 420ms ease,
      background-position 420ms ease;
  }

  .start-card:has(.entry-hero:hover) .entry-btn,
  .start-card:has(.start-actions--primary:hover) .entry-btn,
  .start-card:has(.entry-btn:hover) .entry-btn,
  .start-card:focus-within .entry-btn {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
  }

  .start-actions {
    width: min(420px, 38dvw);
  }

  .topbar {
    /* HUD row scales with viewport height. */
    --hud-h: clamp(54px, 6.2dvh, 72px);
  }

  .roster-ring {
    /* Rings grow with the card. */
    max-width: clamp(58px, 7.6dvh, 88px);
  }

  .stat-pill strong {
    /* Score/Moves numbers scale up. */
    font-size: clamp(22px, 2.8dvh, 34px);
  }

  .game-frame {
    grid-template-columns: clamp(340px, 30%, 500px) minmax(0, 1fr);
    grid-template-rows: auto auto auto auto auto;
    gap: clamp(14px, 2dvh, 24px);
    padding: clamp(14px, 1.8dvh, 22px);
  }

  .game-frame .topbar {
    grid-column: 1;
    grid-row: 1;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto;
    gap: 10px;
    align-self: start;
    align-items: center;
  }

  .game-frame .topbar-left {
    grid-column: 1;
    grid-row: 1;
  }

  .game-frame .topbar-stats {
    grid-column: 2;
    grid-row: 1;
  }

  .game-frame .roster-row {
    grid-column: 1;
    grid-row: 2;
    align-self: start;
    align-items: flex-start;
  }

  .game-frame .color-roster {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(14px, 2dvh, 22px);
    padding: clamp(18px, 2.6dvh, 28px);
  }

  .game-frame .reroll-dock {
    display: block;
    grid-column: 1;
    grid-row: 3;
    align-self: start;
  }

  .game-frame .vibe-status {
    grid-column: 1;
    grid-row: 4;
  }

  .game-frame .board-shell {
    grid-column: 2;
    grid-row: 1 / -1;
    padding: clamp(8px, 1.2dvh, 16px);
  }

  .game-frame .game-footer {
    display: flex;
    grid-column: 1;
    grid-row: 5;
    align-self: end;
  }

  .game-frame .game-footer .mute-btn {
    --hud-h: 58px;
    width: 108px;
    height: var(--hud-h);
    border-radius: 999px;
    border: 2px solid #2f80ff;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(238, 245, 255, 0.96));
    box-shadow:
      0 0 0 4px rgba(47, 128, 255, 0.12),
      0 14px 28px rgba(48, 98, 168, 0.16);
    color: #2f80ff;
  }

  /* Desktop: mute is in game-footer; hide the topbar-embedded mobile buttons. */
  #muteBtnGame { display: none; }
  .topbar-right { display: none; }

  /* Desktop: restore profile chip full label. */
  .profile-chip-label { display: inline; }
  .profile-chip-count { display: none; }
  .profile-chip { min-width: 170px; padding: 0 14px; gap: 8px; }

  .vibe-strip,
  .status-line {
    border-radius: 18px;
  }

  .vibe-strip {
    gap: 14px;
    padding: clamp(12px, 1.7dvh, 18px) clamp(14px, 2dvh, 22px);
  }

  .vibe-strip-badge {
    width: clamp(38px, 5.2dvh, 58px);
    height: clamp(38px, 5.2dvh, 58px);
    border-radius: 12px;
  }

  .vibe-strip-text {
    gap: 3px;
    overflow: visible;
  }

  .vibe-strip-name,
  .vibe-strip-perks {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  .vibe-strip-name {
    font-size: clamp(14px, 1.6dvh, 18px);
  }

  .vibe-strip-perks {
    font-size: clamp(12px, 1.35dvh, 15px);
    line-height: 1.35;
  }

  .status-line {
    min-height: clamp(64px, 8dvh, 92px);
    padding: clamp(14px, 2dvh, 22px);
    font-size: clamp(16px, 1.8dvh, 20px);
    line-height: 1.35;
  }

  .board {
    /* Tile gaps scale with board size. */
    gap: clamp(2px, 0.4dvh, 5px);
  }

  .tile {
    /* Corner radius proportional to tile size. */
    border-radius: clamp(10px, 1.3dvh, 16px);
    transition:
      transform 240ms var(--ease-slow),
      opacity 240ms var(--ease-slow);
  }

  .tile::before {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.86),
      inset 0 -1px 0 rgba(123, 177, 226, 0.12),
      0 6px 12px rgba(71, 146, 214, 0.08);
  }

  .tile-art,
  .tile.evolved .tile-art {
    filter: none;
  }

  .tile.selected,
  .tile.drag-target {
    filter: none;
  }

  .tile.is-swapping {
    animation-duration: 150ms;
  }

  .tile.is-rejecting {
    animation-duration: 220ms;
  }

  .tile.is-falling {
    animation-duration: 260ms;
  }

  .tile.is-reshuffling {
    animation-duration: 240ms;
  }

  .tile.clearing,
  .tile.clearing::before,
  .tile.clearing::after,
  .tile.clearing .tile-art,
  .tile-burst i {
    animation-duration: 210ms;
  }

  /* ── Desktop reroll dock: variant 2 — fill-as-background ────── */
  .game-frame .reroll-dock {
    display: block;
  }

  /* Hide the SVG medallion and the original track */
  .game-frame .reroll-medallion,
  .game-frame .reroll-track { display: none; }

  /* Button: vertical flex column, clipped for fill overlay */
  .game-frame .reroll-bar {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0;
    padding: 14px;
    border-radius: 16px;
    position: relative;
    overflow: hidden;
    background: var(--color-surface-strong);
    border: 1.5px solid var(--color-border);
    box-shadow: 0 4px 18px rgba(15, 39, 66, 0.1);
    color: var(--color-text);
  }

  /* No progress overlay — the whole button lights up once a charge is ready. */

  /* Count block — below the label */
  .game-frame .reroll-pip { display: none; }

  .game-frame .reroll-bar .reroll-pips {
    order: 1;
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
  }

  .game-frame .reroll-bar .reroll-pips::before {
    content: "×" attr(data-charges);
    font-size: 1.8rem;
    font-weight: 900;
    line-height: 1;
    color: var(--color-text);
    transition: color 0.3s;
  }

  .game-frame .reroll-bar .reroll-pips::after {
    content: "rerolls";
    font-size: 0.58rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-text-soft);
  }

  /* has-charge: light up with the Enter-Run pastel fill + rainbow border. */
  .game-frame .reroll-bar.has-charge {
    border: 1.5px solid transparent;
    background: var(--reroll-ready-fill) padding-box, var(--reroll-ready-border) border-box;
    box-shadow:
      0 4px 18px rgba(15, 39, 66, 0.1),
      0 0 18px rgba(255, 235, 128, 0.34),
      0 0 26px rgba(104, 216, 255, 0.22);
  }

  .game-frame .reroll-bar.has-charge .reroll-pips::before {
    color: #075faf;
  }

  .game-frame .reroll-bar:not(:disabled):hover {
    transform: translateY(-1px);
    filter: brightness(1.02);
  }
