:root {
  --pac: #ffe600;
  --pac-bright: #fff39a;
  --pac-glow: rgba(255, 230, 0, 0.45);
  --wall: #1e90ff;
  --wall-bright: #5fb0ff;
  --cyan: #5fb0ff;
  --cyan-bright: #b5d8ff;
  --cyan-dim: rgba(95, 176, 255, 0.35);
  --cyan-glow: rgba(95, 176, 255, 0.5);
  --bg: #05050f;
  --panel: rgba(10, 14, 32, 0.72);
  --text: #e8eeff;
  --text-dim: #6c83ff;
  --danger: #ff4d6d;
  --danger-glow: rgba(255, 77, 109, 0.45);
  --blinky: #ff2d2d;
  --pinky: #ff9ce0;
  --inky: #4be0ff;
  --clyde: #ffa033;
}

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

html, body {
  height: 100%;
  background: #000;
  font-family: "Courier New", "Lucida Console", Monaco, monospace;
  color: #fff;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(circle at 50% 30%, #0b1030 0%, #02020a 60%, #000 100%);
  touch-action: none;
}

#stage {
  position: relative;
  /* Scale to fill viewport while maintaining 580:720 aspect ratio.
     Uses min() so the stage never overflows in either dimension. */
  width: min(100vw, calc(100vh * 580 / 720));
  height: min(100vh, calc(100vw * 720 / 580));
  aspect-ratio: 580 / 720;
  box-shadow:
    0 0 0 2px #161640,
    0 0 60px rgba(80, 120, 255, 0.35),
    0 20px 80px rgba(0, 0, 0, 0.8);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg);
}

/* CRT scanline overlay — extremely subtle horizontal lines + faint vignette.
   Sits above the canvas but below overlays so it textures everything.
   Pseudo-element so it doesn't affect layout. */
#stage::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  /* Phase 1E — drop mix-blend-mode: multiply. Blend modes force a per-frame
     re-composite of the layer beneath. With the canvas no longer redrawing
     on idle (Phase 1A), the cost would have been muted — but multiply was
     still a constant cost on every PLAY frame. Pre-multiplied the alphas
     so the visual result is approximately identical under normal blending:
       scanline 0.08 × opacity 0.6 = 0.048 (raised slightly to 0.10 for visibility)
       vignette 0.4  × opacity 0.6 = 0.24 */
  background:
    repeating-linear-gradient(
      0deg,
      rgba(0, 0, 0, 0) 0,
      rgba(0, 0, 0, 0) 2px,
      rgba(0, 0, 0, 0.10) 3px,
      rgba(0, 0, 0, 0.10) 3px
    ),
    radial-gradient(ellipse at center, transparent 60%, rgba(0, 0, 0, 0.24) 100%);
}
@media (prefers-reduced-motion: reduce) {
  /* Scanlines stay — they're static texture, not motion. */
}

/* Controls bar — pause + music icons grouped top-right. Icon-only by design:
   during gameplay the player's attention is on the maze; text labels compete
   for visual real estate. Icons + consistent positioning + Fitts-sized
   targets win. Hover/long-press surfaces the label as a tooltip. */
.controls-bar {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 100;
  display: flex;
  gap: 6px;
  padding: 4px;
  border: 1px solid var(--cyan-dim);
  border-radius: 22px;
  background: var(--panel);
  backdrop-filter: blur(8px);
  box-shadow: 0 0 16px rgba(95, 176, 255, 0.1);
}

.icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  color: var(--cyan-bright);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 18px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}
.icon-btn .ic {
  width: 16px;
  height: 16px;
  display: block;
  filter: drop-shadow(0 0 4px currentColor);
}
.icon-btn .ic .ic-bar,
.icon-btn .ic .ic-head {
  fill: currentColor;
}
.icon-btn:hover {
  background: rgba(95, 176, 255, 0.18);
  border-color: var(--cyan-dim);
  color: #fff;
  box-shadow: 0 0 14px var(--cyan-glow);
}
.icon-btn:active {
  transform: scale(0.94);
}
.icon-btn.hidden { display: none !important; }

/* Tooltip: hidden by default, shows on hover (desktop). */
.icon-btn::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  padding: 4px 9px;
  font-family: "Courier New", monospace;
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 1.5px;
  color: var(--cyan-bright);
  background: var(--panel);
  border: 1px solid var(--cyan-dim);
  border-radius: 10px;
  backdrop-filter: blur(6px);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.15s, transform 0.15s;
}
.icon-btn:hover::after {
  opacity: 1;
  transform: translateY(0);
}
@media (hover: none) {
  /* On touch devices, no hover tooltip. Long-press handled in JS. */
  .icon-btn::after { display: none; }
}

/* Muted state: icon strike-through in --danger + desaturated icon. */
.icon-btn.muted {
  color: #5a6580;
}
.icon-btn.muted .ic {
  filter: none;
}
.icon-btn.muted .ic-strike {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 2px;
  background: var(--danger);
  border-radius: 1px;
  transform: translate(-50%, -50%) rotate(-45deg);
  box-shadow: 0 0 6px var(--danger-glow);
  animation: strike-in 0.18s ease-out;
}
@keyframes strike-in {
  from { transform: translate(-50%, -50%) rotate(-45deg) scaleX(0); }
  to { transform: translate(-50%, -50%) rotate(-45deg) scaleX(1); }
}
@media (prefers-reduced-motion: reduce) {
  .icon-btn.muted .ic-strike { animation: none; }
}

@media (max-width: 420px) {
  .controls-bar {
    top: 8px;
    right: 8px;
    padding: 3px;
  }
  .icon-btn { width: 30px; height: 30px; }
  .icon-btn .ic { width: 15px; height: 15px; }
}

/* ===== Ability button (Phase 5) =====
   Bottom-right tap target for touch devices. Appears only when the player
   is holding an ability (jump or bomb). Positioned in the bottom-right
   thumb-reach zone, raised ABOVE the HUD's bottom row so it never overlaps
   the LV/DIST/POWER readouts.

   Structure (text is OUTSIDE the icon, per design feedback):
     .ability-btn   — flex column container (icon circle on top, label below)
       ::before     — the circular icon button (colored, glowing, holds SVG)
       ::after      — a separate "SPACE" pill label below the circle

   The icon and the SPACE label are distinct elements: the icon is a pure
   graphic, the label is pure text. Neither crowds the other. */
.ability-btn {
  position: absolute;
  /* Raised so the full stack (circle + label) clears the HUD bottom row,
     which occupies roughly the bottom 50px on the right side. */
  right: 16px;
  bottom: 62px;
  z-index: 90;
  width: 60px;
  /* Container holds the circle + label stacked; height is auto so both fit. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  padding: 0;
  background: transparent;
  border: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.ability-btn::before {
  /* The circular icon button. This is the only colored/glowing part; the
     label below is plain. 54px hits a comfortable thumb target. */
  content: '';
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.45);
  background: rgba(20, 30, 50, 0.78);
  display: block;
  background-size: 62% 62%;
  background-repeat: no-repeat;
  background-position: center;
  backdrop-filter: blur(4px);
  box-shadow: 0 0 14px rgba(0, 0, 0, 0.6);
  transition: transform 0.08s, box-shadow 0.15s, background 0.2s, border-color 0.2s;
}
.ability-btn::after {
  /* "SPACE" label — a separate pill below the icon circle, NOT inside it.
     Small, high-contrast, reads as a keyboard-hint chip. */
  content: 'SPACE';
  font-family: "Courier New", monospace;
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 1.5px;
  color: #fff;
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 8px;
  padding: 2px 7px;
  line-height: 1.2;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
}
.ability-btn.is-jump::before {
  background-color: rgba(40, 120, 60, 0.88);
  border-color: rgba(120, 255, 180, 0.75);
  box-shadow: 0 0 18px rgba(80, 220, 120, 0.55), inset 0 0 10px rgba(120, 255, 180, 0.3);
  /* Coiled spring matching the in-game jump pellet. Same visual recipe:
     a helical coil drawn as alternating dark back halves (#1f7a3a) and bright
     front halves (#7aea9c) so the coil reads as 3D, a thin specular thread
     (#dcffe6) riding the front, a wide dark base plate (#0e3a1c) at the
     foot, and a bright gradient top cap with a white shine spot. Colours are
     lifted verbatim from drawJumpPellet in game.js. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><defs><linearGradient id='cap' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='%23e8ffee'/><stop offset='0.5' stop-color='%237aea9c'/><stop offset='1' stop-color='%232c8a4a'/></linearGradient></defs><path d='M5.5 20.5 Q12 22.5 18.5 20.5' stroke='%230e3a1c' stroke-width='2.4' fill='none' stroke-linecap='round'/><path d='M6 8.5 Q9 7 12 8.5 Q15 10 18 8.5' stroke='%231f7a3a' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 12 Q9 10.5 12 12 Q15 13.5 18 12' stroke='%231f7a3a' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 15.5 Q9 14 12 15.5 Q15 17 18 15.5' stroke='%231f7a3a' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 8.5 Q9 10 12 8.5' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M12 8.5 Q15 7 18 8.5' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 12 Q9 13.5 12 12' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M12 12 Q15 10.5 18 12' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 15.5 Q9 17 12 15.5' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M12 15.5 Q15 14 18 15.5' stroke='%237aea9c' stroke-width='1.7' fill='none' stroke-linecap='round'/><path d='M6 9.1 Q9 10.5 12 9.1' stroke='%23dcffe6' stroke-width='0.5' fill='none' stroke-linecap='round' opacity='0.85'/><path d='M12 9.1 Q15 7.6 18 9.1' stroke='%23dcffe6' stroke-width='0.5' fill='none' stroke-linecap='round' opacity='0.85'/><path d='M6 12.6 Q9 14 12 12.6' stroke='%23dcffe6' stroke-width='0.5' fill='none' stroke-linecap='round' opacity='0.85'/><path d='M12 12.6 Q15 11.1 18 12.6' stroke='%23dcffe6' stroke-width='0.5' fill='none' stroke-linecap='round' opacity='0.85'/><ellipse cx='12' cy='5.5' rx='6' ry='1.4' fill='url(%23cap)' stroke='%231a5a32' stroke-width='0.5'/><ellipse cx='10.3' cy='5.2' rx='1.9' ry='0.4' fill='%23ffffff' opacity='0.6'/></svg>");
}
.ability-btn.is-bomb::before {
  background-color: rgba(60, 24, 16, 0.9);
  border-color: rgba(255, 170, 80, 0.78);
  box-shadow: 0 0 18px rgba(255, 110, 30, 0.55), inset 0 0 10px rgba(255, 170, 80, 0.3);
  /* Bomb matching the in-game bomb pellet. Same visual recipe: a near-black
     sphere with an offset radial highlight (#5a3838 -> #1a0e0e -> #080404),
     a warm lower-right rim-light arc, a soft upper-left specular, a dark
     curving fuse stem (#3a2418), and a layered spark — outer halo, orange
     core, white-hot centre. Colours lifted from drawBombPellet in game.js. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><defs><radialGradient id='bomb' cx='0.35' cy='0.32' r='0.8'><stop offset='0' stop-color='%235a3838'/><stop offset='0.55' stop-color='%231a0e0e'/><stop offset='1' stop-color='%23080404'/></radialGradient><radialGradient id='halo' cx='0.5' cy='0.5' r='0.5'><stop offset='0' stop-color='%23ffc850' stop-opacity='0.85'/><stop offset='0.5' stop-color='%23ff8a30' stop-opacity='0.35'/><stop offset='1' stop-color='%23ff6e1e' stop-opacity='0'/></radialGradient><radialGradient id='spark' cx='0.5' cy='0.5' r='0.5'><stop offset='0' stop-color='%23ffffdc'/><stop offset='0.4' stop-color='%23ffb450'/><stop offset='1' stop-color='%23ff7a1e'/></radialGradient></defs><circle cx='17' cy='5.5' r='4.4' fill='url(%23halo)'/><circle cx='11.5' cy='15' r='6.2' fill='url(%23bomb)'/><path d='M6.3 14.4 A6.2 6.2 0 0 1 13 9' stroke='rgba(255,130,50,0.6)' stroke-width='0.9' fill='none' stroke-linecap='round'/><ellipse cx='9.2' cy='12.5' rx='1.5' ry='0.9' fill='%23ffc8a0' opacity='0.45' transform='rotate(-30 9.2 12.5)'/><path d='M13.4 9.3 Q15 7 16.7 6' stroke='%233a2418' stroke-width='1.3' fill='none' stroke-linecap='round'/><circle cx='17' cy='5.5' r='1.6' fill='url(%23spark)'/><circle cx='17' cy='5.5' r='0.6' fill='%23ffffdc'/></svg>");
}
.ability-btn:active::before { transform: translateY(2px) scale(0.95); }
.ability-btn.hidden { display: none !important; }
/* Mirror variant — same icon, anchored to the left edge for left-handed
   reach. Both buttons stay in sync via updateHud(); both are tap targets. */
.ability-btn.left {
  right: auto;
  left: 16px;
}

#game {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--bg);
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hidden { display: none !important; }

/* ===== HUD ===== */

#hud {
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.hud-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.hud-box {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.hud-box.right { align-items: flex-end; }
.hud-box.center { align-items: center; }
/* Equal-flex spacer — used in the bottom row so the middle box (DIST)
   sits at the true horizontal centre regardless of whether the side
   boxes have visible content (POWER on the left, empty on the right). */
.hud-box.hud-grow { flex: 1; }

.hud-label {
  font-size: 11px;
  letter-spacing: 2px;
  color: #6c83ff;
  text-shadow: 0 0 6px rgba(80, 120, 255, 0.6);
}

/* Secondary indicator below a primary hud-value — used for the level
   chip under SCORE. Smaller and dimmer than .hud-value so it doesn't
   compete with the primary readout. */
.hud-sub {
  font-family: "Courier New", monospace;
  font-size: 10px;
  letter-spacing: 1.5px;
  color: #4a5a8c;
  text-shadow: 0 0 4px rgba(60, 80, 140, 0.4);
  margin-top: 1px;
  opacity: 0.75;
}

/* Lives indicator — a row of small pac-icons. Each icon is a yellow circle
   with a mouth wedge cut by a triangle mask, giving the classic pac shape.
   Sized to match the hud-value baseline; fixed width so the row doesn't
   reflow when lives change. */
.lives-icons {
  display: flex;
  gap: 5px;
  min-height: 22px;
  align-items: center;
}
.life-icon {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 30%, #fff7a0 0%, #ffe600 60%, #d4bd00 100%);
  /* Mouth wedge: a triangle cut from the right side via conic-gradient mask. */
  -webkit-mask: conic-gradient(from -35deg, transparent 0 70deg, #000 70deg);
          mask: conic-gradient(from -35deg, transparent 0 70deg, #000 70deg);
  box-shadow: 0 0 6px rgba(255, 230, 0, 0.6);
}

.hud-value {
  font-size: 22px;
  font-weight: bold;
  letter-spacing: 1px;
  color: #fff;
  text-shadow: 0 0 8px rgba(255, 230, 0, 0.7);
  font-variant-numeric: tabular-nums;
}

#power-wrap .hud-value {
  color: #4be0ff;
  text-shadow: 0 0 10px rgba(75, 224, 255, 0.9);
}

/* ===== Screen overlays ===== */

.overlay-screen {
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 30px;
  background:
    radial-gradient(ellipse at center, rgba(8, 12, 40, 0.7) 0%, rgba(0, 0, 0, 0.92) 100%);
  backdrop-filter: blur(2px);
}

.title-glitch {
  font-size: clamp(48px, 13vw, 78px);
  font-weight: 900;
  letter-spacing: 4px;
  color: var(--pac);
  text-shadow:
    0 0 12px rgba(255, 230, 0, 0.9),
    0 0 32px rgba(255, 200, 0, 0.55),
    0 0 64px rgba(255, 180, 0, 0.3),
    -3px 0 0 rgba(75, 224, 255, 0.78),
    3px 0 0 rgba(255, 77, 109, 0.78);
  margin-bottom: 6px;
  line-height: 1;
  animation: title-pulse 4s ease-in-out infinite;
}
.title-glitch .dash {
  color: #fff;
  text-shadow:
    0 0 10px rgba(255, 255, 255, 0.9),
    0 0 22px rgba(255, 255, 255, 0.5);
}
@keyframes title-pulse {
  0%, 100% {
    text-shadow:
      0 0 12px rgba(255, 230, 0, 0.9),
      0 0 32px rgba(255, 200, 0, 0.55),
      0 0 64px rgba(255, 180, 0, 0.3),
      -3px 0 0 rgba(75, 224, 255, 0.78),
      3px 0 0 rgba(255, 77, 109, 0.78);
  }
  50% {
    text-shadow:
      0 0 18px rgba(255, 230, 0, 1),
      0 0 42px rgba(255, 200, 0, 0.7),
      0 0 90px rgba(255, 180, 0, 0.4),
      -4px 0 0 rgba(75, 224, 255, 0.95),
      4px 0 0 rgba(255, 77, 109, 0.95);
  }
}
@media (prefers-reduced-motion: reduce) {
  .title-glitch { animation: none; }
}

.subtitle {
  font-size: 13px;
  letter-spacing: 3px;
  color: #8da0ff;
  margin-bottom: 30px;
  text-transform: uppercase;
}

.controls {
  margin-bottom: 26px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ctrl-row {
  display: flex;
  gap: 6px;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #b5c4ff;
  letter-spacing: 1px;
}

.ctrl-label {
  color: #7a8ad6;
  font-size: 11px;
  letter-spacing: 2px;
  margin: 0 4px;
  text-transform: uppercase;
}

.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 26px;
  padding: 0 6px;
  border: 1px solid #4a5eaa;
  border-radius: 4px;
  background: linear-gradient(180deg, #1c2447 0%, #0c1230 100%);
  color: #d6e0ff;
  font-size: 12px;
  font-weight: bold;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.4), 0 0 6px rgba(80, 120, 255, 0.3);
}
.key.sm { min-width: 0; padding: 0 8px; height: 20px; font-size: 10px; }

.arcade-btn {
  position: relative;
  margin-top: 10px;
  padding: 14px 52px;
  font-family: inherit;
  font-size: clamp(15px, 3.6vw, 18px);
  font-weight: bold;
  letter-spacing: 3px;
  color: var(--bg);
  background: var(--pac);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  box-shadow:
    0 0 0 2px var(--pac-bright),
    0 0 28px var(--pac-glow),
    0 6px 0 #b89a00,
    0 8px 22px rgba(255, 230, 0, 0.25);
  transition: transform 0.08s ease-out, box-shadow 0.15s, background 0.15s;
  text-transform: uppercase;
  animation: cta-glow 2.6s ease-in-out infinite;
}
.arcade-btn::before,
.arcade-btn::after {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-family: inherit;
  font-size: 0.62em;
  font-weight: 900;
  color: var(--bg);
  letter-spacing: -3px;
  opacity: 0.55;
  transition: opacity 0.15s, transform 0.18s ease-out;
  pointer-events: none;
}
.arcade-btn::before { content: "▶▶"; left: 14px; }
.arcade-btn::after { content: "◀◀"; right: 14px; }

@keyframes cta-glow {
  0%, 100% {
    box-shadow:
      0 0 0 2px var(--pac-bright),
      0 0 22px var(--pac-glow),
      0 6px 0 #b89a00,
      0 8px 22px rgba(255, 230, 0, 0.2);
  }
  50% {
    box-shadow:
      0 0 0 2px var(--pac-bright),
      0 0 36px rgba(255, 230, 0, 0.75),
      0 6px 0 #b89a00,
      0 8px 28px rgba(255, 230, 0, 0.35);
  }
}
.arcade-btn:hover {
  animation: none;
  background: var(--pac-bright);
  box-shadow:
    0 0 0 2px #fff,
    0 0 40px rgba(255, 230, 0, 0.9),
    0 6px 0 #b89a00,
    0 10px 30px rgba(255, 230, 0, 0.4);
}
.arcade-btn:hover::before { opacity: 0.95; transform: translateY(-50%) translateX(2px); }
.arcade-btn:hover::after { opacity: 0.95; transform: translateY(-50%) translateX(-2px); }
.arcade-btn:active {
  transform: translateY(4px);
  box-shadow:
    0 0 0 2px var(--pac-bright),
    0 0 16px var(--pac-glow),
    0 2px 0 #b89a00;
}
@media (prefers-reduced-motion: reduce) {
  .arcade-btn,
  .arcade-btn::before,
  .arcade-btn::after { animation: none; transition: none; }
}

.hint {
  margin-top: 12px;
  font-size: 11px;
  color: #6c7bb5;
  letter-spacing: 2px;
  text-transform: uppercase;
}

/* ===== Game Over ===== */

.go-title {
  font-size: 52px;
  font-weight: 900;
  letter-spacing: 6px;
  color: var(--blinky);
  text-shadow:
    0 0 14px rgba(255, 45, 45, 0.9),
    0 0 30px rgba(255, 45, 45, 0.5),
    2px 0 0 rgba(75, 224, 255, 0.6),
    -2px 0 0 rgba(255, 230, 0, 0.6);
  margin-bottom: 24px;
}

.pause-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(12px, 3vw, 24px);
  font-size: clamp(36px, 9vw, 56px);
  font-weight: 900;
  letter-spacing: clamp(4px, 1.4vw, 8px);
  color: var(--cyan-bright);
  text-shadow:
    0 0 12px rgba(75, 224, 255, 0.9),
    0 0 30px rgba(75, 224, 255, 0.5),
    -2px 0 0 rgba(255, 230, 0, 0.65),
    2px 0 0 rgba(255, 77, 109, 0.6);
  margin-bottom: 24px;
  line-height: 1;
  animation: pause-pulse 3.2s ease-in-out infinite;
}
.pause-title .pause-flank {
  font-size: 0.55em;
  color: var(--cyan);
  letter-spacing: -2px;
  opacity: 0.65;
  text-shadow: 0 0 8px currentColor;
}
@keyframes pause-pulse {
  0%, 100% { opacity: 0.92; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .pause-title { animation: none; }
}

/* ===== OPTIONS panel (shared by title + pause) =====
   Groups settings-style rows (music, fullscreen) into a translucent card.
   Inside, .option-row uses grid: [label | control | optional key hint]. */
.options-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 18px;
  margin-bottom: 18px;
  padding: 14px 18px 16px;
  width: min(100%, 380px);
  border: 1px solid var(--cyan-dim);
  border-radius: 6px;
  /* Phase 1B — flatten nested backdrop-filter. This panel sits inside
     .overlay-screen (which already blurs the canvas beneath), so the extra
     blur was compounding GPU cost for ~0 perceptual gain. Slightly more
     opaque background compensates for the missing blur. */
  background: rgba(8, 14, 36, 0.86);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 0 24px rgba(95, 176, 255, 0.08);
}

.options-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 3px;
  text-transform: uppercase;
  margin-bottom: 2px;
}
.options-divider::before,
.options-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    var(--cyan-dim) 50%,
    transparent
  );
}

.option-row {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: center;
  gap: 12px;
}

.option-label {
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 2px;
  text-transform: uppercase;
  text-align: left;
  text-shadow: 0 0 6px rgba(108, 131, 255, 0.3);
}

.option-key {
  font-family: inherit;
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 1px;
  color: var(--text-dim);
  padding: 2px 6px;
  border: 1px solid var(--cyan-dim);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.35);
  text-transform: uppercase;
}

/* ===== Fullscreen toggle (.fs-toggle) =====
   State pill: hollow dot when OFF, filled cyan when ON. Same component in
   title OPTIONS and pause OPTIONS — single mental model. */
.fs-toggle {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  justify-self: start;
  padding: 5px 12px 5px 10px;
  font-family: inherit;
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1.5px;
  color: var(--cyan);
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--cyan-dim);
  border-radius: 14px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
  text-transform: uppercase;
}
.fs-toggle .fs-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  background: transparent;
  transition: background 0.15s, box-shadow 0.15s;
  flex-shrink: 0;
}
.fs-toggle .fs-state {
  min-width: 26px;
  text-align: left;
}
.fs-toggle:hover {
  background: rgba(95, 176, 255, 0.12);
  color: var(--cyan-bright);
}
.fs-toggle.active {
  background: var(--cyan);
  color: var(--bg);
  border-color: var(--cyan);
  box-shadow:
    0 0 14px var(--cyan-glow),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.fs-toggle.active .fs-dot {
  background: var(--bg);
  border-color: var(--bg);
  box-shadow: 0 0 4px var(--bg);
}
.fs-toggle.active:hover {
  background: var(--cyan-bright);
  color: var(--bg);
}

/* ===== Zone intermission =====
   3-phase reveal modulated by phase classes added in update():
   - .phase-cleared: "ZONE N CLEARED" headline visible (0.0–0.7s)
   - .phase-name:    "ENTERING ZONE N+1 / NAME / TAGLINE / SWATCH" fades in (0.7–2.4s)
   - .phase-ready:   "READY" pulse appears (2.4–3.8s)
   At 3.8s the overlay is hidden and the game resumes in the new zone. */

#zoneintermission {
  /* Vertically biased toward upper third; more visual weight below the focal
     name so the layout doesn't read as cramped at the top. */
  justify-content: flex-start;
  padding-top: 12vh;
}

.zi-card {
  max-width: 480px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 18px;
}

.zi-cleared {
  font-size: clamp(22px, 6vw, 38px);
  font-weight: 900;
  letter-spacing: 4px;
  color: #b5c4ff;
  text-shadow: 0 0 14px rgba(75, 224, 255, 0.7);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
#zoneintermission.phase-cleared .zi-cleared {
  opacity: 1;
  transform: translateY(0);
}

.zi-name {
  font-size: clamp(14px, 4vw, 20px);
  font-weight: 700;
  letter-spacing: 3px;
  color: #8da0ff;
  opacity: 0;
  transition: opacity 0.2s ease;
}
#zoneintermission.phase-name .zi-name {
  opacity: 1;
}

.zi-title {
  /* The focal point — the upcoming zone's name in palette accent. */
  font-size: clamp(36px, 11vw, 60px);
  font-weight: 900;
  letter-spacing: 6px;
  color: var(--pac);
  text-shadow:
    0 0 14px rgba(255, 230, 0, 0.9),
    0 0 32px rgba(255, 200, 0, 0.5);
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
#zoneintermission.phase-name .zi-title {
  opacity: 1;
  transform: scale(1);
}

.zi-tagline {
  /* One-line description of the zone's mechanic. Inline colour is set per
     zone in showZoneIntermission() using the upcoming zone's accent. Kept
     short since the modal is only visible ~2.6s. */
  font-size: clamp(13px, 3.6vw, 20px);
  font-weight: 600;
  font-style: italic;
  letter-spacing: 1.5px;
  color: #b5c4ff;
  text-shadow: 0 0 8px rgba(120, 160, 255, 0.5);
  max-width: 90%;
  line-height: 1.3;
  margin-top: -4px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
#zoneintermission.phase-name .zi-tagline {
  opacity: 1;
}

.zi-swatch {
  display: flex;
  gap: 8px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
#zoneintermission.phase-name .zi-swatch {
  opacity: 1;
}
.zi-chip {
  width: clamp(20px, 6vw, 32px);
  height: clamp(20px, 6vw, 32px);
  border-radius: 4px;
  box-shadow:
    0 0 10px rgba(0, 0, 0, 0.5),
    inset 0 0 6px rgba(255, 255, 255, 0.25);
}

.zi-ready {
  font-size: clamp(20px, 6vw, 32px);
  font-weight: 900;
  letter-spacing: 8px;
  color: #fff;
  text-shadow: 0 0 16px rgba(255, 255, 255, 0.8);
  opacity: 0;
  margin-top: 8px;
}
#zoneintermission.phase-ready .zi-ready {
  animation: zi-ready-pulse 0.9s ease-in-out infinite;
}

@keyframes zi-ready-pulse {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.08); }
}

/* Danger button — "RETURN TO TITLE" / exit-style actions.
   Transparent with red border + red icon. We intentionally don't fill red:
   a saturated red fill reads as "delete" / "destructive", too alarming for
   a non-destructive navigation action. The icon carries the warning. */
.danger-btn {
  margin-top: 14px;
  padding: 11px 28px;
  font-family: inherit;
  font-size: 12px;
  font-weight: bold;
  letter-spacing: 2.5px;
  color: var(--danger);
  background: rgba(40, 12, 22, 0.55);
  border: 1px solid var(--danger-glow);
  border-radius: 4px;
  cursor: pointer;
  box-shadow: 0 0 14px rgba(255, 77, 109, 0.18);
  transition: background 0.15s, color 0.15s, box-shadow 0.15s, border-color 0.15s;
  text-transform: uppercase;
  animation: none;
}
.danger-btn::before,
.danger-btn::after { content: none; }
.danger-btn .danger-icon {
  display: inline-block;
  margin-right: 8px;
  font-size: 1.15em;
  line-height: 1;
  text-shadow: 0 0 8px currentColor;
  transform: translateY(-1px);
}
.danger-btn:hover {
  background: rgba(255, 77, 109, 0.18);
  color: #ffe6ec;
  border-color: var(--danger);
  box-shadow: 0 0 22px var(--danger-glow);
}
.danger-btn:active {
  transform: translateY(2px);
  box-shadow: 0 0 10px rgba(255, 77, 109, 0.4);
}

.go-stats {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
  padding: 18px 32px;
  border: 1px solid #2a3666;
  border-radius: 4px;
  background: rgba(8, 12, 32, 0.6);
  box-shadow: inset 0 0 20px rgba(80, 120, 255, 0.15);
}

.go-stat {
  display: flex;
  justify-content: space-between;
  gap: 40px;
  min-width: 200px;
  align-items: baseline;
}
.go-label {
  font-size: 11px;
  color: #6c83ff;
  letter-spacing: 3px;
}
.go-value {
  font-size: 22px;
  font-weight: bold;
  color: #fff;
  text-shadow: 0 0 8px rgba(255, 230, 0, 0.6);
  font-variant-numeric: tabular-nums;
}

.record {
  font-size: 16px;
  font-weight: bold;
  letter-spacing: 4px;
  color: var(--pac);
  text-shadow: 0 0 12px rgba(255, 230, 0, 0.9);
  margin-bottom: 14px;
  animation: blink 0.8s steps(2) infinite;
}

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

/* responsive — text sizes scale with viewport */
.title-glitch { font-size: clamp(40px, 11vw, 78px); }
.go-title { font-size: clamp(32px, 8vw, 52px); }
.subtitle { font-size: clamp(10px, 2.5vw, 13px); }
.arcade-btn { font-size: clamp(14px, 3.5vw, 18px); padding: clamp(10px, 2.5vw, 14px) clamp(24px, 6vw, 32px); }
.hud-value { font-size: clamp(16px, 4vw, 22px); }
.hud-label { font-size: clamp(9px, 2.2vw, 11px); }
.go-value { font-size: clamp(16px, 4.5vw, 22px); }

/* ===== Music selector + service icons (title screen) ===== */
/* Music selector now lives inside .option-row (grid: label | control | key).
   Only the .music-options segmented control needs styling here. */

.music-select {
  margin-top: 0;
}

.music-select-label {
  display: none;
}

.music-options {
  display: flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--cyan-dim);
  border-radius: 4px;
  /* Phase 1B — flatten nested backdrop-filter. Sits inside .options-panel,
     which itself sits inside .overlay-screen. Triple-nested blur is wasteful.
     Darker background compensates for the missing blur. */
  background: rgba(0, 0, 0, 0.55);
}

.music-option {
  padding: clamp(4px, 1vw, 5px) clamp(9px, 2.4vw, 12px);
  font-family: inherit;
  font-size: clamp(9px, 2vw, 10px);
  font-weight: bold;
  letter-spacing: 1px;
  color: var(--cyan);
  background: transparent;
  border: none;
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
  text-transform: uppercase;
}

.music-option.active {
  background: var(--cyan);
  color: var(--bg);
  text-shadow: none;
  box-shadow:
    0 0 12px var(--cyan-glow),
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25);
}

.music-option:hover:not(.active) {
  background: rgba(95, 176, 255, 0.12);
  color: var(--cyan-bright);
}

.music-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
}

.music-credit {
  font-size: clamp(11px, 2.8vw, 14px);
  font-weight: bold;
  color: #ffe600;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  text-align: center;
  text-shadow:
    0 0 8px rgba(255, 230, 0, 0.7),
    0 0 18px rgba(255, 200, 0, 0.4);
  line-height: 1.3;
}

.music-credit .small {
  display: block;
  margin-top: 3px;
  font-size: clamp(9px, 2vw, 11px);
  font-weight: normal;
  color: #fff39a;
  letter-spacing: 2px;
  text-shadow: 0 0 5px rgba(255, 243, 154, 0.5);
}

.music-icons {
  display: flex;
  gap: clamp(16px, 4vw, 28px);
  align-items: center;
}

.music-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(22px, 5vw, 30px);
  height: clamp(22px, 5vw, 30px);
  color: #8a9ac5;
  transition: color 0.2s, transform 0.2s, filter 0.2s;
  text-decoration: none;
}

.music-icon svg { width: 100%; height: 100%; }

.music-icon:hover {
  transform: scale(1.18);
  filter: drop-shadow(0 0 6px currentColor);
}

.music-icon.spotify:hover { color: #1DB954; }
.music-icon.youtube:hover { color: #FF0000; }

/* ---- Fullscreen mode ----
   document.body is the fullscreen element (not #stage) — the Fullscreen
   spec's UA stylesheet forces `width:100% !important; height:100% !important`
   on `:fullscreen:not(:root)` targets, which would distort #stage's 580:720
   canvas. body survives the stretch and its existing flex centering
   (`display:flex; align-items:center; justify-content:center`) keeps #stage
   aspect-correct via the min() width/height on #stage itself. */
body:fullscreen,
body:-webkit-full-screen {
  background: #000;
}

/* ============================================================
   Leaderboard (pacrun) — leaderboard DOM overlay only
   (name-entry is canvas-drawn, see drawNameEntryScreen in game.js)
   ============================================================ */

/* ---- Leaderboard view ---- */
.lb-title {
  font-size: clamp(26px, 6vw, 38px);
  letter-spacing: 5px;
  color: var(--pac);
  text-shadow: 0 0 14px var(--pac-glow), 0 0 32px rgba(255, 200, 0, 0.3);
  margin: 0 0 22px;
}
.lb-list {
  width: min(440px, 92vw);
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: inherit;
  font-size: 14px;
  letter-spacing: 1px;
}
.lb-row {
  display: grid;
  grid-template-columns: 36px 84px 1fr 80px 44px;
  align-items: center;
  padding: 8px 12px;
  border-radius: 3px;
  background: rgba(10, 18, 40, 0.5);
  border: 1px solid rgba(95, 176, 255, 0.12);
  color: var(--text);
}
.lb-row:nth-child(odd):not(.lb-header):not(.current) {
  background: rgba(14, 22, 48, 0.65);
}
.lb-header {
  font-size: 10px;
  letter-spacing: 2px;
  color: var(--text-dim);
  background: transparent !important;
  border: none;
  padding: 4px 12px 8px;
}
.lb-row .lb-rank {
  color: var(--cyan-bright);
  font-weight: 700;
}
.lb-row .lb-name {
  color: var(--pac-bright);
  font-weight: 800;
  letter-spacing: 3px;
}
.lb-row .lb-score {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  text-align: right;
  padding-right: 10px;
}
.lb-row .lb-dist {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  text-align: right;
  font-size: 12px;
}
.lb-row .lb-level {
  color: var(--cyan);
  font-size: 12px;
  text-align: right;
}
.lb-row.current {
  background: rgba(255, 230, 0, 0.12) !important;
  border-color: var(--pac);
  box-shadow: 0 0 14px var(--pac-glow);
}
.lb-row.current .lb-name,
.lb-row.current .lb-score { color: #fff; }
.lb-empty {
  padding: 30px 12px;
  text-align: center;
  color: var(--text-dim);
  font-size: 13px;
  letter-spacing: 1px;
}
.lb-status {
  margin: 12px 0 0;
  font-size: 11px;
  letter-spacing: 1.5px;
  color: var(--danger);
}
#lbBackBtn { margin-top: 22px; }
