/* ==========================================================================
   Englada Wedding Site — Styles
   Palette: electric yellow, crimson, ink black, bone white, dirty gold
   ========================================================================== */

:root {
  --c-yellow: #FFD60A;
  --c-crimson: #E63946;
  --c-black: #0A0A0A;
  --c-bone: #F1FAEE;
  --c-gold: #C9A227;
  --font-display: 'Bungee', 'Impact', 'Arial Black', sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: var(--font-body);
  background: var(--c-black);
  color: var(--c-bone);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
[hidden] { display: none !important; }

/* Landing screen */
.landing {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  padding: 2rem;
  text-align: center;
  background: radial-gradient(ellipse at center, #1a1a1a 0%, var(--c-black) 70%);
}

.hero-headline {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 11vw, 8rem);
  line-height: 0.9;
  letter-spacing: 0.02em;
  color: var(--c-bone);
  text-shadow: 0 0 40px rgba(255, 214, 10, 0.4);
}
.hero-headline span { display: block; }
.hero-line-1 { color: var(--c-bone); font-size: 0.5em; letter-spacing: 0.15em; }
.hero-line-2 {
  color: var(--c-yellow);
  font-size: 1.5em;
  text-shadow:
    0 0 20px rgba(255, 214, 10, 0.6),
    0 0 60px rgba(255, 214, 10, 0.3);
  animation: hero-pulse 2.5s ease-in-out infinite;
}
.hero-line-3 { font-size: 0.5em; letter-spacing: 0.15em; }

@keyframes hero-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.03); }
}

.play-button {
  display: inline-flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 2.5rem;
  background: var(--c-yellow);
  color: var(--c-black);
  font-family: var(--font-display);
  font-size: clamp(1rem, 3vw, 1.5rem);
  letter-spacing: 0.1em;
  border-radius: 999px;
  box-shadow: 0 10px 40px rgba(255, 214, 10, 0.4);
  transition: transform 0.15s ease;
}
.play-button:hover,
.play-button:focus-visible { transform: scale(1.05); outline: none; }
.play-button:active { transform: scale(0.97); }
.play-icon { font-size: 1.3em; }

.credits {
  font-family: var(--font-display);
  font-size: 0.9rem;
  letter-spacing: 0.25em;
  color: var(--c-gold);
  opacity: 0.7;
}

/* Stage (hidden until play) */
.stage {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* Lyric display */
.lyric-display {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  padding: 2rem;
  max-width: 90vw;
  text-align: center;
}

.lyric-prev,
.lyric-next {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(0.9rem, 2vw, 1.25rem);
  color: rgba(241, 250, 238, 0.35);
  min-height: 1.4em;
  transition: color 0.4s ease;
}

.lyric-current {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 6vw, 4rem);
  line-height: 1.05;
  color: var(--c-bone);
  min-height: 1.1em;
  text-shadow: 0 0 30px rgba(255, 214, 10, 0.5);
}

.lyric-flash {
  animation: lyric-flash 0.35s ease-out;
}

@keyframes lyric-flash {
  0%   { transform: scale(0.96); opacity: 0.7; }
  60%  { transform: scale(1.04); opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}

/* ---- Word-level karaoke ---------------------------------------------
   Each word of the current line is wrapped in <span class="word">.
   Three states drive the highlight:
     .word           — unsung (dimmed, waiting)
     .word.sung      — already sung (full opacity, inherits scene color)
     .word.active    — currently being sung (pops up, brighter, glows)
   Uses currentColor + filter so each scene's own color scheme is respected.
*/
.lyric-current .word {
  display: inline-block;
  opacity: 0.35;
  /* Smooth, non-springy easing. Slightly longer durations so the flip
     between unsung/active/sung feels like a crossfade rather than a snap.
     A small lookahead in app.js compensates for the added duration so
     highlights still peak in time with the vocal. */
  transition:
    opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1),
    color 0.35s cubic-bezier(0.4, 0, 0.2, 1),
    transform 0.45s cubic-bezier(0.25, 0.1, 0.25, 1),
    filter 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, opacity, filter;
}
.lyric-current .word.sung {
  opacity: 1;
}
.lyric-current .word.active {
  opacity: 1;
  transform: scale(1.08) translateY(-3px);
  filter:
    brightness(1.45)
    drop-shadow(0 0 12px rgba(255, 214, 10, 0.9))
    drop-shadow(0 0 26px rgba(255, 214, 10, 0.4));
}
/* Bridge scene previously used crimson to pop against a bone background.
   With the bridge lyric now sitting on a dark band, yellow reads better
   and matches the rest of the karaoke visual language. */
body[data-scene="bridge"] .lyric-current .word.active {
  color: var(--c-yellow);
  filter:
    brightness(1.4)
    drop-shadow(0 0 12px rgba(255, 214, 10, 0.9))
    drop-shadow(0 0 26px rgba(255, 214, 10, 0.4));
}

/* Scene backdrop (full-bleed layer behind lyrics) */
.scene-backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  transition: background 0.8s ease, filter 0.8s ease;
  background: var(--c-black);
}

/* Stage default layer order */
.stage { position: fixed; inset: 0; z-index: auto; }
.scene-overlay {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.5s ease;
}

/* --- Dance-floor silhouette crowd ---
   Hidden by default, flipped on during peak karaoke scenes.
   Sits behind other overlays; lyric band covers dancers' feet. */
.overlay-crowd {
  align-items: flex-end;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.8s ease;
  z-index: 0;
}
.crowd-svg {
  width: 100%;
  height: auto;
  max-height: 32vh;
  display: block;
  filter: drop-shadow(0 0 18px rgba(255, 214, 10, 0.35));
}
.dancer {
  transform-box: fill-box;
  transform-origin: center bottom;
  will-change: transform;
}
/* Two bop variants for organic crowd feel */
@keyframes dancer-bop {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-14px) rotate(2deg); }
}
@keyframes dancer-bop-alt {
  0%, 100% { transform: translateY(-2px) rotate(3deg) scaleX(1); }
  50%      { transform: translateY(-16px) rotate(-3deg) scaleX(-1); }
}
.dancer.d1 { animation: dancer-bop     0.54s ease-in-out 0.00s infinite; }
.dancer.d2 { animation: dancer-bop-alt 0.60s ease-in-out 0.08s infinite; }
.dancer.d3 { animation: dancer-bop     0.50s ease-in-out 0.15s infinite; }
.dancer.d4 { animation: dancer-bop-alt 0.58s ease-in-out 0.03s infinite; }
.dancer.d5 { animation: dancer-bop     0.62s ease-in-out 0.20s infinite; }
.dancer.d6 { animation: dancer-bop-alt 0.52s ease-in-out 0.10s infinite; }
.dancer.d7 { animation: dancer-bop     0.56s ease-in-out 0.25s infinite; }
.dancer.d8 { animation: dancer-bop-alt 0.60s ease-in-out 0.05s infinite; }

/* Crowd visible only during peak karaoke scenes */
body[data-scene="hook1"] .overlay-crowd,
body[data-scene="hook2"] .overlay-crowd,
body[data-scene="bridge"] .overlay-crowd,
body[data-scene="final"] .overlay-crowd {
  opacity: 1;
}

/* --- Stage lights (sweeping beams from top of stage) --- */
.stage-lights {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  /* hidden during bridge since that scene is bright white already */
  opacity: 0;
  transition: opacity 0.6s ease;
}
body[data-scene="hook1"] .stage-lights,
body[data-scene="hook2"] .stage-lights,
body[data-scene="final"] .stage-lights {
  opacity: 1;
}
.beam {
  position: absolute;
  top: -10%;
  left: 50%;
  width: clamp(90px, 14vw, 190px);
  height: 130vh;
  transform-origin: top center;
  mix-blend-mode: screen;
  filter: blur(14px);
  pointer-events: none;
  /* soft cone shape — tapers from source */
  clip-path: polygon(45% 0%, 55% 0%, 100% 100%, 0% 100%);
}
.beam-1 {
  background: linear-gradient(180deg, rgba(255,214,10,0.55) 0%, rgba(255,214,10,0.12) 55%, transparent 100%);
  animation: beam-sweep-a 3.2s ease-in-out infinite;
}
.beam-2 {
  background: linear-gradient(180deg, rgba(230,57,70,0.5) 0%, rgba(230,57,70,0.1) 55%, transparent 100%);
  animation: beam-sweep-b 3.6s ease-in-out 0.4s infinite;
}
.beam-3 {
  background: linear-gradient(180deg, rgba(241,250,238,0.4) 0%, rgba(241,250,238,0.08) 55%, transparent 100%);
  animation: beam-sweep-c 2.8s ease-in-out 0.2s infinite;
  width: clamp(70px, 10vw, 140px);
}
@keyframes beam-sweep-a {
  0%, 100% { transform: translateX(-50%) rotate(-32deg); }
  50%      { transform: translateX(-50%) rotate(32deg); }
}
@keyframes beam-sweep-b {
  0%, 100% { transform: translateX(-50%) rotate(28deg); }
  50%      { transform: translateX(-50%) rotate(-28deg); }
}
@keyframes beam-sweep-c {
  0%, 100% { transform: translateX(-50%) rotate(-18deg); }
  50%      { transform: translateX(-50%) rotate(18deg); }
}

/* --- Lit dance floor (flowing color strips beneath the dancers) --- */
.dance-floor {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 22vh;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.6s ease;
  background:
    linear-gradient(180deg, transparent 0%, rgba(255,214,10,0.18) 45%, rgba(255,214,10,0.55) 100%),
    repeating-linear-gradient(90deg,
      rgba(255,214,10,0.55) 0 40px,
      rgba(230,57,70,0.45) 40px 80px,
      rgba(241,250,238,0.35) 80px 120px,
      rgba(255,214,10,0.55) 120px 160px);
  background-size: 100% 100%, 160px 100%;
  filter: blur(1.5px);
  animation: floor-flow 1.6s linear infinite;
  box-shadow:
    0 -10px 40px rgba(255,214,10,0.3),
    inset 0 -30px 80px rgba(255,214,10,0.35);
}
body[data-scene="hook1"] .dance-floor,
body[data-scene="hook2"] .dance-floor,
body[data-scene="final"] .dance-floor {
  opacity: 1;
}
@keyframes floor-flow {
  from { background-position: 0 0, 0 0; }
  to   { background-position: 0 0, 160px 0; }
}

/* --- Per-scene themes (body[data-scene="X"]) --- */

/* INTRO — near-black with a spotlight */
body[data-scene="intro"] .scene-backdrop {
  background: radial-gradient(circle at 50% 40%, #2a2a2a 0%, var(--c-black) 60%);
}
body[data-scene="intro"] .overlay-intro { opacity: 1; }
body[data-scene="intro"] .lyric-current {
  color: var(--c-bone);
  text-shadow: 0 0 60px rgba(255, 255, 255, 0.6);
}

/* VERSE 1 — yellow on black, punk poster */
body[data-scene="verse1"] .scene-backdrop {
  background:
    repeating-linear-gradient(135deg, rgba(255,214,10,0.04) 0 4px, transparent 4px 12px),
    linear-gradient(180deg, #141414 0%, var(--c-black) 100%);
}
body[data-scene="verse1"] .lyric-current {
  color: var(--c-yellow);
  text-shadow: 0 0 40px rgba(255, 214, 10, 0.7);
  animation: lyric-flash 0.35s ease-out, verse-jitter 3s ease-in-out infinite;
}

@keyframes verse-jitter {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  25%      { transform: translateX(-2px) rotate(-0.3deg); }
  75%      { transform: translateX(2px) rotate(0.3deg); }
}

/* HOOK 1 & HOOK 2 — the big moment */
body[data-scene="hook1"] .scene-backdrop,
body[data-scene="hook2"] .scene-backdrop {
  background:
    radial-gradient(circle at 30% 40%, rgba(230,57,70,0.3) 0%, transparent 50%),
    radial-gradient(circle at 70% 60%, rgba(255,214,10,0.25) 0%, transparent 50%),
    var(--c-black);
  animation: hook-pulse 0.8s ease-in-out infinite alternate;
}
body[data-scene="hook1"] .lyric-current,
body[data-scene="hook2"] .lyric-current {
  color: var(--c-yellow);
  font-size: clamp(2rem, 7vw, 5rem);
  text-shadow:
    0 0 30px var(--c-yellow),
    0 0 80px var(--c-crimson);
}
body[data-scene="hook1"] .overlay-hook,
body[data-scene="hook2"] .overlay-hook { opacity: 1; }

@keyframes hook-pulse {
  from { filter: brightness(1); }
  to   { filter: brightness(1.2); }
}

/* VERSE 2 — red-dominant, legacy vibe */
body[data-scene="verse2"] .scene-backdrop {
  background:
    radial-gradient(ellipse at bottom, rgba(230,57,70,0.4) 0%, transparent 60%),
    linear-gradient(180deg, #1a0a0a 0%, var(--c-black) 100%);
}
body[data-scene="verse2"] .lyric-current {
  color: var(--c-bone);
  text-shadow: 0 0 40px rgba(230, 57, 70, 0.8);
}

/* BRIDGE — high-contrast, gentle pulse (was hard strobe, too seizure-y) */
body[data-scene="bridge"] .scene-backdrop {
  background: var(--c-bone);
  animation: bridge-strobe 1.6s ease-in-out infinite alternate;
}
body[data-scene="bridge"] .lyric-current {
  color: var(--c-black);
  font-size: clamp(2rem, 8vw, 5rem);
  text-shadow: none;
}
body[data-scene="bridge"] .lyric-prev,
body[data-scene="bridge"] .lyric-next { color: rgba(10, 10, 10, 0.4); }
body[data-scene="bridge"] .overlay-bridge { opacity: 1; pointer-events: auto; cursor: pointer; }

@keyframes bridge-strobe {
  from { background: var(--c-bone); }
  to   { background: #FFF5B0; }
}

/* FINAL — all colors, confetti ramp */
body[data-scene="final"] .scene-backdrop {
  background:
    radial-gradient(circle at 20% 30%, rgba(255,214,10,0.4) 0%, transparent 40%),
    radial-gradient(circle at 80% 70%, rgba(230,57,70,0.4) 0%, transparent 40%),
    radial-gradient(circle at 50% 90%, rgba(201,162,39,0.3) 0%, transparent 50%),
    var(--c-black);
}
body[data-scene="final"] .lyric-current {
  color: var(--c-yellow);
  text-shadow: 0 0 50px var(--c-crimson), 0 0 80px var(--c-yellow);
}

/* OUTRO — gold-leaf glow, freeze frame */
body[data-scene="outro"] .scene-backdrop {
  background:
    radial-gradient(ellipse at center, rgba(201,162,39,0.6) 0%, transparent 70%),
    var(--c-black);
}
body[data-scene="outro"] .overlay-outro { opacity: 1; pointer-events: auto; }

/* Hook mega overlay */
.overlay-hook .hook-mega {
  font-family: var(--font-display);
  font-size: clamp(3rem, 14vw, 11rem);
  line-height: 0.85;
  color: var(--c-yellow);
  text-align: center;
  letter-spacing: 0.01em;
  -webkit-text-stroke: 3px var(--c-black);
  text-shadow:
    8px 8px 0 var(--c-crimson),
    16px 16px 0 rgba(0, 0, 0, 0.6);
  animation: hook-slam 0.8s ease-in-out infinite alternate;
  mix-blend-mode: screen;
  opacity: 0.18;
}

@keyframes hook-slam {
  0%   { transform: scale(1) rotate(-1deg); }
  100% { transform: scale(1.04) rotate(1deg); }
}
/* Outro: hide the karaoke ticker entirely — the .freeze text, confetti,
   and REPLAY button are the complete visual story for this moment. The
   final lyric line ("Let's gooooo 🔥") would only collide with the freeze. */
body[data-scene="outro"] .lyric-display { display: none; }

/* Bridge overlay: chant + HEY! pop */
.overlay-bridge {
  flex-direction: column;
  gap: 2rem;
}
.overlay-bridge .chant {
  font-family: var(--font-display);
  font-size: clamp(3rem, 13vw, 10rem);
  color: var(--c-black);
  letter-spacing: 0.05em;
  -webkit-text-stroke: 4px var(--c-yellow);
  animation: chant-bounce 0.5s ease-in-out infinite alternate;
}

@keyframes chant-bounce {
  from { transform: translateY(0) scale(1); }
  to   { transform: translateY(-8px) scale(1.05); }
}

.overlay-bridge .hey {
  position: absolute;
  top: 15%;
  right: 10%;
  font-family: var(--font-display);
  font-size: clamp(2rem, 10vw, 8rem);
  color: var(--c-crimson);
  -webkit-text-stroke: 4px var(--c-black);
  transform: rotate(-8deg) scale(0);
  transition: transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 1.94);
  pointer-events: none;
}

.overlay-bridge .hey.hey-pop-active {
  animation: hey-pop 0.6s ease-out forwards;
}

@keyframes hey-pop {
  0%   { transform: rotate(-8deg) scale(0); opacity: 0; }
  20%  { transform: rotate(-8deg) scale(1.4); opacity: 1; }
  60%  { transform: rotate(-4deg) scale(1);   opacity: 1; }
  100% { transform: rotate(-4deg) scale(0.9); opacity: 0; }
}

/* Make the whole bridge section respond to taps */
body[data-scene="bridge"] .stage { cursor: pointer; }

/* Outro overlay */
.overlay-outro {
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem 1rem;
}

/* Couple photo — chibi portrait of Josiah & Olivia, centered between the
   freeze text and replay button. Enters with a scale+fade when the outro
   scene activates, then gently floats while idle. Confetti rains over it
   because .confetti is absolutely positioned with pointer-events: none. */
.couple-photo {
  width: min(38vh, 300px);
  max-width: 78vw;
  aspect-ratio: 1 / 1;
  height: auto;
  object-fit: cover;
  border-radius: 24px;
  border: 3px solid var(--c-gold);
  box-shadow:
    0 0 60px rgba(201, 162, 39, 0.55),
    0 0 120px rgba(201, 162, 39, 0.22),
    0 12px 40px rgba(0, 0, 0, 0.6);
  background: var(--c-black);
  opacity: 0;
  transform: scale(0.86) translateY(18px);
  transition:
    opacity 0.9s cubic-bezier(0.4, 0, 0.2, 1),
    transform 1.2s cubic-bezier(0.2, 0.9, 0.3, 1);
}
/* Reveal only when the outro scene is active, with a tiny delay so the
   entrance feels like it arrives with the freeze text, not before it. */
body[data-scene="outro"] .couple-photo {
  opacity: 1;
  transform: scale(1) translateY(0);
  animation: couple-float 5s ease-in-out 1.4s infinite alternate;
}
@keyframes couple-float {
  from { transform: scale(1)    translateY(0); }
  to   { transform: scale(1.02) translateY(-6px); }
}
.overlay-outro .freeze {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 6.5vw, 4.75rem);
  color: var(--c-gold);
  text-align: center;
  line-height: 1;
  text-shadow:
    0 0 40px rgba(201, 162, 39, 0.8),
    0 0 80px rgba(201, 162, 39, 0.4);
  animation: freeze-glow 3s ease-in-out infinite;
}

/* ---- Wedding scene elements (outro only) ---------------------------- */

/* "JUST MARRIED" stamp banner: gold block, black text, tilted like a
   banner pinned to a wall. Pulses its glow to feel celebratory. */
.overlay-outro .just-married {
  font-family: var(--font-display);
  font-size: clamp(0.9rem, 2.6vw, 1.4rem);
  letter-spacing: 0.35em;
  color: var(--c-black);
  background: linear-gradient(135deg, var(--c-gold) 0%, var(--c-yellow) 50%, var(--c-gold) 100%);
  padding: 0.45rem 1.4rem 0.4rem;
  transform: rotate(-3deg) scale(0.9);
  box-shadow:
    0 0 40px rgba(201, 162, 39, 0.6),
    0 4px 16px rgba(0, 0, 0, 0.45),
    inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  opacity: 0;
  transition:
    opacity 0.7s cubic-bezier(0.4, 0, 0.2, 1) 0.2s,
    transform 0.9s cubic-bezier(0.2, 0.9, 0.3, 1.2) 0.2s;
}
body[data-scene="outro"] .just-married {
  opacity: 1;
  transform: rotate(-3deg) scale(1);
  animation: just-married-pulse 2.8s ease-in-out 1.2s infinite alternate;
}
/* "(ALMOST)" qualifier: smaller, lighter, reads as a wink-wink prefix.
   JS removes it once the ceremony time (2026-04-10 17:30 local) passes. */
.overlay-outro .just-married .almost {
  font-size: 0.72em;
  opacity: 0.78;
  letter-spacing: 0.18em;
  font-style: italic;
}
@keyframes just-married-pulse {
  from {
    box-shadow:
      0 0 40px rgba(201, 162, 39, 0.6),
      0 4px 16px rgba(0, 0, 0, 0.45),
      inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  }
  to {
    box-shadow:
      0 0 70px rgba(255, 214, 10, 0.9),
      0 4px 22px rgba(0, 0, 0, 0.55),
      inset 0 0 0 2px rgba(255, 255, 255, 0.6);
  }
}

/* Interlocking wedding rings — inline SVG so we can color via gradient
   and stay sharp at any zoom. Glints on a slow loop. */
.overlay-outro .wedding-rings {
  width: min(16vh, 110px);
  height: auto;
  filter: drop-shadow(0 0 18px rgba(255, 214, 10, 0.55));
  opacity: 0;
  transform: translateY(8px) scale(0.92);
  transition:
    opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1) 0.5s,
    transform 1s cubic-bezier(0.2, 0.9, 0.3, 1) 0.5s;
}
body[data-scene="outro"] .wedding-rings {
  opacity: 1;
  transform: translateY(0) scale(1);
  animation: rings-glint 4.5s ease-in-out 1.6s infinite;
}
@keyframes rings-glint {
  0%, 100% { filter: drop-shadow(0 0 18px rgba(255, 214, 10, 0.55)); }
  50%      { filter: drop-shadow(0 0 36px rgba(255, 214, 10, 0.95)); }
}

/* Wedding date stamp, small and letter-spaced under the couple photo. */
.overlay-outro .wedding-date {
  font-family: var(--font-display);
  font-size: clamp(0.75rem, 1.6vw, 1rem);
  letter-spacing: 0.4em;
  color: var(--c-gold);
  text-shadow: 0 0 14px rgba(255, 214, 10, 0.55);
  opacity: 0;
  transition: opacity 1.1s cubic-bezier(0.4, 0, 0.2, 1) 1.7s;
}
body[data-scene="outro"] .wedding-date {
  opacity: 1;
}

/* Twinkling sparkles layered on the outro backdrop. Two pseudo-layers
   with different sizes and animation delays create a sense of depth
   without adding a single DOM node. */
body[data-scene="outro"] .scene-backdrop::before,
body[data-scene="outro"] .scene-backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1.5px 1.5px at 12% 18%, rgba(255, 214, 10, 0.9), transparent 70%),
    radial-gradient(2px   2px   at 78% 34%, rgba(255, 255, 255, 0.85), transparent 70%),
    radial-gradient(1px   1px   at 46% 62%, rgba(201, 162, 39, 0.9), transparent 70%),
    radial-gradient(1.5px 1.5px at 88% 80%, rgba(255, 214, 10, 0.75), transparent 70%),
    radial-gradient(1px   1px   at 22% 88%, rgba(255, 255, 255, 0.7), transparent 70%),
    radial-gradient(2px   2px   at 64% 14%, rgba(201, 162, 39, 0.85), transparent 70%),
    radial-gradient(1.5px 1.5px at 32% 44%, rgba(255, 255, 255, 0.75), transparent 70%),
    radial-gradient(1px   1px   at 92% 56%, rgba(255, 214, 10, 0.85), transparent 70%);
  background-size: 220px 220px;
  background-repeat: repeat;
  animation: twinkle 4s ease-in-out infinite alternate;
}
body[data-scene="outro"] .scene-backdrop::after {
  background-size: 340px 340px;
  background-position: 50% 50%;
  animation: twinkle 6s ease-in-out 1.5s infinite alternate;
  opacity: 0.7;
}
@keyframes twinkle {
  from { opacity: 0.25; }
  to   { opacity: 1; }
}

/* Landscape phones: rings get crowded, hide them to free vertical space. */
@media (max-height: 560px) {
  .overlay-outro .wedding-rings { display: none; }
  .overlay-outro { gap: 0.6rem; }
  .overlay-outro .couple-photo { width: min(28vh, 200px); }
}

@keyframes freeze-glow {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.3); }
}

/* ==========================================================================
   FINALE POP — triggered when <audio> fires 'ended'. body gets .finale
   and everything on the outro scene jumps up a notch: freeze text and
   couple photo burst-scale with a huge gold bloom, backdrop warms up,
   and a quick radial flash punches the moment home.
   ========================================================================== */

/* Backdrop warming flash: brightens the existing outro gradient, then
   settles at a slightly warmer baseline than normal outro. */
body.finale .scene-backdrop {
  animation: finale-backdrop-flash 2.4s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
}
@keyframes finale-backdrop-flash {
  0%   { filter: brightness(1)   saturate(1); }
  12%  { filter: brightness(2.1) saturate(1.6); }
  30%  { filter: brightness(1.5) saturate(1.3); }
  100% { filter: brightness(1.2) saturate(1.15); }
}

/* Freeze text ("JOSIAH · OLIVIA / ENGLADA") — big scale + gold bloom,
   overrides the gentle freeze-glow loop. */
body.finale .overlay-outro .freeze {
  animation: freeze-finale-pop 2.4s cubic-bezier(0.2, 0.9, 0.3, 1.2) forwards;
}
@keyframes freeze-finale-pop {
  0% {
    transform: scale(1);
    text-shadow:
      0 0 40px rgba(201, 162, 39, 0.8),
      0 0 80px rgba(201, 162, 39, 0.4);
  }
  28% {
    transform: scale(1.2);
    text-shadow:
      0 0 90px rgba(255, 214, 10, 1),
      0 0 180px rgba(255, 214, 10, 0.85),
      0 0 260px rgba(255, 214, 10, 0.5),
      0 0 40px rgba(255, 255, 255, 0.9);
  }
  60% {
    transform: scale(1.07);
    text-shadow:
      0 0 60px rgba(255, 214, 10, 0.95),
      0 0 130px rgba(255, 214, 10, 0.65),
      0 0 200px rgba(255, 214, 10, 0.35);
  }
  100% {
    transform: scale(1.1);
    text-shadow:
      0 0 70px rgba(255, 214, 10, 1),
      0 0 150px rgba(255, 214, 10, 0.75),
      0 0 230px rgba(255, 214, 10, 0.4);
  }
}

/* Couple photo — scale burst + massive gold halo, overrides couple-float. */
body.finale .couple-photo {
  animation: couple-finale-pop 2.4s cubic-bezier(0.2, 0.9, 0.3, 1.3) forwards;
}
@keyframes couple-finale-pop {
  0% {
    transform: scale(1) translateY(0);
    box-shadow:
      0 0 60px rgba(201, 162, 39, 0.55),
      0 0 120px rgba(201, 162, 39, 0.22),
      0 12px 40px rgba(0, 0, 0, 0.6);
    filter: brightness(1) saturate(1);
  }
  28% {
    transform: scale(1.18) translateY(-12px);
    box-shadow:
      0 0 140px rgba(255, 214, 10, 1),
      0 0 280px rgba(255, 214, 10, 0.65),
      0 0 60px rgba(255, 255, 255, 0.7),
      0 14px 50px rgba(0, 0, 0, 0.6);
    filter: brightness(1.4) saturate(1.3);
  }
  60% {
    transform: scale(1.06) translateY(-5px);
    box-shadow:
      0 0 100px rgba(255, 214, 10, 0.85),
      0 0 220px rgba(255, 214, 10, 0.5),
      0 0 40px rgba(255, 255, 255, 0.4),
      0 12px 44px rgba(0, 0, 0, 0.6);
    filter: brightness(1.2) saturate(1.15);
  }
  100% {
    transform: scale(1.08) translateY(-7px);
    box-shadow:
      0 0 120px rgba(255, 214, 10, 0.95),
      0 0 250px rgba(255, 214, 10, 0.55),
      0 0 48px rgba(255, 255, 255, 0.45),
      0 12px 44px rgba(0, 0, 0, 0.6);
    filter: brightness(1.25) saturate(1.2);
  }
}

/* Just-married banner gets an extra glow burst too. */
body.finale .just-married {
  animation: just-married-finale 2.4s cubic-bezier(0.2, 0.9, 0.3, 1.2) forwards !important;
}
@keyframes just-married-finale {
  0% {
    transform: rotate(-3deg) scale(1);
    box-shadow:
      0 0 40px rgba(201, 162, 39, 0.6),
      0 4px 16px rgba(0, 0, 0, 0.45),
      inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  }
  28% {
    transform: rotate(-2deg) scale(1.18);
    box-shadow:
      0 0 120px rgba(255, 214, 10, 1),
      0 0 220px rgba(255, 214, 10, 0.7),
      0 6px 24px rgba(0, 0, 0, 0.55),
      inset 0 0 0 3px rgba(255, 255, 255, 0.9);
  }
  100% {
    transform: rotate(-3deg) scale(1.08);
    box-shadow:
      0 0 90px rgba(255, 214, 10, 0.9),
      0 0 180px rgba(255, 214, 10, 0.5),
      0 5px 20px rgba(0, 0, 0, 0.5),
      inset 0 0 0 2px rgba(255, 255, 255, 0.6);
  }
}

.replay-button {
  font-family: var(--font-display);
  font-size: 1.1rem;
  letter-spacing: 0.2em;
  padding: 1rem 2.5rem;
  background: transparent;
  border: 2px solid var(--c-gold);
  color: var(--c-gold);
  border-radius: 999px;
  transition: all 0.2s ease;
  pointer-events: auto;
}
.replay-button:hover { background: var(--c-gold); color: var(--c-black); }

/* Confetti */
.confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.confetti-piece {
  position: absolute;
  top: -20px;
  width: 10px;
  height: 16px;
  display: block;
  animation: confetti-fall linear forwards;
}

@keyframes confetti-fall {
  to { transform: translateY(110vh) rotate(720deg); }
}

/* Author mode overlay */
#author-overlay {
  position: fixed;
  top: 0; right: 0;
  width: min(420px, 100vw);
  height: 100vh;
  background: rgba(10, 10, 10, 0.92);
  color: var(--c-bone);
  font-family: var(--font-body);
  font-size: 0.85rem;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  border-left: 2px solid var(--c-yellow);
}
#author-overlay .author-header {
  padding: 0.75rem;
  border-bottom: 1px solid rgba(255,214,10,0.3);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
#author-overlay .author-header strong { color: var(--c-yellow); }
#author-overlay kbd {
  background: var(--c-yellow);
  color: var(--c-black);
  padding: 2px 6px;
  border-radius: 3px;
  font-family: monospace;
  font-size: 0.75rem;
}
#author-overlay button {
  padding: 0.3rem 0.75rem;
  background: var(--c-yellow);
  color: var(--c-black);
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  margin-left: auto;
}
#author-overlay .author-list {
  flex: 1;
  overflow-y: auto;
  list-style: none;
  padding: 0.5rem;
  margin: 0;
}
#author-overlay .author-list li {
  padding: 0.4rem 0.6rem;
  border-radius: 4px;
  margin-bottom: 2px;
  line-height: 1.3;
  color: rgba(241,250,238,0.5);
  cursor: pointer;
}
#author-overlay .author-list li .t {
  display: inline-block;
  width: 4.5em;
  font-family: monospace;
  font-size: 0.75rem;
  color: var(--c-gold);
}
#author-overlay .author-list li.done { color: rgba(241,250,238,0.7); }
#author-overlay .author-list li.current {
  background: rgba(255,214,10,0.15);
  color: var(--c-yellow);
  font-weight: 700;
}
#author-overlay #author-output {
  position: absolute;
  inset: 0;
  background: var(--c-black);
  color: var(--c-yellow);
  padding: 1rem;
  overflow: auto;
  font-family: monospace;
  font-size: 0.75rem;
  white-space: pre;
  border: 2px solid var(--c-yellow);
  z-index: 2;
}

/* ---- Volume control ------------------------------------------------
   Discrete top-right pill. Idles at 35% opacity so it stays out of the
   way during the visual moments, pops to full on hover/focus. Uses a
   frosted backdrop so it sits inside the scene rather than on top of it.
*/
.volume-control {
  position: fixed;
  top: max(1rem, env(safe-area-inset-top, 0px));
  right: max(1rem, env(safe-area-inset-right, 0px));
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.85rem;
  background: rgba(10, 10, 10, 0.45);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  border: 1px solid rgba(241, 250, 238, 0.18);
  border-radius: 999px;
  opacity: 0.35;
  transition: opacity 0.25s ease, background 0.25s ease;
  pointer-events: auto;
}
.volume-control:hover,
.volume-control:focus-within {
  opacity: 1;
  background: rgba(10, 10, 10, 0.7);
}
.volume-control .volume-label {
  font-family: var(--font-display);
  font-size: 0.65rem;
  letter-spacing: 0.15em;
  color: var(--c-bone);
  user-select: none;
}
#volume-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 90px;
  height: 3px;
  background: rgba(241, 250, 238, 0.25);
  border-radius: 999px;
  outline: none;
  cursor: pointer;
  margin: 0;
}
#volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  background: var(--c-yellow);
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 0 8px rgba(255, 214, 10, 0.6);
  border: none;
  transition: transform 0.15s ease;
}
#volume-slider::-webkit-slider-thumb:hover {
  transform: scale(1.2);
}
#volume-slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  background: var(--c-yellow);
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 0 8px rgba(255, 214, 10, 0.6);
  border: none;
  transition: transform 0.15s ease;
}
#volume-slider::-moz-range-thumb:hover {
  transform: scale(1.2);
}
#volume-slider:focus-visible {
  box-shadow: 0 0 0 2px rgba(255, 214, 10, 0.5);
  border-radius: 999px;
}

/* ---- Hook / Bridge collision fix -----------------------------------
   The giant scene overlays (.hook-mega, .chant) and the karaoke lyrics
   were both centered on the same point, piling on top of each other when
   the song gets busy. During these "peak" scenes, push the karaoke line
   down to the bottom of the stage so the mega-text owns center, and give
   the lyric a dark gradient band so it stays readable against pulsing
   gradients (hooks) and strobing bone/yellow (bridge).
*/
body[data-scene="hook1"] .stage,
body[data-scene="hook2"] .stage,
body[data-scene="bridge"] .stage {
  justify-content: flex-end;
  padding-bottom: max(4vh, 1.5rem);
}

body[data-scene="hook1"] .lyric-display,
body[data-scene="hook2"] .lyric-display,
body[data-scene="bridge"] .lyric-display {
  width: 100%;
  max-width: 100vw;
  padding: 1.25rem 1.5rem 1.75rem;
  background: linear-gradient(
    180deg,
    rgba(10, 10, 10, 0) 0%,
    rgba(10, 10, 10, 0.78) 55%,
    rgba(10, 10, 10, 0.92) 100%
  );
}

/* Hide prev/next context lines on peak scenes — less clutter, single line reads cleaner. */
body[data-scene="hook1"] .lyric-prev,
body[data-scene="hook1"] .lyric-next,
body[data-scene="hook2"] .lyric-prev,
body[data-scene="hook2"] .lyric-next,
body[data-scene="bridge"] .lyric-prev,
body[data-scene="bridge"] .lyric-next {
  display: none;
}

/* Bridge: the earlier rule sets lyric-current to black for the bone background.
   Now that the lyric sits on a dark band instead, swap to bone + yellow accents. */
body[data-scene="bridge"] .lyric-current {
  color: var(--c-bone);
  text-shadow: 0 0 24px rgba(255, 214, 10, 0.5);
}
body[data-scene="bridge"] .lyric-current .word.active {
  color: var(--c-yellow);
  filter:
    brightness(1.4)
    drop-shadow(0 0 10px rgba(255, 214, 10, 0.9))
    drop-shadow(0 0 22px rgba(255, 214, 10, 0.4));
}

/* Keep the giant hook-mega inside the viewport on narrow screens
   (was running off the edges in portrait / small landscape). */
.overlay-hook .hook-mega {
  font-size: clamp(2.25rem, 11vw, 9rem);
  max-width: 96vw;
  word-break: normal;
}

/* Mobile safe-area and polish */
@supports (padding: max(0px)) {
  .landing, .overlay-outro {
    padding-top:    max(2rem, env(safe-area-inset-top));
    padding-bottom: max(2rem, env(safe-area-inset-bottom));
  }
}

/* Small phones: tighten spacing */
@media (max-width: 480px) {
  .landing { gap: 1.5rem; padding: 1.25rem; }
  .lyric-display { padding: 1rem; gap: 0.5rem; }
  .play-button { padding: 1rem 2rem; }
  #author-overlay { width: 100vw; border-left: none; border-top: 2px solid var(--c-yellow); height: 100vh; }
}

/* Landscape phones: shrink hero so play button fits on screen */
@media (max-height: 500px) and (orientation: landscape) {
  .hero-headline { font-size: clamp(2rem, 8vh, 5rem); }
  .landing { gap: 1rem; }
}

/* Reduced motion — respect user preference */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.15s !important;
  }
  .hero-line-2, .scene-backdrop, .hook-mega, .chant, .freeze { animation: none !important; }
}

/* Prevent lyric text from getting clipped on narrow viewports */
.lyric-current, .lyric-prev, .lyric-next {
  word-break: break-word;
  hyphens: auto;
}
