/**
 * Star Weaver — star-weaver.css
 * A turn-based, watch-then-reproduce working-memory game. Deliberately NOT a
 * real-time chase (see firefly-catch.css) nor a field of tappable bubbles
 * (see pop-spiral.css): the sky is still, a sequence flashes, then you
 * retrace it. The whole visual language is calm and contemplative — soft
 * gold stars on deep violet night, gentle shimmers, nothing that flashes
 * harshly or reads as a buzzer/alarm. Forgetting is framed as stars drifting
 * back to sleep, never as failure.
 */

/* ── Reset & Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --color-bg-deep:    hsl(250, 42%, 6%);
  --color-bg-surface: hsl(250, 32%, 9%);
  --color-bg-card:    hsl(250, 26%, 12%);

  --color-text-primary: hsl(250, 20%, 93%);
  --color-text-muted:   hsl(250, 15%, 62%);
  --color-text-dim:     hsl(250, 12%, 42%);

  --font-display: 'DM Sans', sans-serif;
  --font-body:    'Inter', sans-serif;

  --text-xs:   clamp(0.65rem, 1.5vw, 0.75rem);
  --text-sm:   clamp(0.8rem, 2vw, 0.875rem);
  --text-md:   clamp(1rem, 3vw, 1.125rem);
  --text-lg:   clamp(1.1rem, 3.5vw, 1.375rem);
  --text-xl:   clamp(1.3rem, 4vw, 1.75rem);
  --text-2xl:  clamp(1.6rem, 5vw, 2.25rem);
  --text-3xl:  clamp(2rem, 6vw, 3rem);

  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-10: 2.5rem;

  --radius-sm:   6px;
  --radius-lg:   20px;
  --radius-xl:   32px;
  --radius-full: 9999px;

  --ease-bounce:   cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

  --gold-hue: 45;   /* the relevant stars — warm, inviting */
  --cool-hue: 205;  /* filler stars in filtered rounds — dimmer, blue */
  --weave-hue: 270; /* the violet thread that weaves the constellation */
}

html, body {
  height: 100%; width: 100%; overflow: hidden;
  background: var(--color-bg-deep);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
}

/* ── Ambient Background ── */
.bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.blob { position: absolute; border-radius: 50%; filter: blur(110px); opacity: 0.10; animation: blobDrift 22s ease-in-out infinite alternate; }
.blob-a { width: 460px; height: 460px; background: hsl(265, 60%, 45%); top: -160px; left: -110px; animation-duration: 26s; }
.blob-b { width: 360px; height: 360px; background: hsl(var(--gold-hue), 70%, 50%); bottom: -130px; right: -90px; animation-duration: 20s; animation-delay: -6s; }
@keyframes blobDrift { from { transform: translate(0,0) scale(1); } to { transform: translate(26px, 18px) scale(1.06); } }

/* ── Screen System ── */
.screen {
  position: fixed; inset: 0; z-index: 1;
  display: flex; flex-direction: column;
  opacity: 0; pointer-events: none;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  transition: opacity 400ms var(--ease-out-expo);
}
.screen.is-active { opacity: 1; pointer-events: all; }

.scr-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: max(env(safe-area-inset-top), 1.25rem) var(--space-6) var(--space-4);
  position: relative; z-index: 10;
}
.nav-back {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  background: hsla(250, 25%, 24%, 0.6);
  border-radius: var(--radius-full);
  color: var(--color-text-muted);
  cursor: pointer; text-decoration: none;
  transition: background 200ms, color 200ms, transform 200ms var(--ease-bounce);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border: 1px solid hsla(250, 20%, 45%, 0.18);
}
@media (hover: hover) and (pointer: fine) {
  .nav-back:hover { background: hsla(250, 25%, 32%, 0.7); color: var(--color-text-primary); transform: scale(1.05); }
}
.nav-back:active { transform: scale(0.95); }

/* ════════════ START SCREEN ════════════ */
.scr-inner { flex: 1; display: flex; flex-direction: column; padding-bottom: max(env(safe-area-inset-bottom), var(--space-8)); }
.start-inner { padding: 0 var(--space-6); gap: var(--space-6); justify-content: space-between; }

.start-hero {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-4); text-align: center; padding-top: var(--space-4);
}

/* A tiny four-star constellation, gently twinkling, threaded together — the
   logo IS the thing you do. */
.start-constellation-preview { position: relative; width: 140px; height: 110px; margin: 0 auto; }
.preview-star {
  position: absolute; width: 12px; height: 12px; border-radius: 50%;
  background: radial-gradient(circle, hsl(var(--gold-hue), 100%, 88%), hsl(var(--gold-hue), 90%, 60%));
  box-shadow: 0 0 14px hsla(var(--gold-hue), 95%, 65%, 0.8);
  animation: previewTwinkle 3.2s ease-in-out infinite;
}
.preview-star.s1 { left: 10%;  top: 60%; animation-delay: 0s; }
.preview-star.s2 { left: 38%;  top: 18%; animation-delay: 0.5s; }
.preview-star.s3 { left: 66%;  top: 52%; animation-delay: 1.0s; }
.preview-star.s4 { left: 88%;  top: 14%; animation-delay: 1.5s; }
/* the thread between them */
.start-constellation-preview::before {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(to right, transparent, transparent) ; /* placeholder; lines via box-shadow trick below */
}
@keyframes previewTwinkle { 0%, 100% { opacity: 0.55; transform: scale(0.85); } 50% { opacity: 1; transform: scale(1.1); } }

.start-title {
  font-family: var(--font-display); font-size: var(--text-3xl); font-weight: 600; letter-spacing: -0.025em;
  background: linear-gradient(135deg, hsl(var(--gold-hue), 95%, 72%) 0%, hsl(var(--weave-hue), 70%, 74%) 100%);
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.start-sub { font-size: var(--text-md); color: var(--color-text-muted); line-height: 1.65; font-weight: 300; max-width: 30ch; margin: 0 auto; }
.start-best {
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600;
  color: hsl(var(--gold-hue), 85%, 70%); margin-top: var(--space-2); min-height: 1.2em;
}
.start-best:empty { opacity: 0; }

.start-howto {
  flex: 0 1 auto; display: flex; flex-direction: column; justify-content: center;
  gap: var(--space-3); max-width: 32ch; margin: 0 auto; width: 100%;
}
.howto-row {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.4; text-align: left;
}
.howto-row b { color: var(--color-text-primary); font-weight: 600; }
.howto-ic {
  flex: 0 0 auto; width: 1.9rem; height: 1.9rem; display: flex; align-items: center; justify-content: center;
  font-size: 1.05rem; border-radius: 50%;
  background: hsla(250, 25%, 20%, 0.7); border: 1px solid hsla(250, 20%, 45%, 0.18);
}

/* ── Session length picker ── */
.start-length { display: flex; flex-direction: column; gap: var(--space-3); align-items: center; width: 100%; }
.length-label {
  font-family: var(--font-display); font-size: var(--text-xs); font-weight: 500; color: var(--color-text-dim);
  text-transform: uppercase; letter-spacing: 0.12em; text-align: center;
}
.length-row { display: flex; gap: var(--space-2); justify-content: center; flex-wrap: wrap; }
.length-btn {
  min-height: 44px; padding: 0.6rem 1.3rem;
  background: hsla(250, 25%, 16%, 0.7);
  border: 1.5px solid hsla(250, 20%, 32%, 0.25);
  border-radius: var(--radius-full);
  cursor: pointer; color: var(--color-text-muted);
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600;
  transition: background 200ms ease, border-color 200ms ease, transform 200ms var(--ease-bounce), color 200ms;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
@media (hover: hover) and (pointer: fine) {
  .length-btn:hover { background: hsla(250, 25%, 22%, 0.8); border-color: hsla(var(--gold-hue), 60%, 55%, 0.35); transform: translateY(-2px); }
}
.length-btn:active { transform: scale(0.96); }
.length-btn.is-selected {
  background: hsla(var(--gold-hue), 50%, 20%, 0.55);
  border-color: hsla(var(--gold-hue), 85%, 62%, 0.6);
  color: var(--color-text-primary);
  box-shadow: 0 0 20px hsla(var(--gold-hue), 80%, 60%, 0.18);
}

.start-footer { display: flex; justify-content: center; }
.begin-btn {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 1rem 2.5rem; border: none; border-radius: var(--radius-full);
  background: linear-gradient(135deg, hsl(var(--gold-hue), 90%, 62%) 0%, hsl(var(--weave-hue), 65%, 64%) 100%);
  color: hsl(250, 40%, 10%);
  font-family: var(--font-display); font-size: var(--text-md); font-weight: 600;
  cursor: pointer; letter-spacing: -0.01em;
  box-shadow: 0 0 40px hsla(var(--gold-hue), 85%, 60%, 0.35), 0 4px 20px hsla(250, 40%, 3%, 0.5);
  transition: transform 200ms var(--ease-bounce), box-shadow 200ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .begin-btn:hover { transform: scale(1.04) translateY(-1px); box-shadow: 0 0 60px hsla(var(--gold-hue), 85%, 60%, 0.5), 0 6px 30px hsla(250, 40%, 3%, 0.6); }
}
.begin-btn:active { transform: scale(0.97); }
.btn-icon { font-size: 1.15em; }

/* ════════════ PLAY SCREEN ════════════ */
#screen-play { position: fixed; inset: 0; display: flex; flex-direction: column; z-index: 1; }

.play-header { display: flex; align-items: center; padding: max(env(safe-area-inset-top), 1rem) var(--space-5) var(--space-3); gap: var(--space-4); z-index: 10; position: relative; }
.hud {
  flex: 1; display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  background: hsla(250, 30%, 12%, 0.6);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid hsla(250, 20%, 45%, 0.18);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-5);
}
.hud-score-col { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 84px; }
.hud-score { display: flex; flex-direction: column; align-items: center; min-width: 60px; gap: 4px; }
.hud-best-row { display: flex; align-items: center; gap: 4px; opacity: 0.75; }
.hud-label { font-family: var(--font-display); font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-text-dim); font-weight: 500; }
.hud-val { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; color: var(--color-text-primary); line-height: 1.1; transition: transform 150ms var(--ease-bounce), color 300ms; }
.hud-val.pop-anim { transform: scale(1.25); color: hsl(var(--gold-hue), 90%, 70%); }
.hud-best-label { font-family: var(--font-display); font-size: 0.52rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-text-dim); font-weight: 500; }
.hud-best-val { font-family: var(--font-display); font-size: 0.72rem; font-weight: 700; color: hsl(var(--gold-hue), 85%, 66%); }

.timer-ring { position: relative; width: 48px; height: 48px; flex-shrink: 0; }
.timer-svg { width: 48px; height: 48px; transform: rotate(-90deg); }
.timer-track { fill: none; stroke: hsla(250, 20%, 28%, 0.5); stroke-width: 3; }
.timer-arc { fill: none; stroke: hsl(var(--gold-hue), 80%, 62%); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 113.1; stroke-dashoffset: 0; transition: stroke-dashoffset 1s linear, stroke 1s ease; }
.timer-arc.warning { stroke: hsl(var(--weave-hue), 70%, 70%); }
.timer-num { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-size: 0.68rem; font-weight: 600; color: var(--color-text-primary); }

.music-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border: none; border-radius: var(--radius-full);
  background: hsla(250, 25%, 24%, 0.6);
  border: 1px solid hsla(250, 20%, 45%, 0.18);
  font-size: 1rem; opacity: 0.5; cursor: pointer;
  transition: opacity 200ms ease, background 200ms ease;
}
.music-toggle.is-on { opacity: 1; background: hsla(var(--gold-hue), 50%, 24%, 0.6); }

/* ── Scene — the night sky ── */
.scene {
  flex: 1; position: relative; overflow: hidden;
  touch-action: none;
}
.scene.is-ending { transition: opacity 1200ms var(--ease-out-expo); opacity: 0; }

/* Deep-violet night, a warm horizon glow low down. The whole sky warms one
   notch per resonance tier (a reward), via --resonance 0..1 set by JS. */
.sky {
  position: absolute; inset: 0; z-index: -1; overflow: hidden;
  transition: filter 1200ms ease;
  background:
    radial-gradient(120% 70% at 50% 108%, hsla(var(--gold-hue), 55%, 32%, calc(0.10 + var(--resonance, 0) * 0.22)) 0%, transparent 60%),
    radial-gradient(100% 80% at 50% -10%, hsla(265, 60%, 24%, 0.55) 0%, transparent 65%),
    linear-gradient(to top, hsl(252, 40%, 7%) 0%, hsl(258, 42%, 10%) 50%, hsl(248, 44%, 8%) 100%);
}

/* A field of faint background stars (decorative, non-interactive). */
.sky-stars {
  position: absolute; inset: 0;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 22%, hsla(250, 60%, 92%, 0.9), transparent),
    radial-gradient(1.2px 1.2px at 27% 64%, hsla(250, 60%, 90%, 0.7), transparent),
    radial-gradient(1.6px 1.6px at 44% 14%, hsla(250, 60%, 95%, 0.85), transparent),
    radial-gradient(1.2px 1.2px at 58% 48%, hsla(250, 60%, 90%, 0.6), transparent),
    radial-gradient(1.5px 1.5px at 71% 28%, hsla(250, 60%, 93%, 0.8), transparent),
    radial-gradient(1.2px 1.2px at 83% 70%, hsla(250, 60%, 90%, 0.6), transparent),
    radial-gradient(1.4px 1.4px at 90% 38%, hsla(250, 60%, 92%, 0.75), transparent),
    radial-gradient(1.1px 1.1px at 18% 84%, hsla(250, 60%, 90%, 0.55), transparent),
    radial-gradient(1.3px 1.3px at 36% 90%, hsla(250, 60%, 90%, 0.6), transparent),
    radial-gradient(1.2px 1.2px at 64% 82%, hsla(250, 60%, 90%, 0.55), transparent);
  animation: skyTwinkle 6s ease-in-out infinite;
}
@keyframes skyTwinkle { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.5; } }

/* The Milky Way — hidden until a milestone reveals it. */
.sky-milkyway {
  position: absolute; inset: 0; opacity: 0; transition: opacity 4s ease;
  background:
    linear-gradient(118deg, transparent 38%, hsla(255, 70%, 80%, 0.10) 46%, hsla(35, 80%, 80%, 0.08) 52%, hsla(255, 70%, 80%, 0.10) 58%, transparent 66%);
  filter: blur(8px);
}
.sky.show-milkyway .sky-milkyway { opacity: 1; }

/* The moon, low and soft; swells at the final milestone. */
.sky-moon {
  position: absolute; top: 9%; right: 14%; width: 46px; height: 46px; border-radius: 50%;
  background: radial-gradient(circle at 38% 36%, hsl(250, 30%, 96%), hsl(250, 25%, 80%) 70%, hsl(250, 22%, 66%));
  box-shadow: 0 0 36px hsla(250, 40%, 80%, 0.35);
  transition: transform 5s ease, box-shadow 5s ease;
}
.sky.moon-swell .sky-moon { transform: scale(1.55) translate(-4px, 3px); box-shadow: 0 0 64px hsla(250, 50%, 85%, 0.5); }

/* A soft central glow that strengthens with resonance. */
.sky-glow {
  position: absolute; inset: 0;
  background: radial-gradient(60% 45% at 50% 46%, hsla(var(--gold-hue), 70%, 60%, calc(var(--resonance, 0) * 0.14)) 0%, transparent 70%);
  transition: background 1200ms ease;
}

/* ── Threads + woven constellations (SVG) ── */
.thread-layer { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: visible; }
/* The live thread being traced during the flash / recall. */
.thread-line {
  fill: none; stroke: hsla(var(--weave-hue), 80%, 78%, 0.85); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 5px hsla(var(--weave-hue), 90%, 70%, 0.7));
}
/* The reverse-round thread reads visually different (amber, dashed) so the
   "run it backward" instruction is unmistakable, never an unfair trick. */
.thread-line.is-reverse { stroke: hsla(var(--gold-hue), 90%, 72%, 0.9); stroke-dasharray: 7 6; }
/* A permanently-woven constellation: faint, gold, stays for the session. */
.thread-woven {
  fill: none; stroke: hsla(var(--gold-hue), 80%, 70%, 0.34); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 3px hsla(var(--gold-hue), 85%, 65%, 0.3));
}

/* A parked (archived) constellation: a clean mini shape that fades into its
   slot in the growing star-chart. The stroke-width above is in the group's
   pre-scale units, so it stays crisp after the shrink. */
.woven-constellation { opacity: 0; transition: opacity 800ms var(--ease-out-expo); }
.woven-constellation.is-settled { opacity: 1; }
.woven-star {
  fill: hsl(var(--gold-hue), 90%, 80%);
  filter: drop-shadow(0 0 6px hsla(var(--gold-hue), 90%, 65%, 0.6));
}

/* ── Stars ── */
.star-stage { position: absolute; inset: 0; z-index: 2; }
.sw-star {
  position: absolute; width: 54px; height: 54px; /* generous tap target (>44px) */
  margin-left: -27px; margin-top: -27px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  background: none; border: none; padding: 0;
}
/* The visible star core. */
.sw-star::before {
  content: ''; width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle at 40% 38%, hsla(250, 40%, 90%, 0.95), hsla(250, 35%, 60%, 0.5) 65%, transparent);
  box-shadow: 0 0 0 hsla(250, 60%, 80%, 0);
  transition: transform 220ms var(--ease-out-expo), box-shadow 280ms ease, background 280ms ease;
}
/* Resting (dim) state while the sequence plays / before it's tappable. */
.sw-star.is-dim::before { opacity: 0.55; transform: scale(0.8); }

/* A star lighting up during the flash (and its momentary tap echo). */
.sw-star.is-flashing::before {
  background: radial-gradient(circle at 40% 38%, hsl(var(--gold-hue), 100%, 92%), hsl(var(--gold-hue), 95%, 64%) 60%, transparent);
  box-shadow: 0 0 22px 6px hsla(var(--gold-hue), 95%, 65%, 0.85);
  transform: scale(1.4);
  animation: starFlash var(--flash-on, 560ms) ease-out;
}
@keyframes starFlash {
  0% { transform: scale(0.85); }
  35% { transform: scale(1.5); }
  100% { transform: scale(1.0); }
}
/* A filler star flashing in a filtered round — cool/blue, clearly NOT gold. */
.sw-star.is-filler.is-flashing::before {
  background: radial-gradient(circle at 40% 38%, hsl(var(--cool-hue), 90%, 86%), hsl(var(--cool-hue), 80%, 58%) 60%, transparent);
  box-shadow: 0 0 18px 4px hsla(var(--cool-hue), 85%, 60%, 0.6);
}

/* Recall phase: stars are tappable. Gold targets glow softly to invite; in a
   filtered round filler stars stay clearly dimmer/cooler so "tap the gold
   ones" is legible. */
.sw-star.is-tappable.is-gold::before {
  background: radial-gradient(circle at 40% 38%, hsl(var(--gold-hue), 95%, 86%), hsl(var(--gold-hue), 85%, 58%) 62%, transparent);
  box-shadow: 0 0 12px 2px hsla(var(--gold-hue), 90%, 62%, 0.45);
  opacity: 1; transform: scale(1);
}
.sw-star.is-tappable.is-filler::before {
  background: radial-gradient(circle at 40% 38%, hsla(var(--cool-hue), 60%, 70%, 0.7), hsla(var(--cool-hue), 50%, 45%, 0.4) 60%, transparent);
  opacity: 0.6; transform: scale(0.82);
}
@media (hover: hover) and (pointer: fine) {
  .sw-star.is-tappable:hover::before { transform: scale(1.2); }
}
/* A correctly-tapped star locks bright. */
.sw-star.is-correct::before {
  background: radial-gradient(circle at 40% 38%, hsl(var(--gold-hue), 100%, 94%), hsl(var(--gold-hue), 95%, 66%) 60%, transparent);
  box-shadow: 0 0 20px 5px hsla(var(--gold-hue), 95%, 66%, 0.8);
  transform: scale(1.25);
}
/* The whole constellation shimmer when a weave completes. */
.sw-star.is-woven::before {
  background: radial-gradient(circle at 40% 38%, hsl(var(--gold-hue), 100%, 92%), hsl(var(--gold-hue), 90%, 64%) 60%, transparent);
  box-shadow: 0 0 14px 3px hsla(var(--gold-hue), 90%, 64%, 0.6);
  animation: starWeaveShimmer 900ms var(--ease-out-expo);
}
@keyframes starWeaveShimmer {
  0% { transform: scale(1.25); }
  40% { transform: scale(1.55); box-shadow: 0 0 30px 10px hsla(var(--gold-hue), 95%, 70%, 0.9); }
  100% { transform: scale(1.0); }
}
/* A star drifting back to sleep after a slip — gentle fade-down, never a
   harsh "wrong" flash. */
.sw-star.is-sleeping::before {
  animation: starSleep 800ms ease forwards;
}
@keyframes starSleep {
  0% { }
  100% { opacity: 0.28; transform: scale(0.7); box-shadow: 0 0 0 transparent; }
}
/* After the weave shimmer, the full-size stars bow out — the constellation
   lives on as the clean parked copy in the star-chart, not here. */
.sw-star.is-retiring { pointer-events: none; }
.sw-star.is-retiring::before {
  transition: opacity 500ms ease, transform 500ms var(--ease-out-expo), box-shadow 500ms ease;
  opacity: 0; transform: scale(0.5); box-shadow: 0 0 0 transparent;
}

/* ── Round-type banner ── */
.round-banner {
  position: absolute; top: 4%; left: 50%; transform: translate(-50%, -8px);
  display: flex; align-items: center; gap: var(--space-2);
  padding: 0.5rem 1.1rem; border-radius: var(--radius-full);
  background: hsla(250, 35%, 16%, 0.82);
  border: 1px solid hsla(250, 25%, 50%, 0.3);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  z-index: 6; opacity: 0; pointer-events: none;
  transition: opacity 300ms ease, transform 300ms var(--ease-out-expo);
  max-width: 86%;
}
.round-banner.is-visible { opacity: 1; transform: translate(-50%, 0); }
.round-banner.type-reverse { border-color: hsla(var(--gold-hue), 80%, 60%, 0.6); background: hsla(var(--gold-hue), 40%, 18%, 0.8); }
.round-banner.type-filtered { border-color: hsla(var(--cool-hue), 70%, 60%, 0.5); background: hsla(265, 40%, 18%, 0.82); }
.round-banner.type-filtered-reverse { border-color: hsla(var(--gold-hue), 85%, 62%, 0.7); background: hsla(20, 45%, 18%, 0.84); }
.round-banner-icon { font-size: 1.05rem; }
.round-banner-text { font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600; color: var(--color-text-primary); letter-spacing: -0.01em; }

/* ── Gentle status line (e.g. "the stars drift back to sleep") ── */
.status-line {
  position: absolute; bottom: 7%; left: 50%; transform: translate(-50%, 8px);
  padding: 0.45rem 1rem; border-radius: var(--radius-full);
  font-family: var(--font-body); font-size: var(--text-sm); font-style: italic; color: var(--color-text-muted);
  background: hsla(250, 35%, 12%, 0.6); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  z-index: 6; opacity: 0; pointer-events: none; text-align: center; max-width: 88%;
  transition: opacity 400ms ease, transform 400ms var(--ease-out-expo);
}
.status-line.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* ── Resonance meter (consecutive perfect weaves) ── */
.resonance-meter {
  position: absolute; top: 4%; right: 5%;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 0.3rem 0.7rem; border-radius: var(--radius-full);
  background: hsla(250, 30%, 16%, 0.5); border: 1px solid hsla(250, 25%, 45%, 0.25);
  z-index: 5; opacity: 0; transform: scale(0.9);
  transition: opacity 300ms ease, transform 300ms var(--ease-bounce), background 400ms ease, border-color 400ms ease, box-shadow 400ms ease;
}
.resonance-meter.is-visible { opacity: 1; transform: scale(1); }
.resonance-label { font-family: var(--font-display); font-size: 0.5rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; color: hsl(var(--gold-hue), 60%, 74%); }
.resonance-val { font-family: var(--font-display); font-weight: 800; font-size: var(--text-md); color: hsl(var(--gold-hue), 90%, 78%); }
.resonance-meter.is-pop .resonance-val { animation: resonancePop 320ms var(--ease-bounce); }
@keyframes resonancePop { 0% { transform: scale(1); } 50% { transform: scale(1.4); } 100% { transform: scale(1); } }
.resonance-meter.tier-1 { background: hsla(var(--gold-hue), 45%, 20%, 0.55); }
.resonance-meter.tier-2 { background: hsla(var(--gold-hue), 55%, 22%, 0.6); border-color: hsla(var(--gold-hue), 80%, 58%, 0.5); }
.resonance-meter.tier-3 { background: hsla(38, 65%, 24%, 0.66); border-color: hsla(var(--gold-hue), 90%, 60%, 0.6); box-shadow: 0 0 16px hsla(var(--gold-hue), 90%, 55%, 0.3); }
.resonance-meter.tier-4 { background: hsla(32, 78%, 26%, 0.72); border-color: hsla(40, 95%, 62%, 0.7); box-shadow: 0 0 26px hsla(var(--gold-hue), 95%, 58%, 0.5); }

/* ════════════ MILESTONE SCENE MOMENTS ════════════
   One-shot ambient flourishes as constellations accumulate — pure atmosphere,
   each self-removes after its animation. */
.milestone-fx-layer { position: absolute; inset: 0; pointer-events: none; z-index: 3; overflow: hidden; }
.milestone-fx { position: absolute; inset: 0; }

/* A meteor shower — several streaks crossing the upper sky. */
.fx-meteor-shower::before, .fx-meteor-shower::after,
.fx-meteor-shower .m3 {
  content: ''; position: absolute; width: 90px; height: 2px; border-radius: 2px;
  background: linear-gradient(to left, hsla(45, 100%, 92%, 0.95), transparent);
  box-shadow: 0 0 8px hsla(45, 100%, 82%, 0.8);
  transform: rotate(22deg);
  animation: fxMeteor 1600ms var(--ease-out-expo) forwards;
}
.fx-meteor-shower::before { top: 10%; left: -12%; animation-delay: 0ms; }
.fx-meteor-shower::after  { top: 22%; left: -12%; animation-delay: 420ms; }
.fx-meteor-shower .m3     { top: 16%; left: -12%; animation-delay: 820ms; display: block; }
@keyframes fxMeteor {
  0% { opacity: 0; transform: translate(0,0) rotate(22deg); }
  12% { opacity: 1; }
  100% { opacity: 0; transform: translate(120vw, 44vh) rotate(22deg); }
}

/* An aurora ripple low across the sky. */
.fx-aurora::before {
  content: ''; position: absolute; left: -10%; right: -10%; top: 18%; height: 42%;
  background: linear-gradient(180deg, transparent, hsla(155, 80%, 60%, 0.16) 40%, hsla(265, 75%, 65%, 0.14) 70%, transparent);
  filter: blur(14px); opacity: 0;
  animation: fxAurora 5200ms ease forwards;
}
@keyframes fxAurora {
  0% { opacity: 0; transform: translateX(-6%) skewX(-6deg); }
  30% { opacity: 1; }
  70% { opacity: 1; transform: translateX(6%) skewX(6deg); }
  100% { opacity: 0; }
}

/* A planet rising at the horizon. */
.fx-planet-rise::before {
  content: ''; position: absolute; left: 18%; bottom: -60px;
  width: 64px; height: 64px; border-radius: 50%;
  background: radial-gradient(circle at 36% 34%, hsl(20, 70%, 70%), hsl(12, 60%, 46%) 70%, hsl(8, 55%, 32%));
  box-shadow: 0 0 30px hsla(18, 70%, 55%, 0.4);
  animation: fxPlanetRise 6000ms var(--ease-out-expo) forwards;
}
@keyframes fxPlanetRise {
  0% { transform: translateY(0); opacity: 0.2; }
  30% { opacity: 1; }
  100% { transform: translateY(-120px); opacity: 0.9; }
}

/* The Milky-Way milestone is handled by .sky.show-milkyway (a lasting reveal),
   so fx-milky-way only needs to fire a brief caption — no extra visual. */
.fx-milky-way { }

/* ── Bloom (soft completion celebration) ── */
.bloom-layer { position: fixed; inset: 0; pointer-events: none; z-index: 25; }
.bloom-piece { position: absolute; border-radius: 50%; pointer-events: none; filter: blur(0.5px); }
@keyframes bloomDrift {
  0% { transform: translate(-50%, -50%) scale(0.4); opacity: 0; }
  20% { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1); opacity: 0; }
}

/* ════════════ SESSION-COMPLETE OVERLAY ════════════ */
.overlay {
  position: fixed; inset: 0; z-index: 30;
  display: flex; align-items: flex-start; justify-content: center;
  padding: max(env(safe-area-inset-top), var(--space-6)) var(--space-6) max(env(safe-area-inset-bottom), var(--space-6));
  overflow-y: auto;
  opacity: 0; pointer-events: none;
  transition: opacity 400ms var(--ease-out-expo);
}
.overlay.is-visible { opacity: 1; pointer-events: all; }
.overlay-bg { position: absolute; inset: 0; background: hsla(252, 40%, 5%, 0.85); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); pointer-events: none; }
.overlay-card {
  position: relative; background: hsl(250, 28%, 12%);
  border: 1px solid hsla(250, 20%, 45%, 0.22); border-radius: var(--radius-xl);
  padding: var(--space-10) var(--space-8); text-align: center;
  max-width: 380px; width: 100%;
  box-shadow: 0 24px 80px hsla(250, 40%, 3%, 0.7), 0 0 0 1px hsla(250, 20%, 45%, 0.08);
  animation: cardSlideIn 500ms var(--ease-bounce) both;
}
@keyframes cardSlideIn { from { transform: translateY(30px) scale(0.94); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
.overlay-emoji { font-size: 3.5rem; display: block; margin-bottom: var(--space-4); animation: emojiPulse 2s ease-in-out infinite; }
@keyframes emojiPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }
.overlay-title {
  font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 600; letter-spacing: -0.02em; margin-bottom: var(--space-3);
  background: linear-gradient(135deg, hsl(var(--gold-hue), 92%, 72%), hsl(var(--weave-hue), 68%, 74%));
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.overlay-msg { font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.65; margin-bottom: var(--space-8); font-weight: 300; }
.overlay-score-display { display: flex; align-items: stretch; gap: 0; background: hsla(250, 25%, 17%, 0.6); border: 1px solid hsla(250, 20%, 35%, 0.2); border-radius: var(--radius-lg); margin-bottom: var(--space-8); overflow: hidden; }
.final-stat { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--space-2); padding: var(--space-5) var(--space-3); }
.final-label { font-size: 0.58rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-dim); font-family: var(--font-display); font-weight: 500; text-align: center; line-height: 1.3; }
.final-val { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; color: var(--color-text-primary); letter-spacing: -0.02em; }
.final-divider { width: 1px; background: hsla(250, 20%, 35%, 0.3); align-self: stretch; }
.overlay-actions { display: flex; flex-direction: column; gap: var(--space-3); }
.btn-primary {
  width: 100%; padding: 0.9rem var(--space-6); border: none; border-radius: var(--radius-full);
  background: linear-gradient(135deg, hsl(var(--gold-hue), 90%, 62%) 0%, hsl(var(--weave-hue), 65%, 64%) 100%);
  color: hsl(250, 40%, 10%); font-family: var(--font-display); font-size: var(--text-md); font-weight: 600;
  cursor: pointer; box-shadow: 0 0 30px hsla(var(--gold-hue), 85%, 60%, 0.3);
  transition: transform 200ms var(--ease-bounce), box-shadow 200ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { transform: translateY(-2px) scale(1.02); box-shadow: 0 0 50px hsla(var(--gold-hue), 85%, 60%, 0.5); }
}
.btn-primary:active { transform: scale(0.97); }
.btn-ghost {
  display: block; width: 100%; padding: 0.75rem var(--space-6); border-radius: var(--radius-full);
  background: transparent; border: 1px solid hsla(250, 20%, 40%, 0.25); color: var(--color-text-muted);
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 500; text-decoration: none;
  text-align: center; cursor: pointer; transition: background 200ms ease, color 200ms ease, transform 200ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover { background: hsla(250, 20%, 20%, 0.5); color: var(--color-text-primary); transform: translateY(-1px); }
}
.btn-ghost:active { transform: scale(0.98); }

.new-record-badge {
  display: none; align-items: center; justify-content: center; gap: var(--space-2);
  margin: 0 auto var(--space-5); padding: 0.5rem 1.2rem;
  background: linear-gradient(135deg, hsl(var(--gold-hue), 75%, 22%) 0%, hsl(var(--weave-hue), 45%, 20%) 100%);
  border: 1px solid hsla(var(--gold-hue), 80%, 55%, 0.5); border-radius: var(--radius-full);
  box-shadow: 0 0 24px hsla(var(--gold-hue), 80%, 55%, 0.25);
  opacity: 0; transform: scale(0.8);
  transition: opacity 400ms var(--ease-out-expo) 200ms, transform 400ms var(--ease-bounce) 200ms;
}
.new-record-badge.is-visible { display: flex; opacity: 1; transform: scale(1); }
.record-badge-icon { font-size: 1.1rem; }
.record-badge-text { font-family: var(--font-display); font-size: var(--text-sm); font-weight: 700; color: hsl(var(--gold-hue), 85%, 78%); letter-spacing: -0.01em; }
.prev-best-line { font-family: var(--font-body); font-size: var(--text-xs); color: var(--color-text-dim); margin-bottom: var(--space-4); text-align: center; }
.next-suggestion { font-family: var(--font-body); font-size: var(--text-xs); color: var(--color-text-dim); margin-bottom: var(--space-4); text-align: center; min-height: 1em; }

/* ════════════ REDUCED MOTION ════════════
   Ambient motion is removed; progress/reward is still conveyed statically
   (resonance via the meter's tier colour + the sky's --resonance tint, which
   are not animations; milestones via a held caption + lasting sky reveals).
   The flash sequence and tap feedback keep their (brief, essential) state
   changes but drop the scaling animation, so the game stays fully playable. */
@media (prefers-reduced-motion: reduce) {
  .blob, .sky-stars, .preview-star { animation: none !important; }
  .sw-star::before { transition: box-shadow 200ms ease, background 200ms ease, opacity 200ms ease; }
  .sw-star.is-flashing::before,
  .sw-star.is-woven::before,
  .sw-star.is-correct::before { animation: none; transform: none; }
  /* Keep flashes legible without scaling: rely on brightness/glow alone. */
  .sw-star.is-flashing::before { box-shadow: 0 0 22px 6px hsla(var(--gold-hue), 95%, 65%, 0.9); }
  .fx-meteor-shower::before, .fx-meteor-shower::after, .fx-meteor-shower .m3,
  .fx-aurora::before, .fx-planet-rise::before { animation: none; opacity: 0.8; }
  /* A planet/meteor still "appears" (held), just doesn't travel. */
  .fx-planet-rise::before { bottom: 14%; transform: none; }
  .resonance-meter.is-pop .resonance-val { animation: none; }
  .bloom-piece { animation: none !important; }
  .overlay-emoji { animation: none; }
  .overlay-card { animation: none; }
  /* Parked constellations appear instantly (still a clean static shape in its
     slot) rather than fading — progress is conveyed without motion. */
  .woven-constellation { transition: none; opacity: 1; }
  .sw-star.is-retiring::before { transition: opacity 200ms ease; }
}
