/* =========================================================
   TYPEFLOW — DESIGN SYSTEM
   Single source of truth. Every color/spacing/radius used by
   components below comes from the tokens defined here, so
   themes (body[data-theme="..."]) only need to override the
   tokens once and every component reskins automatically.
========================================================= */

:root {
  --bg: #f5f7fb;
  --surface: #ffffff;
  --surface-2: #f1f4fa;
  --border: #e6e9f2;
  --text: #0f172a;
  --muted: #64748b;

  --accent: #4f46e5;
  --accent-2: #06b6d4;
  --accent-soft: rgba(79, 70, 229, 0.08);

  --success: #10b981;
  --danger: #ef4444;

  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 24px;

  --shadow-sm: 0 4px 12px rgba(15, 23, 42, 0.05);
  --shadow-md: 0 10px 30px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 20px 50px rgba(15, 23, 42, 0.08);

  --container: 1100px;
  --font: 'Inter', system-ui, -apple-system, sans-serif;

  color-scheme: light;
}

/* =========================================================
   THEMES
   These slugs match the real ShopItem catalog (item_type="theme")
   so the shop and the navbar customize modal always agree on what's
   unlocked/equipped. Each theme redefines the tokens above; purely
   decorative extras (starfields, glows, animated gradients) layer on
   top via body::before and never touch component styles directly.
========================================================= */

body[data-theme="focus-dark"] {
  --bg: #0b1120;
  --surface: #141b2d;
  --surface-2: #1b2438;
  --border: rgba(255, 255, 255, 0.08);
  --text: #f1f5f9;
  --muted: #94a3b8;
  --accent: #818cf8;
  --accent-2: #22d3ee;
  --accent-soft: rgba(129, 140, 248, 0.12);
  color-scheme: dark;
}

body[data-theme="midnight"] {
  --bg: #040b1a;
  --surface: #0d1b33;
  --surface-2: #132244;
  --border: rgba(99, 140, 255, 0.16);
  --text: #e6edff;
  --muted: #8fa3c9;
  --accent: #3b82f6;
  --accent-2: #60a5fa;
  --accent-soft: rgba(59, 130, 246, 0.14);
  color-scheme: dark;
}

body[data-theme="frost"] {
  --bg: #eef6fb;
  --surface: #ffffff;
  --surface-2: #e4f1fa;
  --border: #cfe6f5;
  --text: #0b2540;
  --muted: #5b7a95;
  --accent: #0ea5e9;
  --accent-2: #67e8f9;
  --accent-soft: rgba(14, 165, 233, 0.1);
  color-scheme: light;
}

body[data-theme="cyber-pulse"] {
  --bg: #05070d;
  --surface: #0c121f;
  --surface-2: #121a2b;
  --border: rgba(6, 247, 214, 0.2);
  --text: #eafffb;
  --muted: #7fa9a3;
  --accent: #06f7d6;
  --accent-2: #ff2ec4;
  --accent-soft: rgba(6, 247, 214, 0.12);
  color-scheme: dark;
}

body[data-theme="aurora"] {
  --bg: #0f172a;
  --surface: rgba(255, 255, 255, 0.06);
  --surface-2: rgba(255, 255, 255, 0.1);
  --border: rgba(255, 255, 255, 0.14);
  --text: #f8fafc;
  --muted: #cbd5e1;
  --accent: #a78bfa;
  --accent-2: #22d3ee;
  --accent-soft: rgba(167, 139, 250, 0.16);
  color-scheme: dark;
}

body[data-theme="sakura"] {
  --bg: #fff5f7;
  --surface: #ffffff;
  --surface-2: #ffe9ef;
  --border: #ffd3e0;
  --text: #402530;
  --muted: #a9748a;
  --accent: #ec4899;
  --accent-2: #f472b6;
  --accent-soft: rgba(236, 72, 153, 0.1);
  color-scheme: light;
}

body[data-theme="lava-flow"] {
  --bg: #1a0700;
  --surface: #2b0d00;
  --surface-2: #3a1400;
  --border: rgba(255, 120, 40, 0.25);
  --text: #ffe8d9;
  --muted: #d99a76;
  --accent: #ff5722;
  --accent-2: #ffb300;
  --accent-soft: rgba(255, 87, 34, 0.16);
  color-scheme: dark;
}

body[data-theme="galaxy"] {
  --bg: #05040e;
  --surface: rgba(255, 255, 255, 0.05);
  --surface-2: rgba(255, 255, 255, 0.09);
  --border: rgba(255, 255, 255, 0.1);
  --text: #f1f0ff;
  --muted: #a9a5c9;
  --accent: #818cf8;
  --accent-2: #38bdf8;
  --accent-soft: rgba(129, 140, 248, 0.16);
  color-scheme: dark;
}

body[data-theme="matrix"] {
  --bg: #000000;
  --surface: #040f04;
  --surface-2: #081a08;
  --border: rgba(0, 255, 65, 0.25);
  --text: #c8ffcf;
  --muted: #5fae6a;
  --accent: #00ff41;
  --accent-2: #00b82e;
  --accent-soft: rgba(0, 255, 65, 0.1);
  color-scheme: dark;
}

body[data-theme="solar-flare"] {
  --bg: #fff8ec;
  --surface: #ffffff;
  --surface-2: #ffedcf;
  --border: #ffd98a;
  --text: #3a2100;
  --muted: #8a6a2e;
  --accent: #f59e0b;
  --accent-2: #ef4444;
  --accent-soft: rgba(245, 158, 11, 0.12);
  color-scheme: light;
}

/* Matches ShopItem slugs (item_type="limited") — exclusive themes sold
   under the Shop's "Limited" tab. Same equip slot as regular themes
   (equipped_theme), just gated behind a higher price/rarity. */

body[data-theme="halloween"] {
  --bg: #0d0221;
  --surface: #1a0b2e;
  --surface-2: #241040;
  --border: rgba(255, 140, 0, 0.25);
  --text: #ffe9d6;
  --muted: #b89bc9;
  --accent: #ff7518;
  --accent-2: #7c3aed;
  --accent-soft: rgba(255, 117, 24, 0.14);
  color-scheme: dark;
}

body[data-theme="christmas"] {
  --bg: #0a1f14;
  --surface: #0f2c1c;
  --surface-2: #153a24;
  --border: rgba(220, 38, 38, 0.22);
  --text: #fef2e8;
  --muted: #9db8a8;
  --accent: #dc2626;
  --accent-2: #eab308;
  --accent-soft: rgba(220, 38, 38, 0.14);
  color-scheme: dark;
}

body[data-theme="prestige-gold"] {
  --bg: #0a0704;
  --surface: #17130a;
  --surface-2: #211a0d;
  --border: rgba(250, 204, 21, 0.25);
  --text: #fff8e1;
  --muted: #c2a86b;
  --accent: #eab308;
  --accent-2: #fde047;
  --accent-soft: rgba(234, 179, 8, 0.14);
  color-scheme: dark;
}

body[data-theme="founder"] {
  --bg: #0b0d12;
  --surface: #14171f;
  --surface-2: #1c202b;
  --border: rgba(148, 163, 255, 0.2);
  --text: #eef2ff;
  --muted: #9aa3c2;
  --accent: #6366f1;
  --accent-2: #ec4899;
  --accent-soft: rgba(99, 102, 241, 0.14);
  color-scheme: dark;
}

/* Limited to 50 units ever — deep volcanic-glass black with a warm gold
   accent, the most understated-premium theme in the shop (no rainbow
   effects, just very dark and very expensive-looking). */
body[data-theme="obsidian"] {
  --bg: #060607;
  --surface: #0f0f11;
  --surface-2: #17171a;
  --border: rgba(234, 179, 8, 0.18);
  --text: #f5f5f0;
  --muted: #8a8a85;
  --accent: #d4af37;
  --accent-2: #f5e7a3;
  --accent-soft: rgba(212, 175, 55, 0.12);
  color-scheme: dark;
}

body[data-theme="deep-ocean"] {
  --bg: #041014;
  --surface: #0a1f26;
  --surface-2: #0f2830;
  --border: rgba(34, 211, 238, 0.18);
  --text: #e0fbff;
  --muted: #7ba8b0;
  --accent: #22d3ee;
  --accent-2: #0891b2;
  --accent-soft: rgba(34, 211, 238, 0.12);
  color-scheme: dark;
}

body[data-theme="autumn-harvest"] {
  --bg: #fdf6ec;
  --surface: #ffffff;
  --surface-2: #fbe8d3;
  --border: #f0c896;
  --text: #4a2c17;
  --muted: #a3775a;
  --accent: #ea580c;
  --accent-2: #b45309;
  --accent-soft: rgba(234, 88, 12, 0.1);
  color-scheme: light;
}

body[data-theme="neon-tokyo"] {
  --bg: #0a0014;
  --surface: #150826;
  --surface-2: #1f0f36;
  --border: rgba(255, 0, 200, 0.25);
  --text: #ffe6fb;
  --muted: #b48ecf;
  --accent: #ff00c8;
  --accent-2: #00e5ff;
  --accent-soft: rgba(255, 0, 200, 0.16);
  color-scheme: dark;
}

body[data-theme="volcanic-ash"] {
  --bg: #0d0b0a;
  --surface: #1a1614;
  --surface-2: #241f1c;
  --border: rgba(220, 38, 38, 0.2);
  --text: #f5efec;
  --muted: #9c8f89;
  --accent: #dc2626;
  --accent-2: #78716c;
  --accent-soft: rgba(220, 38, 38, 0.14);
  color-scheme: dark;
}

/* Decorative background layers per theme */

body[data-theme="aurora"] {
  background:
    radial-gradient(circle at 15% 20%, rgba(124, 58, 237, 0.25), transparent 45%),
    radial-gradient(circle at 85% 15%, rgba(6, 182, 212, 0.2), transparent 40%),
    radial-gradient(circle at 50% 100%, rgba(79, 70, 229, 0.2), transparent 50%),
    var(--bg);
  background-size: 200% 200%;
  animation: auroraDrift 18s ease infinite;
}

@keyframes auroraDrift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

body[data-theme="galaxy"] {
  background: radial-gradient(circle at top, #1b1440, #05040e 65%);
  overflow-x: hidden;
}

body[data-theme="galaxy"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1px 1px at 20% 30%, white, transparent),
    radial-gradient(1px 1px at 70% 60%, white, transparent),
    radial-gradient(1.5px 1.5px at 40% 80%, white, transparent),
    radial-gradient(1px 1px at 90% 20%, white, transparent),
    radial-gradient(1px 1px at 55% 10%, white, transparent);
  background-size: 600px 600px;
  opacity: 0.5;
  animation: driftStars 60s linear infinite;
}

@keyframes driftStars {
  from { background-position: 0 0; }
  to { background-position: -600px 600px; }
}

body[data-theme="matrix"] {
  text-shadow: 0 0 6px rgba(0, 255, 65, 0.25);
}

body[data-theme="matrix"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 255, 65, 0.035) 0px,
      rgba(0, 255, 65, 0.035) 1px,
      transparent 1px,
      transparent 3px
    ),
    repeating-linear-gradient(
      90deg,
      rgba(0, 255, 65, 0.05) 0px,
      transparent 2px,
      transparent 40px
    );
  background-size: auto, 40px 200px;
  animation: matrixDrift 6s linear infinite;
}

@keyframes matrixDrift {
  from { background-position: 0 0, 0 0; }
  to { background-position: 0 0, 0 200px; }
}

body[data-theme="cyber-pulse"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(6, 247, 214, 0.03) 0px,
    rgba(6, 247, 214, 0.03) 1px,
    transparent 1px,
    transparent 3px
  );
}

body[data-theme="lava-flow"] {
  background:
    radial-gradient(circle at 20% 90%, rgba(255, 87, 34, 0.3), transparent 50%),
    radial-gradient(circle at 80% 10%, rgba(255, 179, 0, 0.18), transparent 45%),
    var(--bg);
  background-size: 160% 160%;
  animation: lavaPulse 8s ease-in-out infinite;
}

@keyframes lavaPulse {
  0%, 100% { background-position: 0% 0%; }
  50% { background-position: 30% 20%; }
}

body[data-theme="sakura"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(3px 3px at 15% 20%, #ffb7c9, transparent),
    radial-gradient(2.5px 2.5px at 70% 10%, #ffc9d6, transparent),
    radial-gradient(3px 3px at 40% 60%, #ffb7c9, transparent),
    radial-gradient(2px 2px at 85% 70%, #ffc9d6, transparent),
    radial-gradient(2.5px 2.5px at 55% 85%, #ffb7c9, transparent);
  background-size: 500px 500px;
  opacity: 0.6;
  animation: driftStars 30s linear infinite;
}

body[data-theme="solar-flare"] {
  background:
    radial-gradient(circle at 50% -10%, rgba(245, 158, 11, 0.25), transparent 55%),
    var(--bg);
  animation: solarGlow 5s ease-in-out infinite;
}

@keyframes solarGlow {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.04); }
}

body[data-theme="halloween"] {
  background:
    radial-gradient(circle at 20% 100%, rgba(255, 117, 24, 0.28), transparent 50%),
    radial-gradient(circle at 80% 0%, rgba(124, 58, 237, 0.3), transparent 45%),
    var(--bg);
  background-size: 160% 160%;
  animation: lavaPulse 9s ease-in-out infinite;
}

body[data-theme="halloween"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(2px 2px at 15% 25%, #ff9640, transparent),
    radial-gradient(1.5px 1.5px at 70% 55%, #ffb066, transparent),
    radial-gradient(2px 2px at 40% 80%, #ff9640, transparent),
    radial-gradient(1.5px 1.5px at 88% 15%, #c084fc, transparent),
    radial-gradient(2px 2px at 55% 5%, #ffb066, transparent);
  background-size: 550px 550px;
  opacity: 0.55;
  animation: driftStars 50s linear infinite;
}

body[data-theme="christmas"]::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 10px;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(3px 3px at 5% 50%, #dc2626, transparent),
    radial-gradient(3px 3px at 15% 50%, #eab308, transparent),
    radial-gradient(3px 3px at 25% 50%, #16a34a, transparent),
    radial-gradient(3px 3px at 35% 50%, #dc2626, transparent),
    radial-gradient(3px 3px at 45% 50%, #eab308, transparent),
    radial-gradient(3px 3px at 55% 50%, #16a34a, transparent),
    radial-gradient(3px 3px at 65% 50%, #dc2626, transparent),
    radial-gradient(3px 3px at 75% 50%, #eab308, transparent),
    radial-gradient(3px 3px at 85% 50%, #16a34a, transparent),
    radial-gradient(3px 3px at 95% 50%, #dc2626, transparent);
  background-size: 100% 10px;
  animation: christmasTwinkle 1.6s ease-in-out infinite;
}

@keyframes christmasTwinkle {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

body[data-theme="prestige-gold"] {
  background:
    linear-gradient(120deg, transparent 30%, rgba(253, 224, 71, 0.14) 45%, transparent 60%),
    var(--bg);
  background-size: 300% 300%;
  animation: goldShimmer 6s ease-in-out infinite;
}

@keyframes goldShimmer {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

body[data-theme="founder"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(115deg, transparent 48%, rgba(99, 102, 241, 0.5) 49.5%, transparent 51%),
    linear-gradient(115deg, transparent 68%, rgba(236, 72, 153, 0.4) 69.5%, transparent 71%),
    radial-gradient(1px 1px at 20% 30%, white, transparent),
    radial-gradient(1px 1px at 70% 60%, white, transparent),
    radial-gradient(1.5px 1.5px at 40% 80%, white, transparent),
    radial-gradient(1px 1px at 90% 20%, white, transparent);
  background-size: 100% 100%, 100% 100%, 600px 600px, 600px 600px, 600px 600px, 600px 600px;
  opacity: 0.7;
  animation: founderLaunch 4s linear infinite;
}

@keyframes founderLaunch {
  0% { background-position: -30% 30%, -30% 30%, 0 0, 0 0, 0 0, 0 0; }
  100% { background-position: 130% -30%, 130% -30%, -600px 600px, -600px 600px, -600px 600px, -600px 600px; }
}

/* A slow, subtle gold sweep — restrained compared to Gold Prestige's
   shimmer, since Obsidian is meant to read as understated, not flashy. */
body[data-theme="obsidian"] {
  background:
    linear-gradient(135deg, transparent 40%, rgba(212, 175, 55, 0.06) 50%, transparent 60%),
    var(--bg);
  background-size: 260% 260%;
  animation: obsidianSweep 10s ease-in-out infinite;
}

@keyframes obsidianSweep {
  0%, 100% { background-position: 0% 0%; }
  50% { background-position: 100% 100%; }
}

body[data-theme="deep-ocean"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(3px 3px at 20% 90%, rgba(34, 211, 238, 0.5), transparent),
    radial-gradient(2px 2px at 50% 80%, rgba(8, 145, 178, 0.5), transparent),
    radial-gradient(2.5px 2.5px at 75% 95%, rgba(34, 211, 238, 0.5), transparent),
    radial-gradient(2px 2px at 90% 70%, rgba(8, 145, 178, 0.5), transparent);
  background-size: 300px 300px;
  animation: oceanBubbles 10s linear infinite;
}

@keyframes oceanBubbles {
  from { background-position: 0 0, 0 0, 0 0, 0 0; }
  to { background-position: 20px -300px, -15px -300px, 10px -300px, -20px -300px; }
}

body[data-theme="autumn-harvest"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(3px 3px at 15% 10%, #ea580c, transparent),
    radial-gradient(2.5px 2.5px at 45% 25%, #b45309, transparent),
    radial-gradient(3px 3px at 70% 5%, #ea580c, transparent),
    radial-gradient(2.5px 2.5px at 90% 30%, #b45309, transparent);
  background-size: 280px 280px;
  opacity: 0.5;
  animation: leavesFall 9s linear infinite;
}

@keyframes leavesFall {
  from { background-position: 0 0; }
  to { background-position: 20px 280px; }
}

body[data-theme="neon-tokyo"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(255, 0, 200, 0.08) 0px, transparent 2px, transparent 60px),
    repeating-linear-gradient(0deg, rgba(0, 229, 255, 0.06) 0px, transparent 1px, transparent 40px);
  animation: neonFlicker 3s ease-in-out infinite;
}

@keyframes neonFlicker {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 1; }
}

body[data-theme="volcanic-ash"]::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(2.5px 2.5px at 20% 85%, #f97316, transparent),
    radial-gradient(2px 2px at 50% 70%, #dc2626, transparent),
    radial-gradient(2.5px 2.5px at 75% 90%, #f97316, transparent),
    radial-gradient(2px 2px at 90% 60%, #dc2626, transparent);
  background-size: 260px 260px;
  filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.5));
  animation: emberRise 7s ease-in-out infinite;
}

@keyframes emberRise {
  0%, 100% { opacity: 0.4; background-position: 0 0; }
  50% { opacity: 0.75; background-position: 10px -40px; }
}

/* =========================================================
   BACKGROUND EFFECTS
   Matches ShopItem slugs (item_type="background"). Layered via
   body::after (themes already use ::before) so any background
   can be combined with any theme. No data-background = plain.
========================================================= */

body[data-background]::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Small live preview inside the customize modal's swatch box — same
   background-image/animation as the real effect, just contained to a
   52px box instead of the full viewport, so equipping (or just browsing
   the picker) shows an unmistakable demo even on pages with no visible
   full-screen effect to compare against. */
.customize-swatch[data-background-demo] {
  position: relative;
  overflow: hidden;
}

.customize-swatch[data-background-demo]::after {
  content: "";
  position: absolute;
  inset: 0;
}

body[data-background="particles"]::after,
.customize-swatch[data-background-demo="particles"]::after {
  background-image:
    radial-gradient(3px 3px at 10% 90%, var(--accent), transparent),
    radial-gradient(3px 3px at 30% 80%, var(--accent-2), transparent),
    radial-gradient(2.5px 2.5px at 55% 95%, var(--accent), transparent),
    radial-gradient(3px 3px at 75% 85%, var(--accent-2), transparent),
    radial-gradient(2.5px 2.5px at 90% 92%, var(--accent), transparent),
    radial-gradient(2px 2px at 20% 40%, var(--accent-2), transparent),
    radial-gradient(2.5px 2.5px at 45% 15%, var(--accent), transparent),
    radial-gradient(2px 2px at 68% 55%, var(--accent-2), transparent);
  background-size: 220px 220px;
  opacity: 0.6;
  animation: particlesRise 9s linear infinite;
}

@keyframes particlesRise {
  from { background-position: 0 0; }
  to { background-position: 0 -220px; }
}

/* Individual falling streaks on a repeating tile — matches the technique
   every other background effect uses (particles/snowfall/starfield are
   all sparse discrete shapes on a large tile with a slow loop). The old
   version was a dense, screen-covering diagonal hatch with no tile at
   all, looping every 0.4s — that read as flickering noise, not rain. */
body[data-background="rain"]::after,
.customize-swatch[data-background-demo="rain"]::after {
  background-image:
    radial-gradient(1.5px 10px at 12% 0%, var(--accent), transparent),
    radial-gradient(1.5px 14px at 30% 20%, var(--accent), transparent),
    radial-gradient(1.5px 8px at 48% 8%, var(--accent), transparent),
    radial-gradient(1.5px 12px at 62% 35%, var(--accent), transparent),
    radial-gradient(1.5px 9px at 78% 12%, var(--accent), transparent),
    radial-gradient(1.5px 13px at 20% 55%, var(--accent), transparent),
    radial-gradient(1.5px 10px at 55% 65%, var(--accent), transparent),
    radial-gradient(1.5px 11px at 90% 50%, var(--accent), transparent),
    radial-gradient(1.5px 9px at 8% 80%, var(--accent), transparent),
    radial-gradient(1.5px 12px at 70% 85%, var(--accent), transparent);
  background-size: 260px 260px;
  opacity: 0.4;
  animation: rainFall 0.9s linear infinite;
}

@keyframes rainFall {
  from { background-position: 0 0; }
  to { background-position: 0 260px; }
}

/* var(--text) instead of a hardcoded white — snow/stars need to flip to
   dark dots on light themes (frost, sakura, solar-flare) or they'd be
   nearly invisible against a light background. */
body[data-background="snowfall"]::after,
.customize-swatch[data-background-demo="snowfall"]::after {
  background-image:
    radial-gradient(4px 4px at 20% 10%, var(--text), transparent),
    radial-gradient(3px 3px at 60% 30%, var(--text), transparent),
    radial-gradient(4px 4px at 80% 5%, var(--text), transparent),
    radial-gradient(3px 3px at 40% 50%, var(--text), transparent),
    radial-gradient(3.5px 3.5px at 10% 60%, var(--text), transparent),
    radial-gradient(3px 3px at 90% 45%, var(--text), transparent),
    radial-gradient(2.5px 2.5px at 30% 75%, var(--text), transparent);
  background-size: 320px 320px;
  opacity: 0.5;
  animation: snowDrift 8s linear infinite;
}

@keyframes snowDrift {
  from { background-position: 0 0; }
  to { background-position: 32px 320px; }
}

body[data-background="starfield"]::after,
.customize-swatch[data-background-demo="starfield"]::after {
  background-image:
    radial-gradient(1.5px 1.5px at 15% 25%, var(--text), transparent),
    radial-gradient(1.5px 1.5px at 65% 55%, var(--text), transparent),
    radial-gradient(2px 2px at 35% 80%, var(--text), transparent),
    radial-gradient(1.5px 1.5px at 85% 15%, var(--text), transparent),
    radial-gradient(1.5px 1.5px at 50% 5%, var(--text), transparent),
    radial-gradient(2px 2px at 95% 75%, var(--text), transparent),
    radial-gradient(1.5px 1.5px at 25% 45%, var(--text), transparent),
    radial-gradient(1.5px 1.5px at 70% 90%, var(--text), transparent);
  background-size: 400px 400px;
  opacity: 0.55;
  animation: starTwinkle 3s ease-in-out infinite;
}

@keyframes starTwinkle {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.85; }
}

body[data-background="animated-grid"]::after,
.customize-swatch[data-background-demo="animated-grid"]::after {
  background-image:
    repeating-linear-gradient(0deg, var(--accent) 0px, var(--accent) 1.5px, transparent 1.5px, transparent 36px),
    repeating-linear-gradient(90deg, var(--accent) 0px, var(--accent) 1.5px, transparent 1.5px, transparent 36px);
  opacity: 0.28;
  animation: gridScroll 5s linear infinite;
}

@keyframes gridScroll {
  from { background-position: 0 0, 0 0; }
  to { background-position: 40px 40px, 40px 40px; }
}

/* Darker amber + a drop-shadow safety net — same fix as The Vault below,
   the original pale #fde047/#fbbf24 had poor contrast against the
   default light theme's near-white background. */
body[data-background="fireflies"]::after,
.customize-swatch[data-background-demo="fireflies"]::after {
  background-image:
    radial-gradient(2.5px 2.5px at 15% 70%, #d97706, transparent),
    radial-gradient(2px 2px at 35% 30%, #92400e, transparent),
    radial-gradient(3px 3px at 55% 80%, #d97706, transparent),
    radial-gradient(2px 2px at 75% 20%, #92400e, transparent),
    radial-gradient(2.5px 2.5px at 90% 60%, #d97706, transparent),
    radial-gradient(2px 2px at 25% 45%, #92400e, transparent);
  background-size: 280px 280px;
  opacity: 0.75;
  filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.45));
  animation: firefliesDrift 6s ease-in-out infinite;
}

@keyframes firefliesDrift {
  0%, 100% { opacity: 0.5; background-position: 0 0; }
  50% { opacity: 0.85; background-position: 14px -18px; }
}

/* Legendary tier gets real color instead of the accent-only palette every
   other background uses — a burst of festive confetti dots rather than
   a monochrome ambient effect, since this is meant to feel like the
   flashiest background in the shop. */
body[data-background="confetti-burst"]::after,
.customize-swatch[data-background-demo="confetti-burst"]::after {
  background-image:
    radial-gradient(3px 3px at 10% 10%, #ec4899, transparent),
    radial-gradient(3px 3px at 30% 40%, #22d3ee, transparent),
    radial-gradient(3px 3px at 50% 15%, #fde047, transparent),
    radial-gradient(3px 3px at 70% 50%, #a855f7, transparent),
    radial-gradient(3px 3px at 90% 25%, #4ade80, transparent),
    radial-gradient(3px 3px at 20% 65%, #fb923c, transparent),
    radial-gradient(3px 3px at 45% 85%, #ec4899, transparent),
    radial-gradient(3px 3px at 65% 70%, #22d3ee, transparent),
    radial-gradient(3px 3px at 85% 90%, #fde047, transparent);
  background-size: 260px 260px;
  opacity: 0.7;
  /* Several of these (cyan, green, yellow) have poor contrast against the
     default light theme's near-white background — a drop-shadow darkens
     every dot's silhouette regardless of its own color, fixing all of
     them at once instead of needing per-color contrast tuning. */
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.35));
  animation: confettiFall 3s linear infinite;
}

@keyframes confettiFall {
  from { background-position: 0 0; }
  to { background-position: 12px 260px; }
}

/* Limited to 30 units ever — the rarest background in the shop.
   v2 — the original used pale gold (#fde047) at low opacity, which has
   almost no contrast against the default light theme's near-white
   background (#f5f7fb) — pale-on-pale is invisible regardless of dot
   count or opacity. Switched to a darker, richer gold plus a drop-shadow
   filter, which (unlike background-image alone) reads against ANY
   background color since it darkens the whole layer's silhouette. */
body[data-background="the-vault"]::after,
.customize-swatch[data-background-demo="the-vault"]::after {
  background-image:
    radial-gradient(3px 3px at 15% 15%, #b45309, transparent),
    radial-gradient(2.5px 2.5px at 45% 55%, #d4af37, transparent),
    radial-gradient(3px 3px at 75% 25%, #b45309, transparent),
    radial-gradient(2.5px 2.5px at 30% 75%, #d4af37, transparent),
    radial-gradient(3px 3px at 60% 85%, #b45309, transparent),
    radial-gradient(2.5px 2.5px at 85% 60%, #d4af37, transparent),
    radial-gradient(3px 3px at 10% 45%, #b45309, transparent),
    radial-gradient(2.5px 2.5px at 90% 90%, #d4af37, transparent),
    radial-gradient(circle at 50% 50%, rgba(180, 83, 9, 0.35), transparent 70%);
  background-size:
    260px 260px, 260px 260px, 260px 260px, 260px 260px,
    260px 260px, 260px 260px, 260px 260px, 260px 260px,
    100% 100%;
  opacity: 0.85;
  filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.5));
  animation: vaultDrift 8s ease-in-out infinite;
}

@keyframes vaultDrift {
  0%, 100% { opacity: 0.65; }
  50% { opacity: 0.95; }
}

/* Darker warm tones + drop-shadow from the start this time — see The
   Vault's comment above for why pale colors alone don't work here. */
body[data-background="autumn-leaves"]::after,
.customize-swatch[data-background-demo="autumn-leaves"]::after {
  background-image:
    radial-gradient(3px 3px at 15% 10%, #c2410c, transparent),
    radial-gradient(2.5px 2.5px at 45% 30%, #92400e, transparent),
    radial-gradient(3px 3px at 70% 5%, #c2410c, transparent),
    radial-gradient(2.5px 2.5px at 90% 35%, #92400e, transparent),
    radial-gradient(3px 3px at 30% 60%, #c2410c, transparent),
    radial-gradient(2.5px 2.5px at 60% 75%, #92400e, transparent),
    radial-gradient(3px 3px at 10% 90%, #c2410c, transparent);
  background-size: 300px 300px;
  opacity: 0.7;
  filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.4));
  animation: leavesDrift 7s linear infinite;
}

@keyframes leavesDrift {
  from { background-position: 0 0; }
  to { background-position: 25px 300px; }
}

/* Theme-adaptive accent color, same safe pattern as Particles/Rain — a
   rising bubble field instead of falling, so it reads distinctly. */
body[data-background="bubbles"]::after,
.customize-swatch[data-background-demo="bubbles"]::after {
  background-image:
    radial-gradient(4px 4px at 10% 90%, var(--accent), transparent),
    radial-gradient(3px 3px at 30% 70%, var(--accent-2), transparent),
    radial-gradient(5px 5px at 55% 95%, var(--accent), transparent),
    radial-gradient(3px 3px at 75% 65%, var(--accent-2), transparent),
    radial-gradient(4px 4px at 90% 85%, var(--accent), transparent);
  background-size: 240px 240px;
  opacity: 0.5;
  animation: bubblesRise 8s linear infinite;
}

@keyframes bubblesRise {
  from { background-position: 0 0; }
  to { background-position: 10px -240px; }
}

/* A soft ambient wash (like the Aurora theme's background), not sharp
   dots — diffuse gradients read fine at low opacity since there's no
   hard edge needing contrast against the page behind it. */
body[data-background="northern-lights"]::after,
.customize-swatch[data-background-demo="northern-lights"]::after {
  background-image:
    radial-gradient(circle at 20% 20%, rgba(34, 211, 238, 0.35), transparent 45%),
    radial-gradient(circle at 80% 30%, rgba(74, 222, 128, 0.3), transparent 45%),
    radial-gradient(circle at 50% 80%, rgba(168, 85, 247, 0.3), transparent 50%);
  background-size: 200% 200%;
  opacity: 0.8;
  animation: northernLightsDrift 10s ease-in-out infinite;
}

@keyframes northernLightsDrift {
  0%, 100% { background-position: 0% 0%; }
  50% { background-position: 100% 50%; }
}

/* var(--text) scanlines — always guaranteed contrast against var(--bg)
   by definition, and static/noise is meant to look subtle anyway. */
body[data-background="static-noise"]::after,
.customize-swatch[data-background-demo="static-noise"]::after {
  background-image: repeating-linear-gradient(
    0deg,
    var(--text) 0px,
    var(--text) 1px,
    transparent 1px,
    transparent 3px
  );
  opacity: 0.06;
  animation: staticFlicker 0.15s steps(2) infinite;
}

@keyframes staticFlicker {
  0%, 100% { opacity: 0.04; }
  50% { opacity: 0.09; }
}

/* =========================================================
   RESET / BASE
========================================================= */

* {
  box-sizing: border-box;
}

html {
  /* Stops the browser's pull-to-refresh/rubber-band gesture from
     swallowing vertical drags meant for the page — the single biggest
     thing that makes scrolling feel like "a website" instead of "an
     app" on mobile. */
  overscroll-behavior-y: contain;
}

a, button, .icon-btn, .bottom-tab, .duration-btn, .mode-btn {
  /* Kills the ~300ms delay + double-tap-to-zoom browsers apply to taps
     near clickable elements, and the gray flash Android/iOS show on
     tap by default — both read as "web page", not "app". */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  transition: background 0.3s ease, color 0.3s ease;
  position: relative;

  display: flex;
  flex-direction: column;
}

.site-main {
  flex: 1 1 auto;
}

body > * {
  position: relative;
  z-index: 1;
}

a {
  text-decoration: none;
  color: inherit;
}

button {
  font-family: inherit;
  cursor: pointer;
}

.page-container {
  width: min(var(--container), 92%);
  margin: 0 auto;
}

.legal-page {
  max-width: 760px;
  margin-top: 40px;
  margin-bottom: 40px;
}

.legal-card {
  padding: 40px 44px;
  line-height: 1.65;
  color: var(--text);
}

.legal-card h1 {
  margin: 0 0 4px;
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -0.5px;
}

.legal-card h2 {
  margin: 32px 0 10px;
  font-size: 19px;
  font-weight: 700;
}

.legal-card p,
.legal-card ul {
  margin: 0 0 14px;
  color: var(--muted);
}

.legal-card ul {
  padding-left: 20px;
}

.legal-card li {
  margin-bottom: 6px;
}

.legal-card a {
  color: var(--accent);
  font-weight: 600;
}

.legal-updated {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 24px !important;
}

.legal-contact-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  text-decoration: none;
  font-weight: 700;
  padding: 12px 20px;
  border-radius: var(--radius-md);
}

.section-label {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}

/* =========================================================
   SHARED PRIMITIVES
========================================================= */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.card:hover {
  transform: translateY(-2px);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;

  padding: 10px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);

  background: var(--surface);
  color: var(--text);

  font-weight: 600;
  font-size: 14px;

  transition: all 0.15s ease;
}

.btn:hover {
  background: var(--surface-2);
  transform: translateY(-1px);
}

.btn-primary {
  border: none;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  box-shadow: 0 10px 24px var(--accent-soft);
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 30px var(--accent-soft);
}

/* =========================================================
   HEADER
========================================================= */

.site-header {
  width: min(var(--container), 92%);
  margin: 24px auto 10px;
  /* Only non-zero when running standalone (added to home screen) on a
     notched phone — keeps the logo/nav clear of the status bar/camera
     cutout instead of sitting flush behind it. */
  margin-top: calc(24px + env(safe-area-inset-top, 0px));

  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;

  /* body > * already puts every top-level section at z-index:1, which
     ties with this header — without a higher value here, the account
     dropdown (z-index:500, but scoped to this stacking context) would
     render *behind* later same-level cards like the daily challenge bar. */
  position: relative;
  z-index: 50;

  animation: fadeSlideDown 0.4s ease;
}

@keyframes fadeSlideDown {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
}

.brand-logo {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand-logo .logo-mark {
  width: 38px;
  height: 38px;
  border-radius: 11px;

  display: flex;
  align-items: center;
  justify-content: center;

  font-size: 15px;
  font-weight: 800;
  color: #fff;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.brand-logo .logo-text {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.4px;
  color: var(--text);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;

  padding: 6px;
  border-radius: 999px;

  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.icon-btn {
  width: 38px;
  height: 38px;

  display: flex;
  align-items: center;
  justify-content: center;

  border: none;
  border-radius: 999px;

  background: transparent;
  color: var(--muted);
  font-size: 16px;

  transition: all 0.18s ease;
}

.icon-btn:hover {
  background: var(--accent-soft);
  color: var(--accent);
  transform: translateY(-1px);
}

.support-btn {
  color: #f43f5e;
}

.support-btn:hover {
  background: rgba(244, 63, 94, 0.12);
  color: #f43f5e;
  animation: support-beat 0.7s ease-in-out infinite;
}

@keyframes support-beat {
  0%, 100% { transform: translateY(-1px) scale(1); }
  50% { transform: translateY(-1px) scale(1.18); }
}

.nav-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  font-size: 20px;
  line-height: 1;
}

.icon-badge {
  position: absolute;
  top: 2px;
  right: 2px;

  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;

  align-items: center;
  justify-content: center;

  background: var(--danger);
  color: #fff;

  font-size: 10px;
  font-weight: 800;
  line-height: 1;
}

.coin-pill {
  display: flex;
  align-items: center;
  gap: 6px;

  height: 38px;
  padding: 0 14px;
  margin-left: 2px;

  border-radius: 999px;

  background: var(--accent-soft);
  color: var(--accent);

  font-weight: 700;
  font-size: 14px;

  transition: transform 0.15s ease;
}

.coin-pill:hover {
  transform: scale(1.04);
}

.level-pill {
  display: flex;
  align-items: center;
  gap: 4px;

  height: 38px;
  padding: 0 14px;
  margin-left: 2px;

  border-radius: 999px;

  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);

  font-weight: 700;
  font-size: 14px;

  transition: transform 0.15s ease, border-color 0.15s ease;
}

.level-pill:hover {
  transform: scale(1.04);
  border-color: var(--accent);
}

/* =========================================================
   ACCOUNT MENU
========================================================= */

.account-menu {
  position: relative;
}

.account-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 500;

  min-width: 190px;
  padding: 6px;
  border-radius: var(--radius-md);

  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);

  animation: popIn 0.15s ease;
}

.account-dropdown-header {
  padding: 8px 10px 6px;
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
}

.account-dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;

  padding: 9px 10px;
  border: none;
  border-radius: 8px;

  background: none;
  color: var(--text);
  text-decoration: none;

  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;

  transition: background 0.15s ease;
}

.account-dropdown-item:hover {
  background: var(--surface-2);
}

.account-dropdown-item.danger {
  color: var(--danger);
}

.account-dropdown-item i {
  font-size: 14px;
  width: 16px;
  text-align: center;
}

.account-dropdown-divider {
  height: 1px;
  margin: 6px 4px;
  background: var(--border);
}

/* =========================================================
   MODALS
========================================================= */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;

  display: none;
  align-items: center;
  justify-content: center;
  /* Without this, a modal-card taller than the visible viewport gets
     centered partly above y:0 with no way to scroll up to it — flex
     centering doesn't reflow to the overflow start on its own. */
  overflow-y: auto;
  padding: 24px 0;

  background: rgba(5, 8, 16, 0.55);
  backdrop-filter: blur(6px);
}

.modal-card {
  width: min(480px, 90%);
  max-height: 82vh;
  /* vh is calculated against the browser's largest possible viewport
     (address bar hidden) — on mobile, with the address bar visible,
     that's taller than what's actually on screen, which is exactly
     when this modal most needs to be capped. dvh tracks the real,
     currently-visible viewport instead. Older browsers ignore this
     line and keep the vh value above. */
  max-height: 82dvh;
  overflow-y: auto;

  padding: 28px;
  border-radius: var(--radius-lg);

  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);

  box-shadow: var(--shadow-lg);
  animation: popIn 0.2s ease;
}

@media (max-width: 768px) {
  /* Top-anchored instead of centered — on a short mobile viewport a
     centered tall card has no headroom, so centering math alone can't
     keep the whole thing on screen even with the overlay scroll fix
     above. Anchoring to the top guarantees the card's own header/close
     button are always the first thing visible. */
  .modal-overlay {
    align-items: flex-start;
  }
}

@keyframes popIn {
  from { transform: scale(0.95); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

.modal-card h2 {
  margin: 0 0 18px;
  font-size: 20px;
  font-weight: 800;
}

.modal-card input {
  width: 100%;
  margin-top: 10px;
  padding: 11px 14px;

  border-radius: var(--radius-sm);
  border: 1px solid var(--border);

  background: var(--surface-2);
  color: var(--text);

  font-size: 14px;
  outline: none;
}

.modal-card input:focus {
  border-color: var(--accent);
}

#login-error {
  margin-top: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--danger);
  min-height: 1em;
}

.modal-card p {
  margin-top: 14px;
  font-size: 13px;
  color: var(--muted);
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 16px 0;

  color: var(--muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.google-auth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 10px;

  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);

  font-weight: 600;
  font-size: 14px;

  transition: all 0.15s ease;
}

.google-auth-btn:hover {
  background: var(--surface-2);
  border-color: var(--accent);
}

.google-auth-btn i {
  color: #4285f4;
  font-size: 16px;
}

.modal-card p a {
  color: var(--accent);
  font-weight: 600;
}

.modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.modal-actions button {
  flex: 1;
}

.modal-actions .secondary {
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px;
  font-weight: 600;
}

.modal-actions button:not(.secondary) {
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.modal-actions button.btn-danger {
  background: var(--danger);
  box-shadow: none;
}

.confirm-modal-card {
  width: min(360px, 90%);
}

#confirm-modal-message {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text);
}

/* =========================================================
   CUSTOMIZE MODAL (themes / cursors / sounds / backgrounds)
========================================================= */

.customize-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
  overflow-x: auto;
}

.customize-tab {
  flex-shrink: 0;
  padding: 8px 14px;
  border: none;
  border-radius: 999px;

  background: var(--surface-2);
  color: var(--muted);

  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;

  transition: all 0.15s ease;
}

.customize-tab:hover {
  color: var(--text);
}

.customize-tab.active {
  background: var(--accent-soft);
  color: var(--accent);
}

.customize-login-prompt {
  padding: 20px;
  border-radius: var(--radius-md);
  background: var(--surface-2);
  border: 1px solid var(--border);
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.customize-login-prompt a {
  color: var(--accent);
  font-weight: 700;
}

/* =========================================================
   FRIENDS MODAL
========================================================= */

#friends-body .section-label {
  display: block;
  margin: 4px 0 10px;
}

#friend-requests-section {
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.friends-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 260px;
  overflow-y: auto;
}

.friend-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;

  padding: 10px 12px;
  border-radius: var(--radius-sm);

  background: var(--surface-2);
  border: 1px solid var(--border);
}

.friend-row a {
  font-weight: 700;
  font-size: 13.5px;
  color: var(--text);
}

.friend-row a:hover {
  color: var(--accent);
}

.friend-row-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.friend-action-btn {
  padding: 6px 12px;
  border: none;
  border-radius: 8px;

  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}

.friend-action-btn.accept {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
}

.friend-action-btn.decline {
  background: var(--surface);
  color: var(--muted);
  border: 1px solid var(--border);
}

/* Profile-page friend button states (see .btn in DESIGN SYSTEM) */
.friend-btn-active {
  background: rgba(16, 185, 129, 0.12);
  color: var(--success);
  border-color: transparent;
}

.friend-meta {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 2px;
}

.friend-action-btn.message {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--accent-soft);
  color: var(--accent);
}

/* =========================================================
   MESSAGES
========================================================= */

.conversation-row {
  cursor: pointer;
  transition: transform 0.15s ease;
}

.conversation-row:hover {
  transform: translateX(2px);
}

.conversation-preview {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 260px;
}

.thread-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.thread-header strong {
  font-size: 15px;
}

.thread-messages {
  display: flex;
  flex-direction: column;
  gap: 8px;

  height: 320px;
  overflow-y: auto;

  padding: 4px 2px;
  margin-bottom: 12px;
}

.thread-bubble {
  align-self: flex-start;
  max-width: 75%;

  padding: 9px 13px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid var(--border);

  font-size: 13.5px;
  line-height: 1.4;
  word-break: break-word;
}

.thread-bubble.mine {
  align-self: flex-end;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  border: none;
}

.thread-bubble small {
  display: block;
  margin-top: 4px;
  font-size: 10.5px;
  opacity: 0.7;
}

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

.thread-input-row input {
  flex: 1;
  padding: 10px 14px;
  border-radius: 999px;

  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text);

  font-size: 13.5px;
  outline: none;
}

.thread-input-row input:focus {
  border-color: var(--accent);
}

.thread-input-row .btn {
  flex-shrink: 0;
  padding: 10px 18px;
}

/* =========================================================
   GROUP CHAT
========================================================= */

.messages-list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

.messages-list-header h2 {
  margin: 0;
}

.thread-bubble-sender {
  display: block;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 2px;
}

.group-role-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: 999px;

  background: var(--accent-soft);
  color: var(--accent);

  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.group-rename-row {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.group-rename-row input {
  flex: 1;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
}

#group-add-member-row {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.group-friend-picker-row {
  cursor: pointer;
}

.group-friend-picker-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.customize-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  max-height: 360px;
  overflow-y: auto;
  padding: 2px;
}

.customize-card {
  position: relative;
  padding: 12px;
  border-radius: var(--radius-md);
  overflow: hidden;

  background: var(--surface-2);
  border: 1px solid var(--border);

  transition: transform 0.2s ease, border-color 0.2s ease;
}

.customize-card:hover {
  transform: translateY(-3px);
}

.customize-card.equipped {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.customize-card.locked .customize-swatch {
  filter: grayscale(0.5);
  opacity: 0.75;
}

.customize-swatch {
  height: 52px;
  border-radius: 10px;
  margin-bottom: 8px;

  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
}

.customize-card p {
  margin: 0;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.3;
}

.customize-card small {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 11px;
}

.customize-card.exclusive {
  border-color: rgba(250, 204, 21, 0.45);
  box-shadow: 0 0 0 1px rgba(250, 204, 21, 0.15);
}

.customize-scarcity {
  display: block;
  margin-top: 3px;
  color: #f59e0b;
  font-size: 10.5px;
  font-weight: 800;
}

.customize-scarcity.sold-out {
  color: var(--danger);
}

.customize-card button {
  width: 100%;
  margin-top: 8px;
  padding: 7px;
  border: none;
  border-radius: 8px;

  font-size: 11.5px;
  font-weight: 800;
  cursor: pointer;
  transition: transform 0.15s ease;
}

.customize-card button:hover {
  transform: translateY(-1px);
}

.customize-card .btn-equip {
  background: var(--accent-soft);
  color: var(--accent);
}

.customize-card .btn-equipped {
  background: var(--success);
  color: #fff;
  cursor: default;
}

.customize-card .btn-equipped:hover {
  transform: none;
}

.customize-card .btn-buy {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
}

@media (max-width: 480px) {
  .customize-grid { grid-template-columns: repeat(2, 1fr); }
}

/* =========================================================
   TYPING TEST
========================================================= */

.test-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
  margin: 0 auto;
}

.toolbar-divider {
  width: 1px;
  height: 22px;
  background: var(--border);
}

.mode-picker {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.mode-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 18px;
  border-radius: 999px;

  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);

  font-size: 13px;
  font-weight: 700;

  transition: all 0.15s ease;
}

.mode-btn:hover {
  color: var(--text);
  border-color: var(--accent);
}

.mode-btn.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: transparent;
  color: #fff;
}

.duration-picker {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.duration-btn {
  padding: 8px 18px;
  border-radius: 999px;

  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);

  font-size: 13px;
  font-weight: 700;

  transition: all 0.15s ease;
}

.duration-btn:hover {
  color: var(--text);
  border-color: var(--accent);
}

.duration-btn.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: transparent;
  color: #fff;
}

.typing-panel {
  display: flex;
  justify-content: center;
  margin: 32px 0 16px;
}

.typing-controls {
  display: flex;
  align-items: center;
  gap: 12px;

  padding: 8px 10px 8px 16px;
  border-radius: 999px;

  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.timer-chip {
  min-width: 30px;
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
}

#timer.low {
  color: var(--danger);
  animation: pulse 0.6s infinite;
}

@keyframes pulse {
  50% { transform: scale(1.15); }
}

.restart-btn {
  width: 32px;
  height: 32px;

  display: flex;
  align-items: center;
  justify-content: center;

  border: none;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);

  transition: transform 0.25s ease, background 0.2s ease;
}

.restart-btn:hover {
  background: var(--accent);
  color: #fff;
  transform: rotate(180deg);
}

#word-container {
  width: min(1100px, 92%);
  margin: 0 auto 24px;
  padding: 32px;

  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);

  font-size: 1.5rem;
  line-height: 2.3rem;

  position: relative;
  overflow: hidden;
  white-space: nowrap;

  cursor: text;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

#word-container:hover {
  transform: translateY(-2px);
}

#word-track {
  display: inline-block;
  white-space: nowrap;
  transition: transform 0.12s ease-out;
}

.word {
  display: inline-block;
  margin-right: 16px;
  padding: 4px 6px;
  border-radius: 6px;
  transition: all 0.15s ease;
}

.word.correct-word {
  background: rgba(16, 185, 129, 0.12);
}

.word.incorrect-word {
  background: rgba(239, 68, 68, 0.12);
}

.word.word-shake {
  animation: wordShake 0.28s ease;
  background: rgba(239, 68, 68, 0.18);
}

@keyframes wordShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

.char {
  display: inline-block;
  color: var(--muted);
}

.char.correct {
  color: var(--success);
}

.char.incorrect {
  color: var(--danger);
  text-decoration: underline;
}

.char.current {
  position: relative;
}

.char.current::before {
  content: "";
  position: absolute;
  left: -2px;
  top: 0;
  width: 2px;
  height: 100%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-soft);
  animation: blink 1s infinite;
}

@keyframes blink {
  50% { opacity: 0; }
}

/* =========================================================
   CURSOR SKINS
   Matches ShopItem slugs (item_type="cursor"). No data-cursor
   attribute = the default accent-colored blinking bar above.

   Each rule targets both the real typing-test cursor AND a small
   demo bar in the customize modal ([data-cursor-demo="slug"]) so
   equipping shows an unmistakable live preview even on pages that
   have no typing test (Shop, Dashboard, etc).
========================================================= */

.cursor-demo-bar {
  display: inline-block;
  width: 3px;
  height: 26px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-soft);
  animation: blink 1s infinite;
}

body[data-cursor="neon-cursor"] .char.current::before,
[data-cursor-demo="neon-cursor"] .cursor-demo-bar {
  background: #00f7ff;
  box-shadow: 0 0 10px #00f7ff, 0 0 22px rgba(0, 247, 255, 0.6);
  animation: cursorGlowPulse 1s ease-in-out infinite;
}

@keyframes cursorGlowPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

/* Deliberately a fixed, always-vivid color rather than var(--accent) —
   reusing the accent made this indistinguishable from the free default
   cursor on every theme. */
body[data-cursor="pulse-cursor"] .char.current::before,
[data-cursor-demo="pulse-cursor"] .cursor-demo-bar {
  width: 4px;
  background: #ec4899;
  box-shadow: 0 0 10px rgba(236, 72, 153, 0.6);
  animation: cursorPulse 0.7s ease-in-out infinite;
}

@keyframes cursorPulse {
  0%, 100% { transform: scaleY(1) scaleX(1); opacity: 1; }
  50% { transform: scaleY(0.5) scaleX(1.6); opacity: 0.65; }
}

body[data-cursor="fire-cursor"] .char.current::before,
[data-cursor-demo="fire-cursor"] .cursor-demo-bar {
  width: 3px;
  background: linear-gradient(to bottom, #ff5722, #ffc107);
  box-shadow: 0 0 10px rgba(255, 87, 34, 0.7);
  animation: cursorFlicker 0.4s ease-in-out infinite;
}

@keyframes cursorFlicker {
  0%, 100% { opacity: 1; transform: scaleY(1); }
  50% { opacity: 0.75; transform: scaleY(0.92); }
}

body[data-cursor="lightning-cursor"] .char.current::before,
[data-cursor-demo="lightning-cursor"] .cursor-demo-bar {
  width: 3px;
  background: #fde047;
  box-shadow: 0 0 14px #fde047, 0 0 28px rgba(253, 224, 71, 0.5);
  animation: cursorFlash 0.3s steps(2) infinite;
}

@keyframes cursorFlash {
  50% { opacity: 0.25; }
}

body[data-cursor="rainbow-trail"] .char.current::before,
[data-cursor-demo="rainbow-trail"] .cursor-demo-bar {
  width: 3px;
  background: linear-gradient(to bottom, #ff5252, #ffb74d, #fff176, #66bb6a, #42a5f5, #ba68c8);
  background-size: 100% 300%;
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.4);
  animation: rainbowShift 2s linear infinite;
}

@keyframes rainbowShift {
  0% { background-position: 0 0%; }
  100% { background-position: 0 100%; }
}

body[data-cursor="toxic-cursor"] .char.current::before,
[data-cursor-demo="toxic-cursor"] .cursor-demo-bar {
  width: 3px;
  background: linear-gradient(to bottom, #a3e635, #4d7c0f);
  box-shadow: 0 0 10px rgba(163, 230, 53, 0.7), 0 0 20px rgba(77, 124, 15, 0.4);
  animation: cursorToxicDrip 1.1s ease-in-out infinite;
}

@keyframes cursorToxicDrip {
  0%, 100% { transform: scaleY(1); opacity: 1; }
  50% { transform: scaleY(1.15) translateY(2px); opacity: 0.8; }
}

/* Legendary tier gets the most dramatic treatment — a deep violet glow
   that visibly pulses outward, like the cursor is swallowing light. */
body[data-cursor="void-cursor"] .char.current::before,
[data-cursor-demo="void-cursor"] .cursor-demo-bar {
  width: 4px;
  background: #1e1033;
  box-shadow: 0 0 8px #7c3aed, 0 0 18px rgba(124, 58, 237, 0.7), 0 0 32px rgba(124, 58, 237, 0.4);
  animation: cursorVoidPulse 1.4s ease-in-out infinite;
}

@keyframes cursorVoidPulse {
  0%, 100% { box-shadow: 0 0 8px #7c3aed, 0 0 18px rgba(124, 58, 237, 0.7), 0 0 32px rgba(124, 58, 237, 0.4); }
  50% { box-shadow: 0 0 14px #a855f7, 0 0 28px rgba(168, 85, 247, 0.85), 0 0 48px rgba(124, 58, 237, 0.6); }
}

/* Limited to 40 units ever — the most elaborate cursor in the shop,
   shifting between gold and diamond-white like light catching a jewel. */
body[data-cursor="crown-jewels-cursor"] .char.current::before,
[data-cursor-demo="crown-jewels-cursor"] .cursor-demo-bar {
  width: 4px;
  background: linear-gradient(to bottom, #fde047, #fff, #eab308);
  background-size: 100% 200%;
  box-shadow: 0 0 10px #fde047, 0 0 22px rgba(253, 224, 71, 0.6);
  animation: cursorJewelShimmer 1.6s ease-in-out infinite;
}

@keyframes cursorJewelShimmer {
  0%, 100% { background-position: 0 0%; box-shadow: 0 0 10px #fde047, 0 0 22px rgba(253, 224, 71, 0.6); }
  50% { background-position: 0 100%; box-shadow: 0 0 16px #fff, 0 0 30px rgba(255, 255, 255, 0.8); }
}

body[data-cursor="ice-cursor"] .char.current::before,
[data-cursor-demo="ice-cursor"] .cursor-demo-bar {
  width: 3px;
  background: #38bdf8;
  box-shadow: 0 0 10px #38bdf8, 0 0 20px rgba(56, 189, 248, 0.5);
  animation: cursorIceGlint 1.2s ease-in-out infinite;
}

@keyframes cursorIceGlint {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

/* The bar itself stays dark (that's the point), but a bright silver glow
   keeps it visible against any theme instead of just disappearing. */
body[data-cursor="shadow-cursor"] .char.current::before,
[data-cursor-demo="shadow-cursor"] .cursor-demo-bar {
  width: 4px;
  background: #1c1917;
  box-shadow: 0 0 8px #a8a29e, 0 0 18px rgba(168, 162, 158, 0.5);
  animation: cursorShadowWisp 1.8s ease-in-out infinite;
}

@keyframes cursorShadowWisp {
  0%, 100% { transform: scaleX(1); box-shadow: 0 0 8px #a8a29e, 0 0 18px rgba(168, 162, 158, 0.5); }
  50% { transform: scaleX(1.8); box-shadow: 0 0 12px #d6d3d1, 0 0 26px rgba(214, 211, 209, 0.6); }
}

body[data-cursor="plasma-cursor"] .char.current::before,
[data-cursor-demo="plasma-cursor"] .cursor-demo-bar {
  width: 3px;
  background: linear-gradient(to bottom, #22d3ee, #a855f7);
  box-shadow: 0 0 10px #22d3ee, 0 0 20px rgba(168, 85, 247, 0.6);
  animation: cursorPlasmaArc 0.5s steps(3) infinite;
}

@keyframes cursorPlasmaArc {
  0%, 100% { transform: translateX(0); }
  33% { transform: translateX(-1px); }
  66% { transform: translateX(1px); }
}

body[data-cursor="starlight-cursor"] .char.current::before,
[data-cursor-demo="starlight-cursor"] .cursor-demo-bar {
  width: 3px;
  background: #fff;
  box-shadow: 0 0 8px #fff, 0 0 16px rgba(255, 255, 255, 0.7), 0 0 26px rgba(199, 210, 254, 0.5);
  animation: cursorStarTwinkle 1.5s ease-in-out infinite;
}

@keyframes cursorStarTwinkle {
  0%, 100% { opacity: 1; box-shadow: 0 0 8px #fff, 0 0 16px rgba(255, 255, 255, 0.7), 0 0 26px rgba(199, 210, 254, 0.5); }
  50% { opacity: 0.6; box-shadow: 0 0 4px #fff, 0 0 10px rgba(255, 255, 255, 0.4); }
}

/* =========================================================
   AVATARS
   Matches ShopItem slugs (item_type="avatar"). Rendered as
   [data-avatar="slug"] on any .avatar-badge circle — race lanes, the
   waiting room, results, leaderboard rows, friends list, profile hero.
   No avatar equipped = the fallback initial-letter span stays visible.
========================================================= */

.avatar-badge {
  position: relative;
}

.avatar-badge[data-avatar]:not([data-avatar=""]) .avatar-letter {
  visibility: hidden;
}

/* ::before (not ::after) deliberately — race lane/circle avatars also use
   ::after for the equipped trail cosmetic (see RACE MODE below), and a
   single pseudo-element can't serve both jobs at once. Layout only here,
   no "content", so the per-slug rules below (lower specificity, since
   they don't repeat the :not()) are free to set it without being
   overridden. */
.avatar-badge[data-avatar]:not([data-avatar=""])::before {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1em;
  line-height: 1;
}

.avatar-badge[data-avatar="cool-cat-avatar"]::before { content: "😼"; }
.avatar-badge[data-avatar="sly-fox-avatar"]::before { content: "🦊"; }
.avatar-badge[data-avatar="panda-avatar"]::before { content: "🐼"; }
.avatar-badge[data-avatar="night-owl-avatar"]::before { content: "🦉"; }
.avatar-badge[data-avatar="lone-wolf-avatar"]::before { content: "🐺"; }
.avatar-badge[data-avatar="keybot-avatar"]::before { content: "🤖"; }
.avatar-badge[data-avatar="dragon-avatar"]::before { content: "🐉"; }
.avatar-badge[data-avatar="shark-avatar"]::before { content: "🦈"; }
.avatar-badge[data-avatar="alien-avatar"]::before { content: "👽"; }
.avatar-badge[data-avatar="phoenix-avatar"]::before { content: "🐦‍🔥"; }
.avatar-badge[data-avatar="cosmic-avatar"]::before { content: "🌌"; }
.avatar-badge[data-avatar="champion-avatar"]::before {
  content: "👑";
  animation: avatarChampionGlow 1.6s ease-in-out infinite;
}

@keyframes avatarChampionGlow {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(250, 204, 21, 0.7)); }
  50% { filter: drop-shadow(0 0 7px rgba(250, 204, 21, 0.95)); }
}

/* Limited to 100 units ever — a shifting white-gold shimmer, distinct
   from Champion's steady gold glow, marking it as one of the earliest
   avatars anyone could ever claim. */
.avatar-badge[data-avatar="genesis-avatar"]::before {
  content: "🌟";
  animation: avatarGenesisShimmer 2s ease-in-out infinite;
}

@keyframes avatarGenesisShimmer {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.8)); }
  50% { filter: drop-shadow(0 0 8px rgba(250, 204, 21, 1)); }
}

.avatar-badge[data-avatar="ninja-avatar"]::before { content: "🥷"; }
.avatar-badge[data-avatar="wizard-avatar"]::before { content: "🧙"; }
.avatar-badge[data-avatar="astronaut-avatar"]::before { content: "👨‍🚀"; }
.avatar-badge[data-avatar="superhero-avatar"]::before {
  content: "🦸";
  animation: avatarSuperheroGlow 1.3s ease-in-out infinite;
}

@keyframes avatarSuperheroGlow {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(59, 130, 246, 0.6)); }
  50% { filter: drop-shadow(0 0 6px rgba(220, 38, 38, 0.8)); }
}

#input-field {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* =========================================================
   RESULTS
========================================================= */

.results-shell {
  display: none;
  width: min(var(--container), 92%);
  margin: 40px auto 0;
  padding-bottom: 60px;
}

.results-shell.active {
  display: block;
  /* A short delay lets scrollIntoView get moving first; fading in with a
     vertical slide (the old translateY) fights the scroll since both are
     vertical motion happening at once — scale instead reads as "arriving"
     rather than "sliding against the scroll". */
  animation: resultsReveal 0.4s ease 0.1s both;
}

@keyframes resultsReveal {
  from { opacity: 0; transform: scale(0.98); }
  to { opacity: 1; transform: scale(1); }
}

.results-hero {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  margin-bottom: 24px;
}

.hero-main {
  flex: 1;
  min-width: 240px;
}

.hero-kicker {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--muted);
  margin-bottom: 10px;
}

.hero-score-wrap {
  display: flex;
  align-items: flex-end;
  gap: 20px;
}

.hero-score {
  font-size: 96px;
  line-height: 1;
  font-weight: 800;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.hero-score-meta {
  padding-bottom: 14px;
}

.hero-score-meta span {
  font-size: 15px;
  color: var(--muted);
}

.hero-trend {
  margin-top: 8px;
  color: var(--success);
  font-weight: 700;
  font-size: 14px;
}

.hero-side {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.mini-stat {
  min-width: 130px;
  padding: 18px 20px;

  border-radius: var(--radius-md);

  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.mini-label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 8px;
}

.mini-value {
  font-size: 28px;
  font-weight: 800;
}

.performance-card,
.recent-card,
.chart-card {
  padding: 28px;
  margin-bottom: 24px;
}

.section-head h3,
.section-header h3 {
  margin: 0 0 4px;
  font-size: 20px;
  font-weight: 800;
}

.section-head p,
.section-header p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

.timeline-track {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 200px;
  margin-top: 22px;
}

.timeline-bar {
  flex: 1;
  min-height: 16px;
  border-radius: 999px 999px 6px 6px;

  background: linear-gradient(to top, var(--accent), var(--accent-2));
  transition: transform 0.15s ease, opacity 0.15s ease;
  cursor: pointer;
}

.timeline-bar:hover {
  transform: translateY(-6px) scaleY(1.02);
}

.timeline-bar.slow {
  background: linear-gradient(to top, var(--danger), #ffb86b);
}

.timeline-tooltip {
  position: fixed;
  opacity: 0;
  pointer-events: none;
  z-index: 9999;

  padding: 10px 14px;
  border-radius: 12px;

  background: var(--text);
  color: var(--bg);

  font-size: 13px;
  line-height: 1.5;
  box-shadow: var(--shadow-lg);
  transition: opacity 0.12s ease;
}

.insight-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.insight-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px;
}

.insight-icon {
  width: 52px;
  height: 52px;
  flex-shrink: 0;

  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-size: 20px;
}

.insight-card h4 {
  margin: 0 0 2px;
  font-size: 15px;
}

.insight-card p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

.results-actions {
  margin-top: 8px;
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.primary-action {
  border: none;
  padding: 15px 28px;
  border-radius: var(--radius-md);

  font-weight: 700;
  font-size: 14px;
  color: #fff;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 12px 28px var(--accent-soft);
  transition: transform 0.2s ease;
}

.primary-action:hover {
  transform: translateY(-2px);
}

/* =========================================================
   COMMUNITY (leaderboards + activity)
========================================================= */

.community-wrapper {
  width: min(var(--container), 92%);
  margin: 40px auto 80px;

  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: start;
}

.community-card,
.leaderboard-card,
.coins-board-card {
  padding: 20px;
  min-height: 420px;
  max-height: 420px;

  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.community-header,
.leaderboard-top,
.coins-board-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 16px;
}

.community-header h3,
.leaderboard-top h3,
.coins-board-header h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 800;
}

.community-header p,
.leaderboard-top p,
.coins-board-header p {
  margin: 4px 0 0;
  font-size: 12.5px;
  color: var(--muted);
}

.leaderboard-scope-toggle {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}

.lb-scope-btn {
  padding: 5px 10px;
  border: none;
  border-radius: 999px;

  background: var(--surface-2);
  color: var(--muted);

  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s ease;
}

.lb-scope-btn:hover {
  color: var(--text);
}

.lb-scope-btn.active {
  background: var(--accent-soft);
  color: var(--accent);
}

.live-pill,
.season-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;

  padding: 6px 10px;
  border-radius: 999px;

  background: var(--accent-soft);
  color: var(--accent);

  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
}

.live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  animation: pulseDot 1.5s infinite;
}

@keyframes pulseDot {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.4); opacity: 0.6; }
}

.activity-feed,
.leaderboard-list,
.coins-board-list {
  flex: 1;
  overflow-y: auto;

  display: flex;
  flex-direction: column;
  gap: 8px;

  padding-right: 4px;
  margin: 0;
  list-style: none;
}

.activity-feed::-webkit-scrollbar,
.leaderboard-list::-webkit-scrollbar,
.coins-board-list::-webkit-scrollbar {
  width: 5px;
}

/* A single empty line of text at the top of a 420px card left a wall of
   dead space below it — this fills and centers within whatever room the
   parent flex column gives it instead. */
.empty-state-mini {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;

  text-align: center;
  padding: 20px;

  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.empty-state-mini .empty-state-icon {
  font-size: 28px;
  opacity: 0.6;
}

.activity-feed::-webkit-scrollbar-thumb,
.leaderboard-list::-webkit-scrollbar-thumb,
.coins-board-list::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 999px;
}

.lb-row,
.coin-rank-row,
.activity-item {
  display: flex;
  align-items: center;
  gap: 12px;

  padding: 12px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid transparent;
  transition: transform 0.15s ease, border-color 0.15s ease;
}

.lb-row:hover,
.coin-rank-row:hover,
.activity-item:hover {
  transform: translateY(-1px);
  border-color: var(--accent);
}

/* Legendary+ purchases get a glowing highlight so a rare unlock actually
   stands out from the usual stream of common-tier activity — the whole
   value of a public feed is seeing someone else get something you don't
   have yet. */
.activity-item-exclusive {
  border-color: rgba(250, 204, 21, 0.4);
  background: linear-gradient(135deg, rgba(250, 204, 21, 0.08), var(--surface-2));
  box-shadow: 0 0 0 1px rgba(250, 204, 21, 0.12);
  animation: activityExclusiveGlow 2.2s ease-in-out infinite;
}

@keyframes activityExclusiveGlow {
  0%, 100% { box-shadow: 0 0 0 1px rgba(250, 204, 21, 0.12); }
  50% { box-shadow: 0 0 0 1px rgba(250, 204, 21, 0.3), 0 0 14px rgba(250, 204, 21, 0.15); }
}

.lb-rank,
.coin-rank-number {
  width: 30px;
  height: 30px;
  flex-shrink: 0;

  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;

  background: var(--surface);
  border: 1px solid var(--border);

  font-size: 12px;
  font-weight: 800;
  color: var(--muted);
}

.rank-1 { background: #fef3c7; color: #92400e; border-color: transparent; }
.rank-2 { background: #e5e7eb; color: #374151; border-color: transparent; }
.rank-3 { background: #fed7aa; color: #9a3412; border-color: transparent; }

.lb-avatar {
  width: 30px;
  height: 30px;
  flex-shrink: 0;

  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;

  font-size: 12px;
  font-weight: 800;
}

.lb-user,
.coin-user-info,
.activity-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.lb-user a,
.coin-user-info strong,
.activity-text strong {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.lb-user a:hover,
.coin-user-info strong a:hover,
.activity-text strong a:hover {
  color: var(--accent);
}

.lb-sub,
.coin-user-info span,
.activity-meta {
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--muted);
}

.lb-wpm,
.coin-total,
.activity-coins {
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
}

.lb-wpm span,
.coin-total span {
  margin-left: 3px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
}

.activity-avatar {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 10px;

  display: flex;
  align-items: center;
  justify-content: center;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-size: 14px;
}

.activity-text {
  font-size: 13px;
  color: var(--text);
}

.activity-text .reward {
  font-weight: 700;
  color: var(--accent);
}

.activity-coins.positive { color: var(--success); }
.activity-coins:not(.positive) { color: var(--danger); }

@media (max-width: 1100px) {
  .community-wrapper {
    grid-template-columns: 1fr;
  }
}

/* =========================================================
   DASHBOARD
========================================================= */

.dashboard-shell {
  width: min(1200px, 92%);
  margin: 32px auto 80px;

  display: flex;
  flex-direction: column;
  gap: 20px;
}

.dashboard-hero {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.hero-profile {
  flex: 2;
  min-width: 280px;

  display: flex;
  align-items: flex-start;
  gap: 18px;
  padding: 28px;
}

.hero-avatar {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: 18px;

  display: flex;
  align-items: center;
  justify-content: center;

  font-size: 24px;
  font-weight: 800;
  color: #fff;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.hero-profile h1 {
  margin: 0;
  font-size: 26px;
  font-weight: 800;
}

.hero-profile p {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 14px;
}

.hero-side {
  flex: 1;
  min-width: 200px;

  display: flex;
  flex-direction: column;
  gap: 14px;
}

.mini-card {
  padding: 18px 20px;
}

.mini-card span {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 4px;
}

.mini-card strong {
  font-size: 22px;
}

.mini-card-level {
  display: block;
  color: var(--text);
  transition: border-color 0.15s ease;
}

.mini-card-level:hover {
  border-color: var(--accent);
}

.mini-card-level span {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
}

.mini-level-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  margin-bottom: 6px;
}

.mini-level-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.mini-card-level small {
  color: var(--muted);
  font-size: 11.5px;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.stat-card {
  padding: 22px;
}

.stat-card span {
  color: var(--muted);
  font-size: 13px;
}

.stat-card h2,
.stat-card h3 {
  margin-top: 8px;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -1px;
}

.stat-card.best {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  border: none;
}

.stat-card.best span {
  color: rgba(255, 255, 255, 0.75);
}

.dashboard-main {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 20px;
  /* Grid items stretch to match the tallest sibling by default — with up
     to 30 rows in the recent-tests list and nothing to expand into the
     leftover room, the shorter chart card was being stretched taller than
     its own content, leaving blank space below the chart. Size each card
     to its own content instead. */
  align-items: start;
}

.dashboard-main > * {
  /* Grid items default to min-width:auto, which refuses to shrink below
     the widest piece of content — the WPM chart's <canvas> in particular,
     which Chart.js sizes in actual pixels. Without this, the chart card
     forces the whole grid (and the page) wider than the viewport on
     narrow screens instead of the chart shrinking to fit. */
  min-width: 0;
}

.performance-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 24px;
}

.eyebrow {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--accent);
}

.performance-header h2 {
  margin: 0;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.5px;
}

.performance-stats {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.performance-stats .mini-stat,
.mini-stat {
  min-width: 96px;
  padding: 12px 16px;
}

.performance-stats .mini-stat span {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 4px;
}

.performance-stats .mini-stat strong {
  font-size: 20px;
  font-weight: 800;
}

.chart-wrap {
  position: relative;
  height: 320px;
  display: flex;
}

.recent-tests,
.recent-feed {
  display: flex;
  flex-direction: column;
  gap: 10px;

  max-height: 420px;
  overflow-y: auto;
  padding-right: 4px;
}

.test-item,
.activity-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;

  padding: 14px 16px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  transition: transform 0.15s ease;
}

.test-item:hover,
.activity-row:hover {
  transform: translateX(4px);
}

.test-left,
.activity-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.activity-score {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-weight: 800;
}

.test-main,
.activity-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.test-wpm {
  font-size: 20px;
  font-weight: 800;
}

.test-wpm span,
.wpm {
  font-size: 12px;
  color: var(--muted);
  font-weight: 500;
}

.wpm {
  font-weight: 800;
  font-size: inherit;
  color: var(--accent);
}

.mode-pill {
  display: inline-block;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 11px;
  font-weight: 700;
  width: fit-content;
}

.mode-pill-quote {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--surface-2, var(--surface));
  color: var(--muted);
  border: 1px solid var(--border);
}

.mode,
.date {
  font-size: 12px;
  color: var(--muted);
}

.accuracy,
.accuracy-pill {
  font-weight: 700;
  color: var(--success);
}

.accuracy-pill {
  padding: 8px 12px;
  border-radius: 999px;
  background: rgba(16, 185, 129, 0.12);
  font-size: 13px;
}

/* Badge showcase */

.badge-showcase {
  margin-top: 20px;
  width: 100%;
}

.badge-showcase-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 14px;
}

.badge-showcase-head h3 {
  margin: 0;
  font-size: 16px;
}

.badge-link {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
}

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

.showcase-section {
  padding: 24px;
}

.showcase-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
}

.showcase-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;

  padding: 18px 12px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid var(--border);
  transition: transform 0.2s ease;
}

.showcase-item:hover {
  transform: translateY(-3px);
}

.showcase-icon {
  font-size: 32px;
  margin-bottom: 4px;
}

.showcase-item strong {
  font-size: 13.5px;
}

.showcase-rarity {
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.showcase-scarcity {
  margin-top: 4px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--muted);
}

.badge-card {
  display: flex;
  align-items: center;
  gap: 12px;

  padding: 14px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid var(--border);
  transition: transform 0.2s ease;
}

.badge-card:hover {
  transform: translateY(-3px);
}

.badge-icon-wrap {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;

  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 20px;
}

.badge-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 3px;
}

.badge-body strong {
  font-size: 14px;
}

.badge-body small {
  color: var(--muted);
  font-size: 12px;
}

.badge-rarity,
.rarity-pill,
.shop-rarity {
  display: inline-flex;
  align-items: center;
  padding: 4px 9px;
  border-radius: 999px;

  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;

  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
}

.rarity-common { color: var(--muted); border-color: var(--border); }
.rarity-rare { color: #3b82f6; border-color: rgba(59, 130, 246, 0.35); }
.rarity-epic { color: #a855f7; border-color: rgba(168, 85, 247, 0.35); }
.rarity-legendary { color: #ca8a04; border-color: rgba(250, 204, 21, 0.4); }
.rarity-mythical { color: #ec4899; border-color: rgba(236, 72, 153, 0.4); }
.rarity-exclusive { color: #f97316; border-color: rgba(249, 115, 22, 0.4); }
.rarity-ultra { color: #dc2626; border-color: rgba(220, 38, 38, 0.45); }

.badge-empty {
  margin-top: 18px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;

  padding: 18px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid var(--border);
}

.empty-icon {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;

  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 22px;
}

.badge-empty h3 {
  margin: 0 0 4px;
  font-size: 15px;
}

.badge-empty p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  max-width: 420px;
}

@media (max-width: 950px) {
  .dashboard-main { grid-template-columns: 1fr; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
  .dashboard-hero { flex-direction: column; }
}

@media (max-width: 640px) {
  .stats-grid { grid-template-columns: 1fr; }
  .hero-profile { flex-direction: column; text-align: center; }
}

/* =========================================================
   DAILY CHALLENGE
========================================================= */

.daily-challenge-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;

  padding: 16px 20px;
}

.dc-info {
  display: flex;
  align-items: center;
  gap: 14px;
}

.dc-icon {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;

  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.dc-text {
  display: flex;
  flex-direction: column;
}

.dc-text strong {
  font-size: 14px;
}

.dc-text span {
  font-size: 13px;
  color: var(--muted);
}

.dc-reward {
  flex-shrink: 0;
  padding: 8px 16px;
  border: none;
  border-radius: 999px;

  font-size: 13px;
  font-weight: 800;

  background: var(--accent-soft);
  color: var(--accent);
  white-space: nowrap;
}

.dc-reward.done {
  background: rgba(16, 185, 129, 0.14);
  color: var(--success);
}

.dc-reward.locked {
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.dc-reward.locked:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

/* =========================================================
   ACHIEVEMENT PROGRESS (locked shop badges)
========================================================= */

.achievement-progress {
  margin-top: 10px;
}

.achievement-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  margin-bottom: 6px;
}

.achievement-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width 0.3s ease;
}

.achievement-progress small {
  color: var(--muted);
  font-size: 11px;
}

/* =========================================================
   SHOP
========================================================= */

.shop-layout {
  width: 100%;
  margin: 0 0 80px;

  display: flex;
  gap: 24px;
  align-items: flex-start;
}

/* =========================================================
   ACHIEVEMENTS SECTION (shop page)
========================================================= */

.achievements-section {
  padding: 24px;
  margin-bottom: 28px;
}

.achievements-teaser {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 22px;
  margin-bottom: 28px;

  color: var(--text);
  transition: transform 0.15s ease, border-color 0.15s ease;
}

.achievements-teaser:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
}

.achievements-teaser-icon {
  font-size: 26px;
}

.achievements-teaser-body {
  flex: 1;
  min-width: 0;
}

.achievements-teaser-body h3 {
  font-size: 15px;
  margin: 0 0 2px;
}

.achievements-teaser-body p {
  font-size: 12.5px;
  color: var(--muted);
  margin: 0;
}

.achievements-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.achievement-card {
  display: flex;
  gap: 14px;
  padding: 16px;
  border-radius: var(--radius-md);

  background: var(--surface-2);
  border: 1px solid var(--border);
  opacity: 0.7;

  transition: transform 0.2s ease, opacity 0.2s ease;
}

.achievement-card.unlocked {
  opacity: 1;
  border-color: var(--accent);
}

.achievement-card:hover {
  transform: translateY(-2px);
}

.achievement-icon {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;

  background: var(--surface);
  border: 1px solid var(--border);
}

.achievement-body {
  flex: 1;
  min-width: 0;
}

.achievement-body h3 {
  font-size: 15px;
  margin: 0;
}

.achievement-status {
  margin-top: 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
}

.achievement-status.done {
  color: var(--success);
}

/* =========================================================
   ACHIEVEMENTS PAGE (level hero + tiered family ladders)
========================================================= */

.level-hero {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 24px;
  margin-bottom: 24px;
}

.level-hero-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  flex-shrink: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
}

.level-hero-number {
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
}

.level-hero-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.85;
}

.level-hero-progress {
  flex: 1;
  min-width: 0;
}

.level-hero-bar {
  height: 10px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  margin-bottom: 8px;
}

.level-hero-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width 0.3s ease;
}

.level-hero-progress small {
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
}

.family-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
  margin-bottom: 60px;
}

.family-card {
  padding: 20px;
}

.family-card.maxed {
  border-color: var(--accent);
}

.family-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}

.family-icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);

  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;

  background: var(--surface-2);
  border: 1px solid var(--border);
}

.family-head h3 {
  font-size: 15px;
  margin: 0 0 2px;
}

.family-count {
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
}

.tier-ladder {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}

.tier-pip {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px;
  border-radius: var(--radius-sm);

  background: var(--surface-2);
  border: 1px solid var(--border);
  opacity: 0.45;

  transition: transform 0.15s ease, opacity 0.15s ease;
}

.tier-pip.unlocked {
  opacity: 1;
  background: var(--surface);
}

.tier-pip:hover {
  transform: translateY(-2px);
}

.tier-pip-icon {
  font-size: 18px;
}

.tier-pip-label {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}

.shop-sidebar {
  width: 200px;
  flex-shrink: 0;
  padding: 10px;
  position: sticky;
  top: 20px;
}

.shop-tab {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}

.shop-tab:hover {
  background: var(--surface-2);
  color: var(--text);
}

.shop-tab.active {
  background: var(--accent-soft);
  color: var(--accent);
}

.shop-content {
  flex: 1;
  min-width: 0;
}

.page-header {
  margin-bottom: 24px;
}

.page-header h1 {
  margin: 0;
  font-size: 30px;
  font-weight: 800;
}

.page-header p {
  margin: 6px 0 0;
  color: var(--muted);
}

.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 18px;
}

.shop-card {
  position: relative;
  overflow: hidden;
  padding: 0;
}

/* Limited-supply items get their own visual treatment site-wide — a gold
   ribbon + border — so scarcity reads at a glance, not just in the text. */
.shop-card.exclusive {
  border: 1px solid rgba(250, 204, 21, 0.4);
  box-shadow: 0 0 0 1px rgba(250, 204, 21, 0.15), var(--shadow-md);
}

.exclusive-ribbon {
  position: absolute;
  top: 12px;
  right: -32px;
  transform: rotate(45deg);
  width: 120px;
  padding: 3px 0;
  text-align: center;

  background: linear-gradient(135deg, #facc15, #f59e0b);
  color: #1a1200;

  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;

  z-index: 2;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}

.shop-scarcity {
  font-size: 12px;
  font-weight: 700;
  color: #f59e0b;
  margin-top: 2px;
}

.shop-scarcity.sold-out {
  color: var(--danger);
}

.shop-preview {
  height: 130px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 44px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.shop-info {
  padding: 16px;
}

.shop-title-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.shop-card h3 {
  margin: 0;
  font-size: 16px;
}

.shop-price {
  font-size: 16px;
  font-weight: 800;
  margin: 6px 0 12px;
}

.buy-btn,
.owned-btn {
  width: 100%;
  padding: 11px;
  border-radius: var(--radius-sm);
  border: none;
  font-weight: 700;
  font-size: 13px;
  transition: 0.2s ease;
}

.buy-btn {
  color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.buy-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 20px var(--accent-soft);
}

.owned-btn {
  background: var(--surface-2);
  color: var(--muted);
  cursor: default;
  border: 1px solid var(--border);
}

@media (max-width: 768px) {
  .shop-layout { flex-direction: column; }
  .shop-sidebar {
    width: 100%;
    position: static;
    display: flex;
    gap: 6px;
    overflow-x: auto;
  }
}

/* =========================================================
   PROFILE PAGE
========================================================= */

.profile-container {
  width: min(var(--container), 92%);
  margin: 32px auto 80px;

  display: flex;
  flex-direction: column;
  gap: 20px;
}

.hero-profile { flex-wrap: wrap; }

.hero-profile > .btn,
.hero-profile > .profile-actions {
  margin-left: auto;
  align-self: center;
}

.profile-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.btn-text-danger {
  background: none;
  border: none;
  padding: 6px 4px;

  color: var(--danger);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.btn-text-danger:hover {
  text-decoration: underline;
}

.profile-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.profile-title-row h1 {
  margin: 0;
  font-size: 26px;
  font-weight: 800;
}

.rank-pill,
.you-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.rank-pill {
  background: var(--accent-soft);
  color: var(--accent);
}

.you-pill {
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
}

.recent-tests h3 {
  margin: 0 0 14px;
  font-size: 18px;
  font-weight: 800;
}

.test-row {
  display: flex;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}

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

/* =========================================================
   FOOTER
========================================================= */

.site-footer {
  margin-top: 60px;
  padding: 60px 24px 30px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}

.footer-inner {
  max-width: var(--container);
  margin: 0 auto;

  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 40px;
}

.footer-left {
  max-width: 320px;
}

.footer-logo {
  font-size: 1.3rem;
  font-weight: 800;
  margin-bottom: 12px;
}

.footer-left p {
  color: var(--muted);
  line-height: 1.7;
  font-size: 0.92rem;
}

.footer-links {
  display: flex;
  gap: 50px;
  flex-wrap: wrap;
}

.footer-column {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-column h4 {
  font-size: 0.9rem;
  font-weight: 800;
  margin: 0 0 4px;
}

.footer-column a {
  color: var(--muted);
  font-size: 0.9rem;
  transition: color 0.15s ease;
}

.footer-column a:hover {
  color: var(--accent);
}

.footer-bottom {
  max-width: var(--container);
  margin: 40px auto 0;
  padding-top: 20px;
  border-top: 1px solid var(--border);

  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;

  color: var(--muted);
  font-size: 0.85rem;
}

.footer-credit {
  font-weight: 600;
}

@media (max-width: 900px) {
  .footer-inner { flex-direction: column; }
  .footer-links { width: 100%; justify-content: space-between; gap: 24px; }
}

/* =========================================================
   COIN FX
========================================================= */

.coin-fx {
  position: fixed;
  font-size: 18px;
  pointer-events: none;
  z-index: 9999;
  animation: coinPop 0.7s ease-out forwards;
}

@keyframes coinPop {
  0% { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--x), var(--y)) scale(0.4) rotate(180deg); opacity: 0; }
}

.coin-pop {
  animation: coinBounce 0.3s ease;
}

@keyframes coinBounce {
  0% { transform: scale(1); }
  50% { transform: scale(1.3); color: #facc15; }
  100% { transform: scale(1); }
}

.coin-popup {
  position: fixed;
  top: 20%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;

  padding: 10px 18px;
  border-radius: var(--radius-sm);

  background: var(--text);
  color: var(--bg);

  font-weight: 700;
  font-size: 15px;

  animation: coinFade 1.5s ease forwards;
}

@keyframes coinFade {
  0% { opacity: 0; transform: translate(-50%, 10px); }
  20% { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -20px); }
}

.error-popup {
  background: var(--danger);
  color: #fff;
  max-width: min(360px, 90vw);
  text-align: center;
  animation: coinFade 2.6s ease forwards;
}

/* =========================================================
   RESPONSIVE — TYPING TEST / RESULTS
========================================================= */

@media (max-width: 768px) {
  .hero-score { font-size: 60px; }
  .timeline-track { height: 140px; }
  .performance-header { flex-direction: column; }
}

/* =========================================================
   RESPONSIVE — HEADER
========================================================= */

@media (max-width: 480px) {
  .site-header { gap: 8px; }

  .brand-logo .logo-text { display: none; }

  .nav-actions { gap: 3px; padding: 4px; }

  /* 40px rather than the 44px ideal — anything larger and the full row
     (customize/friends/messages/account) stops fitting a narrow phone
     screen alongside the coin pill. Still a meaningful bump from 32px. */
  .icon-btn { width: 40px; height: 40px; font-size: 16px; }

  .coin-pill { height: 32px; padding: 0 10px; font-size: 13px; }
  .level-pill { height: 32px; padding: 0 10px; font-size: 13px; }
}

/* =========================================================
   BOTTOM TAB BAR (mobile only)
========================================================= */

.bottom-tab-bar {
  display: none;
}

@media (max-width: 768px) {
  .bottom-tab-bar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 500;

    background: var(--surface);
    border-top: 1px solid var(--border);
    /* Safe-area padding keeps tabs clear of the home-indicator bar on
       notched phones when running standalone (added-to-homescreen). */
    padding-bottom: env(safe-area-inset-bottom, 0);

    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
  }

  /* Content would otherwise sit underneath the fixed bar. */
  body {
    padding-bottom: calc(58px + env(safe-area-inset-bottom, 0));
  }

  /* The Customize/Friends/Messages/Support icons stay reachable from the
     top bar; the bottom bar covers primary navigation only, so trim the
     duplicated ones out of the top row to reduce clutter. */
  .support-btn,
  .coin-pill {
    display: none;
  }
}

.bottom-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 4px 6px;

  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;

  -webkit-tap-highlight-color: transparent;
}

.bottom-tab i {
  font-size: 20px;
  line-height: 1;
}

.bottom-tab.active {
  color: var(--accent);
}

/* =========================================================
   RACE MODE
========================================================= */

.race-lobby-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}

.race-lobby-card {
  padding: 26px 22px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.race-lobby-icon {
  font-size: 34px;
  line-height: 1;
}

.race-lobby-card h3 {
  font-size: 17px;
  font-weight: 700;
}

.race-lobby-card p {
  color: var(--muted);
  font-size: 13.5px;
  min-height: 36px;
}

.race-join-row {
  display: flex;
  gap: 8px;
  width: 100%;
}

.race-join-row input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}

.race-inline-error {
  color: var(--danger);
  font-size: 12.5px;
  min-height: 16px;
}

/* --- Waiting room --- */

.race-waiting-card {
  padding: 28px;
}

.race-code-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.race-code-label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
}

.race-code-row strong {
  font-size: 28px;
  letter-spacing: 0.1em;
  font-family: monospace;
}

.race-participants-list {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 18px;
}

.race-waiting-participant {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
}

.race-avatar-circle {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-weight: 800;
  font-size: 16px;
  box-shadow: 0 6px 16px var(--accent-soft);
}

.race-countdown {
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 14px;
}

.race-hint {
  color: var(--muted);
  font-size: 13.5px;
  margin-bottom: 14px;
}

/* --- Live race track --- */

.race-track-shell {
  width: min(1100px, 92%);
  margin: 0 auto;
}

.race-lanes {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

.race-lane {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
}

.race-lane.you {
  border-color: var(--accent);
}

.race-lane-label {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  font-weight: 700;
  margin-bottom: 6px;
}

.race-lane-wpm {
  color: var(--muted);
  font-weight: 600;
}

.race-lane-track {
  position: relative;
  height: 30px;
  background: var(--bg);
  border-radius: 999px;
  overflow: hidden;
}

.race-lane-avatar {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  transition: left 0.4s ease-out;
  box-shadow: 0 0 0 3px var(--bg);
}

.race-lane-avatar.finished {
  background: linear-gradient(135deg, #facc15, #f59e0b);
}

/* --- Race trail cosmetics ---
   Matches ShopItem slugs (item_type="trail"). Applied both on the live
   lane avatar and the small circle avatars in the waiting room / results
   so equipping a trail is visible everywhere a player shows up. */

.race-lane-avatar[data-trail]::after,
.race-avatar-circle[data-trail]::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 100%;
  transform: translateY(-50%);
  height: 6px;
  width: 26px;
  border-radius: 999px;
  pointer-events: none;
}

.race-avatar-circle[data-trail]::after { display: none; }

.race-lane-avatar[data-trail="spark-trail"]::after {
  background: linear-gradient(to left, #fde047, transparent);
  box-shadow: 0 0 8px #fde047;
  animation: raceTrailFlicker 0.5s ease-in-out infinite;
}

.race-lane-avatar[data-trail="comet-trail"]::after {
  width: 40px;
  background: linear-gradient(to left, #38bdf8, transparent);
  box-shadow: 0 0 10px #38bdf8;
}

.race-lane-avatar[data-trail="flame-trail"]::after {
  width: 34px;
  background: linear-gradient(to left, #f97316, #facc15, transparent);
  box-shadow: 0 0 10px #f97316;
  animation: raceTrailFlicker 0.35s ease-in-out infinite;
}

.race-lane-avatar[data-trail="ghost-trail"]::after {
  width: 34px;
  background: linear-gradient(to left, rgba(226,232,240,0.9), transparent);
  box-shadow: 0 0 10px rgba(226,232,240,0.6);
  animation: raceTrailDrift 1.2s ease-in-out infinite;
}

.race-lane-avatar[data-trail="prism-trail"]::after {
  width: 40px;
  background: linear-gradient(to left, #ec4899, #a855f7, #38bdf8, transparent);
  background-size: 200% 100%;
  box-shadow: 0 0 12px rgba(168,85,247,0.6);
  animation: raceTrailShift 1.4s linear infinite;
}

@keyframes raceTrailFlicker {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

@keyframes raceTrailDrift {
  0%, 100% { transform: translateY(-50%) translateX(0); opacity: 0.9; }
  50% { transform: translateY(-50%) translateX(-4px); opacity: 0.5; }
}

@keyframes raceTrailShift {
  0% { background-position: 0 0; }
  100% { background-position: 200% 0; }
}

/* Limited to 75 units ever — the biggest, brightest trail in the shop,
   wider and hotter than the regular Flame Trail. */
.race-lane-avatar[data-trail="eternal-flame-trail"]::after {
  width: 48px;
  height: 8px;
  background: linear-gradient(to left, #fff7ed, #fb923c, #dc2626, transparent);
  box-shadow: 0 0 14px #f97316, 0 0 26px rgba(220, 38, 38, 0.5);
  animation: raceTrailFlicker 0.3s ease-in-out infinite;
}

.race-lane-avatar[data-trail="ice-trail"]::after {
  background: linear-gradient(to left, #e0f2fe, #38bdf8, transparent);
  box-shadow: 0 0 8px #38bdf8;
  animation: raceTrailFlicker 0.6s ease-in-out infinite;
}

/* Dark core + bright silver glow — same "visible regardless of what's
   behind it" trick as the Shadow Cursor above. */
.race-lane-avatar[data-trail="shadow-trail"]::after {
  background: linear-gradient(to left, #78716c, #1c1917, transparent);
  box-shadow: 0 0 10px rgba(214, 211, 209, 0.7);
  animation: raceTrailDrift 1s ease-in-out infinite;
}

.race-lane-avatar[data-trail="electric-trail"]::after {
  width: 34px;
  background: linear-gradient(to left, #fde047, #22d3ee, transparent);
  box-shadow: 0 0 10px #fde047, 0 0 18px rgba(34, 211, 238, 0.6);
  animation: raceTrailFlicker 0.2s steps(2) infinite;
}

.race-lane-avatar[data-trail="galaxy-trail"]::after {
  width: 40px;
  background: linear-gradient(to left, #a855f7, #6366f1, #38bdf8, transparent);
  background-size: 200% 100%;
  box-shadow: 0 0 12px rgba(99, 102, 241, 0.6);
  animation: raceTrailShift 1.6s linear infinite;
}

/* Small moving-dot demo used in the Customize modal's Race Trails tab */
.trail-demo-track {
  position: relative;
  overflow: hidden;
}

.trail-demo-dot {
  position: absolute;
  top: 50%;
  left: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateY(-50%);
  animation: trailDemoMove 1.8s ease-in-out infinite;
}

[data-trail-demo] .trail-demo-dot { background: var(--accent); }

[data-trail-demo="spark-trail"] .trail-demo-dot {
  background: #fde047;
  box-shadow: -14px 0 10px -4px #fde047;
}

[data-trail-demo="comet-trail"] .trail-demo-dot {
  background: #38bdf8;
  box-shadow: -18px 0 12px -4px #38bdf8;
}

[data-trail-demo="flame-trail"] .trail-demo-dot {
  background: #f97316;
  box-shadow: -18px 0 12px -4px #f97316;
}

[data-trail-demo="ghost-trail"] .trail-demo-dot {
  background: #e2e8f0;
  box-shadow: -18px 0 12px -4px rgba(226,232,240,0.8);
}

[data-trail-demo="prism-trail"] .trail-demo-dot {
  background: #a855f7;
  box-shadow: -18px 0 14px -4px #ec4899;
}

@keyframes trailDemoMove {
  0%, 100% { left: 8px; }
  50% { left: calc(100% - 16px); }
}

/* --- Results --- */

.race-results-shell {
  padding: 28px;
}

.race-results-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 18px 0;
}

.race-result-row {
  display: grid;
  grid-template-columns: 44px auto 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: var(--bg);
  border: 1px solid var(--border);
}

.race-result-row.you {
  border-color: var(--accent);
}

.race-result-place {
  font-weight: 800;
  color: var(--accent);
  text-align: center;
}

.race-result-name {
  font-weight: 700;
}

.race-result-wpm {
  font-weight: 700;
}

.race-result-wpm span {
  color: var(--muted);
  font-weight: 500;
  font-size: 12px;
}

.race-result-acc {
  color: var(--muted);
  font-size: 13px;
}

@media (max-width: 640px) {
  .race-lobby-grid { grid-template-columns: 1fr; }
  .race-result-row { grid-template-columns: 32px auto 1fr; }
  .race-result-wpm, .race-result-acc { grid-column: span 3; }
}
