/* ============================================================
   FIELDBRIGHT — prototype stylesheet
   Palette tokens are CSS variables so we can swap them on
   the <body> element when a trail unlock is triggered.
   ============================================================ */

:root {
  /* Palette A — default (deep red + lime green, matching the reference) */
  --bg: #8B1010;
  --accent: #B8D332;
  --tri-fill: #B8D332;
  --tri-flipped: #F5F1E6;
  --text: #B8D332;

  /* timing */
  --t-palette: 1.2s cubic-bezier(0.4, 0.0, 0.2, 1);
  --t-flip: 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
  --t-move: 1.6s cubic-bezier(0.65, 0.05, 0.36, 1);

  /* spacing */
  --pad-section: clamp(4rem, 9vh, 8rem) clamp(1.5rem, 6vw, 6rem);
}

/* Palette B — Midnight Signal (scene 1) */
body.palette-b {
  --bg: #0E1B3A;
  --accent: #3FE0FF;
  --tri-fill: #3FE0FF;
  --tri-flipped: #FFFFFF;
  --text: #3FE0FF;
}

/* Palette C — Iron Chartreuse (scene 2) */
body.palette-c {
  --bg: #15171A;
  --accent: #D8FF3A;
  --tri-fill: #D8FF3A;
  --tri-flipped: #FFFFFF;
  --text: #D8FF3A;
}

/* Palette D — Bone & Iron (scene 3) */
body.palette-d {
  --bg: #222630;
  --accent: #E8E0C8;
  --tri-fill: #E8E0C8;
  --tri-flipped: #FFFFFF;
  --text: #E8E0C8;
}

/* Palette E — Night Sky (scene 4 — finale, mobile default) */
body.palette-e {
  --bg: #0A1432;
  --accent: #F4E9D6;
  --tri-fill: #F4E9D6;
  --tri-flipped: #FFFFFF;
  --text: #F4E9D6;
}

/* Palettes F–I — extra mobile palettes, surfaced by tapping triangles. */
body.palette-f {
  --bg: #2A0E3E;
  --accent: #F5B3D6;
  --tri-fill: #F5B3D6;
  --tri-flipped: #FFFFFF;
  --text: #F5B3D6;
}
body.palette-g {
  --bg: #0D2818;
  --accent: #E8E0C8;
  --tri-fill: #E8E0C8;
  --tri-flipped: #FFFFFF;
  --text: #E8E0C8;
}
body.palette-h {
  --bg: #3A1808;
  --accent: #E8C89C;
  --tri-fill: #E8C89C;
  --tri-flipped: #FFFFFF;
  --text: #E8C89C;
}
body.palette-i {
  --bg: #062B3D;
  --accent: #F59E8E;
  --tri-fill: #F59E8E;
  --tri-flipped: #FFFFFF;
  --text: #F59E8E;
}

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

html, body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  transition: background var(--t-palette), color var(--t-palette);
}

a { color: inherit; }

/* ---------- Hero ---------- */

.hero {
  position: relative;
  width: 100%;
  height: 100vh;
  min-height: 600px;
  overflow: hidden;
  isolation: isolate;
}

.hero-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  color: var(--accent);
  transition: color var(--t-palette);
}

.hero-svg .bg {
  fill: var(--bg);
  transition: fill var(--t-palette);
}

.hero-svg .linework {
  pointer-events: none;
}

.hero-svg .linework-decor {
  opacity: 0.95;
}

/* Trail lines fade in/out per scene */
#trail-lines polyline {
  opacity: 0;
  transition: opacity 0.9s ease;
}
#trail-lines polyline.visible { opacity: 0.95; }
#trail-lines polyline.exiting { opacity: 0; }

/* Calm-section ripples: thin outlines that grow and fade.
   Each ripple is a single <circle> appended/removed by JS. */
.cue-ripple {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  pointer-events: none;
  transition: stroke var(--t-palette);
  animation: ripple-grow 2.8s ease-out forwards;
}
@keyframes ripple-grow {
  0%   { r: 2;  opacity: 0.55; stroke-width: 2; }
  100% { r: 90; opacity: 0;    stroke-width: 0.4; }
}
.cue-ripple.wide {
  /* Wave-sweep ripples grow larger and more horizontal-feeling */
  animation: ripple-wide 3.2s ease-out forwards;
}
@keyframes ripple-wide {
  0%   { r: 4;   opacity: 0.5; stroke-width: 2.5; }
  100% { r: 140; opacity: 0;   stroke-width: 0.3; }
}

/* Digit cue (00:17-00:19): triangles temporarily become digits 0-9 */
.digit {
  font-family: 'Space Grotesk', sans-serif;
  fill: var(--accent);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  transition: fill var(--t-palette);
  font-weight: 700;
}

/* Rocket exhaust — soft smoke puffs that accumulate as rockets launch */
.rocket-smoke {
  fill: var(--accent);
  pointer-events: none;
  animation: smoke-fade 4s ease-out forwards;
}
@keyframes smoke-fade {
  0%   { opacity: 0;    r: 1; }
  15%  { opacity: 0.40; r: 6; }
  60%  { opacity: 0.22; r: 14; }
  100% { opacity: 0;    r: 22; }
}

/* Rocket sparks — sharp twinkles in the exhaust */
.rocket-spark {
  fill: #FFFFFF;
  pointer-events: none;
  animation: spark-fade 0.85s ease-out forwards;
}
@keyframes spark-fade {
  0%   { opacity: 0; r: 0; }
  18%  { opacity: 1; r: 2.5; }
  100% { opacity: 0; r: 0.5; }
}

/* Chorus sparkles — tiny dots that twinkle near each triangle */
.sparkle {
  fill: var(--accent);
  pointer-events: none;
  animation: sparkle 0.85s ease-out forwards;
  transition: fill var(--t-palette);
}
@keyframes sparkle {
  0%   { opacity: 0;   r: 0.5; }
  25%  { opacity: 1;   r: 3; }
  60%  { opacity: 0.7; r: 4; }
  100% { opacity: 0;   r: 1.5; }
}

/* Triangle wrappers move via transform; CSS transitions animate the drift. */
.tri-wrap {
  transition: transform var(--t-move);
}
/* During the finale's per-frame drift loop, kill the transition so JS-driven
   transforms feel smooth (transitions would lag every frame). */
.tri-wrap.drifting {
  transition: none;
}

.tri {
  fill: var(--tri-fill);
  cursor: pointer;
  transform: rotate(var(--rot, 0deg));
  transform-origin: 0 0;
  transform-box: view-box;
  transition: fill var(--t-palette), transform var(--t-flip);
}

.tri[data-orient="up"]:not(.flipped)   { --rot: 0deg; }
.tri[data-orient="up"].flipped         { --rot: 180deg; }
.tri[data-orient="down"]:not(.flipped) { --rot: 180deg; }
.tri[data-orient="down"].flipped       { --rot: 0deg; }

.tri.flipped { fill: var(--tri-flipped); }
.tri:hover   { filter: brightness(1.15); }

/* While the song is playing, the drift loop sets each triangle's fill every
   frame. Killing the fill transition prevents per-frame lag. When the class
   comes off, the base fill transition animates the colors back to the
   palette's default tri-fill. */
.tri.color-cycling {
  transition: transform var(--t-flip);
}

/* Beat pulse during countdown */
.tri.pulse {
  animation: tri-pulse 0.32s ease-out;
}
@keyframes tri-pulse {
  0%   { filter: brightness(1); }
  50%  { filter: brightness(2); }
  100% { filter: brightness(1); }
}

/* Idle hint: trail triangles jiggle subtly to suggest the path */
.tri.jiggle {
  animation: jiggle 0.7s ease-in-out;
}
@keyframes jiggle {
  0%, 100% { transform: rotate(var(--rot, 0deg)) scale(1); }
  18%      { transform: rotate(calc(var(--rot, 0deg) + 9deg)) scale(1.08); }
  44%      { transform: rotate(calc(var(--rot, 0deg) - 7deg)) scale(0.94); }
  72%      { transform: rotate(calc(var(--rot, 0deg) + 4deg)) scale(1.04); }
}

/* Synth-key cue: sequential brightness flash as each triangle "plays" */
.tri.synth-pulse {
  animation: synth-pulse 0.3s ease-out;
}
@keyframes synth-pulse {
  0%   { filter: brightness(1) drop-shadow(0 0 0 transparent); }
  50%  { filter: brightness(2.6) drop-shadow(0 0 6px currentColor); }
  100% { filter: brightness(1) drop-shadow(0 0 0 transparent); }
}

/* Solo fragment cue: triangles disintegrate quickly (shrink, rotate, fade) */
.tri.fragmenting {
  animation: fragment 1.2s ease-out forwards;
}
@keyframes fragment {
  0%   { opacity: 1; }
  60%  { opacity: 0.55; }
  100% { opacity: 0; }
}
.tri-wrap.fragmenting > .tri {
  animation: fragment-rotate 1.2s ease-out forwards;
}
@keyframes fragment-rotate {
  0%   { transform: rotate(var(--rot, 0deg)) scale(1); }
  100% { transform: rotate(calc(var(--rot, 0deg) + 540deg)) scale(0); }
}

/* Solo phase 3: giant triangles spin — JS drives the rotation each frame
   for the exponential acceleration curve. */
.tri.giant-spinning {
  mix-blend-mode: screen;
  opacity: 0.75;
  pointer-events: none;
  /* JS overrides transform inline; this is the default in case JS hasn't
     written yet (avoids snap-back to scale 1 between class swap & frame). */
  transform: rotate(var(--rot, 0deg)) scale(5.5);
}

/* Wrong-choice triangles in the desktop puzzle disintegrate and are out
   of play until the next scene (or reset). */
.tri.disintegrating {
  animation: disintegrate 0.85s ease-out forwards;
  pointer-events: none;
}
@keyframes disintegrate {
  0%   { opacity: 1; transform: rotate(var(--rot, 0deg)) scale(1); }
  55%  { opacity: 0.6; transform: rotate(calc(var(--rot, 0deg) + 360deg)) scale(0.5); }
  100% { opacity: 0; transform: rotate(calc(var(--rot, 0deg) + 540deg)) scale(0); }
}

/* Solo cue second half: triangles re-emerge ENORMOUS and overlap each
   other with a screen blend so intersections show averaged colors. */
.tri.giant {
  animation: tri-giant 1.4s ease-out forwards;
  mix-blend-mode: screen;
  pointer-events: none;
}
@keyframes tri-giant {
  0%   { opacity: 0; transform: rotate(var(--rot, 0deg)) scale(0); }
  100% { opacity: 0.75; transform: rotate(var(--rot, 0deg)) scale(5.5); }
}

/* Chorus 3 letter explosion — letters get split into spans at boot and fly
   to random positions, then back, on repeat. */
.letter {
  display: inline-block;
  transition: transform 0.9s cubic-bezier(0.65, 0.05, 0.36, 1),
              opacity 0.9s ease;
}
.letter.flying {
  animation: letter-fly var(--fly-duration, 3.2s) ease-in-out infinite alternate;
}
@keyframes letter-fly {
  to {
    transform: translate(var(--fly-x, 0), var(--fly-y, 0)) rotate(var(--fly-rot, 0deg));
    opacity: 0.85;
  }
}

/* Disable interaction during scene transitions and in desktop finale.
   Mobile finale keeps triangles tappable (each tap swaps the palette). */
.hero-svg.transitioning .tri                    { pointer-events: none; }
body.palette-e:not(.mobile-mode) .tri           { pointer-events: none; cursor: default; }
body.mobile-mode .tri                           { pointer-events: auto; cursor: pointer; }

.dust-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  width: 100%;
  height: 100%;
  z-index: 2;
}

.brand {
  position: absolute;
  top: clamp(20px, 3vh, 36px);
  left: clamp(20px, 3vw, 48px);
  font-size: clamp(1.4rem, 2.6vw, 2.2rem);
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--text);
  z-index: 3;
  transition: color var(--t-palette), opacity var(--t-palette);
  user-select: none;
}

body.palette-e .brand { opacity: 0; pointer-events: none; }

.hero-footer {
  position: absolute;
  bottom: clamp(16px, 3vh, 30px);
  left: clamp(20px, 3vw, 48px);
  right: clamp(20px, 3vw, 48px);
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 3;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--text);
  opacity: 0.65;
  transition: color var(--t-palette), opacity 0.6s;
}

body.palette-e .hero-hint { opacity: 0; }

.hero-footer .reset {
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  font: inherit;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}
.hero-footer .reset:hover {
  background: var(--accent);
  color: var(--bg);
}

/* ---------- Finale overlays ---------- */

.finale-text {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  color: var(--text);
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  text-align: center;
  padding: 0 1rem;
  transition: opacity 1.4s ease, color var(--t-palette);
}
.finale-text.visible { opacity: 1; }

.finale-band {
  font-size: clamp(2.6rem, 8.5vw, 8.4rem);
  font-weight: 700;
  letter-spacing: 0.18em;
  line-height: 1;
}
.finale-song {
  font-size: clamp(0.85rem, 1.4vw, 1.15rem);
  font-weight: 500;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  opacity: 0.85;
}
.finale-time {
  font-size: clamp(0.6rem, 0.9vw, 0.8rem);
  font-weight: 400;
  letter-spacing: 0.18em;
  font-variant-numeric: tabular-nums;
  opacity: 0.4;
  margin-top: 0.5rem;
}

/* Desktop blend: dramatic white-on-difference for the post-countdown reveal.
   White over red bg = cyan, white over a yellow triangle = blue, etc. */
body.audio-playing .finale-text {
  mix-blend-mode: difference;
  color: #FFFFFF;
}

/* Mobile blend: keep the text in the palette's accent color (lime on the
   red home state, matching the rest of the brand). "lighten" preserves
   the accent color over plain backdrops; where a brighter/different
   triangle drifts behind, the lighter channels dominate and the
   intersection shifts to that triangle's color. */
body.mobile-mode .finale-text {
  mix-blend-mode: lighten;
  color: var(--accent);
}

/* Pause / resume button — appears once audio has started in the finale */
.audio-toggle {
  position: absolute;
  left: 50%;
  bottom: clamp(60px, 9vh, 110px);
  transform: translateX(-50%);
  z-index: 5;
  background: transparent;
  border: 1px solid currentColor;
  color: var(--text);
  font: inherit;
  font-size: 0.72rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding: 0.65rem 1.2rem;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease, background 0.2s, color 0.2s;
}
.audio-toggle.visible {
  opacity: 0.7;
  pointer-events: auto;
}
.audio-toggle:hover {
  opacity: 1;
  background: var(--accent);
  color: var(--bg);
}

.countdown {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  z-index: 5;
  color: var(--text);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease, color var(--t-palette);
}
.countdown.visible {
  opacity: 1;
  pointer-events: auto;
}
.countdown-label {
  font-size: 0.75rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 0.4rem;
}
.countdown-number {
  font-size: clamp(8rem, 22vw, 18rem);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.countdown-number.tick {
  animation: count-pulse 0.6s ease-out;
}
@keyframes count-pulse {
  0%   { transform: scale(0.6); opacity: 0; }
  35%  { transform: scale(1);   opacity: 1; }
  100% { transform: scale(1);   opacity: 1; }
}
.countdown-skip {
  margin-top: 1.5rem;
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  font: inherit;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  padding: 0.55rem 1.1rem;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}
.countdown-skip:hover {
  background: var(--accent);
  color: var(--bg);
}

/* Unlock prompt — shown when the finale scene first lands. User clicks
   "press play" to start the countdown (and supply the audio gesture). */
.unlock-prompt {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  z-index: 5;
  color: var(--text);
  opacity: 0;
  pointer-events: none;
  text-align: center;
  padding: 0 1rem;
  transition: opacity 0.7s ease, color var(--t-palette);
}
.unlock-prompt.visible {
  opacity: 1;
  pointer-events: auto;
}
.unlock-eyebrow {
  font-size: 0.75rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  opacity: 0.7;
}
.unlock-title {
  font-size: clamp(1.8rem, 4.5vw, 3.8rem);
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-bottom: 0.8rem;
}
.unlock-play {
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding: 0.9rem 1.6rem;
  cursor: pointer;
  transition: background 0.2s, color 0.2s, transform 0.2s;
}
.unlock-play:hover {
  background: var(--accent);
  color: var(--bg);
  transform: scale(1.03);
}

/* Last-resort fallback in case autoplay still gets blocked after a click
   (rare — kept as a safety net). */
.play-fallback {
  position: absolute;
  left: 50%;
  bottom: 18%;
  transform: translateX(-50%);
  z-index: 5;
  background: transparent;
  border: 1px solid currentColor;
  color: var(--text);
  font: inherit;
  font-size: 0.75rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  padding: 0.75rem 1.3rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.6s ease, background 0.2s, color 0.2s, transform 0.3s;
}
.play-fallback.visible { opacity: 1; }
.play-fallback:hover  { background: var(--accent); color: var(--bg); }

/* ---------- Sections ---------- */

.section {
  padding: var(--pad-section);
  background: var(--bg);
  color: var(--text);
  transition: background var(--t-palette), color var(--t-palette);
}

.eyebrow {
  font-size: 0.7rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  opacity: 0.65;
  margin-bottom: 0.6rem;
}

/* ---------- Player ---------- */

.player {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  max-width: 1100px;
  margin: 0 auto;
  align-items: center;
}

@media (max-width: 720px) {
  .player {
    grid-template-columns: 1fr;
    max-width: 420px;
  }
}

.cover {
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--accent);
  display: grid;
  place-items: stretch;
  transition: border-color var(--t-palette);
}

.cover svg { width: 100%; height: 100%; display: block; }

.player-controls {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.track-title {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.4rem;
}

.hidden-audio { display: none; }

/* ---------- Custom audio player ---------- */

.custom-player {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  padding: 0.55rem 0.85rem;
  border: 1px solid var(--accent);
  background: transparent;
  transition: border-color var(--t-palette), background var(--t-palette);
  user-select: none;
}

.player-play-pause {
  background: transparent;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 0.3rem 0.4rem;
  font-size: 0.95rem;
  line-height: 1;
  flex-shrink: 0;
  transition: color var(--t-palette), transform 0.15s ease;
}
.player-play-pause:hover { transform: scale(1.1); }
.player-play-pause:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }

.player-time {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  transition: color var(--t-palette);
  opacity: 0.85;
}

.player-bar {
  flex: 1;
  height: 6px;
  background: rgba(255, 255, 255, 0.14);
  position: relative;
  cursor: pointer;
  transition: height 0.15s ease;
}
.player-bar:hover { height: 9px; }
.player-bar:focus-visible { outline: 1px solid var(--accent); outline-offset: 4px; }

.player-progress {
  height: 100%;
  background: var(--accent);
  width: 0%;
  transition: background var(--t-palette);
  pointer-events: none;
}

.player-thumb {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  background: var(--accent);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  left: 0%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, background var(--t-palette);
}
.player-bar:hover .player-thumb,
.custom-player:focus-within .player-thumb { opacity: 1; }

.streaming-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.4rem;
}

.streaming-links a {
  color: var(--text);
  border: 1px solid var(--accent);
  padding: 0.6rem 1rem;
  text-decoration: none;
  letter-spacing: 0.18em;
  font-size: 0.72rem;
  text-transform: uppercase;
  transition:
    background var(--t-palette),
    color var(--t-palette),
    border-color var(--t-palette);
}

.streaming-links a:hover,
.streaming-links a:focus-visible {
  background: var(--accent);
  color: var(--bg);
  outline: none;
}

/* ---------- About ---------- */

.about {
  max-width: 680px;
  margin: 0 auto;
}

.about p {
  font-size: clamp(1.05rem, 1.4vw, 1.25rem);
  line-height: 1.7;
  margin-bottom: 1.2rem;
}

/* ---------- Footer ---------- */

footer {
  padding: 2.4rem 6vw;
  text-align: center;
  font-size: 0.7rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  opacity: 0.45;
  background: var(--bg);
  color: var(--text);
  transition: background var(--t-palette), color var(--t-palette);
}

/* ---------- Motion preferences ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
  .dust-canvas { display: none; }
}

/* ---------- Mobile / touch ----------
   On phones and tablets we skip the interactive puzzle and land directly on
   the finale. The 16:9 SVG composition is shown with "meet" so all the
   drifting triangles stay visible. UI elements that only make sense on
   desktop (dust trail, "move · flip · listen" hint, reset) are hidden, and
   tap targets are bumped up. */
@media (max-width: 720px), (pointer: coarse) {
  .hero {
    height: 88vh;
    min-height: 580px;
    aspect-ratio: auto;
  }

  .dust-canvas,
  .hero-hint,
  .hero-footer .reset,
  .linework-decor {
    display: none;
  }

  /* Hide the top-left brand on mobile — the big centered FIELDBRIGHT is
     the title; the small one is redundant. */
  .brand {
    display: none;
  }

  /* Bigger taps for the primary actions, but the persistent pause button
     should stay subtle so it doesn't dominate the composition. */
  .unlock-play,
  .countdown-skip {
    font-size: 0.9rem;
    padding: 1rem 1.6rem;
    letter-spacing: 0.28em;
  }

  .audio-toggle {
    font-size: 0.65rem;
    padding: 0.5rem 0.95rem;
    letter-spacing: 0.25em;
    bottom: clamp(36px, 7vh, 80px);
  }

  /* On mobile the "you've unlocked" framing doesn't fit (no puzzle solved),
     so the eyebrow is hidden — but the "don't leave the browser" warning
     is still relevant, so we keep the title and shrink it to a subtle
     hint above the press-play button. */
  .unlock-eyebrow {
    display: none;
  }
  .unlock-title {
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    opacity: 0.7;
    margin-bottom: 0.6rem;
  }
  .unlock-prompt {
    justify-content: flex-end;
    padding-bottom: clamp(60px, 13vh, 140px);
  }

  /* Slightly smaller finale title so it doesn't crowd a narrow viewport */
  .finale-band { font-size: clamp(2.4rem, 11vw, 4.6rem); }
  .finale-song { font-size: clamp(0.78rem, 2.4vw, 1rem); letter-spacing: 0.36em; }

  /* Countdown stays prominent */
  .countdown-number { font-size: clamp(6rem, 28vw, 12rem); }
}
