/* ═══════════════════════════════════════════════════════════════
   AURA — Global Stylesheet
   Phase 1: Foundation

   Design philosophy:
   - Dark first. The background IS the product.
   - Controls barely exist until you need them.
   - Every transition is 300ms ease-out — nothing snaps.
   - CSS variables drive the color theme; JS swaps them dynamically.
═══════════════════════════════════════════════════════════════ */

/* ── CSS Custom Properties (Design Tokens) ──────────────────────
   These are the "live" values JS will update based on album art.
   They start as neutral defaults and get overwritten by the
   color extraction algorithm in app.js.
─────────────────────────────────────────────────────────────── */
:root {
  /* Album-derived palette (updated dynamically by JS) */
  --color-primary:   #6b4f8e;   /* dominant album color */
  --color-secondary: #2d1f5e;   /* second most prominent */
  --color-accent:    #c084fc;   /* brightest / most vivid */
  --color-text:      #f0e6ff;   /* readable text over dark bg */

  /* Static design tokens */
  --font-display:    'Playfair Display', Georgia, serif;
  --font-mono:       'Space Mono', 'Courier New', monospace;

  --transition-fast: 150ms ease-out;
  --transition-std:  300ms ease-out;
  --transition-slow: 600ms ease-out;
  --transition-xslow: 2400ms ease-out;

  --border-radius:   16px;
  --glass-bg:        rgba(0, 0, 0, 0.35);
  --glass-border:    rgba(255, 255, 255, 0.08);
}

/* ── Reset & Base ────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  /* Nothing on this app is ever selectable — it's a display/kiosk surface */
  user-select: none;
  -webkit-user-select: none;
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;        /* no scrollbars — this is a screensaver app */
  background: #0a0a0f;    /* absolute darkest fallback */
  color: var(--color-text);
  font-family: var(--font-mono);
  -webkit-font-smoothing: antialiased;
}

/* ── Screen Utility (Login vs App) ──────────────────────────── */
.screen {
  position: fixed;
  inset: 0;                /* shorthand for top/right/bottom/left: 0 */
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity var(--transition-xslow);
}

.hidden {
  display: none !important;
}

/* Pre-hide login screen for users with a valid token — eliminates the flash
   before the JS auth check runs.  The data-authed attribute is set by the
   inline script in <head> only when a non-expired token is found.           */
[data-authed='1'] #login-screen {
  display: none !important;
}

.fade-out {
  opacity: 0;
  pointer-events: none;
}


/* ════════════════════════════════════════════════════════════════
   LOGIN SCREEN
════════════════════════════════════════════════════════════════ */

#login-screen {
  /* Same midnight gradient as the main app's curated theme */
  background: radial-gradient(ellipse at 35% 45%, #0c0325 0%, #01000d 70%);
  flex-direction: column;
  gap: 0;
}

/* ── Ambient Orbs ────────────────────────────────────────────── */
.login-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(120px);
  opacity: 0.28;
  animation: orb-drift 16s ease-in-out infinite alternate;
}

.orb-1 {
  width: 80vw;
  height: 80vw;
  max-width: 900px;
  max-height: 900px;
  background: #3b0f8c;
  top: -30vw;
  left: -20vw;
  animation-delay: 0s;
}

.orb-2 {
  width: 60vw;
  height: 60vw;
  max-width: 700px;
  max-height: 700px;
  background: #0d1b6e;
  bottom: -20vw;
  right: -15vw;
  animation-delay: -6s;
}

.orb-3 {
  width: 40vw;
  height: 40vw;
  max-width: 500px;
  max-height: 500px;
  background: #6d28d9;
  top: 38%;
  left: 52%;
  animation-delay: -11s;
}

@keyframes orb-drift {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(40px, -25px) scale(1.06); }
}

/* ── Film grain — same CSS pattern as main app ───────────────── */
.login-grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.045) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.025) 1px, transparent 1px);
  background-size: 3px 3px, 5px 5px;
  background-position: 0 0, 2px 2px;
  opacity: 0.55;
  mix-blend-mode: overlay;
}

/* ── Vignette — same as main app ─────────────────────────────── */
.login-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background: radial-gradient(
    ellipse at 50% 50%,
    transparent 50%,
    rgba(0, 0, 0, 0.36) 100%
  );
}

/* ── Login Content ───────────────────────────────────────────── */
.login-content {
  position: relative;
  z-index: 10;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-sizing: border-box;
}

/* ── Brand — centrepiece, fills the room ────────────────────── */
.brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  flex: 1;
  justify-content: center;
}

/* "aura" — monumental. No cap so it scales with the viewport. */
.brand-name {
  font-family: var(--font-display);
  font-size: 21vw;
  font-weight: 900;
  letter-spacing: -0.04em;
  color: rgba(255, 255, 255, 0.96);
  line-height: 0.85;
  /* Soft purple haze makes the letters glow from within */
  text-shadow:
    0 0 180px rgba(139, 92, 246, 0.30),
    0 0  80px rgba(139, 92, 246, 0.15),
    0 0  30px rgba(255, 255, 255, 0.08);
}

.brand-tagline {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 8px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.22);
}

/* ── Footer — pinned to bottom ──────────────────────────────── */
.login-footer {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 0 40px 6vh;
  box-sizing: border-box;
}

.btn-spotify {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 38px;
  border: none;
  border-radius: 100px;
  background: #1DB954;
  color: #000;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    transform 200ms ease,
    background 200ms ease,
    box-shadow 200ms ease;
}

.btn-spotify:hover {
  background: #1ed760;
  transform: translateY(-3px);
  box-shadow: 0 16px 48px rgba(29, 185, 84, 0.40);
}

.btn-spotify:active {
  transform: translateY(-1px);
}

.spotify-icon {
  width: 20px;
  height: 20px;
  fill: #000;
  flex-shrink: 0;
}

.login-note {
  font-family: var(--font-mono);
  font-size: 10px;
  color: rgba(255, 255, 255, 0.13);
  letter-spacing: 0.3px;
  line-height: 1.9;
  max-width: 480px;
}


/* ════════════════════════════════════════════════════════════════
   MAIN APP SCREEN
════════════════════════════════════════════════════════════════ */

#app-screen {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* ── Dynamic Color Background ──────────────────────────────────
   This <div> is the canvas for our extracted album colors.
   JS sets its background property to a radial-gradient made from
   the dominant colors pulled from the album art.
─────────────────────────────────────────────────────────────── */
#color-bg {
  position: absolute;
  inset: 0;
  background: #08070f; /* default — overwritten immediately by JS */
  z-index: 0;
}

/* ── Particle Canvas ───────────────────────────────────────────
   Sits above the color-bg gradient but below the overlay.
   JS keeps its width/height in sync with the window size.
─────────────────────────────────────────────────────────────── */
#aura-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;   /* clicks pass through to the UI beneath */
}

/* ── Dark Overlay ──────────────────────────────────────────────
   Slightly darkens the background so text stays readable
   no matter what wild colors the album art gives us.
─────────────────────────────────────────────────────────────── */
.bg-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.22);  /* was 0.45 — was crushing all color */
  z-index: 1;
}

/* ── Now Playing Card ──────────────────────────────────────────
   The central UI element. Uses glass-morphism:
   a semi-transparent, blurred background panel.
─────────────────────────────────────────────────────────────── */
.now-playing {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 48px;
  padding: 48px 56px;
  border-radius: var(--border-radius);

  /* Glass morphism effect */
  background: var(--glass-bg);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--glass-border);

  /* Soft shadow to lift the card off the background */
  box-shadow:
    0 24px 64px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);

  /* Animate in when first revealed */
  animation: card-appear 600ms ease-out forwards;

  max-width: 760px;
  width: calc(100% - 64px);
}

@keyframes card-appear {
  from {
    opacity: 0;
    transform: translateY(20px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ── Album Art ─────────────────────────────────────────────── */
.album-art-wrapper {
  position: relative;
  flex-shrink: 0;
}

.album-art {
  width: 220px;
  height: 220px;
  border-radius: 12px;
  object-fit: cover;
  display: block;
  position: relative;
  z-index: 2;

  /* Subtle shadow for depth */
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.6),
    0 2px 8px rgba(0, 0, 0, 0.4);

  /* Smooth swap when album changes */
  transition: opacity var(--transition-std);
}

/* The glow ring behind the album art.
   Its color is set dynamically by JS to match the album's primary color. */
.album-glow {
  position: absolute;
  inset: -12px;
  border-radius: 20px;
  background: var(--color-primary);
  filter: blur(24px);
  opacity: 0.6;
  z-index: 1;
  /* Slow breathing animation — connects the card to the "living" background */
  animation: glow-breathe 3s ease-in-out infinite alternate;
  transition: background var(--transition-xslow);
}

@keyframes glow-breathe {
  from { opacity: 0.4; transform: scale(0.96); }
  to   { opacity: 0.7; transform: scale(1.04); }
}

/* ── Song Info ─────────────────────────────────────────────── */
.song-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;    /* prevents flex children from overflowing */
}

.song-meta-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.35);

  /* Truncate long album names */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.song-title {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 900;
  line-height: 1.1;
  color: #ffffff;
  letter-spacing: -0.5px;

  /* Prevent super-long titles from breaking layout */
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;

  transition: color var(--transition-std);
}

.song-artist {
  font-family: var(--font-mono);
  font-size: 16px;
  color: rgba(255, 255, 255, 0.65);
  letter-spacing: 0.5px;

  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Progress Bar ───────────────────────────────────────────── */
.progress-wrapper {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

.progress-bar {
  width: 100%;
  height: 3px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 3px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-accent);
  border-radius: 3px;
  transition:
    width 1s linear,           /* smooth tick-forward movement */
    background var(--transition-xslow);
}

.progress-times {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.3);
  font-family: var(--font-mono);
  letter-spacing: 1px;
}

/* ── Playback Status Dot ────────────────────────────────────── */
.playback-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
  font-family: var(--font-mono);
}

.status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #1DB954;    /* green = playing */
  flex-shrink: 0;
}

/* The dot pulses when song is actively playing */
.status-dot.playing {
  animation: dot-pulse 1.5s ease-in-out infinite;
}

.status-dot.paused {
  background: rgba(255, 255, 255, 0.3);
  animation: none;
}

@keyframes dot-pulse {
  0%, 100% { opacity: 1;   box-shadow: 0 0 0 0 rgba(29, 185, 84, 0.4); }
  50%       { opacity: 0.8; box-shadow: 0 0 0 4px rgba(29, 185, 84, 0); }
}


/* ── Idle State ─────────────────────────────────────────────── */
.idle-state {
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  animation: card-appear 600ms ease-out forwards;
}

.idle-icon {
  font-size: 56px;
  color: rgba(255, 255, 255, 0.15);
  animation: icon-pulse 4s ease-in-out infinite;
}

.idle-text {
  font-family: var(--font-display);
  font-size: 22px;
  color: rgba(255, 255, 255, 0.4);
}

.idle-subtext {
  font-family: var(--font-mono);
  font-size: 13px;
  color: rgba(255, 255, 255, 0.2);
  letter-spacing: 1px;
}


/* ── Bottom Bar ─────────────────────────────────────────────── */
.bottom-bar {
  position: absolute;     /* pinned to the bottom of #app-screen */
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20;

  /* CSS Grid 3-column layout: left | center | right
     Each column is 1fr so they share space equally.
     The center button is truly centered regardless of
     whether the left/right items have different widths.
     This is more robust than the flex + absolute trick. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  padding: 16px 32px;

  background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, transparent 100%);

  /* Fades out when idle — only visible on hover or mouse movement */
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity var(--transition-std),
    transform var(--transition-std);
  pointer-events: none;
}

/* Show bottom bar when the body has the "active" class
   (JS adds/removes this on mousemove) */
body.ui-visible .bottom-bar {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.app-logo {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 3px;
  color: rgba(255, 255, 255, 0.3);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 100px;
  color: rgba(255, 255, 255, 0.5);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 6px 16px;
  cursor: pointer;
  transition:
    background var(--transition-fast),
    color var(--transition-fast);
}

.icon-btn:hover {
  background: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.9);
}

/* Playback control buttons (prev/play/pause/next/like) — icon only, square */
.playback-btn {
  padding: 7px 9px;
}

/* Like button — filled heart gets accent colour */
#like-btn.liked {
  color: rgba(255, 80, 120, 0.9);
  border-color: rgba(255, 80, 120, 0.3);
  background: rgba(255, 80, 120, 0.08);
}


/* ── Top-Right Info (Clock) ─────────────────────────────────── */
.top-right-info {
  position: absolute;
  top: 24px;
  right: 32px;
  z-index: 20;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 2px;
  color: rgba(255, 255, 255, 0.25);
  opacity: 0;
  transition: opacity var(--transition-std);
}

body.ui-visible .top-right-info {
  opacity: 1;
}


/* ── Error Toast ────────────────────────────────────────────── */
.error-toast {
  position: fixed;
  bottom: 80px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  background: rgba(220, 38, 38, 0.85);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 100, 100, 0.3);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 12px 24px;
  border-radius: 100px;
  letter-spacing: 0.5px;

  animation: toast-appear 300ms ease-out forwards;
}

@keyframes toast-appear {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.error-toast.hidden {
  display: none !important;
}


/* ════════════════════════════════════════════════════════════════
   LYRICS OVERLAY — Phase 3 v3  (Transform-based Karaoke)
   ─────────────────────────────────────────────────────────────
   Architecture:
     .lyrics-overlay   — full-screen transparent shell
       .lyrics-viewport — clips the track, applies gradient mask
         .lyrics-track  — translateY set by JS to center current line
           .lyric-line  — one per synced lyric line
   ─────────────────────────────────────────────────────────────
   No scroll. No scrollbar. JS moves the track so the current
   line is always EXACTLY at 50% of the viewport height.
════════════════════════════════════════════════════════════════ */

.lyrics-overlay {
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none; /* overlay itself is transparent to events */
}

/* Viewport must capture scroll + touch events */
.lyrics-viewport {
  pointer-events: auto;
}

/* Non-current lines are interactive — user can scroll and click-to-seek */
.lyric-line:not(.current) {
  pointer-events: auto;
}

/* ── Scrollable viewport with gradient depth-of-field mask ─────
   The viewport is scrollable (scrollbar hidden).  JS sets the
   padding-top / padding-bottom of the track to half the viewport
   height so the first and last lines can be scrolled to center.
   scrollTo() from JS positions the current line exactly at 50%.
   The mask fades lines in/out at the edges for the depth effect.
─────────────────────────────────────────────────────────────── */
.lyrics-viewport {
  position: absolute;
  inset: 0;
  bottom: 140px;              /* gap for mini-player + bottom bar */
  overflow-y: scroll;
  overflow-x: hidden;
  scroll-behavior: auto;      /* must be instant — OS smooth-scroll would fight the rAF loop */
  scrollbar-width: none;      /* Firefox */
  -ms-overflow-style: none;

  /* Depth-of-field gradient — lines near center are fully visible.
     We never go fully transparent so lines remain faintly readable
     even when the user scrolls them to the very edge.              */
  /* Depth-of-field mask: 0.30 at extremes keeps scrolled lines legible */
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0,0,0,0.30)  0%,
    rgba(0,0,0,0.75) 10%,
    black             24%,
    black             76%,
    rgba(0,0,0,0.75) 90%,
    rgba(0,0,0,0.30) 100%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0,0,0,0.30)  0%,
    rgba(0,0,0,0.75) 10%,
    black             24%,
    black             76%,
    rgba(0,0,0,0.75) 90%,
    rgba(0,0,0,0.30) 100%
  );
}
.lyrics-viewport::-webkit-scrollbar { display: none; }

/* ── Track — normal flow, padding set by JS for first/last centering */
.lyrics-track {
  position: relative;         /* changed from absolute */
  display: flex;
  flex-direction: column;
  align-items: center;
  /* padding-top / padding-bottom injected by setLyricsPadding() */

  transition: opacity 350ms ease-out;
}

/* Song-to-song fade — purely opacity now (no transform drift) */
.lyrics-track.fading {
  opacity: 0 !important;
  transition: opacity 500ms ease-out !important;
}

/* ── Individual lyric line ──────────────────────────────────── */
/*
  SCALE ARCHITECTURE — all lyric lines are pre-rendered at the final "current"
  font-size.  Proximity classes only change transform:scale(), opacity, color.
  Since scale() is GPU-composited and never causes layout reflow, there is
  ZERO wrap-event, ZERO height jump, ZERO drift.  The element's CENTRE stays
  fixed during any scale transition — the centering loop only needs one call.
*/
.lyric-line {
  /* Always full "current" size — JS locks each slot's height after measurement */
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: min(1280px, 96vw);   /* much wider — use the screen */
  padding: 12px 28px;
  box-sizing: border-box;
  text-align: center;

  font-family: var(--font-display);
  /* Single font-size for ALL lines — scale() handles visual sizing */
  font-size: clamp(
    calc(40px * var(--lyrics-font-scale, 1)),
    calc(6.4vw * var(--lyrics-font-scale, 1)),
    calc(88px * var(--lyrics-font-scale, 1))
  );
  font-weight: 900;
  letter-spacing: -1px;
  line-height: 1.15;

  /* Faintly visible at rest (no class = far from current) */
  color: rgba(255, 255, 255, 0.15);
  opacity: 0.06;
  transform: scale(0.16);
  transform-origin: center center;

  cursor: pointer;
  user-select: none;
  overflow: hidden;
  word-break: break-word;
  overflow-wrap: break-word;

  /* Smooth cinematic ease — slightly longer, gentler curve */
  transition:
    transform  720ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity    500ms ease-out,
    color      400ms ease-out;
}

/* ── Proximity classes — ONLY scale + opacity + color ──────── */

.lyric-line.near-4 {
  opacity:   0.10;
  transform: scale(0.19);
  z-index: 2;
}
.lyric-line.near-3 {
  opacity:   0.16;
  transform: scale(0.23);
  color: rgba(255, 255, 255, 0.22);
  z-index: 3;
}
.lyric-line.near-2 {
  opacity:   0.33;
  transform: scale(0.31);
  color: rgba(255, 255, 255, 0.42);
  z-index: 4;
}
.lyric-line.near-1 {
  opacity:   0.56;
  transform: scale(0.39);
  color: rgba(255, 255, 255, 0.66);
  z-index: 5;
}

/* ── Current line — always on top, never collides ───────────── */
.lyric-line.current {
  opacity:   1;
  transform: scale(1);
  z-index: 20;
  /* Falls back to pure white when no mood color is set */
  color: var(--lyric-mood-color, rgba(255, 255, 255, 0.94));
  cursor: default;
  pointer-events: none;
  overflow: visible;   /* allow text-shadow to bleed outside slot */

  text-shadow:
    0 0 90px rgba(0, 0, 0, 0.85),
    0 2px 36px rgba(0, 0, 0, 0.9),
    0 0 52px rgba(255, 255, 255, 0.07),       /* very subtle white luminance bloom */
    0 0 60px var(--lyric-mood-glow, transparent); /* mood-tinted glow */

  transition:
    transform  680ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity    440ms ease-out,
    color      900ms ease,
    text-shadow 900ms ease;
}

/* Hover: non-current lines brighten on mouse-over */
.lyric-line:not(.current):hover {
  opacity: 0.88 !important;
  color: rgba(255, 255, 255, 0.82) !important;
}

/* ── Empty / instrumental lines ─────────────────────────────── */
.lyric-line.empty-line { color: rgba(255, 255, 255, 0.08); }

.lyric-line.empty-line.current {
  letter-spacing: 10px;
  color: rgba(255, 255, 255, 0.22);
  animation: breathe-dim 3s ease-in-out infinite;
}

@keyframes breathe-dim {
  0%, 100% { opacity: 0.25; }
  50%       { opacity: 0.55; }
}

/* ── Word-level elements (rendered inside .current line) ─────── */
/*
 * When a line becomes current, JS splits its text into <span class="lyric-word">
 * elements.  Each word has one of three states that change every ~80ms:
 *
 *   .upcoming — not yet reached  → soft white
 *   .active   — being sung right now → bright white + accent glow
 *   .past     — already sung     → tinted in the album accent color
 */
.lyric-word {
  display: inline-block;
  transition:
    color     160ms ease-out,
    opacity   160ms ease-out,
    filter    160ms ease-out,
    transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.lyric-word.upcoming {
  color: rgba(255, 255, 255, 0.58);
}

.lyric-word.active {
  color: #ffffff;
  /* Accent-colored glow makes the active word pop without being garish */
  filter: drop-shadow(0 0 16px var(--color-accent))
          drop-shadow(0 0 4px rgba(255, 255, 255, 0.6));
  transform: scale(1.06);
}

.lyric-word.past {
  color: var(--color-accent);
  opacity: 0.78;
}

/* ── Lyric status overlay ────────────────────────────────────── */
.lyric-status {
  position: fixed;
  top: 18px;
  left: 50%;
  transform: translateX(-50%) translateY(-4px);
  z-index: 40;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 100px;
  padding: 5px 16px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease, transform 400ms ease;
}

.lyric-status.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ════════════════════════════════════════════════════════════════
   BOTTOM BAR — Phase 4 expanded layout
════════════════════════════════════════════════════════════════ */

/* ── Active lyrics toggle button state ─────────────────────── */
.lyrics-toggle-btn.active {
  background: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.95);
  border-color: rgba(255, 255, 255, 0.25);
}

/* Center section of bottom bar — grid column 2 */
.bottom-center {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Left section */
.bottom-left  { display: flex; align-items: center; }

/* Right section */
.bottom-right { display: flex; align-items: center; justify-content: flex-end; }

.btn-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* (playback-btn handles prev/play/pause/next/like sizing) */

/* ── Bar divider between pill group and action buttons ─────── */
.bar-divider {
  display: inline-block;
  width: 1px;
  height: 18px;
  background: rgba(255, 255, 255, 0.12);
  margin: 0 2px;
}

/* ════════════════════════════════════════════════════════════════
   ROOM MODE PILLS — Phase 4
════════════════════════════════════════════════════════════════ */

.mode-pills {
  display: flex;
  gap: 3px;
  align-items: center;
}

.mode-pill {
  padding: 4px 11px;
  border-radius: 100px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: transparent;
  color: rgba(255, 255, 255, 0.3);
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background  220ms ease-out,
    color       220ms ease-out,
    border-color 220ms ease-out;
}

.mode-pill:hover {
  color: rgba(255, 255, 255, 0.65);
  border-color: rgba(255, 255, 255, 0.2);
}

.mode-pill.active {
  background: rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.95);
  border-color: rgba(255, 255, 255, 0.22);
}

/* ════════════════════════════════════════════════════════════════
   SETTINGS PANEL — Phase 5
   Slides up from above the bottom bar on settings-btn click.
════════════════════════════════════════════════════════════════ */

.settings-panel {
  position: absolute;
  bottom: 76px;
  left: 50%;
  transform: translateX(-50%) translateY(14px);
  z-index: 25;

  min-width: 380px;
  max-width: 420px;
  padding: 16px 22px 18px;

  background: rgba(6, 6, 14, 0.88);
  backdrop-filter: blur(28px) saturate(1.4);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 18px;

  display: flex;
  flex-direction: column;
  gap: 11px;

  opacity: 0;
  pointer-events: none;
  transition:
    opacity    240ms ease-out,
    transform  240ms cubic-bezier(0.22, 1, 0.36, 1);
}

.settings-panel.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.settings-header {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.28);
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}

.setting-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
  letter-spacing: 0.3px;
}

.toggle-btn {
  padding: 3px 12px;
  border-radius: 100px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: transparent;
  color: rgba(255, 255, 255, 0.28);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 1px;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 200ms ease-out;
  min-width: 36px;
  text-align: center;
}

.toggle-btn.active {
  background: rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.92);
  border-color: rgba(255, 255, 255, 0.2);
}

.setting-slider {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  min-width: 100px;
  height: 4px;
  background: rgba(255, 255, 255, 0.14);
  border-radius: 3px;
  outline: none;
  cursor: pointer;
}

/* Filled portion track colour */
.setting-slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
}
.setting-slider::-moz-range-track {
  height: 4px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
}

.setting-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 0 2px rgba(192, 132, 252, 0.35), 0 1px 4px rgba(0,0,0,0.5);
  cursor: pointer;
  transition: transform 140ms ease, box-shadow 140ms ease;
}

.setting-slider::-webkit-slider-thumb:hover {
  transform: scale(1.2);
  box-shadow: 0 0 0 3px rgba(192, 132, 252, 0.55), 0 2px 6px rgba(0,0,0,0.6);
}

.setting-slider::-moz-range-thumb {
  width: 15px; height: 15px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 0 2px rgba(192, 132, 252, 0.35);
  border: none; cursor: pointer;
}

/* Font selector & preview */
/* ── Professional-grade dark dropdown ─────────────────────────────────────
   Uses color-scheme: dark so the OS renders the <option> list in dark mode.
   The trigger itself is fully custom-styled with appearance: none.
────────────────────────────────────────────────────────────────────────── */
.setting-select {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  color-scheme: dark;               /* tells OS: use dark UI for the popup */

  background-color: rgba(255,255,255,0.05);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='rgba(255,255,255,0.40)' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;

  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 9px;
  color: rgba(255,255,255,0.82);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.3px;
  padding: 9px 32px 9px 12px;
  outline: none;
  cursor: pointer;
  transition: border-color 200ms ease, background-color 200ms ease, box-shadow 200ms ease;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 1px 3px rgba(0,0,0,0.40);
}

.setting-select:hover {
  background-color: rgba(255,255,255,0.09);
  border-color: rgba(255,255,255,0.20);
}

.setting-select:focus {
  background-color: rgba(255,255,255,0.09);
  border-color: rgba(255,255,255,0.32);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 0 0 2px rgba(192,132,252,0.18);
}

/* Dark option list */
.setting-select option {
  background-color: #0f0a1a;
  color: rgba(255,255,255,0.88);
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 8px 12px;
}

.setting-select option:checked {
  background-color: #2a1840;
}

/* Inline variant — used inside a settings-row next to a label */
.setting-select-inline {
  flex: 1;
  padding: 6px 28px 6px 10px;
  font-size: 10px;
}

.font-preview {
  font-size: 16px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  padding: 6px 0 2px;
  min-height: 28px;
  line-height: 1.2;
  transition: font-family 200ms ease;
}

/* ── Background themes — applied via data-bg-theme on #app-screen ─────── */
#app-screen[data-bg-theme="black"]    #color-bg { background: #000 !important; }
#app-screen[data-bg-theme="midnight"] #color-bg {
  background: radial-gradient(ellipse at 35% 45%, #0c0325 0%, #01000d 70%) !important;
}
#app-screen[data-bg-theme="aurora"]   #color-bg {
  background: radial-gradient(ellipse at 20% 60%, #00202e 0%, #050013 45%, #001512 100%) !important;
}
#app-screen[data-bg-theme="sunset"]   #color-bg {
  background: radial-gradient(ellipse at 50% 85%, #250407 0%, #0f0018 60%) !important;
}
#app-screen[data-bg-theme="forest"]   #color-bg {
  background: radial-gradient(ellipse at 50% 50%, #041008 0%, #010300 70%) !important;
}

/* ════════════════════════════════════════════════════════════════
   WEATHER DISPLAY — Phase 5 (top-right area)
════════════════════════════════════════════════════════════════ */

.weather-display {
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 1px;
  margin-right: 10px;
}

/* ════════════════════════════════════════════════════════════════
   TEXTURE OVERLAYS — Phase 5
   Positioned absolute, cover the entire screen.
   z-index sits between canvas (z:1) and UI elements (z:8+).
════════════════════════════════════════════════════════════════ */

/* ── Emotional Arc Visualizer ─────────────────────────────────────────────
   A thin SVG line drawn along the bottom 64px of the screen, tracing the
   session's emotional journey (valence + energy) as a coloured bezier path.
   Dots are hoverable — they show a tooltip with the song name.
────────────────────────────────────────────────────────────────────────── */
.arc-wrapper {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 72px;
  z-index: 28;
  pointer-events: none;
}

.arc-label {
  position: absolute;
  top: -18px;
  left: 16px;
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.22);
  pointer-events: none;
  white-space: nowrap;
}

.emotion-arc {
  display: block;
  width: 100%;
  height: 80px;
  pointer-events: auto;
  overflow: visible;
  opacity: 0.75;
  transition: opacity 300ms ease;
}
.emotion-arc:hover { opacity: 1; }
.arc-wrapper:hover .arc-label { color: rgba(255,255,255,0.45); }

.arc-dot {
  cursor: pointer;
  filter: drop-shadow(0 0 4px currentColor);
  transition: r 200ms ease;
}
.arc-dot:hover { r: 7; }

.arc-tooltip {
  position: fixed;
  background: rgba(10,5,25,0.88);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 8px;
  padding: 6px 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: rgba(255,255,255,0.80);
  pointer-events: none;
  z-index: 200;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 180ms ease;
}
.arc-tooltip.visible { opacity: 1; }

.texture-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}

/* Vignette: darkens edges, draws eye to center — always on by default */
.texture-vignette {
  background: radial-gradient(
    ellipse at center,
    transparent 50%,
    rgba(0, 0, 0, 0.36) 100%
  );
  z-index: 4;
}

/* CRT Scanlines — very fine, barely-there horizontal rule.
   Keep it a pure hint of texture, never a dominant grey pattern. */
.texture-scanlines {
  background: repeating-linear-gradient(
    to bottom,
    transparent                0px,
    transparent                3px,
    rgba(0,   0,   0,   0.07)  3px,
    rgba(0,   0,   0,   0.07)  4px
  );
  mix-blend-mode: multiply;   /* gentler than overlay on dark backgrounds */
  opacity: 0;
  transition: opacity 400ms ease;
}

.texture-scanlines.active { opacity: 1; }

/* Film grain: high-contrast animated dot-field for visible analog grain.
   Uses two overlapping patterns at different sizes/offsets for texture depth.*/
.texture-grain {
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.065) 1px, transparent 1px),
    radial-gradient(circle, rgba(0,0,0,0.055) 1px, transparent 1px);
  background-size: 3px 3px, 5px 5px;
  background-position: 0 0, 1px 1px;
  mix-blend-mode: overlay;
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease;
  animation: grain-shift 0.07s steps(1) infinite;
}

.texture-grain.active { opacity: 1; }

@keyframes grain-shift {
  0%   { background-position: 0 0,  1px 1px;  }
  12%  { background-position: 2px -1px, -1px 2px; }
  25%  { background-position: -2px 2px,  2px -1px; }
  37%  { background-position: 1px  2px, -2px  1px; }
  50%  { background-position: -1px -2px,  1px -2px; }
  62%  { background-position: 2px  1px, -1px  2px; }
  75%  { background-position: -2px -1px,  2px  1px; }
  87%  { background-position: 1px -2px, -2px -1px; }
  100% { background-position: 0 0,  1px 1px;  }
}

/* Mode pills inside settings panel (full-width pill group) */
.settings-panel .mode-pills {
  flex-wrap: wrap;
  gap: 4px;
  justify-content: flex-start;
  width: 100%;
}
.settings-panel .mode-pill {
  flex: 1;
  text-align: center;
  min-width: 52px;
}

/* QR Code section */
.qr-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.qr-label {
  font-size: 9.5px;
  text-align: center;
  line-height: 1.5;
}

.qr-img {
  width: 100px;
  height: 100px;
  border-radius: 10px;
  background: #fff;
  padding: 4px;
  box-sizing: border-box;
  display: block;
}

/* ════════════════════════════════════════════════════════════════
   WEATHER DISPLAY — more prominent top-right
════════════════════════════════════════════════════════════════ */
.top-right-info {
  position: absolute;
  top: 20px;
  right: 24px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
  letter-spacing: 1px;
  pointer-events: none;
}

.weather-display {
  color: rgba(255, 255, 255, 0.55);
  font-size: 13px;
  letter-spacing: 0.5px;
}

/* ════════════════════════════════════════════════════════════════
   SHORTCUTS MODAL — Phase 6
════════════════════════════════════════════════════════════════ */

.shortcuts-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 250ms ease-out;
}

.shortcuts-modal.visible {
  opacity: 1;
  pointer-events: auto;
}

.shortcuts-card {
  position: relative;
  background: rgba(8, 8, 18, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 22px;
  padding: 36px 48px 32px;
  min-width: 340px;
}

.shortcuts-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 24px;
  letter-spacing: -0.3px;
}

.shortcuts-grid {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.shortcut-row {
  display: flex;
  align-items: center;
  gap: 16px;
}

.shortcut-row kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  padding: 3px 8px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.75);
  letter-spacing: 0.5px;
  flex-shrink: 0;
}

.shortcut-row span {
  font-family: var(--font-mono);
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  letter-spacing: 0.3px;
}

.shortcuts-close {
  position: absolute;
  top: 14px;
  right: 18px;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.3);
  font-size: 16px;
  cursor: pointer;
  padding: 4px 6px;
  transition: color 200ms ease;
}

.shortcuts-close:hover { color: rgba(255, 255, 255, 0.8); }

/* ════════════════════════════════════════════════════════════════
   KIOSK / SCREENSAVER MODE — Phase 4
════════════════════════════════════════════════════════════════ */

body.kiosk-active        { cursor: none !important; }
body.kiosk-active *      { cursor: none !important; }
body.kiosk-cursor-hidden { cursor: none !important; }

/* ════════════════════════════════════════════════════════════════
   PHASE 6 — Prefers-reduced-motion
   Respect the OS accessibility setting: disable all heavy transitions
   and animations for users who are sensitive to motion.
════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .lyrics-track,
  .lyric-line,
  .lyric-word,
  .texture-grain,
  .settings-panel,
  .shortcuts-modal,
  .bottom-bar,
  .now-playing,
  .mini-player { transition: none !important; animation: none !important; }
}


/* ════════════════════════════════════════════════════════════════
   MINI PLAYER — Phase 3
   A compact strip at the bottom of the screen, visible when
   lyrics are toggled on. Replaces the centered now-playing card.
════════════════════════════════════════════════════════════════ */

.mini-player {
  position: absolute;
  bottom: 64px;            /* just above the bottom bar */
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  z-index: 15;

  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 20px 14px; /* extra bottom padding for the progress bar */

  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 100px;    /* pill shape */
  min-width: 280px;
  max-width: 460px;

  /* Slide up animation: starts translated down, enters on .visible */
  opacity: 0;
  transition:
    opacity var(--transition-std),
    transform var(--transition-std);

  /* Progress bar runs along the very bottom of the pill */
  overflow: hidden;        /* so mini-progress-bar clips to rounded corners */
}

.mini-player.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Tiny album art thumbnail */
.mini-album-art {
  width: 36px;
  height: 36px;
  border-radius: 6px;
  object-fit: cover;
  flex-shrink: 0;
  opacity: 0.9;
}

/* Song / Artist text */
.mini-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;            /* allows text-overflow to work inside flex */
}

.mini-title {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.9);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.3px;
}

.mini-artist {
  font-family: var(--font-mono);
  font-size: 10px;
  color: rgba(255, 255, 255, 0.4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.5px;
}

/* Progress bar — absolute positioned at the very bottom of the pill */
.mini-progress-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: rgba(255, 255, 255, 0.08);
}

.mini-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-accent);
  transition:
    width 1s linear,
    background var(--transition-xslow);
}

/* ════════════════════════════════════════════════════════════════
   RESPONSIVE — Mobile (minimal support for now, desktop-first)
════════════════════════════════════════════════════════════════ */
@media (max-width: 600px) {
  .now-playing {
    flex-direction: column;
    padding: 32px 24px;
    gap: 28px;
    text-align: center;
  }

  .album-art {
    width: 160px;
    height: 160px;
  }

  .song-title {
    font-size: 26px;
  }

  .progress-times {
    justify-content: space-around;
  }
}


/* ════════════════════════════════════════════════════════════════
   ACCESSIBILITY — Reduced Motion
   Respects the OS-level "Reduce Motion" accessibility setting.
════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
