:root {
  /* Defaults match the DEFAULT theme (MIDNIGHT) so a first visit — before JS runs
     applyTheme — renders in the right colors instead of flashing another palette.
     Returning visitors get their picked theme painted pre-render by the inline
     script in index.html. */
  --bg: #040406;           /* near-black onyx ground (default theme = ONYX) */
  --bg-soft: #131318;
  --phosphor: #ececf4;     /* primary silver-white phosphor */
  --phosphor-dim: #727285;
  --amber: #ff2e4e;        /* accent */
  --magenta: #ff5c7a;      /* hot accent */
  --ink: #f6f6fa;
  --glow: 236,236,244;
  --bg-top: #0a0a0e;
  --line: rgba(var(--glow), 0.18);
  --vignette: 0.5;   /* CRT corner-darkening; light themes lower this */
  --font-logo: "Orbitron", "Space Grotesk", sans-serif;   /* the VIBREAK wordmark only */
  --font-display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;  /* headings + HUD chrome */
  --font-accent: "Space Grotesk", "Segoe UI", system-ui, sans-serif;   /* tagline + labels */
  /* Motion tokens — strong custom curves (the built-in CSS easings are too weak
     to feel intentional). --ease-out for entrances/press; --ease-spring for the
     panels/toasts that get a touch of overshoot. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.2, 1.1, 0.4, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  margin: 0; width: 100%; height: 100%;
  position: fixed; inset: 0;        /* iOS Safari: lock the document so it can't
                                       rubber-band (which flashed white) */
  overflow: hidden;
  overscroll-behavior: none;        /* no bounce / pull-to-refresh */
  background:
    radial-gradient(ellipse at 50% 0%, var(--bg-top) 0%, var(--bg) 60%);
  background-color: var(--bg);      /* solid base so nothing ever flashes white */
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 600;                 /* Space Grotesk semibold base — punchy across the UI */
  -webkit-font-smoothing: antialiased;
}

/* animated ctOS-style line network — a live canvas painted from the theme
   colors (see setupBackground() in main.js). Sits behind everything. */
#bgfx {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  width: 100%; height: 100%; display: block;
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,var(--vignette)) 100%);
}
#app { position: relative; z-index: 2; }

/* Whole-viewport CRT glass: a static grain wash (no scanlines) so every surface
   reads as light coming through a phosphor tube rather than a flat webpage.
   Sits above the content but below the vignette; never blocks input.
   Static (no animation) so it costs nothing after first paint. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 59; pointer-events: none;
  /* Static phosphor grain only — NO scanlines. Static (no animation) so it's
     free after first paint; never blocks input. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.28'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  opacity: .6;
}

/* ===== PREMIUM THEMES — an exclusive flourish the free themes don't get.
   Toggled by the .premium class on <html> in applyTheme(). ===== */
/* twin accent blooms (top-corner + a low counter-glow) for a lit, deep backdrop */
html.premium body {
  background:
    radial-gradient(85% 65% at 12% 4%, rgba(var(--glow), 0.24), transparent 46%),
    radial-gradient(70% 55% at 90% 100%, rgba(var(--glow), 0.10), transparent 50%),
    radial-gradient(ellipse at 50% 0%, var(--bg-top) 0%, var(--bg) 60%);
  background-color: var(--bg);
}
/* the VIBREAK title becomes polished metal: a gradient fill with a crisp gleam
   sweeping across it, keeping its neon glow underneath */
html.premium .logo {
  background: linear-gradient(100deg,
    var(--phosphor) 0%, var(--phosphor) 44%,
    #ffffff 50%,
    var(--phosphor) 56%, var(--phosphor) 100%);
  background-size: 280% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: logopulse 3.6s ease-in-out infinite, premiumShine 5s ease-in-out infinite;
}
@keyframes premiumShine {
  from { background-position: 210% 0; }
  to   { background-position: -110% 0; }
}
/* premium cards catch the light: a bright hairline top edge + a richer glow */
html.premium .card {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 0 16px rgba(var(--glow), 0.16);
}
html.premium .card:not(.soon):hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 12px 30px rgba(0, 0, 0, 0.5), 0 0 30px rgba(var(--glow), 0.4);
}

#app {
  /* No scroll: the portal fits the viewport (scaled down if need be, see below);
     game views size their canvas to fit. position:relative anchors the absolutely
     centered portal. */
  height: 100%; overflow: hidden; position: relative;
  overscroll-behavior: none;
}
#game-view {
  max-width: 880px; margin: 0 auto; padding: 7vh 24px 40px;
}
/* The portal is absolutely centered and, if it's taller/wider than the screen,
   uniformly scaled down via --fit (computed in main.js's fitPortal()) so it always
   fits with NO scroll on any screen. */
#portal {
  position: absolute; left: 50%; top: var(--ptop, 50%);
  width: min(880px, 100%);
  transform: translate(-50%, -50%) scale(var(--fit, 1));
  transform-origin: center center;
  padding: clamp(10px, 2.4vh, 32px) clamp(14px, 3vw, 24px);
}

/* ---------- PORTAL ---------- */
/* UI chrome text isn't editable content — no I-beam / type-caret on click */
.logo, .tag, .card-name, .card-sub, #opt-theme-name, .foot {
  user-select: none; -webkit-user-select: none;
}
.logo, .tag, #opt-theme-name { cursor: default; }   /* non-clickable labels (links/cards keep pointer) */

.hero { text-align: center; margin-bottom: clamp(16px, 3.5vh, 44px); }

.logo {
  font-family: var(--font-logo);
  font-weight: 900;
  font-size: clamp(30px, 7.5vw, 68px);
  color: var(--phosphor);
  letter-spacing: 4px;
  text-shadow: 0 0 4px var(--phosphor), 0 0 13px rgba(var(--glow),0.32);   /* crisp neon, no fringe */
  line-height: 1.2;
  animation: neonBreathe 3.8s ease-in-out infinite;   /* arcade-cabinet hum */
}
.blink { animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* Neon glow gently pulses in the theme color — a humming-arcade-cabinet vibe.
   Uses --glow so it recolors per theme for free. Portal-only, so it never runs
   during gameplay (the portal is display:none while a game is up). */
@keyframes neonBreathe {
  0%, 100% { text-shadow:
    -1.5px 0 rgba(255,0,80,0.35), 1.5px 0 rgba(60,255,150,0.30),
    0 0 5px var(--phosphor), 0 0 16px rgba(var(--glow),0.30); }
  50%      { text-shadow:
    -2.5px 0 rgba(255,0,80,0.42), 2.5px 0 rgba(60,255,150,0.36),   /* split widens at the peak */
    0 0 9px var(--phosphor), 0 0 34px rgba(var(--glow),0.70); }
}
/* respect users who ask for less motion — freeze the ambient loops (neon
   breathe, metal shine, brand/LED blink, the pulsing task-done title) and drop
   the transform-based entrance overshoot, but KEEP opacity/color transitions
   that aid comprehension (Apple §14, Emil a11y). Games run their own canvas
   motion; this only governs the portal chrome. */
@media (prefers-reduced-motion: reduce) {
  .logo, .card, .nc-led, .blink, .td-title, .td-spark, .gover-new,
  html.premium .logo, .card:not(.soon):hover::before,
  .hero, .daily, #game-grid .card, .notify, .foot {   /* skip the entrance rise */
    animation: none !important;
  }
  /* replace overshoot-scaling entrances with a plain, still fade */
  .opt-panel, .gover-card, .daily-toast, .ach-toast, .task-done, .coin-toast,
  .mascot-bubble {
    transition-timing-function: ease !important;
    transform: none !important;
  }
}

.tag {
  margin-top: 18px; color: var(--phosphor-dim);
  font-family: var(--font-accent); font-weight: 700;
  font-size: clamp(13px, 2.8vw, 17px); letter-spacing: .5px;
}

/* ---- daily challenge — a slim one-line pill above the game grid ---- */
.daily {
  margin: 0 0 18px; padding: 8px 10px 8px 15px;
  background: rgba(var(--glow), 0.05); border-radius: 999px;
}
.daily-bar { display: flex; align-items: center; gap: 10px; }
.daily-kicker {
  flex: 0 0 auto; white-space: nowrap;
  font-family: var(--font-display); font-size: 10px; letter-spacing: 2px;
  text-transform: uppercase; color: var(--phosphor-dim);
}
.daily-name {
  flex: 0 0 auto; white-space: nowrap;
  font-family: var(--font-display); font-weight: 700; font-size: 14px;
  letter-spacing: 1px; color: var(--phosphor);
}
.daily-meta {
  flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 11.5px; letter-spacing: .2px; color: var(--phosphor-dim);
}
.daily-play {
  flex: 0 0 auto; -webkit-appearance: none; appearance: none; cursor: pointer;
  font-family: var(--font-display); font-size: 11px; letter-spacing: 1px;
  color: var(--bg); background: var(--phosphor); border: none; border-radius: 999px;
  padding: 7px 16px; transition: filter .12s, transform .12s;
}
.daily-play:hover { filter: brightness(1.1); transform: translateY(-1px); }
@media (max-width: 480px) { .daily-meta { display: none; } }

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

/* ============ PORTAL ENTRANCE ============ */
/* The menu ASSEMBLES on arrival instead of just being there — a quick staggered
   rise that plays on load and every time you come back from a game (portal.hidden
   flips false, so the animations restart). This is what stops the portal feeling
   static. Non-blocking: content is fully present and clickable throughout — it's
   pure opacity+transform (GPU). `backwards` fill (not forwards) is deliberate: it
   shows the start frame during the stagger delay, then RELEASES the transform when
   done, so the cards' :hover lift/scale still works afterward. */
@keyframes portalRise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
.hero, .daily, #game-grid .card, .notify, .foot {
  animation: portalRise .5s var(--ease-out) backwards;
}
.hero  { animation-delay: 0s; }
.daily { animation-delay: .06s; }
#game-grid .card:nth-child(1) { animation-delay: .12s; }
#game-grid .card:nth-child(2) { animation-delay: .16s; }
#game-grid .card:nth-child(3) { animation-delay: .20s; }
#game-grid .card:nth-child(4) { animation-delay: .24s; }
#game-grid .card:nth-child(5) { animation-delay: .28s; }
#game-grid .card:nth-child(6) { animation-delay: .32s; }
#game-grid .card:nth-child(7) { animation-delay: .36s; }
#game-grid .card:nth-child(8) { animation-delay: .40s; }
.notify { animation-delay: .08s; }
.foot   { animation-delay: .48s; }

/* daily-completed toast — top-center, distinct from the coin (bottom) toast */
.daily-toast {
  position: fixed; top: 16px; left: 50%; z-index: 10045;
  display: flex; align-items: center; gap: 8px;
  background: var(--bg-soft); border: 1px solid var(--amber); border-radius: 11px;
  padding: 10px 15px;
  font-family: var(--font-display); font-size: 12px; letter-spacing: 1px; color: var(--amber);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.5), 0 0 22px rgba(var(--glow), 0.3);
  opacity: 0; transform: translate(-50%, -14px);
  transition: opacity .3s ease, transform .3s cubic-bezier(.2, 1.1, .4, 1);
  pointer-events: none;
}
.daily-toast.show { opacity: 1; transform: translate(-50%, 0); }
.dt-fire { font-size: 16px; }

.card {
  position: relative;
  appearance: none; cursor: pointer; text-align: left;
  background: linear-gradient(165deg, var(--bg-soft) 0%, var(--bg) 135%);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--ink);
  padding: 11px 12px 13px;
  display: flex; flex-direction: column; gap: 6px;
  overflow: hidden;
  isolation: isolate;   /* own stacking context so the spotlight can sit behind text */
  transition: transform .22s var(--ease-spring), border-color .18s, box-shadow .18s;
  font-family: inherit;
  /* At rest the card is a dark, silent little screen — a faint inner recess for
     depth, NO outer bloom. Glow is reserved for hover, so it reads as a response
     instead of being sprayed on everything (the tell that read as AI). */
  box-shadow: inset 0 0 22px rgba(0,0,0,0.45);
}
/* cursor-reactive spotlight — the card lights up under the pointer (--mx/--my set in main.js) */
.card::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; pointer-events: none; opacity: 0;
  background: radial-gradient(200px circle at var(--mx, 50%) var(--my, 50%),
    rgba(var(--glow), 0.22), transparent 62%);
  transition: opacity .3s ease;
}
.card:not(.soon):hover::after { opacity: 1; }
/* a light sweep glides across the card on hover */
.card::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: -70%; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.07), transparent);
  transform: skewX(-18deg); pointer-events: none; z-index: 4; opacity: 0;
}
.card:not(.soon):hover {
  transform: translateY(-5px) scale(1.02);
  border-color: var(--phosphor);
  box-shadow: 0 12px 30px rgba(0,0,0,0.5), 0 0 16px rgba(var(--glow), 0.28);
}
.card:not(.soon):hover::before { opacity: 1; animation: cardsweep .7s ease; }
@keyframes cardsweep { from { left: -70%; } to { left: 130%; } }

/* each icon sits on a little recessed arcade "screen" — bezel + inner glow —
   so both the animated previews and the glyph logos read as tiny monitors */
.card-art {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  min-height: 58px; border-radius: 4px;
  border: 1px solid var(--line);
  background: radial-gradient(ellipse at 50% 32%, rgba(var(--glow),0.09), var(--bg) 78%);
  box-shadow: inset 0 0 20px rgba(0,0,0,0.6);
  font-size: 24px; letter-spacing: 3px; color: var(--phosphor);
  transition: border-color .18s, box-shadow .18s, color .18s;
}
.card:not(.soon):hover .card-art {
  color: var(--amber);
  border-color: rgba(var(--glow), 0.55);
  box-shadow: inset 0 0 20px rgba(0,0,0,0.6), 0 0 14px rgba(var(--glow), 0.22);
}
.card-canvas { display: block; width: 100%; height: auto; image-rendering: pixelated; }
.card:not(.soon):hover .card-canvas { filter: drop-shadow(0 0 6px rgba(var(--glow), 0.6)); }

.card-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: 15px; letter-spacing: 1px; color: var(--ink); margin-top: 3px;
  text-shadow: none;
  transition: text-shadow .18s;
}
.card:not(.soon):hover .card-name {
  text-shadow: 0 0 12px rgba(var(--glow), 0.5);   /* clean glow on hover */
}
.card-sub { font-size: 11px; color: var(--phosphor-dim); letter-spacing: 1px; }

/* "▶ PLAY" cue: a small pill that drops into the screen's corner on hover */
.play-cue {
  position: absolute; top: 8px; right: 8px; z-index: 5;
  font-size: 9px; letter-spacing: 1px; color: var(--bg);
  background: var(--phosphor); border-radius: 999px; padding: 3px 9px;
  opacity: 0; transform: translateY(-5px);
  box-shadow: 0 0 12px rgba(var(--glow), 0.6);
  transition: opacity .16s, transform .16s;
}
.card:not(.soon):hover .play-cue { opacity: 1; transform: none; }

.card.soon { opacity: .4; cursor: not-allowed; }
.card.soon .card-art { color: var(--phosphor-dim); }

.foot {
  margin-top: clamp(14px, 3vh, 48px);
  display: flex; justify-content: center; align-items: center; gap: 12px; flex-wrap: wrap;
  color: var(--phosphor-dim); font-size: 12px; letter-spacing: 2px;
}
/* support pill — coffee-warm, outlined by default, lifts + glows on hover */
.coffee {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg-soft);
  color: var(--amber); text-decoration: none;
  font-family: var(--font-accent); font-weight: 700; font-size: 11px;
  letter-spacing: 1.5px; text-transform: uppercase;
  transition: color .16s ease, background .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.coffee svg { flex: none; }
.coffee:hover {
  color: var(--bg); background: var(--amber); border-color: var(--amber);
  box-shadow: 0 8px 22px rgba(var(--glow), 0.28); transform: translateY(-2px);
}
/* X / social icon button — same outlined-pill language as the coffee button */
.xlink {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg-soft);
  color: var(--phosphor); text-decoration: none;
  transition: color .16s ease, background .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.xlink:hover {
  color: var(--bg); background: var(--amber); border-color: var(--amber);
  box-shadow: 0 8px 22px rgba(var(--glow), 0.28); transform: translateY(-2px);
}
/* quiet legal link — sits on its own line under the coffee/X buttons */
.foot-link {
  flex-basis: 100%; text-align: center; margin-top: 2px;
  color: var(--phosphor-dim); font-size: 11px; letter-spacing: 1px; text-decoration: none;
  transition: color .16s ease;
}
.foot-link:hover { color: var(--phosphor); text-decoration: underline; }

/* theme swatches (live inside the options panel) */
.theme-dot {
  width: 28px; height: 28px; border-radius: 50%; cursor: pointer;
  border: none; position: relative; appearance: none;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.25);
  transition: transform .12s, box-shadow .12s;
}
.theme-dot:hover { transform: scale(1.12); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.25), 0 0 12px rgba(var(--glow), 0.5); }
.theme-dot.active {
  transform: scale(1.08);
  box-shadow: 0 0 0 2px var(--bg-soft), 0 0 0 4px var(--phosphor), 0 0 16px rgba(var(--glow), 0.7);
}
.theme-dot.active::after {
  content: "✓"; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 14px; font-weight: 700; text-shadow: 0 0 3px rgba(0,0,0,0.75);
}

/* ---------- GAME SHELL ---------- */
/* "select difficulty" gate shown on entering a game */
.diff-gate {
  display: flex; flex-direction: column; align-items: center;
  gap: 16px; padding: 64px 16px;
}
.gate-title {
  font-family: var(--font-display); font-weight: 800; font-size: 24px;
  color: var(--phosphor); letter-spacing: 3px;
  text-shadow: 0 0 8px rgba(var(--glow),0.5);
}
.gate-sub {
  font-size: 11px; letter-spacing: 3px; color: var(--phosphor-dim);
  margin-bottom: 6px;
}
.gate-row { margin-bottom: 0; }
.gate-btn { padding: 12px 22px; font-size: 13px; }

/* full-screen name overlay (asked on entry) */
.name-overlay {
  position: fixed; inset: 0; z-index: 10080;   /* above the Options overlay (10060) so CHANGE isn't hidden behind it */
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.82);
}
.name-sub { font-size: 10px; letter-spacing: 2px; color: var(--phosphor-dim); margin: -4px 0 4px; }

/* difficulty selector row above a game */
.diff-bar {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 14px; flex-wrap: wrap; justify-content: center;
}
.diff-label {
  font-size: 10px; letter-spacing: 2px; color: var(--phosphor-dim);
  margin-right: 4px;
}
.diff-btn {
  appearance: none; cursor: pointer; font-family: inherit;
  background: var(--bg-soft); color: var(--phosphor-dim);
  border: 1px solid var(--line); padding: 6px 12px;
  font-size: 11px; letter-spacing: 2px;
  transition: color .1s, border-color .1s, box-shadow .1s;
}
.diff-btn:hover { color: var(--phosphor); border-color: var(--phosphor-dim); }
.diff-btn.active {
  color: var(--bg); background: var(--phosphor);
  border-color: var(--phosphor);
  box-shadow: 0 0 12px rgba(var(--glow),0.5);
}
.diff-btn:disabled { cursor: not-allowed; }
.diff-btn:disabled:not(.active) { opacity: .35; }
.diff-btn:disabled:not(.active):hover { color: var(--phosphor-dim); border-color: var(--line); }

.back {
  appearance: none; cursor: pointer; font-family: inherit;
  background: transparent; color: var(--amber);
  border: 1px solid var(--line); padding: 8px 14px;
  margin-bottom: 18px; letter-spacing: 1px;
  transition: border-color .14s ease, transform .12s var(--ease-out);
}
.back:hover { border-color: var(--amber); }

#game-mount { display: flex; flex-direction: column; align-items: center; position: relative; }

/* ---------- end-of-run screen (games/_gameover.js) ---------- */
/* covers the whole game area so it also swallows the "tap to retry" tap */
.gover {
  position: absolute; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(var(--glow), 0.10), transparent 62%),
    rgba(6, 3, 14, 0.74);
  opacity: 0; transition: opacity 0.2s ease;
}
.gover.show { opacity: 1; }
.gover-card {
  width: min(300px, 82%); padding: 24px 22px 18px; text-align: center;
  background: linear-gradient(165deg, var(--bg-soft) 0%, var(--bg) 140%);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55), 0 0 34px rgba(var(--glow), 0.12);
  transform: translateY(10px) scale(0.97);
  transition: transform 0.24s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
.gover.show .gover-card { transform: none; }
.gover-title {
  font-family: var(--font-display); font-size: 13px; letter-spacing: 4px;
  color: var(--phosphor-dim);
}
.gover.win .gover-title { color: var(--amber); text-shadow: 0 0 12px rgba(var(--glow), 0.5); }
.gover-score {
  font-family: var(--font-display); font-weight: 700; font-size: 46px; line-height: 1.05;
  color: var(--phosphor); margin: 6px 0 2px; text-shadow: 0 0 18px rgba(var(--glow), 0.4);
}
.gover-new {
  display: inline-block; vertical-align: middle; margin-left: 8px;
  font-family: var(--font-display); font-size: 9px; letter-spacing: 1.5px;
  color: var(--bg); background: var(--amber); padding: 3px 8px; border-radius: 999px;
  animation: goverPop 0.4s ease both;
}
@keyframes goverPop { 0% { transform: scale(0); } 70% { transform: scale(1.18); } 100% { transform: scale(1); } }
.gover-stats { display: flex; gap: 12px; justify-content: center; margin: 16px 0 18px; }
.gover-stat {
  min-width: 74px; border: 1px solid var(--line); border-radius: 9px; padding: 9px 12px;
  background: rgba(var(--glow), 0.05);
}
.gover-stat-v { display: block; font-family: var(--font-display); font-weight: 700; font-size: 19px; color: var(--amber); }
.gover-stat-k { display: block; margin-top: 3px; font-size: 8px; letter-spacing: 1.5px; color: var(--phosphor-dim); }
.gover-btns { display: flex; gap: 10px; }
.gover-btn {
  appearance: none; cursor: pointer; font-family: inherit; flex: 1;
  padding: 10px 12px; border-radius: 8px; font-size: 12px; letter-spacing: 2px;
  color: var(--bg); background: var(--phosphor); border: 1px solid var(--phosphor);
  box-shadow: 0 0 14px rgba(var(--glow), 0.4);
  transition: transform 0.1s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.gover-btn:hover { transform: translateY(-1px); box-shadow: 0 0 20px rgba(var(--glow), 0.6); }
.gover-btn.ghost { color: var(--phosphor-dim); background: transparent; border-color: var(--line); box-shadow: none; }
.gover-btn.ghost:hover { color: var(--phosphor); border-color: var(--phosphor-dim); box-shadow: none; }
.gover-hint { margin-top: 13px; font-size: 9px; letter-spacing: 1px; color: var(--phosphor-dim); }

/* leaderboard panel on the gate */
.lb-panel {
  margin-top: 26px; width: min(280px, 86vw);
  border: 1px solid var(--line); padding: 14px 16px;
  background: var(--bg-soft);
}
.lb-title {
  font-size: 10px; letter-spacing: 3px; color: var(--amber);
  text-align: center; margin-bottom: 10px;
}
.lb-empty { font-size: 11px; color: var(--phosphor-dim); text-align: center; letter-spacing: 1px; }
.lb-list { display: flex; flex-direction: column; gap: 5px; }
.lb-row {
  display: grid; grid-template-columns: 22px 1fr auto; align-items: center;
  font-size: 13px; color: var(--ink); letter-spacing: 1px;
}
.lb-row.lb-top { color: var(--phosphor); text-shadow: 0 0 8px rgba(var(--glow),0.5); }
.lb-rank { color: var(--phosphor-dim); }
.lb-name { font-family: var(--font-display); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-score { font-variant-numeric: tabular-nums; }

/* GLOBAL / LOCAL toggle on the gate leaderboard */
.lb-tabs { display: flex; gap: 6px; justify-content: center; margin-bottom: 12px; }
.lb-tab {
  appearance: none; cursor: pointer; font-family: inherit;
  background: transparent; color: var(--phosphor-dim);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 4px 12px; font-size: 10px; letter-spacing: 2px;
  transition: color .12s, border-color .12s, background .12s, transform .12s var(--ease-out);
}
.lb-tab:hover { color: var(--phosphor); border-color: var(--phosphor-dim); }
.lb-tab.active { color: var(--bg); background: var(--phosphor); border-color: var(--phosphor); }
/* your own row, so you can spot yourself in the global board */
.lb-row.lb-me, .lb-row.lb-me .lb-rank, .lb-row.lb-me .lb-name, .lb-row.lb-me .lb-score { color: var(--amber); }

/* leaderboards overlay: the game picker + the board mount */
.lb-games { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin: 4px 0 2px; }
.lb-game-btn {
  appearance: none; cursor: pointer; font-family: var(--font-display);
  background: transparent; color: var(--phosphor-dim);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 5px 9px; font-size: 9px; letter-spacing: 1px;
  transition: color .12s, border-color .12s, background .12s, transform .12s var(--ease-out);
}
.lb-game-btn:hover { color: var(--phosphor); border-color: var(--phosphor-dim); }
.lb-game-btn.active { color: var(--bg); background: var(--phosphor); border-color: var(--phosphor); }
.lb-mount { display: flex; justify-content: center; }

/* new-high-score initials overlay, shown over the game */
.hs-overlay {
  position: absolute; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: rgba(12, 7, 22, 0.85);
}
.hs-box {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  border: 1px solid var(--phosphor); padding: 28px 32px;
  background: var(--bg-soft); box-shadow: 0 0 24px rgba(var(--glow),0.35);
}
.hs-title {
  font-family: var(--font-display); font-size: 13px;
  color: var(--phosphor); letter-spacing: 1px; text-shadow: 0 0 8px rgba(var(--glow),0.6);
}
.hs-score { font-size: 30px; color: var(--amber); font-variant-numeric: tabular-nums; }
.hs-input {
  width: 190px; text-align: center; text-transform: uppercase;
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  font-family: var(--font-display); font-size: 15px; letter-spacing: 3px;
  padding: 10px 6px; outline: none;
}
.hs-input:focus { border-color: var(--phosphor); }

/* brief confirmation toast when a remembered name auto-saves a score */
.hs-toast {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  z-index: 60; background: var(--bg-soft); border: 1px solid var(--phosphor);
  color: var(--phosphor); font-family: var(--font-display);
  font-size: 9px; letter-spacing: 1px; padding: 8px 12px; white-space: nowrap;
  box-shadow: 0 0 14px rgba(var(--glow), 0.4);
  animation: toastfade 1.9s ease forwards;
}
@keyframes toastfade {
  0% { opacity: 0; transform: translate(-50%, -6px); }
  12% { opacity: 1; transform: translate(-50%, 0); }
  78% { opacity: 1; }
  100% { opacity: 0; }
}

/* arcade screen frame wrapping a game's canvas */
.screen-frame {
  position: relative;
  width: max-content;
  max-width: 96vw;
  padding: 14px;
  background: #0f0a06;
  border: 1px solid rgba(var(--glow),0.35);
  box-shadow:
    0 0 28px rgba(var(--glow),0.14),
    inset 0 0 40px rgba(0,0,0,0.6);
}
.screen-frame .corner {
  position: absolute; width: 16px; height: 16px;
  border: 2px solid var(--phosphor);
}
.screen-frame .tl { top: 4px; left: 4px; border-right: none; border-bottom: none; }
.screen-frame .tr { top: 4px; right: 4px; border-left: none; border-bottom: none; }
.screen-frame .bl { bottom: 4px; left: 4px; border-right: none; border-top: none; }
.screen-frame .br { bottom: 4px; right: 4px; border-left: none; border-top: none; }

/* loading flash shown while a game module is fetched */
.loading {
  color: var(--phosphor); font-family: var(--font-display);
  font-size: 14px; padding: 60px 0; text-align: center;
  animation: blink 0.6s steps(1) infinite;
}

/* Noodle loading screen — covers the WHOLE screen while a game warms up (see
   _loader.js), so nothing shows around the edges during the load */
.game-loader {
  position: fixed; inset: 0; z-index: 9500;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background: var(--bg);
  transition: opacity .32s ease;
}
.game-loader.gl-out { opacity: 0; }
.gl-cv { width: 168px; height: 168px; }
.gl-cap {
  font-family: var(--font-display); font-size: 17px; letter-spacing: 3px;
  color: var(--phosphor); text-shadow: 0 0 12px rgba(var(--glow), 0.6);
}
.gl-bar {
  width: 170px; max-width: 62vw; height: 6px; margin-top: 4px;
  border-radius: 6px; background: var(--line); overflow: hidden;
}
.gl-bar i {
  display: block; height: 100%; width: 0%; border-radius: 6px;
  background: var(--phosphor); box-shadow: 0 0 10px rgba(var(--glow), 0.7);
}

/* ===== JUICE: power-on, screen-change flash, game-enter ===== */

/* boot power-on flourish — pointer-events:none so it NEVER blocks clicks */
#boot {
  position: fixed; inset: 0; z-index: 10000; pointer-events: none;
  background: rgba(255, 255, 255, 0.03);
  animation: bootflick 0.5s ease forwards;
}
#boot::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: rgba(var(--glow), 0.85); box-shadow: 0 0 16px 2px rgba(var(--glow), 0.9);
  animation: bootsweep 0.5s ease forwards;
}
@keyframes bootsweep { 0% { top: 0; opacity: 1; } 100% { top: 100%; opacity: 0; } }
@keyframes bootflick {
  0% { opacity: 0; } 8% { opacity: 1; } 22% { opacity: .3; }
  34% { opacity: .9; } 50% { opacity: .2; } 100% { opacity: 0; }
}

/* quick flash when switching between menu and a game */
#crtfx {
  position: fixed; inset: 0; z-index: 9000; pointer-events: none;
  opacity: 0; background: rgba(var(--glow), 0.10);
}
#crtfx.flash { animation: crtflash 0.26s ease; }
@keyframes crtflash { 0% { opacity: 0; } 28% { opacity: 1; } 100% { opacity: 0; } }

/* theme-change glitch: quick RGB-split + horizontal jitter, snapping between
   frames (steps) so it reads as a signal tear, not a smooth fade */
#crtfx.glitch { animation: crtglitch 0.34s steps(1) forwards; }
@keyframes crtglitch {
  0%   { opacity: 0;  transform: translateX(0);    background: rgba(255,0,80,0.14); }
  15%  { opacity: 1;  transform: translateX(-6px); background: rgba(60,255,150,0.16); }
  30%  { opacity: .8; transform: translateX(5px);  background: rgba(255,0,80,0.12); }
  45%  { opacity: 1;  transform: translateX(-3px); background: rgba(60,255,150,0.12); }
  60%  { opacity: .6; transform: translateX(4px);  background: rgba(255,0,80,0.10); }
  78%  { opacity: .9; transform: translateX(-2px); background: rgba(60,255,150,0.08); }
  100% { opacity: 0;  transform: translateX(0);    background: transparent; }
}

/* CRT power-on when a game appears */
#game-view.enter-fx { animation: poweron 0.34s ease; transform-origin: center; }
@keyframes poweron {
  /* transform + opacity only (GPU-composited) — no filter repaint on game entry */
  0%   { transform: scaleY(0.42) scaleX(0.985); opacity: .25; }
  42%  { transform: scaleY(1.015); opacity: 1; }
  100% { transform: none; opacity: 1; }
}

/* ============ MOBILE / TOUCH ============ */

/* never let a touch on the play area scroll or zoom the page */
#game-mount canvas { touch-action: none; }

/* on-screen control pad (renders only on touch devices) */
.gamepad { display: none; }
@media (pointer: coarse) {
  .gamepad {
    display: flex; gap: 10px; justify-content: center; align-items: center;
    flex-wrap: wrap; margin-top: 14px; touch-action: none;
  }
}
.gp-btn {
  -webkit-appearance: none; appearance: none; touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent;
  min-width: 58px; height: 56px; padding: 0 4px; font-size: 22px; line-height: 1;
  background: var(--bg-soft); color: var(--phosphor);
  border: 1px solid var(--line); border-radius: 9px;
  font-family: monospace; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.gp-btn.gp-big { min-width: 92px; font-size: 13px; letter-spacing: 1px; }
.gp-btn.on { border-color: var(--phosphor); background: var(--phosphor-dim);
  box-shadow: 0 0 12px rgba(var(--glow), 0.55); }

/* phone layout: roomier cards, smaller chrome, no accidental zoom */
html { -webkit-text-size-adjust: 100%; }
@media (max-width: 640px) {
  #app { padding: 16px 12px 24px; }
  .hero { margin-bottom: 5vh; }
  .grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
  .card { padding: 14px; }
  .back { font-size: 12px; }
  .diff-bar { flex-wrap: wrap; justify-content: center; }
}
@media (max-width: 380px) {
  .grid { grid-template-columns: 1fr 1fr; }
}

/* fixed sound toggle (top-right, visible on portal and in games) */
.hud-btn {
  position: fixed; top: 14px; right: 14px; z-index: 120;
  width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background: var(--bg-soft); border: 1px solid var(--line); color: var(--phosphor);
  border-radius: 9px; transition: border-color .12s, box-shadow .12s, color .12s, transform .12s var(--ease-out);
}
.hud-btn:hover { border-color: var(--phosphor); box-shadow: 0 0 12px rgba(var(--glow), 0.45); }
.hud-btn .sl { display: none; }
.hud-btn.muted { color: var(--phosphor-dim); }
.hud-btn.muted .wv { display: none; }
.hud-btn.muted .sl { display: block; }
/* the options gear sits just left of the mute button; the trophy left of that */
.hud-btn-2 { right: 62px; }
.hud-btn-3 { right: 110px; }
.hud-btn-4 { right: 158px; }
.hud-btn-5 { right: 206px; }
@media (max-width: 640px) {
  .hud-btn { width: 36px; height: 36px; top: 10px; right: 10px; }
  .hud-btn-2 { right: 54px; }
  .hud-btn-3 { right: 98px; }
  .hud-btn-4 { right: 142px; }
  .hud-btn-5 { right: 186px; }
}

/* ============ ACHIEVEMENTS ============ */
/* unlock toast — top-center, works on the portal or over a game */
.ach-toast {
  position: fixed; top: 16px; left: 50%; z-index: 10050;
  display: flex; align-items: center; gap: 11px;
  background: var(--bg-soft); border: 1px solid var(--phosphor); border-radius: 11px;
  padding: 10px 15px 10px 12px;
  box-shadow: 0 10px 34px rgba(0,0,0,0.5), 0 0 24px rgba(var(--glow), 0.4);
  opacity: 0; transform: translate(-50%, -14px); transition: opacity .3s ease, transform .3s cubic-bezier(.2,1.1,.4,1);
  pointer-events: none;
}
.ach-toast.show { opacity: 1; transform: translate(-50%, 0); }
.ach-toast-ico { font-size: 24px; line-height: 1; }
.ach-toast-txt { display: flex; flex-direction: column; gap: 2px; }
.ach-toast-kick { font-size: 8px; letter-spacing: 2.5px; color: var(--amber); }
.ach-toast-name {
  font-family: var(--font-display); font-size: 13px; letter-spacing: 1px;
  color: var(--phosphor); text-shadow: 0 0 9px rgba(var(--glow), 0.6);
}

/* board (inside the shared .opt-overlay / .opt-panel) */
.ach-prog {
  text-align: center; font-size: 10px; letter-spacing: 3px; color: var(--amber);
  margin: -6px 0 18px;
}
.ach-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.ach-tile {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 5px;
  padding: 14px 8px; border: 1px solid var(--line); border-radius: 10px;
  background: rgba(var(--glow), 0.04);
  opacity: 0.45; filter: grayscale(1);
  transition: opacity .15s, filter .15s, border-color .15s, box-shadow .15s;
}
.ach-tile.got {
  opacity: 1; filter: none; border-color: rgba(var(--glow), 0.55);
  box-shadow: inset 0 0 18px rgba(var(--glow), 0.1);
}
.ach-ico { font-size: 26px; line-height: 1; }
.ach-name {
  font-family: var(--font-display); font-size: 11px; letter-spacing: 0.5px; color: var(--phosphor);
}
.ach-tile.got .ach-name { text-shadow: 0 0 8px rgba(var(--glow), 0.5); }
.ach-desc { font-size: 9.5px; line-height: 1.3; color: var(--phosphor-dim); }
@media (max-width: 380px) {
  .ach-desc { font-size: 9px; }
}

/* ============ OPTIONS OVERLAY ============ */
.opt-overlay {
  position: fixed; inset: 0; z-index: 10060;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(0, 0, 0, 0.72);
  opacity: 0; transition: opacity .2s ease;
}
.opt-overlay[hidden] { display: none; }
.opt-overlay.show { opacity: 1; }
.opt-panel {
  position: relative; width: min(420px, 94vw); max-height: 88vh; overflow-y: auto;
  background: var(--bg-soft); border: 1px solid var(--phosphor); border-radius: 14px;
  padding: 26px 24px 28px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.55), 0 0 34px rgba(var(--glow), 0.28);
  transform: translateY(10px) scale(.98);
  transition: transform .2s cubic-bezier(.2,1.1,.4,1);
}
.opt-overlay.show .opt-panel { transform: none; }
.opt-title {
  font-family: var(--font-display); font-size: 15px; color: var(--phosphor);
  letter-spacing: 2px; text-align: center;
  padding-bottom: 16px; margin-bottom: 20px; border-bottom: 1px solid var(--line);
  text-shadow: 0 0 10px rgba(var(--glow), 0.6);
}
.opt-close {
  position: absolute; top: 12px; right: 12px; width: 30px; height: 30px;
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background: transparent; color: var(--phosphor-dim);
  border: 1px solid var(--line); border-radius: 8px; font-size: 14px; line-height: 1;
  transition: color .12s, border-color .12s, transform .12s;
}
.opt-close:hover { color: var(--phosphor); border-color: var(--phosphor); transform: rotate(90deg); }
.opt-sec { margin-bottom: 22px; }
.opt-sec:last-child { margin-bottom: 0; }
.opt-sec + .opt-sec { border-top: 1px solid var(--line); padding-top: 22px; }  /* divider */
/* section header: label on the left, live value/name on the right */
.opt-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 16px; }
.opt-label { font-size: 10px; letter-spacing: 3px; color: var(--amber); }
.opt-value {
  font-family: var(--font-display); font-size: 12px; letter-spacing: 1px;
  color: var(--phosphor); text-shadow: 0 0 8px rgba(var(--glow), 0.5);
  font-variant-numeric: tabular-nums;
}
.opt-grp { font-size: 9px; letter-spacing: 2px; color: var(--phosphor-dim); margin: 12px 0 9px; }

/* ---- SHOP (its own overlay) ---- */
.shop-coins {
  text-align: center; font-family: var(--font-display); font-size: 18px; letter-spacing: 2px;
  color: var(--amber); text-shadow: 0 0 12px rgba(var(--glow), 0.5); margin: -6px 0 20px;
}
.shop-grid { display: flex; flex-direction: column; gap: 8px; }
.shop-ico { font-size: 20px; width: 24px; text-align: center; flex: none; }
.shop-item.equipped { border-color: rgba(var(--glow), 0.55); box-shadow: inset 0 0 14px rgba(var(--glow), 0.1); }
.shop-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 9px;
  background: rgba(var(--glow), 0.04);
}
.shop-item.owned { opacity: 0.66; }
.shop-sw {
  width: 22px; height: 22px; border-radius: 6px; flex: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}
.shop-name { flex: 1; font-family: var(--font-display); font-size: 12px; letter-spacing: 1px; color: var(--phosphor); }
.shop-own { font-size: 9px; letter-spacing: 2px; color: var(--phosphor-dim); }
.shop-buy {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  font-family: var(--font-display); font-size: 11px; letter-spacing: 0.5px;
  color: var(--bg); background: var(--amber); border: none; border-radius: 7px;
  padding: 6px 11px; transition: filter .12s, opacity .12s, transform .12s var(--ease-out);
}
.shop-buy:hover:not(:disabled) { filter: brightness(1.12); }
.shop-buy:disabled { opacity: 0.4; cursor: not-allowed; background: var(--phosphor-dim); }
/* EQUIP buttons are outlined; the EQUIPPED (disabled) one reads as active, not faded */
.shop-buy.equip { background: transparent; color: var(--phosphor); border: 1px solid var(--phosphor); }
.shop-buy.equip:hover:not(:disabled) { filter: none; background: rgba(var(--glow), 0.12); }
.shop-buy.equip:disabled { opacity: 1; background: transparent; color: var(--amber); border-color: var(--amber); }

/* coin-earned toast — rises from the bottom-center after a run */
.coin-toast {
  position: fixed; bottom: 26px; left: 50%; z-index: 10040;
  font-family: var(--font-display); font-size: 15px; letter-spacing: 1px;
  color: var(--amber); text-shadow: 0 0 12px rgba(var(--glow), 0.5);
  opacity: 0; transform: translate(-50%, 16px);
  transition: opacity .3s ease, transform .5s cubic-bezier(.2, 1, .4, 1);
  pointer-events: none;
}
.coin-toast.show { opacity: 1; transform: translate(-50%, 0); }
.opt-dots { display: flex; gap: 13px; flex-wrap: wrap; justify-content: center; }
.opt-row { display: flex; align-items: center; gap: 12px; }
.opt-min, .opt-max { font-size: 9px; letter-spacing: 1px; color: var(--phosphor-dim); }
.opt-range {
  flex: 1; -webkit-appearance: none; appearance: none; height: 6px; margin: 0;
  background: var(--line); border-radius: 6px; outline: none; cursor: pointer;
}
.opt-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%;
  background: var(--phosphor); border: 3px solid var(--bg-soft); margin-top: -6px;
  box-shadow: 0 0 10px rgba(var(--glow), 0.8); cursor: pointer;
}
.opt-range::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--phosphor); border: 3px solid var(--bg-soft);
  box-shadow: 0 0 10px rgba(var(--glow), 0.8); cursor: pointer;
}
.opt-hint {
  margin-top: 14px; font-size: 11px; letter-spacing: .5px;
  color: var(--phosphor-dim); opacity: .85; text-align: center; line-height: 1.5;
}
/* pill on/off toggle (music, etc.) */
.opt-toggle {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  font-family: var(--font-display); font-size: 11px; letter-spacing: 1px;
  padding: 5px 18px; border-radius: 999px;
  background: var(--bg); color: var(--phosphor-dim); border: 1px solid var(--line);
  transition: color .14s, background .14s, border-color .14s, box-shadow .14s, transform .12s var(--ease-out);
}
.opt-toggle:hover { color: var(--phosphor); border-color: var(--phosphor-dim); }
.opt-toggle.on {
  background: var(--phosphor); color: var(--bg); border-color: var(--phosphor);
  box-shadow: 0 0 12px rgba(var(--glow), 0.55);
}

/* ============ PIXELATED CURSOR (fine pointers only) ============ */
/* The real OS cursor becomes a themed pixel-art arrow. The SVG (with the
   theme's colors) is generated in main.js and handed in via --cursor-img, so it
   recolors with the theme. Games that set cursor:none inline still win. */
@media (pointer: fine) {
  html.pixel-cursor, html.pixel-cursor * { cursor: var(--cursor-img), auto; }
}

/* ============ POLISH ============ */

/* breathing glow on the logo */
.logo { animation: logopulse 3.6s ease-in-out infinite; }
@keyframes logopulse {
  0%, 100% { text-shadow: 0 0 4px var(--phosphor), 0 0 13px rgba(var(--glow), 0.32); }
  50%      { text-shadow: 0 0 7px var(--phosphor), 0 0 21px rgba(var(--glow), 0.55); }
}

/* soft CRT vignette for depth (never blocks input) */
body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 60;
  background: radial-gradient(ellipse at 50% 42%, transparent 56%, rgba(0,0,0,var(--vignette)) 100%);
}

/* (card + screen hover polish is handled in the card block above) */

/* difficulty buttons feel more tactile */
.diff-btn { transition: transform .1s ease, box-shadow .12s ease, border-color .12s ease, background .12s ease; }
.diff-btn:not(.active):hover { transform: translateY(-1px); border-color: var(--phosphor); }

/* ============ PRESS FEEDBACK ============ */
/* Every pressable control dips the instant you press it — the single biggest
   thing that makes an interface feel like it's listening (Emil/Apple: respond on
   pointer-DOWN, not on release). transform-only, GPU-composited, zero load cost.
   Each :active carries its own quick curve so the press-in is snappy; the base
   rule's transform transition eases the release. */
.diff-btn:not(:disabled):active, .gover-btn:active, .back:active, .hud-btn:active,
.lb-tab:active, .lb-game-btn:active, .theme-dot:active, .opt-toggle:active,
.opt-close:active, .shop-buy:not(:disabled):active, .notify-toggle:active,
.gate-btn:active {
  transform: scale(0.96);
  transition: transform .1s var(--ease-out);
}
/* elements that lift on hover press down FROM the lifted spot, not from rest */
.card:not(.soon):active { transform: translateY(-3px) scale(0.985); transition: transform .1s var(--ease-out); }
.daily-play:active { transform: translateY(-1px) scale(0.96); transition: transform .1s var(--ease-out); }
.nc-copy:active { transform: translateY(0) scale(0.97); }
/* touch devices fire :hover on tap and leave it stuck — keep the decorative card
   lift/sweep/spotlight for real (fine) pointers only; press feedback still works
   on touch because it's driven by :active, not :hover. */
@media (hover: none) {
  .card:not(.soon):hover { transform: none; border-color: var(--line);
    box-shadow: inset 0 0 22px rgba(0,0,0,0.45); }
  .card:not(.soon):hover::before { opacity: 0; animation: none; }
  .card:not(.soon):hover::after { opacity: 0; }
}

/* ============ KEYBOARD FOCUS ============ */
/* Every interactive control gets a visible, on-brand focus ring for keyboard
   users — the site had none (two rules even set outline:none). :focus-visible so
   it never shows on mouse press; `outline` (not box-shadow) so the cards'
   overflow:hidden can't clip it. :where() keeps specificity at 0 so it never
   fights a control's own styles. */
:where(.card, .diff-btn, .gate-btn, .back, .hud-btn, .lb-tab, .lb-game-btn,
  .theme-dot, .opt-toggle, .opt-close, .shop-buy, .daily-play, .gover-btn,
  .notify-toggle, .nc-copy, .coffee, .xlink, .foot-link, .gp-btn):focus-visible {
  outline: 2px solid var(--phosphor);
  outline-offset: 2px;
}

/* gate title glow */
.gate-title { text-shadow: 0 0 10px rgba(var(--glow), 0.5); }

/* the screen-frame gets a gentle outer glow */
.screen-frame { box-shadow: 0 0 30px rgba(var(--glow), 0.10), inset 0 0 30px rgba(0,0,0,0.4); }

/* ============ TASK-DONE TOAST (corner, non-blocking) ============ */
/* A side toast instead of a center modal: it slides in at the top-right (just
   below the mute button) and never blocks gameplay — the container is
   pointer-events:none, only the toast box itself is interactive. */
/* A centered card that unmistakably grabs you the moment your task finishes:
   a dim backdrop, a check badge that pops with an expanding ring, a confetti
   burst in the theme's colors, and a draining timer. Dismissible + auto-closes. */
.task-done {
  position: fixed; inset: 0; z-index: 10050;
  display: grid; place-items: center;
  opacity: 0; pointer-events: none;
  transition: opacity .24s ease;
}
.task-done.show { opacity: 1; pointer-events: auto; }
.td-backdrop {
  position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 42%, rgba(var(--glow), 0.16), rgba(0,0,0,0.64) 70%);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.td-card {
  position: relative; z-index: 1; text-align: center;
  width: min(340px, calc(100vw - 40px));
  padding: 30px 26px 26px;
  background: var(--bg-soft);
  border: 1px solid var(--phosphor); border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.55), 0 0 30px rgba(var(--glow), 0.4);
  transform: translateY(10px) scale(.9); opacity: 0;
}
.task-done.show .td-card { animation: tdPop .4s cubic-bezier(.22,1,.36,1) forwards; }
@keyframes tdPop { to { transform: none; opacity: 1; } }

/* check badge with an expanding ring */
.td-badge {
  position: relative; width: 56px; height: 56px; margin: 0 auto 14px;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--phosphor); color: var(--bg);
  box-shadow: 0 0 22px rgba(var(--glow), 0.7);
  animation: tdBadge .5s ease .12s both;
}
.td-badge svg { width: 30px; height: 30px; }
@keyframes tdBadge { 0% { transform: scale(0); } 60% { transform: scale(1.15); } 100% { transform: scale(1); } }
.td-badge::after {
  content: ""; position: absolute; inset: -6px; border-radius: 50%;
  border: 2px solid var(--phosphor); opacity: 0;
  animation: tdRing .8s ease .3s;
}
@keyframes tdRing { 0% { transform: scale(.7); opacity: .85; } 100% { transform: scale(1.65); opacity: 0; } }

.td-title {
  font-family: var(--font-display); font-size: 19px; letter-spacing: 2px;
  color: var(--phosphor); text-shadow: 0 0 14px rgba(var(--glow), 0.8);
  margin-bottom: 8px;
}
.td-msg { color: var(--ink); font-size: 13px; line-height: 1.5; letter-spacing: .3px; margin-bottom: 18px; word-break: break-word; opacity: .92; }
.task-done .td-btn { font-size: 10px; padding: 9px 22px; }

/* draining auto-dismiss bar along the bottom of the card */
.td-timer {
  position: absolute; left: 16px; right: 16px; bottom: 10px; height: 2px;
  border-radius: 2px; background: var(--phosphor); transform-origin: left;
  box-shadow: 0 0 8px rgba(var(--glow), 0.7);
  animation: tdTimer 6s linear forwards;
}
@keyframes tdTimer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* confetti burst — particles fan out from just under the badge */
.td-confetti { position: absolute; left: 50%; top: 46px; width: 0; height: 0; pointer-events: none; }
.td-bit {
  position: absolute; left: 0; top: 0; width: 7px; height: 7px; border-radius: 1px;
  opacity: 0; transform: translate(-50%, -50%);
  animation: tdBit .9s ease-out var(--d) forwards;
}
.td-bit.c0 { background: var(--phosphor); }
.td-bit.c1 { background: var(--amber); }
.td-bit.c2 { background: var(--magenta); }
.td-bit.c3 { background: var(--ink); }
@keyframes tdBit {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.4) rotate(0deg); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1) rotate(var(--rot)); }
}

/* Non-blocking corner toast — used when a game is open (class added in taskDone)
   so a finished task never covers the play area or steals input. There's no
   backdrop and the container ignores pointer events; only the card is interactive,
   so every click/tap outside it goes straight to the game. */
.task-done.toast { display: block; place-items: initial; pointer-events: none; }
.task-done.toast.show { pointer-events: none; }
.task-done.toast .td-backdrop { display: none; }
.task-done.toast .td-card {
  position: fixed; top: 64px; right: 14px; left: auto;
  width: min(280px, calc(100vw - 28px)); padding: 18px 20px 16px;
  pointer-events: auto; transform: translateX(26px); opacity: 0;
}
.task-done.toast.show .td-card { animation: tdToast .34s cubic-bezier(.22,1,.36,1) forwards; }
@keyframes tdToast { to { transform: none; opacity: 1; } }
.task-done.toast .td-badge { width: 40px; height: 40px; margin-bottom: 10px; }
.task-done.toast .td-badge svg { width: 22px; height: 22px; }
.task-done.toast .td-title { font-size: 15px; letter-spacing: 1.5px; }
.task-done.toast .td-msg { font-size: 12px; margin-bottom: 12px; }

@media (max-width: 640px) {
  .td-card { width: calc(100vw - 32px); padding: 26px 20px 24px; }
  .task-done.toast .td-card { top: 54px; right: 10px; left: 10px; width: auto; }
}

/* ============ MASCOT — the arcade gremlin ============ */
/* He walks across the bottom of the screen: JS drives his horizontal `left`,
   the canvas plays the walk cycle. The wrapper ignores pointer events so it
   never blocks the UI; only the little guy is clickable. */
.mascot {
  position: fixed; bottom: 12px; left: 0; width: 76px; z-index: 9400;
  pointer-events: none; opacity: 0; transition: opacity .3s;
}
.mascot.show { opacity: 1; }
.mascot-cv {
  display: block; width: 100%; height: auto; pointer-events: auto; cursor: pointer;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.45));
}
/* speech bubble floats above him — its `left` is set in JS and clamped so it
   never runs off the edge of the screen */
.mascot-bubble {
  position: absolute; left: 0; bottom: calc(100% + 4px);
  max-width: min(210px, calc(100vw - 20px)); width: max-content;
  background: var(--bg-soft); color: var(--ink);
  border: 1px solid var(--phosphor); border-radius: 12px;
  padding: 8px 13px; text-align: center; letter-spacing: .3px;
  font-family: var(--font-accent); font-size: 12.5px; line-height: 1.35;
  box-shadow: 0 6px 20px rgba(0,0,0,0.4), 0 0 16px rgba(var(--glow), 0.25);
  opacity: 0; transform: translateY(6px) scale(.96);
  transition: opacity .25s, transform .25s;
}
.mascot-bubble.show { opacity: 1; transform: none; }
.mascot-bubble::after {   /* comic tail, centered under the bubble */
  content: ""; position: absolute; left: 50%; bottom: -7px;
  width: 12px; height: 12px; background: var(--bg-soft);
  border-right: 1px solid var(--phosphor); border-bottom: 1px solid var(--phosphor);
  transform: translateX(-50%) rotate(45deg);
}
@media (max-width: 520px) {
  .mascot { width: 60px; bottom: 8px; }
  .mascot-bubble { font-size: 11.5px; max-width: 160px; padding: 7px 11px; }
}

/* ============ NOTIFY — collapsible pill ============ */
/* Tucked above the footer: a quiet one-line toggle you'll spot when you want it
   but that never competes with the games. Click to reveal the command. */
.notify { max-width: 520px; margin: 0 auto clamp(20px, 3.5vh, 40px); text-align: center; }
/* A filled, softly-glowing pill so it reads as a real feature (not footer text):
   an amber bell, the label, and a green "listening" dot. */
.notify-toggle {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
  list-style: none; user-select: none;
  font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase; font-weight: 700;
  color: var(--phosphor);
  padding: 10px 18px;
  background: var(--bg-soft);
  border: 1px solid var(--phosphor-dim); border-radius: 999px;
  box-shadow: 0 4px 18px rgba(0,0,0,0.35), 0 0 16px rgba(var(--glow), 0.14);
  transition: color .16s, border-color .16s, box-shadow .16s, transform .16s;
}
.notify-toggle::-webkit-details-marker { display: none; }   /* hide default ▸ */
.nc-bell { color: var(--amber); filter: drop-shadow(0 0 4px rgba(var(--glow), 0.5)); flex: none; }
.nc-label { white-space: nowrap; }
/* green "armed & listening" dot that gently pulses + a chevron that flips open */
.nc-led {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: #35d07f; box-shadow: 0 0 8px #35d07f;
  animation: ncPulse 1.9s ease-in-out infinite;
}
@keyframes ncPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.75); } }
.notify-toggle::after {
  content: "\25BE"; margin-left: 1px; font-size: 10px;
  transition: transform .18s ease; opacity: .7;
}
.notify-toggle:hover {
  border-color: var(--phosphor);
  box-shadow: 0 6px 22px rgba(0,0,0,0.42), 0 0 24px rgba(var(--glow), 0.3);
  transform: translateY(-1px);
}
.notify[open] .notify-toggle {
  border-color: var(--phosphor);
  box-shadow: 0 6px 22px rgba(0,0,0,0.42), 0 0 20px rgba(var(--glow), 0.26);
}
.notify[open] .notify-toggle::after { transform: rotate(180deg); }
@media (max-width: 460px) {
  .notify-toggle { font-size: 10px; letter-spacing: 1px; padding: 9px 14px; gap: 8px; }
}

/* the revealed panel — a clean command card (no fake terminal chrome) */
.notify-body {
  position: relative; text-align: left;
  margin: 12px auto 0; max-width: 560px; padding: 16px 16px 14px;
  background: var(--bg-soft);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 12px 30px rgba(0,0,0,0.4);
  animation: ncReveal .2s ease;
}
@keyframes ncReveal { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.nc-sub { color: var(--ink); font-size: 12px; line-height: 1.5; letter-spacing: .2px; margin-bottom: 11px; opacity: .8; }
/* a short natural-language prompt the player pastes to their AI; copy icon docks
   in the top-right corner. The embedded curl line wraps rather than scrolls. */
.nc-row { position: relative; }
.nc-prompt {
  display: block; width: 100%; margin: 0;
  max-height: 190px; overflow-y: auto;
  font-family: "Courier New", ui-monospace, monospace; font-size: 12px; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 46px 12px 14px; line-height: 1.6;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.nc-prompt::-webkit-scrollbar { width: 6px; }
.nc-prompt::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; }
.nc-copy {
  position: absolute; top: 6px; right: 6px; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background: var(--bg-soft); color: var(--phosphor-dim);
  border: 1px solid var(--line); border-radius: 6px;
  transition: color .12s, background .12s, border-color .12s;
}
.nc-copy:hover { color: var(--phosphor); border-color: var(--phosphor-dim); background: rgba(var(--glow), 0.08); }
.nc-copy svg { width: 15px; height: 15px; display: block; }
.nc-copy .ic-check { display: none; }
.nc-copy.copied { color: #35d07f; border-color: #35d07f; }
.nc-copy.copied .ic-copy { display: none; }
.nc-copy.copied .ic-check { display: block; }
.nc-note { margin-top: 11px; font-size: 11px; letter-spacing: .2px; color: var(--phosphor-dim); }

/* ============ LIVE "PEOPLE ONLINE" COUNTER (top-left) ============ */
/* A playful presence pill: a live green dot + a count that re-rolls every 2 min
   (11–25) with a rotating label. Portal-only; hidden while a game is open. */
.live-counter {
  position: fixed; top: 14px; left: 14px; z-index: 120;
  display: flex; align-items: center; gap: 8px;
  padding: 7px 13px 7px 11px;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  font-family: var(--font-display); user-select: none; cursor: default;
  transition: opacity .3s ease, transform .3s var(--ease-out);
}
.live-counter.hide { opacity: 0; transform: translateY(-10px); pointer-events: none; }
.lc-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: #35d07f; box-shadow: 0 0 8px #35d07f;
  animation: lcPulse 2s ease-in-out infinite;
}
@keyframes lcPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.65); } }
.lc-num {
  font-size: 14px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; text-shadow: 0 0 8px rgba(var(--glow), 0.5);
  transition: transform .22s var(--ease-spring);
}
.live-counter.bump .lc-num { transform: scale(1.32); }
.lc-label { font-size: 10px; letter-spacing: 1px; color: var(--phosphor-dim); }
@media (max-width: 640px) {
  .live-counter { top: 10px; left: 10px; padding: 6px 11px 6px 9px; }
  .lc-label { display: none; }   /* keep it tiny on phones: just dot + number */
}
@media (prefers-reduced-motion: reduce) { .lc-dot { animation: none; } }

/* ============ GATE LEADERBOARD (floating, middle-left, hideable) ============ */
.gate-lb {
  position: fixed; left: 14px; top: 50%; z-index: 40;
  width: min(240px, 44vw); transform: translateY(-50%);
  transition: transform .32s var(--ease-out), opacity .28s ease;
}
.gate-lb.hidden { transform: translateY(-50%) translateX(calc(-100% - 24px)); opacity: 0; pointer-events: none; }
.gate-lb .lb-panel {
  margin-top: 0; width: 100%;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5), 0 0 22px rgba(var(--glow), 0.16);
}
.gate-lb-x {
  position: absolute; top: 8px; right: 10px; z-index: 2;
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background: transparent; color: var(--phosphor-dim); border: none;
  font-family: var(--font-display); font-size: 9px; letter-spacing: 1px;
  padding: 4px 4px; transition: color .12s;
}
.gate-lb-x:hover { color: var(--phosphor); }
/* the reveal tab, shown only when the board is hidden */
.gate-lb-tab {
  position: fixed; left: 0; top: 50%; z-index: 40;
  transform: translateY(-50%) translateX(-100%);
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background: var(--bg-soft); color: var(--phosphor);
  border: 1px solid var(--phosphor-dim); border-left: none;
  border-radius: 0 10px 10px 0; padding: 12px 9px; font-size: 15px; line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
  opacity: 0; pointer-events: none;
  transition: transform .32s var(--ease-spring), opacity .28s ease, box-shadow .12s;
}
.gate-lb-tab.show { transform: translateY(-50%) translateX(0); opacity: 1; pointer-events: auto; }
.gate-lb-tab:hover { box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4), 0 0 16px rgba(var(--glow), 0.4); }
@media (max-width: 640px) { .gate-lb { width: min(210px, 62vw); } }
