/* ============================================================================
 * Lyrics overlay — multiple "music-video" styles plus kinetic per-word reveal
 * and beat/drop-driven kick + glitch animations.
 * ========================================================================== */

#lyrics {
  position: absolute;
  text-align: center;
  /* Default coloring: palette hue + dark drop shadow. --lyric-sat / --lyric-light
     are pushed from settings.js (white mode = sat 0); --lyric-hue is set per
     line by lyrics.js. Per-style rules below override these for their own look. */
  color: hsl(var(--lyric-hue, 200), var(--lyric-sat, 95%), var(--lyric-light, 78%));
  text-shadow: 0 4px 30px rgba(0,0,0,0.85),
               0 0 30px hsla(var(--lyric-hue, 200), var(--lyric-sat, 95%), 50%, 0.5);
  letter-spacing: -0.02em;
  line-height: 0.95;
  max-width: 90vw;
  opacity: 0;
  pointer-events: none;
  text-transform: uppercase;
  z-index: 5;
  font-weight: 900;
  left: 50%;
  transform: translateX(-50%);
  transition: opacity 0.35s ease,
              transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}

#lyrics[data-style="0"] { top: 50%;    transform: translate(-50%, -50%); font-size: calc(clamp(50px,  9vw, 140px) * var(--lyric-scale, 1)); }
#lyrics[data-style="1"] { bottom: 16%;                                   font-size: calc(clamp(32px, 5.5vw,  88px) * var(--lyric-scale, 1)); }
#lyrics[data-style="2"] { top: 12%;                                      font-size: calc(clamp(36px, 6.5vw, 100px) * var(--lyric-scale, 1)); }
#lyrics[data-style="3"] { top: 50%;    transform: translate(-50%, -50%); font-size: calc(clamp(60px, 12vw, 180px) * var(--lyric-scale, 1)); font-style: italic; }
#lyrics[data-style="4"] {
  bottom: 25%; left: 6%; transform: none;
  text-align: left;
  font-size: calc(clamp(36px, 6vw, 92px) * var(--lyric-scale, 1));
  max-width: 60vw;
}
#lyrics[data-style="5"] {
  top: 35%;
  transform: translate(-50%, 0) rotate(-2deg);
  font-size: calc(clamp(44px, 8vw, 120px) * var(--lyric-scale, 1));
}

#lyrics.show                     { opacity: 1; }
#lyrics.show[data-style="0"]     { transform: translate(-50%, calc(-50% - 8px)); }
#lyrics.show[data-style="3"]     { transform: translate(-50%, calc(-50% - 8px)) skewX(-3deg); }
#lyrics.show[data-style="5"]     { transform: translate(-50%, -8px) rotate(-2deg); }

/* ----------------------------------------------------------------------------
 * Additional styles (6–15). Each one overrides whatever it needs from the base
 * — color, text-shadow, position, weight, font — so they read as visually
 * distinct rather than minor variations.
 * -------------------------------------------------------------------------- */

/* 6. Outline — bold transparent fill with a white stroke. Reads like a poster. */
#lyrics[data-style="6"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(60px, 12vw, 180px) * var(--lyric-scale, 1));
  color: transparent;
  -webkit-text-stroke: 2px #fff;
  text-shadow: 0 0 25px rgba(0,0,0,0.5);
  letter-spacing: -0.04em;
}
#lyrics.show[data-style="6"] { transform: translate(-50%, calc(-50% - 8px)); }

/* 7. Neon — saturated colored halo, palette-tinted. */
#lyrics[data-style="7"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(56px, 10vw, 160px) * var(--lyric-scale, 1));
  color: #fff;
  text-shadow:
    0 0 6px  #fff,
    0 0 14px hsl(var(--lyric-hue, 200), 100%, 65%),
    0 0 36px hsl(var(--lyric-hue, 200), 100%, 55%),
    0 0 70px hsl(var(--lyric-hue, 200), 100%, 50%);
}
#lyrics.show[data-style="7"] { transform: translate(-50%, calc(-50% - 8px)); }

/* 8. Cinematic — small lowercase subtitle at the bottom, like a film. */
#lyrics[data-style="8"] {
  bottom: 10%;
  font-size: calc(clamp(22px, 3vw, 44px) * var(--lyric-scale, 1));
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  color: #f7f7f7;
  text-shadow: 0 2px 18px rgba(0,0,0,0.95);
}

/* 9. Gradient Fade — text fades vertically from solid white at the top
   through the palette hue toward a deeper hue at the bottom. PREVIOUSLY
   the gradient ended at `transparent 100%` so the bottom 20% of each
   letter rendered with zero alpha; on dark backgrounds the descender
   half of the line was effectively missing, reading as "black/cut-off"
   text. Fix: end the gradient on a darker fully-opaque hue so the whole
   letter is always visible, while still keeping the top-bright /
   bottom-dim fade-through-hue feel. */
#lyrics[data-style="9"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(60px, 11vw, 170px) * var(--lyric-scale, 1));
  color: transparent;
  background: linear-gradient(180deg,
    #fff 30%,
    hsl(var(--lyric-hue, 200), 95%, 65%) 70%,
    hsl(var(--lyric-hue, 200), 95%, 40%) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  text-shadow: 0 4px 22px rgba(0,0,0,0.85);
}
#lyrics.show[data-style="9"] { transform: translate(-50%, calc(-50% - 8px)); }

/* 10. 3D Stack — stacked drop shadows give a chunky depth. */
#lyrics[data-style="10"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(56px, 10vw, 160px) * var(--lyric-scale, 1));
  color: #fff;
  text-shadow:
    2px 2px 0  rgba(0,0,0,0.65),
    4px 4px 0  rgba(0,0,0,0.55),
    6px 6px 0  rgba(0,0,0,0.45),
    8px 8px 0  rgba(0,0,0,0.35),
   10px 10px 0 rgba(0,0,0,0.25),
   12px 12px 30px rgba(0,0,0,0.45);
}
#lyrics.show[data-style="10"] { transform: translate(-50%, calc(-50% - 8px)); }

/* 11. Cyber Chip — bordered box in the top-right with a subtle blur. */
#lyrics[data-style="11"] {
  top: 14%;
  right: 6%;
  left: auto;
  transform: none;
  font-size: calc(clamp(24px, 3.6vw, 52px) * var(--lyric-scale, 1));
  padding: 10px 22px;
  border: 2px solid rgba(255,255,255,0.85);
  letter-spacing: 0.18em;
  word-spacing: 0.55em;
  color: #fff;
  background: rgba(0,0,0,0.32);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  text-shadow: 0 0 14px hsla(var(--lyric-hue, 200), 95%, 70%, 0.65);
  max-width: 80vw;
}

/* 12. Karaoke Wipe — animated highlight sweeps from left to right. */
#lyrics[data-style="12"] {
  bottom: 22%;
  font-size: calc(clamp(40px, 7vw, 110px) * var(--lyric-scale, 1));
  color: transparent;
  background: linear-gradient(90deg,
    #fff 0%, #fff 50%,
    hsla(var(--lyric-hue, 200), 95%, 80%, 0.35) 50%,
    hsla(var(--lyric-hue, 200), 95%, 80%, 0.35) 100%);
  background-size: 200% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
          background-clip: text;
  text-shadow: 0 3px 20px rgba(0,0,0,0.85);
}
#lyrics.show[data-style="12"] { animation: lyricKaraoke 2.6s ease-out; }
@keyframes lyricKaraoke {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}

/* 13. Mega Tight — ultra-condensed wall of caps. */
#lyrics[data-style="13"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(80px, 16vw, 240px) * var(--lyric-scale, 1));
  font-stretch: 70%;
  letter-spacing: -0.06em;
  word-spacing: 0.25em;
  font-weight: 900;
  line-height: 0.82;
}
#lyrics.show[data-style="13"] { transform: translate(-50%, calc(-50% - 8px)) scaleY(1.04); }

/* 14. Typewriter — bottom-left, monospaced, lowercase preserved, with prompt. */
#lyrics[data-style="14"] {
  bottom: 18%;
  left: 8%;
  right: auto;
  transform: none;
  text-align: left;
  font-family: 'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace;
  font-size: calc(clamp(20px, 3.1vw, 44px) * var(--lyric-scale, 1));
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: #f7f7f7;
  text-shadow: 0 2px 14px rgba(0,0,0,0.9);
  max-width: 60vw;
}
#lyrics[data-style="14"] .inner::before {
  content: '> ';
  opacity: 0.6;
}

/* 15. Vapor — thin weight + soft glowing halo. */
#lyrics[data-style="15"] {
  top: 50%; transform: translate(-50%, -50%);
  font-size: calc(clamp(56px, 10vw, 150px) * var(--lyric-scale, 1));
  font-weight: 300;
  letter-spacing: 0.04em;
  color: hsl(var(--lyric-hue, 200), 95%, 88%);
  text-shadow:
    0 0 20px hsla(var(--lyric-hue, 200), 95%, 70%, 0.8),
    0 0 50px hsla(var(--lyric-hue, 200), 95%, 60%, 0.55),
    0 4px 30px rgba(0,0,0,0.7);
  filter: blur(0.3px);
}
#lyrics.show[data-style="15"] { transform: translate(-50%, calc(-50% - 8px)); }

/* Kinetic typography: per-word reveal + beat/drop reactions */
#lyrics .inner { display: inline-block; will-change: transform, filter; }
#lyrics .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(22px) scale(0.92);
  transition: opacity 0.28s ease,
              transform 0.5s cubic-bezier(0.18, 0.85, 0.2, 1);
}
#lyrics.show .word { opacity: 1; transform: translateY(0) scale(1); }

#lyrics.kick .inner   { animation: lyricKick   220ms cubic-bezier(0.2, 0.8, 0.2, 1); }
#lyrics.glitch .inner { animation: lyricGlitch 380ms steps(3, end); }

@keyframes lyricKick {
  0%   { transform: scale(1.12); }
  100% { transform: scale(1); }
}
@keyframes lyricGlitch {
  0%, 100% { transform: translate(0, 0);   filter: none; }
  20%      { transform: translate(4px,-2px); filter: drop-shadow(-3px 0 #ff00d4) drop-shadow(3px 0 #00ffea); }
  45%      { transform: translate(-4px, 2px); filter: drop-shadow(3px 0 #ff00d4) drop-shadow(-3px 0 #00ffea); }
  70%      { transform: translate(2px, 0);  filter: drop-shadow(-2px 0 #fff700); }
}

/* ============================================================================
   Karaoke word sweep — while settings.karaokeMode is on (= lyric style 16
   is selected), lyrics.js sweeps these classes through the .word spans as
   the line plays. Active word is bright with a soft glow; past words stay
   solid; future words dim. setLyricStyle() strips the classes when another
   style is picked, so no half-swept line is left behind.
   ========================================================================= */
#lyrics .word.is-past { opacity: 1; }
#lyrics .word.is-future {
  opacity: 0.42;
  filter: saturate(0.55) brightness(0.85);
}
#lyrics .word.is-active {
  opacity: 1;
  filter: drop-shadow(0 0 14px currentColor)
          drop-shadow(0 0 28px currentColor)
          brightness(1.15);
}
/* Tasteful gold accent for the active word in styles that use white/grey
   text (so it pops without clashing with the per-style palette tints). */
#lyrics[data-style="6"]  .word.is-active,
#lyrics[data-style="8"]  .word.is-active,
#lyrics[data-style="10"] .word.is-active,
#lyrics[data-style="13"] .word.is-active,
#lyrics[data-style="14"] .word.is-active {
  color: #ffd66b;
  filter: drop-shadow(0 0 14px rgba(255,214,107,0.95))
          drop-shadow(0 0 28px rgba(255,214,107,0.7));
}

/* Bug-fix: style 12 ("Karaoke Wipe") was unreadable. The gradient base used
   color: transparent with -webkit-background-clip: text and a 2.6s sweep
   animation with no fill-mode, so after the animation ended the text snapped
   back to its starting "off" position (the right half of the gradient = 35%
   alpha hued color). On dark backgrounds that read as nearly black, and on
   short lines (~1.6s display, < the 2.6s animation) the user only ever saw
   the dim state. Fix: use animation-fill-mode: forwards to hold the bright
   end-state, and bump the dim half from 0.35 → 0.65 alpha so even the pre-
   sweep frames are legibly visible. The wipe effect still reads clearly —
   bright sweep across dim-but-readable text.
   ========================================================================= */
#lyrics[data-style="12"] {
  background: linear-gradient(90deg,
    #fff 0%, #fff 50%,
    hsla(var(--lyric-hue, 200), 95%, 82%, 0.65) 50%,
    hsla(var(--lyric-hue, 200), 95%, 82%, 0.65) 100%);
}
#lyrics.show[data-style="12"] { animation-fill-mode: forwards; }

/* ============================================================================
   Style 16 — Karaoke. ONE feature with two entry points: picking
   "Karaoke" in Lyrics → Text style, or the Karaoke auto-change preset
   (which just selects this style). Selecting it turns on the word sweep
   (settings.karaokeMode) + the stage dim; picking any other style turns
   both off (setLyricStyle in ui/settings.js).

   Layout: huge centered current line dominating the screen, with a smaller
   dimmer next-line preview ~22px below so the singer can read ahead. The
   active word is hot-gold + glowing; sung words are 50% white; upcoming
   words are 22% white — three clear states the eye reads instantly.

   Style 16 also adds body.karaoke-mode (see rule further down) which dims
   the scene canvases to ~45% opacity so lyrics dominate.
   ========================================================================= */
#lyrics[data-style="16"] {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 92vw;
  max-width: 92vw;
  font-size: calc(clamp(56px, 8.5vw, 130px) * var(--lyric-scale, 1));
  font-weight: 900;
  letter-spacing: -0.01em;
  line-height: 1.05;
  color: #fff;
  text-align: center;
  /* Strong but soft drop-shadow + dark halo for readability on ANY backdrop.
     No saturated colored glow — color belongs to the active word, not the
     surrounding text. */
  text-shadow:
    0 4px 24px rgba(0, 0, 0, 0.95),
    0 0 50px rgba(0, 0, 0, 0.7);
}
#lyrics.show[data-style="16"] {
  transform: translate(-50%, calc(-50% - 8px));
}

/* Per-word states in karaoke. These OVERRIDE the generic .word.is-* rules
   added with karaoke mode earlier — karaoke needs distinctive contrast
   between past/active/future, not a subtle drop-shadow glow. */
#lyrics[data-style="16"] .word.is-past {
  color: rgba(255, 255, 255, 0.55);
  filter: none;
}
#lyrics[data-style="16"] .word.is-future {
  color: rgba(255, 255, 255, 0.22);
  filter: none;
}
#lyrics[data-style="16"] .word.is-active {
  color: #ffd66b;                 /* hot gold — works on any backdrop */
  filter:
    drop-shadow(0 0 16px rgba(255, 214, 107, 0.95))
    drop-shadow(0 0 36px rgba(255, 214, 107, 0.60));
  /* Slight scale-up reinforces "this is the one to sing" without shifting
     the whole line's layout. */
  transform: translateY(0) scale(1.05);
}

/* Next-line preview — built as a child of #lyrics by lyrics.js when there
   IS a next line. Hidden by default for every other style; rendered only
   inside the karaoke style so it doesn't contaminate the 16 normal looks. */
#lyrics .next-line {
  display: none;
}
#lyrics[data-style="16"] .next-line {
  display: block;
  margin-top: 22px;
  /* em-relative so it scales with --lyric-scale alongside the main line */
  font-size: 0.42em;
  font-weight: 600;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.55);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.85);
  text-transform: uppercase;
  opacity: 0;
  animation: karaokeNextFadeIn 0.6s 0.5s ease-out forwards;
}
@keyframes karaokeNextFadeIn {
  to { opacity: 1; }
}

/* Scene dim — when body.karaoke-mode is set (Karaoke lyric style picked), step the
   visual backdrop back so lyrics are unambiguously the focal point. 45%
   keeps motion visible (still feels alive) without competing with text.
   Transition keeps the dim/undim feeling intentional, not jarring. */
body.karaoke-mode #canvas,
body.karaoke-mode #glCanvas,
body.karaoke-mode #video {
  /* !important: karaoke-mode's scene-dim is an opinionated visual treatment
     and should always win, including against any inline opacity that a
     future code path might set on these elements. */
  opacity: 0.45 !important;
  transition: opacity 400ms ease;
}
body:not(.karaoke-mode) #canvas,
body:not(.karaoke-mode) #glCanvas,
body:not(.karaoke-mode) #video {
  transition: opacity 400ms ease;
}
