:root{
  --abyss:#0A2438;
  --abyss-mid:#1B5478;
  --panel:rgba(10,26,44,.74);
  --panel-edge:rgba(255,255,255,.12);
  --cyan:#4DF2FF;
  --cyan-dim:rgba(77,242,255,.35);
  --food:#CFEFFF;
  --danger:#FF3B3B;
  --danger-dim:rgba(255,59,59,.4);
  --text:#EDFAFF;
  --text-dim:#8FB0C2;
}
*{ box-sizing:border-box; }
html,body{ height:100%; margin:0; overflow:hidden; }
body{
  background:var(--abyss);
  color:var(--text);
  font-family:'Manrope',sans-serif;
}
#c{ position:fixed; inset:0; display:block; cursor:none; touch-action:none; }
.touch-ripple{
  position:fixed; left:0; top:0;
  width:56px; height:56px; margin:-28px 0 0 -28px;
  border-radius:50%;
  border:2px solid rgba(255,255,255,.9);
  background:rgba(255,255,255,.15);
  pointer-events:none;
  opacity:0;
  z-index:50;
}
.touch-ripple.active{ animation: touch-pulse .38s ease-out; }
@keyframes touch-pulse{
  0%{ opacity:.85; transform:scale(.4); }
  100%{ opacity:0; transform:scale(1); }
}
.vignette{
  position:fixed; inset:0; pointer-events:none;
  background:radial-gradient(ellipse 78% 78% at 50% 50%, transparent 50%, rgba(0,3,8,.7) 100%);
  animation: vignette-breathe 8s ease-in-out infinite;
}
/* A slow, barely-there pulse — reads as ambient current/pressure rather
   than an obvious effect. */
@keyframes vignette-breathe{
  0%,100%{ opacity:.82; }
  50%{ opacity:1; }
}

.hud-top{
  position:fixed; top:0; left:0; right:0;
  display:flex; justify-content:space-between; align-items:flex-start;
  padding:18px 20px;
  pointer-events:none;
}
.brand-row{
  display:flex;
  align-items:center;
  gap:10px;
  pointer-events:auto;
}
.brand{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:1rem;
  letter-spacing:.03em;
  color:var(--cyan);
  text-shadow:0 0 20px var(--cyan-dim);
}
.mute-btn{
  width:30px; height:30px;
  border-radius:8px;
  border:1px solid var(--panel-edge);
  background:var(--panel);
  color:var(--text-dim);
  font-size:.85rem;
  line-height:1;
  cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  backdrop-filter:blur(6px);
}
.mute-btn:focus-visible{ outline:2px solid var(--cyan); outline-offset:2px; }
.leaderboard{
  background:var(--panel);
  border:1px solid var(--panel-edge);
  border-radius:12px;
  padding:10px 14px;
  min-width:172px;
  backdrop-filter:blur(6px);
}
.leaderboard h3{
  margin:0 0 6px;
  font-size:.6rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--text-dim);
  font-weight:700;
}
.lb-row{
  display:flex; justify-content:space-between; gap:10px;
  font-family:'JetBrains Mono',monospace;
  font-size:.74rem;
  padding:2px 0;
  color:var(--text-dim);
}
.lb-row.me{ color:var(--cyan); font-weight:600; }
.lb-row .n{ font-variant-numeric:tabular-nums; }

.hud-bottom{
  position:fixed; bottom:0; left:0; right:0;
  display:flex; justify-content:center; align-items:center; gap:16px;
  padding:18px;
}
.readout{
  background:var(--panel);
  border:1px solid var(--panel-edge);
  border-radius:10px;
  padding:8px 16px;
  text-align:center;
  backdrop-filter:blur(6px);
  pointer-events:none;
}
.readout .rl{ font-size:.58rem; letter-spacing:.13em; text-transform:uppercase; color:var(--text-dim); margin-bottom:2px; }
.readout .rv{ font-family:'JetBrains Mono',monospace; font-weight:600; font-size:1.02rem; font-variant-numeric:tabular-nums; }
.readout.len .rv{ color:var(--cyan); }

.overlay{
  position:fixed; inset:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:14px;
  background:rgba(2,5,10,.88);
  backdrop-filter:blur(3px);
  text-align:center;
  padding:24px;
}
.overlay.hidden{ display:none; }

/* The death screen specifically: lighter and vignette-shaped rather than a
   flat scrim, so the reef (bots still swimming, via the JS spectator loop)
   stays visible behind it — darkest where the text/panel sit, most open
   at the edges. The start screen keeps the plain opaque .overlay look.
   No backdrop-filter here (unlike .overlay's own blur(3px), which this
   still overrides away): a real on-device trace showed this exact panel
   as the single biggest cost in the last few seconds of a match. It's a
   FULL-VIEWPORT layer, and unlike the small blurred UI chrome elsewhere
   (mute button, HUD readouts — those stay, they're cheap), this one sits
   on top of a background the spectator loop keeps redrawing every frame
   for as long as the death screen is up, so the browser was re-blurring
   the whole screen continuously, every frame, for however long the player
   lingers on the end screen. The gradient tint alone still reads as "the
   reef, dimmed" without asking the GPU to do that.  */
#endOverlay{
  background: radial-gradient(ellipse 68% 62% at 50% 46%, rgba(3,8,16,.82) 0%, rgba(3,8,16,.55) 55%, rgba(3,8,16,.32) 100%);
  backdrop-filter: none;
}

/* Win screen gets the same lighter vignette as the death screen, for the
   same reason -- it's a FULL-VIEWPORT layer sitting over a scene the
   spectator loop keeps redrawing every frame, so no continuous
   backdrop-filter here either. Direct ask: the win screen was reading as
   flat/"game over"-ish because it was inheriting the plain .overlay rule
   (88%-opaque + blur), which blacks out the confetti/shockwave burst
   winGame() spawns almost immediately after it appears -- the dots are
   there, just hidden behind an opaque wall. A warmer gold-leaning tint
   instead of the death screen's cool dark, so the two don't read as the
   same moment.
*/
#winOverlay{
  background: radial-gradient(ellipse 68% 62% at 50% 46%, rgba(10,7,2,.78) 0%, rgba(10,7,2,.5) 55%, rgba(10,7,2,.28) 100%);
  backdrop-filter: none;
}

/* Screen-space confetti rain for the win panel. The canvas confetti in
   game.js (spawnConfetti) lives in WORLD coordinates and gets scaled down
   by the camera zoom same as everything else -- direct feedback after
   seeing it was "doesn't look like confetti celebration, looks like game
   ended" even after fixing the overlay-opacity bug that was hiding it.
   This is a second, independent layer that falls over the win PANEL
   itself in plain viewport pixels, immune to camera/zoom, which is what
   actually guarantees it reads as a celebration regardless of how
   zoomed-out the match camera happened to be. `position:absolute` inside
   `.overlay`'s own `position:fixed` pulls it out of the flex column
   layout so it doesn't push the h2/p/stats around.
*/
.confetti-rain{
  position:absolute; inset:0;
  overflow:hidden;
  pointer-events:none;
}
.confetti-piece{
  position:absolute;
  top:-14px;
  width:9px; height:15px;
  opacity:0;
  animation-name: confettiFall;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes confettiFall{
  0%   { opacity:1; transform:translateY(0) rotate(0deg); }
  92%  { opacity:1; }
  100% { opacity:0; transform:translateY(112vh) rotate(560deg); }
}
.overlay h1{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:1.9rem;
  letter-spacing:.01em;
  color:var(--cyan);
  text-shadow:0 0 28px var(--cyan-dim);
  margin:0;
  text-wrap:balance;
}
.overlay h2{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:1.25rem;
  color:var(--danger);
  margin:0;
  letter-spacing:.01em;
}
.overlay p{
  max-width:440px;
  color:var(--text-dim);
  font-size:.92rem;
  line-height:1.55;
  margin:0;
}
.tagline{
  max-width:440px;
  color:var(--text);
  font-size:1rem;
  font-weight:600;
  line-height:1.4;
  margin:0;
}
.feature-list{
  list-style:none;
  margin:2px 0 0;
  padding:0;
  display:flex;
  flex-direction:column;
  gap:5px;
  align-items:flex-start;
}
.feature-list li{
  display:flex;
  align-items:center;
  gap:9px;
  color:var(--text-dim);
  font-size:.85rem;
}
.feature-list .fi{
  font-size:1rem;
  line-height:1;
  width:1.2em;
  text-align:center;
}
.start-subtext{
  font-size:.68rem;
  color:var(--text-dim);
  margin-top:-6px;
}
.end-stats{ display:flex; gap:26px; margin:6px 0; }
.end-stat b{
  display:block;
  font-family:'JetBrains Mono',monospace;
  font-size:1.4rem;
  color:var(--text);
}
.end-stat span{ font-size:.58rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-dim); }
.new-best{ color:var(--cyan); font-size:.7rem; letter-spacing:.1em; text-transform:uppercase; visibility:hidden; }
.death-tip{
  display:none;
  max-width:320px;
  background:rgba(77,242,255,.08);
  border:1px solid var(--cyan-dim);
  border-radius:10px;
  padding:10px 16px;
}
.death-tip-main{
  font-size:.88rem;
  font-weight:700;
  line-height:1.35;
  color:var(--cyan);
}
.death-tip-bonus{
  display:none;
  margin-top:5px;
  font-size:.68rem;
  line-height:1.4;
  color:var(--text-dim);
}
.primary-btn{
  font-family:'Unbounded',sans-serif;
  font-weight:700;
  letter-spacing:.02em;
  font-size:.95rem;
  padding:13px 34px;
  border-radius:10px;
  border:1px solid var(--cyan);
  background:linear-gradient(180deg, rgba(77,242,255,.22), rgba(77,242,255,.06));
  color:var(--cyan);
  cursor:pointer;
  margin-top:6px;
}
.primary-btn:active{ transform:scale(.97); }
.primary-btn:focus-visible{ outline:2px solid var(--cyan); outline-offset:3px; }

.username-row{
  width:100%;
  max-width:280px;
}
#usernameInput{
  width:100%;
  font-family:'Manrope',sans-serif;
  font-size:.95rem;
  padding:10px 14px;
  border-radius:10px;
  border:1px solid var(--panel-edge);
  background:var(--panel);
  color:var(--text);
  text-align:center;
}
#usernameInput:focus-visible{ outline:2px solid var(--cyan); outline-offset:2px; }
#usernameInput::placeholder{ color:var(--text-dim); }
.username-hint{
  max-width:340px;
  font-size:.68rem;
  color:var(--text-dim);
  line-height:1.4;
  margin-top:-6px;
}
.username-hint.error{ color:var(--danger); }

.color-row{
  width:100%;
  max-width:280px;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:8px;
}
.color-row-label{
  font-size:.6rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--text-dim);
  font-weight:700;
}
.color-swatches{
  display:flex;
  gap:9px;
  flex-wrap:wrap;
  justify-content:center;
}
.color-swatch{
  width:28px; height:28px;
  border-radius:50%;
  border:2px solid rgba(255,255,255,.15);
  cursor:pointer;
  padding:0;
  transition:transform .12s ease, border-color .12s ease;
}
.color-swatch:hover{ transform:scale(1.12); }
.color-swatch.selected{
  border-color:#fff;
  box-shadow:0 0 0 2px rgba(255,255,255,.2), 0 0 10px currentColor;
  transform:scale(1.08);
}
.color-swatch:focus-visible{ outline:2px solid var(--cyan); outline-offset:2px; }
.color-swatch.random-swatch{
  background:conic-gradient(from 0deg, #4DF2FF, #4DFFA6, #FFC24D, #FF4DA6, #8CFF6B, #B98CFF, #FF8C4D, #FFE94D, #4DF2FF);
  display:flex; align-items:center; justify-content:center;
  font-size:.8rem;
}

/* ---- mode select + Challenge difficulty ----
   Two new screens between the start overlay and a match: "Choose Your
   Mode" (#modeOverlay) and Challenge's own difficulty picker
   (#challengeDifficultyOverlay), one tap deeper. Card layout/sizing is
   shared between the two so they read as one flow; .mode-title uses its
   own color rule rather than the bare `.overlay h2` selector, which is
   reserved for the death screen's red "Lost In The Dark" styling. */
.mode-title{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:1.3rem;
  letter-spacing:.01em;
  color:var(--cyan);
  text-shadow:0 0 24px var(--cyan-dim);
  margin:0;
}
/* No Mercy win screen's title -- bare `.overlay h2` is reserved for the
   death screen's red styling (see comment above), wrong tone entirely
   for a win, so this gets the same cyan treatment as .mode-title instead
   of inheriting red by accident. */
.overlay .win-title{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:1.25rem;
  letter-spacing:.01em;
  color:var(--cyan);
  text-shadow:0 0 24px var(--cyan-dim);
  margin:0;
}
.mode-title-sub{
  font-size:.78rem;
  color:var(--text-dim);
  margin-top:-8px;
}
.back-link{
  align-self:flex-start;
  font-family:'Manrope',sans-serif;
  font-size:.78rem;
  font-weight:600;
  color:var(--text-dim);
  background:none;
  border:none;
  cursor:pointer;
  padding:4px 0;
}
.back-link:hover{ color:var(--text); }
.back-link:focus-visible{ outline:2px solid var(--cyan); outline-offset:2px; }

.mode-cards, .challenge-diff-cards{
  display:flex;
  gap:14px;
  flex-wrap:wrap;
  justify-content:center;
  max-width:610px;
}
.mode-card, .challenge-diff-card{
  width:170px;
  box-sizing:border-box;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:8px;
  text-align:center;
  padding:20px 14px;
  border-radius:14px;
  border:1px solid var(--panel-edge);
  background:var(--panel);
  cursor:pointer;
  transition:border-color .12s ease, background .12s ease, transform .12s ease;
}
.mode-card:hover{ border-color:var(--cyan-dim); transform:translateY(-2px); }
.challenge-diff-card:hover{ border-color:var(--cyan-dim); }
.mode-card:focus-visible, .challenge-diff-card:focus-visible{
  outline:2px solid var(--cyan); outline-offset:2px;
}
.mode-icon{ font-size:1.6rem; line-height:1; }
.mode-name, .cd-name{
  font-family:'Unbounded',sans-serif;
  font-weight:800;
  font-size:.85rem;
  letter-spacing:.02em;
  color:var(--text);
}
.mode-desc, .cd-desc{
  font-size:.72rem;
  color:var(--text-dim);
  line-height:1.45;
  min-height:2.6em;
}
.mode-sub-link{
  font-size:.68rem;
  font-weight:600;
  color:var(--cyan);
  margin-top:2px;
  cursor:pointer;
}
.mode-sub-link:hover{ color:var(--text); }
.mode-sub-link:focus-visible{ outline:2px solid var(--cyan); outline-offset:2px; }
.mode-badge{
  font-family:'JetBrains Mono',monospace;
  font-size:.6rem;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--text-dim);
  border:1px solid var(--panel-edge);
  border-radius:6px;
  padding:3px 8px;
  margin-top:2px;
}
.mode-card.disabled, .challenge-diff-card.disabled{
  cursor:default;
  opacity:.55;
  border-style:dashed;
}
.challenge-diff-card.selected{
  border-color:var(--cyan);
  background:rgba(77,242,255,.10);
}
.challenge-diff-card.selected .cd-name{ color:var(--cyan); }

.color-dot{
  display:inline-block;
  width:8px; height:8px;
  border-radius:50%;
  margin-right:6px;
  vertical-align:middle;
  box-shadow:0 0 4px currentColor;
}

.save-status{
  font-size:.72rem;
  color:var(--text-dim);
  min-height:1.2em;
}
.save-status.ok{ color:var(--cyan); }
.save-status.warn{ color:var(--danger); }

.visually-hidden{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap;
}
