/* ============================================================================
 * YT Player — "Cinematic Control Deck"
 * Warm near-black editorial dark theme · single vermilion accent ·
 * Bricolage Grotesque (display) / Hanken Grotesk (UI) / JetBrains Mono (data)
 * ========================================================================== */

:root {
  /* Warm, layered near-blacks */
  --bg: #0a0a0c;
  --bg-1: #101013;
  --bg-2: #16161b;
  --bg-3: #1d1d24;
  --line: #26262f;
  --line-soft: #1c1c23;

  /* Type */
  --text: #f5f3f0;
  --text-2: #b6b5bf;
  --text-dim: #76757f;

  /* Signature accent — vermilion with a warm halo */
  --accent: #ff4b32;
  --accent-bright: #ff6a52;
  --accent-deep: #d4321d;
  --accent-glow: rgba(255, 75, 50, 0.45);

  --display: "Bricolage Grotesque", Georgia, serif;
  --ui: "Hanken Grotesk", system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;

  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 18px 50px -12px rgba(0, 0, 0, 0.7);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.45;
  overflow: hidden;
  user-select: none;
  -webkit-font-smoothing: antialiased;
}

/* Ambient warm light bleed from top-left + film grain over everything */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(900px 600px at 18% -10%, rgba(255, 75, 50, 0.10), transparent 60%),
    radial-gradient(700px 500px at 100% 110%, rgba(90, 120, 255, 0.05), transparent 55%);
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: 20px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #34343f; background-clip: content-box; }

.app {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 264px 1fr;
  height: 100vh;
}

/* ===================== Sidebar ===================== */
.sidebar {
  background: linear-gradient(180deg, var(--bg-1), var(--bg));
  border-right: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  padding: 22px 14px 16px;
  overflow-y: auto;
  overflow-x: hidden;
}
/* The whole sidebar scrolls as a single unit; keep its sections at their
   natural height so the playlists are always reachable on short screens
   instead of collapsing competing inner scroll regions. */
.sidebar > * { flex-shrink: 0; }

.brand {
  font-family: var(--display);
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.02em;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 2px 10px 22px;
}
.brand-mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  font-size: 13px;
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  box-shadow: 0 6px 18px -4px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.25);
}

.nav { display: flex; flex-direction: column; gap: 3px; margin-bottom: 20px; }
.nav-item {
  position: relative;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--text-dim);
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: var(--ui);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  transition: color 0.18s, background 0.18s;
}
.nav-item::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 3px; height: 0;
  border-radius: 3px;
  background: var(--accent);
  transform: translateY(-50%);
  transition: height 0.22s var(--ease);
}
.nav-item:hover { color: var(--text); background: var(--bg-2); }
.nav-item.active { color: var(--text); background: var(--bg-2); font-weight: 600; }
.nav-item.active::before { height: 18px; box-shadow: 0 0 12px var(--accent-glow); }

.pl-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px 8px;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
.icon-btn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-2);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  border-radius: 8px;
  width: 26px; height: 26px;
  transition: all 0.18s var(--ease);
}
.icon-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; transform: rotate(90deg); }

.playlist-list { flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; padding-right: 2px; }
.playlist-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-2);
  transition: background 0.16s, color 0.16s;
}
.playlist-item::before {
  content: "▸";
  color: var(--text-dim);
  font-size: 10px;
  transition: color 0.16s, transform 0.16s;
}
.playlist-item:hover { background: var(--bg-2); color: var(--text); }
.playlist-item:hover::before { color: var(--accent); transform: translateX(2px); }
.playlist-item.active { background: var(--bg-2); color: var(--text); }
.playlist-item.active::before { color: var(--accent); }
.playlist-item .pl-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; font-weight: 500; }
.playlist-item .pl-count {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-dim);
  background: var(--bg-3);
  padding: 2px 7px;
  border-radius: 20px;
}
.playlist-item .pl-offline-badge {
  font-family: var(--mono);
  line-height: 1;
  flex-shrink: 0;
}
.playlist-item .pl-offline-badge.all {
  display: inline-grid;
  place-items: center;
  width: 17px;
  height: 17px;
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  box-shadow: 0 1px 4px var(--accent-glow);
}
.playlist-item .pl-offline-badge.partial {
  font-size: 10px;
  color: var(--text-dim);
  background: var(--bg-3);
  padding: 2px 6px;
  border-radius: 20px;
}

.sidebar-footer { border-top: 1px solid var(--line-soft); padding-top: 12px; margin-top: auto; flex-shrink: 0; }

/* Linked online profile — share/copy the full URL that opens this profile */
.sb-profile {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px; margin-bottom: 8px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg-2);
}
.sb-profile-id { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sb-profile-mark { flex-shrink: 0; font-size: 13px; }
.sb-profile-name {
  font-family: var(--mono); font-size: 12px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sb-profile-actions { display: flex; gap: 6px; }
.sb-profile-btn {
  flex: 1; padding: 6px 8px; font-size: 11px; cursor: pointer;
  color: var(--text-2); background: var(--bg-1);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}
.sb-profile-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.switch {
  display: flex; align-items: center; gap: 10px;
  color: var(--text-2); cursor: pointer; padding: 8px 10px;
  border-radius: var(--radius-sm); font-size: 13px;
  transition: background 0.16s;
}
.switch:hover { background: var(--bg-2); }
.switch input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* ===================== Main ===================== */
.main { display: flex; flex-direction: column; overflow: hidden; }

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 26px;
  border-bottom: 1px solid var(--line-soft);
  background: linear-gradient(180deg, rgba(16,16,19,0.7), transparent);
  backdrop-filter: blur(8px);
}
.search-form { flex: 1; display: flex; gap: 10px; max-width: 760px; position: relative; }

/* Recent-searches dropdown — device-local, kept in localStorage (RecentSearches in app.js) */
.search-recent {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  z-index: 60;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.5);
  padding: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.search-recent.hidden { display: none; }
.search-recent-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-radius: 8px;
  cursor: pointer;
  color: var(--text-2);
  font-size: 13px;
  font-family: var(--ui);
}
.search-recent-row:hover, .search-recent-row:focus-visible { background: var(--bg-3); color: var(--text); }
.search-recent-row .sr-icon { flex-shrink: 0; opacity: 0.55; font-size: 12px; }
.search-recent-row.is-cached .sr-icon { opacity: 0.85; color: var(--accent); }
.search-recent-row .sr-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-recent-row .sr-remove {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 3px 6px;
  border-radius: 6px;
}
.search-recent-row .sr-remove:hover { color: #fff; background: var(--accent); }
.search-recent-clear {
  display: block;
  width: 100%;
  text-align: center;
  background: none;
  border: none;
  border-top: 1px solid var(--line-soft);
  color: var(--text-dim);
  font-family: var(--ui);
  font-size: 12px;
  padding: 8px 6px 4px;
  margin-top: 4px;
  cursor: pointer;
}
.search-recent-clear:hover { color: var(--text); }

/* Hamburger toggle — hidden on desktop, revealed in the mobile breakpoint */
.sidebar-toggle {
  display: none;
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--text);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s;
}
.sidebar-toggle:hover { background: var(--bg-3); border-color: var(--accent); }

/* Backdrop behind the off-canvas drawer — only shown when the drawer is open */
.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
#searchInput {
  flex: 1;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 12px 16px;
  color: var(--text);
  font-family: var(--ui);
  font-size: 14px;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}
#searchInput::placeholder { color: var(--text-dim); }
#searchInput:focus {
  border-color: var(--accent);
  background: var(--bg-1);
  box-shadow: 0 0 0 4px rgba(255, 75, 50, 0.12);
}
.search-btn {
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  color: #fff;
  border: none;
  padding: 0 24px;
  border-radius: 11px;
  font-family: var(--ui);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.01em;
  cursor: pointer;
  box-shadow: 0 8px 22px -8px var(--accent-glow);
  transition: transform 0.16s var(--ease), box-shadow 0.16s;
}
.search-btn:hover { transform: translateY(-1px); box-shadow: 0 12px 28px -8px var(--accent-glow); }
.search-btn:active { transform: translateY(0); }

.body { flex: 1; display: flex; overflow: hidden; }

/* ===================== Player pane ===================== */
.player-pane {
  flex: 1.5;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 26px 26px 30px;
  overflow-y: auto;
}
.player-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow), 0 0 0 1px var(--line) inset;
}
/* Cinematic glow ring when something is loaded */
.player-pane:not(.empty) .player-stage {
  box-shadow: var(--shadow), 0 0 60px -20px var(--accent-glow), 0 0 0 1px var(--line) inset;
}
#video { width: 100%; height: 100%; background: #000; display: block; }

.art-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: radial-gradient(circle at 50% 40%, var(--bg-3), #000); }
.art-fallback img { max-width: 58%; max-height: 78%; border-radius: 14px; box-shadow: var(--shadow); }

.player-placeholder {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 28px;
  background:
    radial-gradient(680px 420px at 50% 30%, rgba(255, 75, 50, 0.10), transparent 70%),
    radial-gradient(circle at 50% 120%, rgba(90, 120, 255, 0.06), transparent 60%),
    linear-gradient(180deg, var(--bg-1), #000);
}
/* Hero landing */
.hero {
  display: flex; flex-direction: column; align-items: center;
  gap: 16px; max-width: 460px;
  animation: heroIn 0.6s var(--ease) both;
}
@keyframes heroIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* Empty home: the playlist grid takes the hero's place once playlists exist */
.player-placeholder.showing-playlists { padding: 16px; align-items: stretch; }
/* The 16:9 stage exists to hold a video, and on the empty home there isn't one
   (controls / now-meta / up-next are hidden too). Constraining the playlist
   grid to that short box clipped it mid-card, so let the stage take the pane's
   height instead. Reverts the moment something plays — `.empty` comes off. */
.player-pane.empty.home-playlists .player-stage {
  aspect-ratio: auto;
  flex: 1 1 auto;
  min-height: 260px;
}
/* Bottom fade, applied only while the grid actually overflows and isn't
   scrolled to the end — a half-row under a hard edge reads as broken. */
.home-pl-grid.is-scrollable:not(.at-end) {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 30px), transparent 100%);
          mask-image: linear-gradient(180deg, #000 calc(100% - 30px), transparent 100%);
}
.home-pl {
  flex: 1 1 auto; align-self: stretch; min-width: 0; max-height: 100%;
  display: flex; flex-direction: column; gap: 10px;
  text-align: left; overflow: hidden;
  animation: heroIn 0.5s var(--ease) both;
}
.home-pl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-shrink: 0; }
.home-pl-title { font-family: var(--display); font-size: 17px; font-weight: 700; color: var(--text); }
.home-pl-new {
  padding: 5px 10px; font-size: 12px; cursor: pointer;
  color: var(--text-2); background: var(--bg-2);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}
.home-pl-new:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.home-pl-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(122px, 1fr));
  gap: 12px; align-content: start;
  overflow-y: auto; scrollbar-gutter: stable; padding-right: 4px;
}
.home-pl-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: 0; border: 0; background: none; color: inherit;
  text-align: left; cursor: pointer; min-width: 0;
}
.home-pl-thumb {
  position: relative; display: block; aspect-ratio: 16 / 9;
  border-radius: var(--radius-sm); overflow: hidden;
  background: var(--bg-3); border: 1px solid var(--line-soft);
  transition: border-color 0.16s, transform 0.16s var(--ease);
}
.home-pl-card:hover .home-pl-thumb { border-color: var(--accent); transform: translateY(-2px); }
.home-pl-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.home-pl-thumb-fallback { position: absolute; inset: 0; display: grid; place-items: center; font-size: 22px; }
.home-pl-play {
  position: absolute; right: 6px; bottom: 6px;
  width: 26px; height: 26px; display: grid; place-items: center;
  font-size: 11px; color: #fff; border-radius: 50%;
  background: rgba(0, 0, 0, 0.62); backdrop-filter: blur(4px);
  opacity: 0; transition: opacity 0.16s, background 0.16s;
}
.home-pl-offline {
  position: absolute; top: 6px; left: 6px;
  display: grid; place-items: center;
  font-family: var(--mono);
  line-height: 1;
  z-index: 2;
  pointer-events: none;
}
.home-pl-offline.all {
  width: 22px; height: 22px;
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}
.home-pl-offline.partial {
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.65);
  color: var(--text-2);
  border-radius: 10px;
  font-size: 10px;
  backdrop-filter: blur(4px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}
.home-pl-card:hover .home-pl-play, .home-pl-play:focus-visible { opacity: 1; }
.home-pl-play:hover { background: var(--accent); }
.home-pl-name {
  font-size: 13px; font-weight: 600; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.home-pl-count { font-size: 11px; color: var(--text-dim); }
/* Touch devices have no hover — keep the play badge permanently visible */
@media (hover: none) {
  .home-pl-play { opacity: 1; }
}
.ph-logo {
  font-size: 32px;
  width: 88px; height: 88px;
  display: grid; place-items: center;
  border-radius: 26px;
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  box-shadow: 0 18px 50px -14px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.25);
  animation: float 4s ease-in-out infinite;
}
@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
.hero-title {
  margin: 6px 0 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: 40px;
  letter-spacing: -0.03em;
  line-height: 1;
  background: linear-gradient(180deg, #fff, #c8c6cf);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.hero-tagline {
  margin: 0; max-width: 380px;
  color: var(--text-2); font-size: 14.5px; line-height: 1.5;
}
.hero-pills { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 2px; }
.hero-pill {
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--text-2);
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 6px 12px 6px 26px;
  border-radius: 20px;
  position: relative;
}
.hero-pill::before {
  content: "✓";
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--accent); font-size: 10px; font-weight: 800;
}
.hero-suggests {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; align-items: center;
  margin-top: 10px;
}
.hero-suggests-label {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-dim);
  margin-right: 2px;
}
.chip {
  font-family: var(--ui); font-size: 13px; font-weight: 600;
  color: var(--text);
  background: var(--bg-3);
  border: 1px solid var(--line);
  padding: 8px 15px;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.16s var(--ease);
}
.chip:hover {
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent;
  transform: translateY(-2px);
  box-shadow: 0 8px 20px -8px var(--accent-glow);
}

.spinner {
  position: absolute;
  width: 48px; height: 48px;
  border: 3px solid rgba(255,255,255,0.12);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  filter: drop-shadow(0 0 8px var(--accent-glow));
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Control deck ---- */
.controls {
  margin-top: 16px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
}
.seek-row { display: flex; align-items: center; gap: 14px; }
.time {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  min-width: 46px;
  text-align: center;
}

/* Custom range tracks (seek + volume) */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 5px;
  border-radius: 10px;
  background: var(--bg-3);
  cursor: pointer;
  outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--accent-bright);
  border: 2px solid #fff;
  box-shadow: 0 0 0 4px rgba(255,75,50,0.18), 0 2px 6px rgba(0,0,0,0.5);
  transition: transform 0.14s var(--ease);
}
input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.25); }
.seek { flex: 1; }

.btn-row { display: flex; align-items: center; gap: 9px; margin-top: 15px; flex-wrap: wrap; }

/* The five transport buttons stay together, in transport order, at EVERY width.
   They are scattered through the markup (shuffle/loop/repeat sit after the tool
   buttons), so without this they only group where a media query said so — which
   left shuffle and repeat stranded among the tools on anything wider than a
   phone. Tools take order 7; the mobile blocks add a forced line break at 6. */
#shuffleBtn { order: 1; }
#prevBtn    { order: 2; }
#playBtn    { order: 3; }
#nextBtn    { order: 4; }
#repeatBtn  { order: 5; }
.btn-row > *:not(#shuffleBtn):not(#prevBtn):not(#playBtn):not(#nextBtn):not(#repeatBtn) { order: 7; }
.ctrl {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text);
  min-width: 42px; height: 40px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 15px;
  display: grid; place-items: center;
  transition: all 0.16s var(--ease);
}
.ctrl:hover { border-color: var(--accent); color: var(--accent-bright); transform: translateY(-1px); }
.ctrl:active { transform: translateY(0); }
.ctrl.play {
  width: 52px; height: 44px;
  font-size: 17px;
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent;
  box-shadow: 0 8px 20px -8px var(--accent-glow);
}
.ctrl.play:hover { color: #fff; box-shadow: 0 12px 26px -8px var(--accent-glow); }

.vol { display: flex; align-items: center; gap: 8px; }
.vol input { width: 92px; }
.spacer { flex: 1; }

.sel {
  display: flex; align-items: center; gap: 7px;
  color: var(--text-dim); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700;
}
.sel select {
  background: var(--bg-3);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 8px 9px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  transition: border-color 0.16s;
}
.sel select:hover { border-color: var(--accent); }

.now-meta {
  margin-top: 18px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
.np-text { min-width: 0; }
.np-actions { display: flex; gap: 8px; flex-shrink: 0; }
.np-avail { font-size: 12px; color: var(--text-dim); margin-top: 4px; cursor: default; }
.np-avail.stale { opacity: 0.6; font-style: italic; }
.np-btn {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  border-radius: 9px;
  padding: 9px 14px;
  cursor: pointer;
  font-family: var(--ui);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: all 0.16s var(--ease);
}
.np-btn:hover { color: var(--text); border-color: var(--accent); background: var(--bg-2); transform: translateY(-1px); }
.np-btn:disabled { opacity: 0.6; cursor: default; transform: none; }
.np-btn.done { color: #7ee0a8; border-color: rgba(126,224,168,0.35); }
.np-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.np-channel {
  color: var(--text-dim);
  margin-top: 6px;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.np-channel::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 8px var(--accent-glow);
}

.player-pane.empty .controls,
.player-pane.empty .now-meta,
.player-pane.empty .upnext { display: none; }

/* ===================== Up next queue ===================== */
.upnext {
  margin-top: 16px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
}
.upnext-header {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--mono);
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--text-dim);
  margin-bottom: 10px;
}
.upnext-count {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  background: rgba(255,75,50,0.12);
  padding: 0 7px;
  border-radius: 10px;
  line-height: 17px;
}
.upnext-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 200px; overflow-y: auto;
}
.upnext-item {
  display: flex; gap: 10px;
  padding: 6px;
  border-radius: 9px;
  cursor: pointer;
  transition: background 0.16s;
}
.upnext-item:hover { background: var(--bg-3); }
.upnext-item img {
  width: 80px; aspect-ratio: 16/9;
  border-radius: 6px;
  object-fit: cover;
  background: #000;
  flex-shrink: 0;
}
.upnext-info { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.upnext-title {
  font-size: 12.5px; font-weight: 600;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.upnext-channel {
  font-size: 11px; color: var(--text-dim);
  margin-top: 3px;
}

/* ===================== List pane ===================== */
.list-pane {
  width: 452px;
  flex-shrink: 0;
  border-left: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: linear-gradient(180deg, var(--bg-1), var(--bg));
}
.list-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 20px 12px;
  gap: 12px;
}
.list-header h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.01em;
}
.list-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.list-actions button {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-2);
  border-radius: 8px;
  padding: 7px 11px;
  cursor: pointer;
  font-family: var(--ui);
  font-size: 12px;
  font-weight: 600;
  transition: all 0.16s;
}
.list-actions button:hover { color: var(--text); border-color: var(--accent); background: var(--bg-3); }
.list-actions button:disabled,
.list-actions button.disabled {
  opacity: 0.6;
  cursor: default;
  pointer-events: none;
  border-color: var(--line);
  background: var(--bg-2);
  color: var(--text-dim);
}
.list-actions button.pinned {
  background: var(--bg-3);
  border-color: var(--accent);
  color: var(--accent);
}

.status { padding: 16px 20px; color: var(--text-dim); font-size: 13px; }

/* ===================== Skeleton loading ===================== */
.skeleton-card {
  cursor: default !important;
  pointer-events: none;
  border-color: transparent !important;
  animation: cardIn 0.45s var(--ease) backwards !important;
}
.skeleton-shimmer {
  position: relative;
  overflow: hidden;
  background: var(--bg-3);
  border-radius: 9px;
}
.skeleton-shimmer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255,255,255,0.04) 40%,
    rgba(255,255,255,0.07) 50%,
    rgba(255,255,255,0.04) 60%,
    transparent
  );
  animation: shimmer 1.6s ease-in-out infinite;
}
@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
.skeleton-card .thumb {
  background: var(--bg-3);
}
.skeleton-line {
  height: 14px;
  width: 100%;
  border-radius: 8px;
}
.skeleton-dot {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  align-self: center;
  flex-shrink: 0;
}

/* ===================== Empty state ===================== */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 32px 60px;
  gap: 8px;
  animation: heroIn 0.5s var(--ease) both;
}
.empty-icon {
  font-size: 42px;
  width: 80px; height: 80px;
  display: grid; place-items: center;
  border-radius: 24px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  margin-bottom: 10px;
  transition: transform 0.3s var(--ease), box-shadow 0.3s;
}
.empty-state:hover .empty-icon {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px -12px var(--accent-glow);
}
.empty-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--text);
}
.empty-desc {
  margin: 4px 0 0;
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.5;
  max-width: 300px;
}
.empty-desc strong { color: var(--text-2); font-weight: 600; }
.empty-cta {
  margin-top: 16px;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  color: #fff;
  border: none;
  padding: 10px 22px;
  border-radius: 11px;
  font-family: var(--ui);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.01em;
  cursor: pointer;
  box-shadow: 0 8px 22px -8px var(--accent-glow);
  transition: transform 0.16s var(--ease), box-shadow 0.16s;
}
.empty-cta:hover { transform: translateY(-2px); box-shadow: 0 12px 28px -8px var(--accent-glow); }
.empty-cta:active { transform: translateY(0); }

.cards { flex: 1; overflow-y: auto; padding: 6px 14px 28px; display: flex; flex-direction: column; gap: 5px; }

.card {
  display: flex;
  gap: 12px;
  padding: 9px;
  border-radius: 12px;
  cursor: pointer;
  position: relative;
  border: 1px solid transparent;
  transition: background 0.16s, border-color 0.16s, transform 0.16s var(--ease);
  animation: cardIn 0.45s var(--ease) backwards;
}
/* staggered reveal */
.card:nth-child(1){animation-delay:.02s}.card:nth-child(2){animation-delay:.05s}
.card:nth-child(3){animation-delay:.08s}.card:nth-child(4){animation-delay:.11s}
.card:nth-child(5){animation-delay:.14s}.card:nth-child(6){animation-delay:.17s}
.card:nth-child(7){animation-delay:.20s}.card:nth-child(8){animation-delay:.23s}
.card:nth-child(9){animation-delay:.26s}.card:nth-child(10){animation-delay:.29s}
@keyframes cardIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.card:hover { background: var(--bg-2); border-color: var(--line); }
.card.playing {
  background: var(--bg-2);
  border-color: var(--accent);
  box-shadow: 0 0 26px -12px var(--accent-glow);
}
.card.playing::after {
  content: "▶ NOW PLAYING";
  position: absolute; top: 9px; right: 44px;
  font-family: var(--mono); font-size: 8px; font-weight: 700;
  letter-spacing: 0.1em; color: var(--accent);
}

.thumb {
  position: relative;
  width: 138px;
  flex-shrink: 0;
  aspect-ratio: 16/9;
  border-radius: 9px;
  overflow: hidden;
  background: #000;
}
.thumb img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.4s var(--ease), filter 0.3s;
}
.card:hover .thumb img { transform: scale(1.07); }
.thumb::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(circle at center, rgba(255,75,50,0.0), transparent);
  opacity: 0; transition: opacity 0.25s;
}
.card:hover .thumb::after { opacity: 1; background: radial-gradient(circle at center, rgba(255,75,50,0.18), transparent 70%); }
.thumb .dur {
  position: absolute; right: 5px; bottom: 5px;
  background: rgba(0,0,0,0.82); color: #fff;
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  padding: 2px 6px; border-radius: 5px;
  backdrop-filter: blur(2px);
}

.card-info { min-width: 0; flex: 1; display: flex; flex-direction: column; justify-content: center; }
.card-title {
  font-size: 13.5px; font-weight: 600; line-height: 1.32;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-channel { font-size: 12px; color: var(--text-dim); margin-top: 5px; }
.card-note {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.card-menu {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  border-radius: 8px;
  width: 32px; height: 32px;
  cursor: pointer;
  align-self: center;
  flex-shrink: 0;
  font-size: 19px;
  line-height: 1;
  transition: all 0.16s;
  opacity: 0.9;
}
.card:hover .card-menu { opacity: 1; }
.card-menu:hover { color: #fff; border-color: var(--accent); background: var(--accent); }

/* Drag-to-reorder */
.card.dragging { opacity: 0.4; }
.card.drag-over { border-color: var(--accent) !important; box-shadow: 0 0 0 2px var(--accent-glow); }

/* Saved-offline badge on cards — just the glyph, no boundary shape behind it */
.saved-badge {
  position: absolute; left: 5px; bottom: 5px;
  display: none;
  align-items: center; justify-content: center;
  width: 18px; height: 18px;
  color: #7ee0a8;
  font-size: 12px; font-weight: 700;
  text-shadow: 0 1px 3px rgba(0,0,0,0.85);
}
.card.cached .saved-badge { display: flex; }
.card.downloading .saved-badge {
  display: flex;
  color: #ffc850;
  animation: pulse 1s ease-in-out infinite;
}
.card.downloading .saved-badge::before { content: "⏳"; }
.card.downloading .saved-badge { font-size: 0; }
.card.downloading .saved-badge::before { font-size: 12px; }

/* Download progress bar on card thumb */
.dl-progress {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 3px;
  background: rgba(0,0,0,0.5);
  overflow: hidden;
}
.dl-bar {
  height: 100%;
  width: 30%;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-bright));
  border-radius: 0 2px 2px 0;
  animation: dlSlide 1.2s ease-in-out infinite;
}
@keyframes dlSlide {
  0% { transform: translateX(-100%); width: 30%; }
  50% { width: 45%; }
  100% { transform: translateX(400%); width: 30%; }
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }

/* ===================== Settings page ===================== */
.settings { display: flex; flex-direction: column; gap: 18px; padding: 4px 6px 28px; }
.set-group {
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
}
.set-group-title {
  font-family: var(--mono);
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--accent);
  margin-bottom: 14px;
}
.set-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid var(--line-soft);
}
.set-group .set-row:first-of-type { border-top: none; }
.set-row > span { display: flex; flex-direction: column; gap: 3px; color: var(--text); font-size: 13.5px; font-weight: 500; }
.set-row small { color: var(--text-dim); font-size: 11.5px; font-weight: 400; line-height: 1.4; max-width: 280px; }
.set-row input[type="range"] { width: 150px; }
.set-row input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
.about-version { color: var(--text-dim); font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; user-select: text; }
.set-select {
  background: var(--bg-3); color: var(--text);
  border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 10px; font-family: var(--mono); font-size: 12px; cursor: pointer;
}
.set-select:hover { border-color: var(--accent); }
.set-stat { font-family: var(--mono); font-size: 12px; color: var(--text-2); }
.set-actions { padding-top: 14px; }
.cache-list { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.cache-empty { color: var(--text-dim); font-size: 12.5px; padding: 8px 0; }
.cache-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  background: var(--bg-3);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
}
.cache-item .ci-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
.cache-item .ci-size { font-family: var(--mono); font-size: 11px; color: var(--text-dim); }
.cache-item .ci-del {
  background: transparent; border: 1px solid var(--line);
  color: var(--text-dim); width: 24px; height: 24px;
  border-radius: 6px; cursor: pointer; font-size: 12px; line-height: 1;
  transition: all 0.16s;
}
.cache-item .ci-del:hover { color: #fff; background: var(--accent); border-color: var(--accent); }

/* ===================== Modal ===================== */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(5,5,7,0.7);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  z-index: 100;
  animation: fade 0.18s ease;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal {
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  width: 400px;
  max-width: 90vw;
  box-shadow: var(--shadow);
  animation: pop 0.24s var(--ease);
}
@keyframes pop { from { opacity: 0; transform: translateY(14px) scale(0.97); } to { opacity: 1; transform: none; } }
.modal h3 { margin: 0 0 16px; font-family: var(--display); font-weight: 700; font-size: 19px; letter-spacing: -0.01em; }
.modal input[type="text"] {
  width: 100%;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 11px 13px;
  color: var(--text);
  font-family: var(--ui);
  font-size: 14px;
  outline: none;
  transition: border-color 0.16s, box-shadow 0.16s;
}
.modal input[type="text"]:focus { border-color: var(--accent); box-shadow: 0 0 0 4px rgba(255,75,50,0.12); }
.modal textarea {
  width: 100%;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 11px 13px;
  color: var(--text);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.45;
  outline: none;
  resize: vertical;
  min-height: 90px;
  box-sizing: border-box;
  transition: border-color 0.16s, box-shadow 0.16s;
}
.modal textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 4px rgba(255,75,50,0.12); }
.modal-subhead {
  font-size: 13px;
  color: var(--text-2);
  margin: -10px 0 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.modal-char-count {
  font-size: 11px;
  color: var(--text-dim);
  text-align: right;
  margin-top: 5px;
  font-family: var(--mono);
}
.modal-list { display: flex; flex-direction: column; gap: 5px; max-height: 280px; overflow-y: auto; margin-top: 2px; }
.modal-list button {
  text-align: left;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 11px 13px;
  border-radius: 9px;
  cursor: pointer;
  font-family: var(--ui);
  font-size: 13.5px;
  transition: border-color 0.16s, background 0.16s, transform 0.12s;
}
.modal-list button:hover { border-color: var(--accent); transform: translateX(3px); }
.modal-actions { display: flex; justify-content: flex-end; gap: 9px; margin-top: 20px; }
.btn {
  border: 1px solid var(--line);
  background: var(--bg-3);
  color: var(--text);
  padding: 10px 18px;
  border-radius: 9px;
  cursor: pointer;
  font-family: var(--ui);
  font-size: 13.5px;
  font-weight: 600;
  transition: all 0.16s var(--ease);
}
.btn:hover { border-color: var(--text-dim); }
.btn.primary {
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent; color: #fff;
  box-shadow: 0 8px 20px -8px var(--accent-glow);
}
.btn.primary:hover { transform: translateY(-1px); }
.btn.danger { color: #ff8a7a; border-color: rgba(255,75,50,0.3); }
.btn.danger:hover { background: rgba(255,75,50,0.12); }

/* ===================== Toast ===================== */
.toast-container {
  position: fixed;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.toast {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 13px 20px;
  border-radius: 11px;
  box-shadow: var(--shadow);
  font-size: 13.5px;
  font-weight: 500;
  /* Short toasts stay on one line; longer ones wrap inside the viewport
     instead of running off both edges on a phone. */
  width: max-content;
  max-width: min(560px, calc(100vw - 32px));
  box-sizing: border-box;
  white-space: normal;
  text-align: center;
  animation: toastIn 0.3s var(--ease);
  pointer-events: auto;
}
@keyframes toastIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
.toast-exit {
  animation: toastOut 0.25s var(--ease) forwards;
}
@keyframes toastOut {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-8px); }
}
/* PWA update banner — persistent toast with inline action button */
.toast-update {
  border-color: var(--accent);
  display: flex;
  align-items: center;
  gap: 10px;
}
.toast-reload-btn {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

/* ===================== Keyboard shortcut overlay ===================== */
.shortcut-overlay {
  position: fixed; inset: 0;
  z-index: 500;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  animation: fadeIn 0.2s ease;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.shortcut-panel {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px 32px;
  min-width: 380px;
  max-width: 480px;
  box-shadow: 0 24px 64px -16px rgba(0,0,0,0.6);
  animation: panelIn 0.2s var(--ease);
}
@keyframes panelIn { from { opacity: 0; transform: scale(0.95) translateY(10px); } to { opacity: 1; transform: none; } }
.shortcut-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 20px;
}
.shortcut-header h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.01em;
}
.shortcut-close {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-2);
  width: 32px; height: 32px;
  border-radius: 9px;
  cursor: pointer;
  font-size: 15px;
  display: grid; place-items: center;
  transition: all 0.16s;
}
.shortcut-close:hover { color: var(--text); border-color: var(--accent); background: var(--bg-3); }
.shortcut-grid {
  display: flex; flex-direction: column; gap: 10px;
}
.shortcut-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line-soft);
}
.shortcut-row:last-child { border-bottom: none; }
.shortcut-row span { color: var(--text-2); font-size: 13px; flex: 1; }
.shortcut-row kbd {
  font-family: var(--mono);
  font-size: 11px; font-weight: 700;
  color: var(--text);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 4px 9px;
  min-width: 28px;
  text-align: center;
  line-height: 1;
}

.hidden { display: none !important; }

/* ============================================================================
 * Bottom Navigation Bar — YouTube-style, portrait PWA mode only
 * Hidden by default; made visible inside the portrait-PWA media query.
 * ========================================================================== */
.bottom-nav {
  display: none; /* hidden on desktop and non-portrait modes */
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 310; /* above mini-bar (300) so it's always accessible */
  flex-direction: row;
  align-items: stretch;
  background: linear-gradient(180deg, var(--bg-1), var(--bg));
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
}

.bottom-nav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 8px 4px 6px;
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  position: relative;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.16s var(--ease);
  min-width: 0;
}

.bottom-nav-btn:active {
  background: var(--bg-2);
}

.bottom-nav-btn.active {
  color: var(--accent-bright);
}

.bottom-nav-btn.active .bottom-nav-icon {
  /* Subtle scale pop on active */
  transform: scale(1.12);
}

.bottom-nav-icon {
  font-size: 20px;
  line-height: 1;
  display: block;
  transition: transform 0.18s var(--ease);
}

.bottom-nav-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.bottom-nav-badge {
  position: absolute;
  top: 6px;
  left: 50%;
  margin-left: 6px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 8px;
  display: grid;
  place-items: center;
  line-height: 1;
  pointer-events: none;
}

.bottom-nav-badge.hidden { display: none; }

/* ===================== Mini now-playing bar ===================== */
.mini-bar {
  position: fixed; bottom: 0; left: 0; right: 0;
  z-index: 300;
  cursor: pointer;
  animation: miniBarIn 0.25s var(--ease);
}
@keyframes miniBarIn {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.mini-bar-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-top: 1px solid var(--line);
  backdrop-filter: blur(8px);
}
.mini-btn {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text);
  width: 34px; height: 34px;
  border-radius: 9px;
  cursor: pointer;
  font-size: 14px;
  display: grid; place-items: center;
  flex-shrink: 0;
  transition: all 0.16s;
}
.mini-btn:hover { border-color: var(--accent); color: var(--accent-bright); }
.mini-close {
  width: 28px; height: 28px;
  font-size: 12px;
  color: var(--text-dim);
}
.mini-close:hover { color: var(--text); border-color: var(--text-dim); }
/* Set-list view straight from the now-playing bar. */
.mini-service { font-size: 15px; }
.mini-service:hover { border-color: var(--accent); }
.mini-info {
  min-width: 0; flex: 1;
  display: flex; flex-direction: column;
  gap: 2px;
}
.mini-title {
  font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mini-channel {
  font-size: 11px; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mini-time {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-2);
  flex-shrink: 0;
}
.mini-progress {
  height: 3px;
  background: var(--bg-3);
}
.mini-progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-bright));
  transition: width 1s linear;
}

@media (max-width: 1080px) {
  .body { flex-direction: column; }
  .list-pane { width: auto; border-left: none; border-top: 1px solid var(--line-soft); }
  /* In the stacked layout both panes must be allowed to shrink below their
     content height (flex min-height defaults to auto), or they overflow the
     hidden .body instead of engaging their own scrollbars — on a landscape
     phone that made "Up next" unreachable. The base .list-pane rule sets
     flex-shrink: 0 (right for the fixed-width side column); here the pane
     must shrink or long views (Settings) get clipped with no scrollbar. */
  .player-pane { min-height: 0; }
  .list-pane { min-height: 0; flex-shrink: 1; }
}

/* ============================================================================
 * Responsive sidebar — off-canvas drawer on small screens
 * Below 860px the fixed 264px grid column is dropped; the sidebar becomes a
 * slide-in drawer toggled by the hamburger button so the playlist and every
 * other sidebar item stay reachable from 320px up to tablet width.
 * ========================================================================== */
@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }

  /* Keep the five playback buttons on one line at the top of the control
     deck; everything else (📍, A-B, volume, transition, EQ, PiP, speed…)
     flows into a tool row underneath. A control with no explicit order
     defaults to 0 and would otherwise jump ahead of the transport group. */
  .btn-row { justify-content: center; }
  .btn-row::before { content: ""; width: 100%; order: 6; height: 0; }
  #shuffleBtn { order: 1; }
  #prevBtn    { order: 2; }
  #playBtn    { order: 3; }
  #nextBtn    { order: 4; }
  #repeatBtn  { order: 5; }
  .btn-row > *:not(#shuffleBtn):not(#prevBtn):not(#playBtn):not(#nextBtn):not(#repeatBtn) { order: 7; }
  .btn-row .spacer { display: none; }

  .sidebar-toggle { display: inline-flex; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(86vw, 300px);
    max-width: 300px;
    z-index: 100;
    border-right: 1px solid var(--line-soft);
    box-shadow: var(--shadow);
    transform: translateX(-100%);
    transition: transform 0.28s var(--ease);
    will-change: transform;
  }

  .app.sidebar-open .sidebar { transform: translateX(0); }

  .app.sidebar-open .sidebar-backdrop { display: block; opacity: 1; }

  /* Empty-home playlist grid: the player stage is short on phones, so pack in
     more, smaller cards rather than one oversized full-width column. */
  .player-placeholder.showing-playlists { padding: 12px; }
  /* …but don't let it eat the whole screen — the list pane must stay reachable
     without scrolling past a full-height board. */
  .player-pane.empty.home-playlists .player-stage { max-height: 58vh; }
  .home-pl-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 10px; }
  .home-pl-title { font-size: 15px; }
  .home-pl-name { font-size: 12px; }
}

/* Very narrow screens (e.g. 320px) — keep the topbar usable and the drawer
   from ever exceeding the viewport. */
@media (max-width: 420px) {
  .topbar { padding: 12px 14px; }
  .sidebar { width: min(88vw, 280px); }
}

/* ============================================================================
 * Loop / repeat active state
 * ========================================================================== */
.ctrl.active {
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent;
  box-shadow: 0 6px 16px -8px var(--accent-glow);
}

/* ============================================================================
 * Sidebar nav badges (queue / downloads counts)
 * ========================================================================== */
.nav-badge {
  display: inline-grid;
  place-items: center;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  margin-left: 4px;
  font-family: var(--mono);
  font-size: 10px; font-weight: 700;
  color: #fff;
  background: var(--accent);
  border-radius: 10px;
  vertical-align: middle;
}

/* ============================================================================
 * Clickable channel links
 * ========================================================================== */
.card-channel.link { cursor: pointer; }
.card-channel.link:hover { color: var(--accent); text-decoration: underline; }
.np-channel { cursor: pointer; }
.np-channel:hover { color: var(--text-2); }
.upnext-channel.link { cursor: pointer; }
.upnext-channel.link:hover { color: var(--accent); text-decoration: underline; }
.ri-channel.link { cursor: pointer; }
.ri-channel.link:hover { color: var(--accent); text-decoration: underline; }
.mini-channel.link { cursor: pointer; }
.mini-channel.link:hover { color: var(--accent); text-decoration: underline; }

/* ============================================================================
 * Per-card delete button (playlist / queue / saved)
 * ========================================================================== */
.card-del {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-dim);
  width: 30px; height: 30px;
  border-radius: 8px;
  cursor: pointer;
  align-self: center;
  flex-shrink: 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0;
  transition: all 0.16s var(--ease);
}
.card:hover .card-del { opacity: 1; }
.card-del:hover { color: #fff; background: var(--accent); border-color: var(--accent); }
.saved-card .card-del { opacity: 0.85; }

/* ============================================================================
 * Per-card note button (playlist view)
 * ========================================================================== */
.card-note-btn {
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--text-dim);
  width: 30px; height: 30px;
  border-radius: 8px;
  cursor: pointer;
  align-self: center;
  flex-shrink: 0;
  font-size: 14px;
  line-height: 1;
  opacity: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.16s var(--ease);
}
.card:hover .card-note-btn { opacity: 1; }
.card-note-btn:hover { color: #fff; background: var(--accent); border-color: var(--accent); }
.card-note-btn.has-note {
  opacity: 1;
  color: var(--accent);
  border-color: rgba(255, 75, 50, 0.35);
  background: rgba(255, 75, 50, 0.1);
}
.card-note-btn.has-note:hover {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}

/* ============================================================================
 * Modal divider label
 * ========================================================================== */
.modal-divider {
  font-family: var(--mono);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--text-dim);
  padding: 12px 2px 2px;
}

/* ============================================================================
 * Saved / Downloads summary header
 * ========================================================================== */
.saved-summary {
  display: flex; align-items: baseline; gap: 10px;
  padding: 8px 9px 14px;
}
.saved-total {
  font-family: var(--display);
  font-weight: 800;
  font-size: 26px;
  letter-spacing: -0.02em;
  color: var(--text);
}
.saved-sub { color: var(--text-dim); font-size: 13px; }
.saved-size { font-family: var(--mono); font-size: 11.5px; color: var(--text-dim); }

/* ============================================================================
 * THEMES
 * ========================================================================== */
:root[data-theme="light"] {
  --bg: #f4f2ee;
  --bg-1: #ffffff;
  --bg-2: #efece6;
  --bg-3: #e5e0d8;
  --line: #d8d2c8;
  --line-soft: #e6e1d9;
  --text: #1b1a18;
  --text-2: #4a4843;
  --text-dim: #7c776e;
  --shadow: 0 18px 50px -18px rgba(0, 0, 0, 0.25);
}
:root[data-theme="light"] body::after { opacity: 0.02; }
:root[data-theme="light"] .hero-title {
  background: linear-gradient(180deg, #1b1a18, #514d46);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
:root[data-theme="light"] #video,
:root[data-theme="light"] .player-stage { background: #000; }

:root[data-theme="contrast"] {
  --bg: #000000;
  --bg-1: #000000;
  --bg-2: #0a0a0a;
  --bg-3: #161616;
  --line: #ffffff;
  --line-soft: #9a9a9a;
  --text: #ffffff;
  --text-2: #ffffff;
  --text-dim: #d8d8d8;
  --accent: #ff5a3c;
  --accent-bright: #ff8a6c;
  --accent-deep: #ff5a3c;
  --accent-glow: rgba(255, 90, 60, 0.85);
}
:root[data-theme="contrast"] body::after { display: none; }
:root[data-theme="contrast"] body::before { display: none; }
:root[data-theme="contrast"] .hero-title {
  background: none;
  -webkit-text-fill-color: var(--text);
  color: var(--text);
}
:root[data-theme="contrast"] .card { border-color: var(--line-soft); }
:root[data-theme="contrast"] .card-channel,
:root[data-theme="contrast"] .card-note,
:root[data-theme="contrast"] .card-title { color: var(--text); }

/* ============================================================================
 * FONT SIZE — scales the whole UI (zoom is supported by WebView2 + WKWebView)
 * ========================================================================== */
:root[data-font="small"] { zoom: 0.9; }
:root[data-font="normal"] { zoom: 1; }
:root[data-font="large"] { zoom: 1.12; }
:root[data-font="xl"] { zoom: 1.26; }

/* ============================================================================
 * LAYOUT DENSITY — compact tightens spacing
 * ========================================================================== */
:root[data-density="compact"] .player-pane { padding: 14px 16px 18px; }
:root[data-density="compact"] .cards { gap: 2px; padding: 4px 10px 20px; }
:root[data-density="compact"] .card { padding: 6px; gap: 9px; }
:root[data-density="compact"] .thumb { width: 104px; }
:root[data-density="compact"] .card-title { font-size: 12.5px; -webkit-line-clamp: 1; }
:root[data-density="compact"] .card-channel { margin-top: 2px; }
:root[data-density="compact"] .card-note { font-size: 11px; margin-top: 1px; }
:root[data-density="compact"] .nav-item { padding: 8px 12px; }
:root[data-density="compact"] .playlist-item { padding: 7px 12px; }
:root[data-density="compact"] .controls { padding: 12px 14px; margin-top: 12px; }
:root[data-density="compact"] .btn-row { margin-top: 11px; gap: 7px; }
:root[data-density="compact"] .list-header { padding: 16px 16px 10px; }
:root[data-density="compact"] .topbar { padding: 11px 18px; }

/* ============================================================================
 * PERFORMANCE MODE — drop expensive paints (grain, blur, big glows)
 * ========================================================================== */
:root[data-perf="on"] body::before,
:root[data-perf="on"] body::after { display: none; }
:root[data-perf="on"] .topbar { backdrop-filter: none; }
:root[data-perf="on"] .modal-backdrop,
:root[data-perf="on"] .shortcut-overlay,
:root[data-perf="on"] .mini-bar-inner { backdrop-filter: none; }
:root[data-perf="on"] .player-pane:not(.empty) .player-stage {
  box-shadow: 0 0 0 1px var(--line) inset;
}
:root[data-perf="on"] .ph-logo,
:root[data-perf="on"] .skeleton-shimmer::after { animation: none; }
:root[data-perf="on"] .card { animation: none; }

/* ============================================================================
 * REDUCE MOTION — honor explicit toggle and OS preference
 * ========================================================================== */
:root[data-motion="reduced"] *,
:root[data-motion="reduced"] *::before,
:root[data-motion="reduced"] *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ============================================================================
 * Seek wrap + A-B markers
 * ========================================================================== */
.seek-wrap { position: relative; flex: 1; display: flex; flex-direction: column; gap: 4px; }
.seek-wrap .seek { width: 100%; flex: none; }
.ab-indicator {
  display: flex; align-items: center; padding: 0 2px;
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.05em;
}
.ab-label { color: var(--text-dim); transition: color 0.16s; }
.ab-label.active { color: var(--accent); }
.ab-ctrl { font-family: var(--mono); font-size: 12px; font-weight: 800; min-width: 34px; }
.ab-ctrl.active {
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent;
  box-shadow: 0 6px 16px -8px var(--accent-glow);
}

/* ============================================================================
 * Sleep timer status bar
 * ========================================================================== */
.sleep-status {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 16px; margin-top: 10px;
  background: rgba(255,75,50,0.07);
  border: 1px solid rgba(255,75,50,0.22);
  border-radius: var(--radius-sm);
}
.sleep-countdown {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: var(--accent); flex: 1;
}
.sleep-cancel {
  background: transparent; border: 1px solid rgba(255,75,50,0.35);
  color: var(--accent); border-radius: 7px;
  padding: 5px 10px; cursor: pointer; font-size: 12px; font-weight: 600;
  transition: all 0.16s;
}
.sleep-cancel:hover { background: rgba(255,75,50,0.14); }
.ctrl.sleep-active {
  color: #fff;
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border-color: transparent;
}

/* ============================================================================
 * Related videos panel
 * ========================================================================== */
.related-panel {
  margin-top: 16px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.related-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.related-label {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.16em; color: var(--text-dim);
}
.related-toggle-btn {
  background: transparent; border: none; color: var(--text-dim);
  font-size: 16px; cursor: pointer; padding: 0 4px; line-height: 1;
  transition: color 0.16s;
}
.related-toggle-btn:hover { color: var(--text); }
.related-list {
  display: flex; flex-direction: column; gap: 4px;
  padding: 8px 10px; max-height: 280px; overflow-y: auto;
}
.related-item {
  display: flex; gap: 10px; padding: 6px 8px;
  border-radius: 9px; cursor: pointer;
  border: 1px solid transparent;
  transition: background 0.16s, border-color 0.16s;
}
.related-item:hover { background: var(--bg-3); border-color: var(--line); }
.related-item img { width: 80px; aspect-ratio: 16/9; border-radius: 6px; object-fit: cover; background: #000; flex-shrink: 0; }
.related-item .ri-info { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.related-item .ri-title {
  font-size: 12.5px; font-weight: 600; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.related-item .ri-channel { font-size: 11px; color: var(--text-dim); margin-top: 3px; }

/* ============================================================================
 * Smart / auto playlists in sidebar
 * ========================================================================== */
.smart-pl-header { opacity: 0.75; margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--line-soft); }
.smart-pl-list { flex: 0 0 auto !important; margin-bottom: 6px; }
.smart-item .pl-name::before { content: "◈ "; color: var(--text-dim); font-size: 9px; }
.smart-item.active .pl-name::before { color: var(--accent); }

/* ============================================================================
 * List filter bar
 * ========================================================================== */
.list-filter-bar { padding: 0 14px 8px; }
.list-filter-bar input {
  width: 100%; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 9px; padding: 8px 12px;
  color: var(--text); font-family: var(--ui); font-size: 13px;
  outline: none; transition: border-color 0.16s, box-shadow 0.16s;
}
.list-filter-bar input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(255,75,50,0.1); }
.list-filter-bar input::placeholder { color: var(--text-dim); }

/* ============================================================================
 * Batch selection bar
 * ========================================================================== */
.batch-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 14px;
  background: rgba(255,75,50,0.07);
  border-bottom: 1px solid rgba(255,75,50,0.18);
}
.batch-count { font-family: var(--mono); font-size: 12px; font-weight: 700; color: var(--accent); flex: 1; }
.batch-btn {
  background: var(--bg-3); border: 1px solid var(--line); color: var(--text-2);
  border-radius: 7px; padding: 6px 11px; cursor: pointer;
  font-family: var(--ui); font-size: 12px; font-weight: 600; transition: all 0.16s;
}
.batch-btn:hover { color: var(--text); border-color: var(--accent); }
.batch-danger { color: #ff8a7a !important; border-color: rgba(255,75,50,0.28) !important; }
.batch-danger:hover { background: rgba(255,75,50,0.12) !important; }

/* Batch checkboxes on cards */
.card .batch-check {
  display: none; position: absolute; left: 8px; top: 8px; z-index: 3;
  width: 20px; height: 20px; border-radius: 6px;
  border: 2px solid var(--line); background: var(--bg-1);
  align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; transition: all 0.14s;
  pointer-events: none;
}
.cards.select-mode .card .batch-check { display: flex; }
.cards.select-mode .card { cursor: pointer; }
.card.selected .batch-check { background: var(--accent); border-color: var(--accent); color: #fff; }
.card.selected .batch-check::after { content: "✓"; }
.card.selected { border-color: var(--accent) !important; background: var(--bg-2); }

/* ============================================================================
 * PORTRAIT PWA — activates only in standalone (installed) mode + portrait
 *
 * Triggers:   @media (display-mode: standalone) and (orientation: portrait)
 * Safe areas: env(safe-area-inset-*) applied to all fixed/sticky containers
 *             so notches and home-indicator bars never obscure UI chrome.
 * Layout:     Full single-column vertical stack; sidebar stays as drawer only.
 * ========================================================================== */
@media (display-mode: standalone) and (orientation: portrait) {

  /* --- Root layout: single-column full-width stack ----------------------- */
  .app {
    grid-template-columns: 1fr;
    /* Stack children: topbar → body → mini-bar (all in .main) */
  }

  /* --- Bottom nav: shown in portrait PWA, hidden everywhere else ---------- */
  .bottom-nav {
    display: flex;
  }

  /* --- Sidebar toggle: visible in portrait for playlist/drawer access ---- */
  /* Primary navigation is now the bottom bar; the hamburger gives access
     to playlists and auto-playlists which are not in the bottom nav. */
  .sidebar-toggle { display: inline-flex; }

  /* --- Sidebar: always off-canvas drawer (never occupies grid column) ---- */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(86vw, 300px);
    max-width: 300px;
    z-index: 100;
    border-right: 1px solid var(--line-soft);
    box-shadow: var(--shadow);
    transform: translateX(-100%);
    transition: transform 0.28s var(--ease);
    will-change: transform;
    /* Respect notch/home-bar on the left edge */
    padding-top: calc(22px + env(safe-area-inset-top));
    padding-left: calc(14px + env(safe-area-inset-left));
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
  }

  .app.sidebar-open .sidebar { transform: translateX(0); }
  .app.sidebar-open .sidebar-backdrop { display: block; opacity: 1; }

  /* --- Topbar: full-width, padded for status-bar notch ------------------- */
  /* Width 100% ensures the topbar background fills behind the notch/status
     bar area so its colour (the gradient) extends edge-to-edge. */
  .topbar {
    width: 100%;
    /* iOS < 11.2 fallback — constant() was the predecessor to env() */
    padding-top: calc(12px + constant(safe-area-inset-top, 0px));
    padding-left: calc(14px + constant(safe-area-inset-left, 0px));
    padding-right: calc(14px + constant(safe-area-inset-right, 0px));
    padding-bottom: 12px;
    /* Modern browsers: env() overrides the constant() lines above */
    padding-top: calc(12px + env(safe-area-inset-top, 0px));
    padding-left: calc(14px + env(safe-area-inset-left, 0px));
    padding-right: calc(14px + env(safe-area-inset-right, 0px));
    position: sticky;
    top: 0;
    z-index: 50;
  }

  /* --- Body: vertical stack (player above list), THE scroll container ---- */
  .body {
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    /* The body is the single scroll container in portrait. A playing player
       pane (stage + control deck + meta + up-next + related) is taller than
       the whole viewport, so it must be able to scroll out of the way — with
       overflow:hidden here the list-pane sat unreachable below the fold and
       every sidebar/bottom-nav tap looked dead while a track was playing. */
  }

  /* --- Player pane: full width, compact vertical padding ----------------- */
  .player-pane {
    flex: none;
    width: 100%;
    padding: 14px calc(14px + env(safe-area-inset-right)) 14px
             calc(14px + env(safe-area-inset-left));
    overflow-y: visible;
  }

  /* Player stage: keep 16:9 aspect ratio, fill viewport width */
  .player-stage {
    width: 100%;
    aspect-ratio: 16 / 9;
  }

  /* Controls: wrap btn-row so nothing overflows on narrow screens */
  .btn-row {
    flex-wrap: wrap;
    gap: 7px;
  }

  /* The five playback buttons stay together on the first line: every OTHER
     control is pushed into the tool row below. Without an explicit order a
     button defaults to 0 and jumps ahead of the transport group. */
  .btn-row::before { content: ""; width: 100%; order: 6; height: 0; }
  #shuffleBtn { order: 1; }
  #prevBtn    { order: 2; }
  #playBtn    { order: 3; }
  #nextBtn    { order: 4; }
  #repeatBtn  { order: 5; }
  .btn-row > *:not(#shuffleBtn):not(#prevBtn):not(#playBtn):not(#nextBtn):not(#repeatBtn) { order: 7; }
  .btn-row { justify-content: center; }
  .btn-row .spacer { display: none; }

  /* Now-playing meta: stack vertically */
  .now-meta {
    flex-direction: column;
    gap: 12px;
    margin-top: 14px;
  }

  .np-actions {
    flex-wrap: wrap;
    gap: 6px;
  }

  /* --- List pane: full width below player, flows in the body scroll ------ */
  .list-pane {
    flex: none;
    /* At least one full body-height so navigating always yields a full-screen
       page; longer content just grows the body scroll. */
    min-height: 100%;
    width: 100%;
    border-left: none;
    border-top: 1px solid var(--line-soft);
    overflow-y: visible;
    overflow-x: hidden;
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
    /* Pad bottom to clear bottom-nav (~56px) + mini-bar (~52px) + safe area */
    padding-bottom: calc(116px + env(safe-area-inset-bottom));
  }

  /* Cards list: unconstrained height — list-pane is now the scroll container */
  .cards {
    max-height: none;
    overflow-y: visible;
    padding-bottom: 0;
  }

  /* Settings panel: ensure full accessibility with bottom clearance */
  .settings {
    padding-bottom: calc(80px + env(safe-area-inset-bottom));
  }

  /* --- Mini now-playing bar: sit above the bottom-nav -------------------- */
  /* bottom-nav is ~56px tall; mini-bar floats on top of it.
     The bottom-nav's own padding-bottom handles the safe-area-inset, so
     mini-bar only needs to clear the nav height itself (no extra inset). */
  .mini-bar {
    bottom: calc(56px + env(safe-area-inset-bottom));
    padding-bottom: 0;
  }

  .mini-bar-inner {
    padding-left: calc(16px + env(safe-area-inset-left));
    padding-right: calc(16px + env(safe-area-inset-right));
  }

  /* --- Toast container: clear bottom-nav + mini-bar ---------------------- */
  .toast-container {
    bottom: calc(82px + env(safe-area-inset-bottom));
  }

  /* --- Modal: safe-area aware -------------------------------------------- */
  .modal-backdrop {
    padding: calc(16px + env(safe-area-inset-top))
             calc(16px + env(safe-area-inset-right))
             calc(16px + env(safe-area-inset-bottom))
             calc(16px + env(safe-area-inset-left));
  }

  /* --- Shortcut overlay: safe-area aware --------------------------------- */
  .shortcut-overlay {
    padding: calc(16px + env(safe-area-inset-top))
             calc(16px + env(safe-area-inset-right))
             calc(16px + env(safe-area-inset-bottom))
             calc(16px + env(safe-area-inset-left));
  }

  /* --- Up next list: allow reasonable height on portrait screen ---------- */
  .upnext-list {
    max-height: 160px;
  }

  /* --- Related videos panel: compact on portrait ------------------------- */
  .related-list {
    max-height: 200px;
  }

  /* --- Hero title: slightly smaller on narrow portrait screens ----------- */
  .hero-title { font-size: 30px; }
  .ph-logo { width: 68px; height: 68px; font-size: 26px; }
  .hero-tagline { font-size: 13px; }
}

/* ============================================================================
 * INSTALLED PWA ON TOUCH DEVICES — drop expensive full-screen composites
 *
 * The film-grain overlay (mix-blend-mode over the whole viewport), the fixed
 * gradient wash, and the chrome backdrop-blurs all re-composite over the
 * playing <video> every frame. On iPhones that GPU contention audibly
 * stutters audio — backgrounding the PWA (which stops rendering) made
 * playback smooth, which is how this was diagnosed. Same cuts as
 * data-perf="on", applied automatically where they hurt most; desktop
 * browsers and fine-pointer devices are untouched.
 * ========================================================================== */
@media (display-mode: standalone) and (pointer: coarse) {
  body::before,
  body::after { display: none; }
  .topbar,
  .bottom-nav,
  .mini-bar-inner {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .player-pane:not(.empty) .player-stage {
    box-shadow: 0 0 0 1px var(--line) inset;
  }
}

/* ============================================================================
 * PORTRAIT PWA — mobile app design refresh
 *
 * Same media query as the structural block above; being later in the cascade,
 * these rules win ties. Scope is intentionally identical so desktop, browser
 * tabs, and landscape are never affected. Design goals (mobile-app UI):
 *   • 44px minimum tap targets, thumb-zone transport controls
 *   • music-app control deck: centered shuffle/prev/play/next/repeat row,
 *     secondary tools on a second row; volume slider hidden (hardware keys)
 *   • bottom-sheet modals, floating mini-player card, nav active pill
 *   • 16px input font to stop iOS focus-zoom
 * ========================================================================== */
@media (display-mode: standalone) and (orientation: portrait) {

  /* --- Global touch polish ---------------------------------------------- */
  ::-webkit-scrollbar { width: 0; height: 0; }
  button, .card, .nav-item, .playlist-item { -webkit-tap-highlight-color: transparent; }

  /* --- Topbar: app-bar with pill search --------------------------------- */
  .sidebar-toggle {
    width: 44px;
    height: 44px;
    border-radius: 14px;
  }
  .search-form { min-width: 0; } /* flex item: allow shrinking to the viewport */
  #searchInput {
    height: 44px;
    min-width: 0; /* let the pill shrink below intrinsic input width */
    border-radius: 22px;
    padding: 0 18px;
    font-size: 16px; /* ≥16px prevents iOS focus-zoom */
  }
  .search-btn {
    height: 44px;
    border-radius: 22px;
    padding: 0 18px;
  }

  /* --- Player pane ------------------------------------------------------- */
  .player-pane {
    padding: 12px calc(12px + env(safe-area-inset-right)) 12px
             calc(12px + env(safe-area-inset-left));
  }
  .player-stage { border-radius: 16px; }

  /* --- Control deck: two-row music-app transport ------------------------- */
  .controls {
    margin-top: 12px;
    border-radius: 18px;
    padding: 14px 14px 16px;
  }
  .seek-row { gap: 10px; }
  /* Fatter seek track + thumb for touch */
  .seek { height: 6px; }
  .seek::-webkit-slider-thumb { width: 18px; height: 18px; }

  .btn-row {
    justify-content: center;
    gap: 10px 8px;
    margin-top: 14px;
  }
  /* Forced line break between transport row (order ≤ 5) and tool row (≥ 7) */
  .btn-row::before { content: ""; width: 100%; order: 6; height: 0; }

  /* Row A — transport, centered in the thumb zone */
  #shuffleBtn { order: 1; }
  #prevBtn    { order: 2; }
  #playBtn    { order: 3; }
  #nextBtn    { order: 4; }
  #repeatBtn  { order: 5; }

  #prevBtn, #nextBtn, #shuffleBtn, #repeatBtn {
    background: transparent;
    border-color: transparent;
    width: 48px;
    height: 48px;
    border-radius: 50%;
  }
  #prevBtn, #nextBtn { font-size: 20px; }
  #shuffleBtn, #repeatBtn { font-size: 17px; color: var(--text-2); }
  #shuffleBtn.active, #repeatBtn.active {
    color: var(--accent-bright);
    background: rgba(255, 75, 50, 0.16);
    border-color: transparent;
    box-shadow: none;
  }
  #playBtn {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    font-size: 24px;
    margin: 0 6px;
  }

  /* Row B — secondary tools, uniform 44px targets (sizes only: colors and
     .active/.sleep-active states keep their class-based styling) */
  #abABtn, #abBBtn, #abClearBtn, #muteBtn, #loopBtn, #sleepTimerBtn, #fsBtn,
  #rememberPosBtn, #transitionBtn, #eqBtn, #pipBtn {
    order: 7;
    min-width: 44px;
    height: 44px;
    border-radius: 13px;
  }
  .vol { order: 7; }
  .vol input { display: none; } /* hardware volume keys on mobile */
  .btn-row .spacer { display: none; }
  .btn-row .sel { order: 8; }
  .sel select {
    height: 44px;
    border-radius: 13px;
    padding: 0 10px;
  }

  /* --- Now playing meta: full-width action grid --------------------------- */
  .now-meta { margin-top: 16px; }
  .np-title { font-size: 18px; }
  .np-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    width: 100%;
  }
  .np-btn {
    padding: 12px 8px;
    text-align: center;
    border-radius: 13px;
  }

  /* --- Up next / related: comfier touch rows ------------------------------ */
  .upnext { border-radius: 18px; }
  .upnext-item { padding: 8px; border-radius: 12px; }
  .upnext-item img { width: 96px; border-radius: 8px; }
  .related-panel { border-radius: 18px; }
  .related-item { padding: 8px; border-radius: 12px; }
  .related-item img { width: 96px; border-radius: 8px; }

  /* --- List pane: large title, touch-sized rows --------------------------- */
  .list-header { padding: 18px 16px 10px; }
  .list-header h2 { font-size: 24px; letter-spacing: -0.02em; }
  .list-actions button { padding: 9px 13px; border-radius: 10px; }
  .list-filter-bar input {
    padding: 11px 14px;
    border-radius: 13px;
    font-size: 16px;
  }
  .batch-btn { padding: 10px 14px; border-radius: 10px; }

  .cards { gap: 8px; padding-left: 12px; padding-right: 12px; }
  .card { padding: 10px; gap: 12px; border-radius: 16px; }
  .thumb { border-radius: 12px; }
  .card-title { font-size: 14px; }
  .card-channel { margin-top: 6px; }
  /* No hover on touch — keep row actions always visible and finger-sized */
  .card-menu { width: 38px; height: 38px; border-radius: 12px; opacity: 1; }
  .card-note-btn { opacity: 1; width: 36px; height: 36px; border-radius: 11px; font-size: 15px; }
  .card-del { opacity: 1; width: 36px; height: 36px; border-radius: 11px; }

  /* --- Settings: roomier rows --------------------------------------------- */
  .set-group { border-radius: 18px; }
  .set-row { padding: 14px 0; }
  .set-row input[type="checkbox"] { width: 22px; height: 22px; }
  .set-select { padding: 10px 12px; border-radius: 11px; }

  /* --- Sidebar drawer: rounded sheet edge --------------------------------- */
  .sidebar {
    border-right: none;
    border-radius: 0 22px 22px 0;
  }
  .nav-item { padding: 13px 14px; font-size: 15px; }
  .playlist-item { padding: 12px 14px; }
  .switch { padding: 12px 10px; }

  /* --- Bottom nav: active pill indicator ---------------------------------- */
  .bottom-nav-btn { padding: 8px 4px 10px; gap: 4px; }
  .bottom-nav-icon {
    font-size: 21px;
    padding: 4px 16px;
    border-radius: 16px;
    transition: background 0.2s var(--ease), transform 0.18s var(--ease);
  }
  .bottom-nav-btn.active .bottom-nav-icon {
    background: rgba(255, 75, 50, 0.16);
    transform: none;
  }
  .bottom-nav-badge { top: 4px; margin-left: 10px; }

  /* --- Mini player: floating card above the nav --------------------------- */
  .mini-bar {
    left: 10px;
    right: 10px;
    bottom: calc(72px + env(safe-area-inset-bottom));
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid var(--line);
    box-shadow: 0 12px 34px -10px rgba(0, 0, 0, 0.65);
  }
  .mini-bar-inner {
    border-top: none;
    padding: 10px 6px 10px 14px;
  }
  .mini-btn { width: 40px; height: 40px; border-radius: 12px; }
  .mini-close { width: 36px; height: 36px; }

  /* List pane clearance for taller nav + floating mini-bar */
  .list-pane { padding-bottom: calc(152px + env(safe-area-inset-bottom)); }

  /* --- Toasts: clear the floating mini-bar -------------------------------- */
  .toast-container { bottom: calc(148px + env(safe-area-inset-bottom)); }
  .toast { white-space: normal; max-width: calc(100vw - 32px); text-align: center; }

  /* --- Modals: bottom sheet ----------------------------------------------- */
  .modal-backdrop {
    align-items: flex-end;
    padding: 0;
    z-index: 400; /* above mini-bar (300) and bottom-nav (310) */
  }
  .modal {
    width: 100%;
    max-width: 100%;
    border-radius: 22px 22px 0 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    padding: 12px 20px calc(24px + env(safe-area-inset-bottom));
    animation: sheetUp 0.3s var(--ease);
  }
  .modal::before {
    content: "";
    display: block;
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: var(--line);
    margin: 0 auto 16px;
  }
  .modal input[type="text"] { font-size: 16px; padding: 13px 15px; border-radius: 13px; }
  .modal textarea { font-size: 16px; padding: 13px 15px; border-radius: 13px; }
  .modal-list button { padding: 14px 15px; border-radius: 13px; }
  .modal-actions { margin-top: 22px; }
  .modal-actions .btn { padding: 13px 20px; border-radius: 13px; }

  /* --- Shortcut overlay: fit narrow screens ------------------------------- */
  .shortcut-panel { min-width: 0; width: 100%; max-width: 480px; }
}

@keyframes sheetUp {
  from { opacity: 0; transform: translateY(40%); }
  to { opacity: 1; transform: none; }
}

/* ============================================================================
 * PORTRAIT PWA — JS-class mirror (.portrait-pwa on .app)
 *
 * The JS layer (setupPortraitPwaWatcher in app.js) adds / removes
 * `.portrait-pwa` on `.app` whenever the media query fires, giving a CSS hook
 * that works inside JS-conditional code paths (e.g. scroll position checks,
 * layout reads) without re-evaluating matchMedia inline.
 *
 * These selectors intentionally duplicate nothing from the @media block above
 * — they only fill gaps that require the JS class (e.g. interaction states
 * that can't be expressed purely with CSS media queries).
 * ========================================================================== */
.portrait-pwa .body {
  /* Body does not scroll in portrait — list-pane handles scrolling.
     Scroll-snap is intentionally omitted since there is no scroll root here. */
}
.portrait-pwa .player-pane {
  /* Player pane is always visible at top; no snap needed. */
}

/* ============================================================================
 * LANDSCAPE PWA — activates in standalone (installed) mode + landscape
 *
 * In landscape, the notch (if present) sits on one of the horizontal edges.
 * We apply safe-area-inset-* to the topbar so its content never slides under
 * the notch or the status-bar area, and ensure the topbar background spans
 * the full screen width so the theme colour fills the notch region.
 * ========================================================================== */
@media (display-mode: standalone) and (orientation: landscape) {
  /* Topbar: full width + safe-area padding on all sides.
     constant() for iOS < 11.2; env() for all modern browsers (overrides above). */
  .topbar {
    width: 100%;
    /* iOS < 11.2 fallback */
    padding-top: calc(8px + constant(safe-area-inset-top, 0px));
    padding-left: calc(14px + constant(safe-area-inset-left, 0px));
    padding-right: calc(14px + constant(safe-area-inset-right, 0px));
    padding-bottom: 8px;
    /* Modern browsers */
    padding-top: calc(8px + env(safe-area-inset-top, 0px));
    padding-left: calc(14px + env(safe-area-inset-left, 0px));
    padding-right: calc(14px + env(safe-area-inset-right, 0px));
  }
}

/* ---- Share modal: send a playlist straight to another profile ------------- */
.share-send {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.share-send-label {
  display: block;
  font-size: 12px;
  color: var(--text-2);
  margin-bottom: 6px;
}
.share-send-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.share-send-row input {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  font-family: var(--ui);
  font-size: 14px;
}
.share-send-row input:focus { outline: none; border-color: var(--accent); }
.share-send-row .btn { flex: 0 0 auto; }
.share-send-msg {
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-2);
  min-height: 1.45em;
}
.share-send-msg.ok  { color: #34d399; }
.share-send-msg.err { color: var(--accent-bright); }

/* ============================================================================
 * Video editor modal (Edit & download) + edited-video badges
 * ========================================================================== */
.video-editor { display: flex; flex-direction: column; gap: 12px; }
.video-editor .ve-intro { margin: 0; color: var(--text-2); font-size: 13px; line-height: 1.5; }
.video-editor .ve-add-row {
  display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap;
}
.video-editor .ve-add-row label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--text-2); flex: 1 1 90px;
}
.video-editor .ve-add-row input {
  background: var(--bg-2); border: 1px solid var(--line); color: var(--text);
  border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px; width: 100%;
}
.video-editor .ve-add-row input:focus { outline: none; border-color: var(--accent); }
.video-editor .ve-add { flex: 0 0 auto; }
.video-editor .ve-error {
  color: var(--accent-bright); font-size: 12.5px; margin: -4px 0 0;
}
.video-editor .ve-cuts { display: flex; flex-direction: column; gap: 6px; }
.video-editor .ve-cut {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 7px 10px; font-size: 13.5px;
}
.video-editor .ve-cut-del {
  background: transparent; border: none; color: var(--text-2);
  cursor: pointer; font-size: 14px; padding: 2px 6px; border-radius: 6px;
}
.video-editor .ve-cut-del:hover { color: #fff; background: var(--accent); }
.video-editor .ve-title-row {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--text-2);
}
.video-editor .ve-title {
  background: var(--bg-2); border: 1px solid var(--line); color: var(--text);
  border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px;
}
.video-editor .ve-title:focus { outline: none; border-color: var(--accent); }
.video-editor .ve-summary { color: var(--text); font-size: 13.5px; }

/* Badge marking an edited (custom) copy in the Saved list and on cards. */
.edit-badge {
  position: absolute; top: 4px; left: 4px;
  background: var(--accent); color: #fff; font-size: 11px;
  line-height: 1; padding: 3px 5px; border-radius: 6px;
  box-shadow: 0 2px 6px -2px var(--accent-glow);
}
.saved-card.custom .thumb { position: relative; }

/* Video Editor Scrubber */
.ve-scrubber-track {
  height: 30px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  position: relative;
  cursor: pointer;
  margin: 10px 0;
}
.ve-scrubber-bar {
  height: 100%;
  background: var(--bg-2);
  border-radius: var(--radius-sm);
}
.ve-marker {
  position: absolute;
  top: 0;
  width: 20px;
  height: 100%;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 10px;
  font-weight: bold;
  cursor: pointer;
  pointer-events: auto;
}
.ve-marker-a { left: 0; }
.ve-marker-b { right: 0; }

/* ===================== Service Mode (Set-List View) ===================== */
.service-mode {
  /* Sized by inset alone — deliberately NOT `width: 100vw`. On iOS a fixed
     element that reaches past the viewport (the off-canvas .sidebar, which
     escapes body's overflow:hidden) makes Safari widen the layout viewport and
     shrink-to-fit the page, but vw units keep resolving against the ORIGINAL
     width. A 100vw overlay then covers only ~90% of the screen and the app
     shows through on the right. left/right:0 resolve against the widened
     containing block, so the overlay stays full-bleed either way. */
  position: fixed;
  inset: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  /* Above .bottom-nav (310) and .mini-bar (300); modals (400) still win. */
  z-index: 320;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: calc(env(safe-area-inset-top, 0px) + 24px)
           calc(env(safe-area-inset-right, 0px) + 28px)
           calc(env(safe-area-inset-bottom, 0px) + 28px)
           calc(env(safe-area-inset-left, 0px) + 28px);
  box-sizing: border-box;
  animation: fade 0.2s var(--ease);
  overflow-y: auto;
  user-select: none;
}

/* Top bar, view toggles and the exit button live in service-ui.css. */

/* Video panel on: the overlay is moved into the player pane (see
   applyServiceVideoLayout) and rendered inline beneath the stage, so the video
   is simply visible where it already is. A full-screen overlay can never show
   it — .app is its own stacking context at z-index 1, which caps anything
   inside it below the overlay's 320. */
body.service-video .service-mode {
  position: static;
  inset: auto;
  height: auto;
  min-height: 0;
  z-index: auto;
  background: transparent;
  overflow: visible;
  animation: none;
  padding: 12px 0 0;
}

/* Everything except the stage, the app's own transport controls and the
   service info steps aside. */
body.service-video .topbar,
body.service-video .list-pane { display: none; }

body.service-video .player-pane {
  padding-top: calc(env(safe-area-inset-top, 0px) + 10px);
}

/* With the picture carrying the song, the type steps back so both fit. */
body.service-video .service-center {
  flex: 0 0 auto;
  padding: 10px 0;
}
body.service-video .service-title {
  font-size: clamp(20px, 4.2vw, 30px);
  margin-bottom: 4px;
}
body.service-video .service-channel {
  font-size: clamp(14px, 2.2vw, 18px);
  margin-bottom: 4px;
}
body.service-video .service-upnext {
  margin-top: 10px;
}
body.service-video .service-bottom {
  padding-bottom: 14px;
}

.service-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  max-width: 900px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 0;
  flex: 1 1 auto;
}

.service-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.service-title {
  margin: 0 0 12px;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(28px, 5.5vw, 56px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 100%;
  word-break: break-word;
}

.service-channel {
  font-family: var(--ui);
  font-size: clamp(16px, 2.5vw, 22px);
  color: var(--text-2);
  font-weight: 500;
  margin-bottom: 12px;
}

.service-note {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 14px 20px;
  margin: 12px 0 0;
  color: var(--text);
  font-family: var(--ui);
  font-size: clamp(14px, 2vw, 17px);
  line-height: 1.5;
  max-width: 680px;
  width: calc(100% - 32px);
  text-align: left;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.service-upnext {
  margin-top: 24px;
  font-family: var(--ui);
  font-size: clamp(15px, 2.2vw, 20px);
  color: var(--text-dim);
  font-weight: 500;
  letter-spacing: -0.01em;
  max-width: 100%;
  word-break: break-word;
}

.service-bottom {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
}

.service-time {
  font-family: var(--mono);
  font-size: clamp(17px, 2.8vw, 24px);
  color: var(--text-2);
  letter-spacing: 0.04em;
  font-weight: 600;
}

.service-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(18px, 4vw, 36px);
}

.service-btn {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 50%;
  width: clamp(56px, 12vw, 70px);
  height: clamp(56px, 12vw, 70px);
  font-size: clamp(20px, 4vw, 26px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
  transition: all 0.16s var(--ease);
}

.service-btn:hover {
  background: var(--bg-3);
  border-color: var(--text-dim);
  transform: scale(1.06);
}

.service-btn:active {
  transform: scale(0.95);
}

.service-btn-play {
  width: clamp(72px, 15vw, 92px);
  height: clamp(72px, 15vw, 92px);
  font-size: clamp(28px, 5.5vw, 38px);
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  border: none;
  color: #fff;
  box-shadow: 0 10px 28px -6px var(--accent-glow);
}

.service-btn-play:hover {
  background: linear-gradient(145deg, var(--accent-bright), var(--accent-deep));
  box-shadow: 0 14px 34px -4px var(--accent-glow);
  transform: scale(1.06);
}

.service-btn-play:active {
  transform: scale(0.95);
}

/* While the set-list overlay is up it owns the screen: the mini now-playing
   bar and the bottom nav duplicate controls service mode already shows, and
   both sit above it in the stacking order. The off-canvas sidebar is dropped
   too so no fixed element reaches past the viewport to trigger the iOS
   layout-viewport widening described on .service-mode. */
body.service-open .mini-bar,
body.service-open .bottom-nav,
body.service-open .sidebar,
body.service-open .sidebar-backdrop {
  display: none;
}

/* Phones — the flat 28px gutters left a narrow centred column on a 390px
   screen, so service mode never looked full-bleed in the iOS PWA. Pull the
   gutters in to the safe-area edge and scale type/controls off the viewport
   width so the set list actually uses the screen. */
@media (max-width: 640px) {
  .service-mode {
    padding: calc(env(safe-area-inset-top, 0px) + 14px)
             calc(env(safe-area-inset-right, 0px) + 14px)
             calc(env(safe-area-inset-bottom, 0px) + 18px)
             calc(env(safe-area-inset-left, 0px) + 14px);
  }
  .service-center {
    padding: 16px 0;
  }
  .service-title {
    font-size: clamp(30px, 8.5vw, 44px);
  }
  .service-channel {
    font-size: clamp(15px, 4.4vw, 20px);
  }
  .service-upnext {
    margin-top: 18px;
    font-size: clamp(14px, 4vw, 18px);
  }
  .service-note {
    width: 100%;
    max-width: none;
    padding: 12px 14px;
  }
  body.service-video .service-title { font-size: clamp(19px, 5.2vw, 26px); }
  body.service-video .service-note { display: none; }
  .service-time {
    font-size: clamp(16px, 4.6vw, 22px);
  }
  .service-controls {
    width: 100%;
    justify-content: space-evenly;
    gap: 0;
  }
  .service-btn {
    width: 64px;
    height: 64px;
    font-size: 24px;
  }
  .service-btn-play {
    width: 84px;
    height: 84px;
    font-size: 34px;
  }
}

@media (max-height: 520px) {
  .service-mode {
    padding: 12px 20px;
  }
  .service-center {
    padding: 8px 0;
  }
  .service-title {
    font-size: clamp(22px, 4.5vh, 32px);
    margin-bottom: 4px;
  }
  .service-channel {
    font-size: 14px;
    margin-bottom: 4px;
  }
  .service-upnext {
    margin-top: 8px;
    font-size: 14px;
  }
  .service-bottom {
    gap: 10px;
  }
  .service-time {
    font-size: 15px;
  }
  .service-btn {
    width: 48px;
    height: 48px;
    font-size: 18px;
  }
  .service-btn-play {
    width: 58px;
    height: 58px;
    font-size: 22px;
  }
}

/* ============================================================================
 * LAYOUT THEMES — scoped to html[data-layout="..."]
 * All themes preserve the existing DOM; only colors, fonts, and structural
 * CSS properties are overridden. The mini-bar, service-mode overlay, and
 * video element remain fully functional in every theme.
 * ========================================================================== */

/* --- Sanctuary Stage -------------------------------------------------------
 * Dark near-black with warm amber/gold accent. Sidebar collapses; bottom-nav
 * takes over navigation so all views remain accessible.
 * ------------------------------------------------------------------------- */
html[data-layout="sanctuary-stage"] {
  --bg: #090b10;
  --bg-1: #0d1018;
  --bg-2: #121620;
  --bg-3: #181c28;
  --line: #1e2232;
  --line-soft: #171b2a;
  --accent: #f59e0b;
  --accent-bright: #fbbf24;
  --accent-deep: #d97706;
  --accent-glow: rgba(245, 158, 11, 0.4);
}
html[data-layout="sanctuary-stage"] body::before {
  background:
    radial-gradient(900px 600px at 50% -10%, rgba(245, 158, 11, 0.10), transparent 60%),
    radial-gradient(700px 500px at 50% 110%, rgba(245, 158, 11, 0.04), transparent 55%);
}
html[data-layout="sanctuary-stage"] .app {
  grid-template-columns: 1fr;
}
html[data-layout="sanctuary-stage"] .sidebar {
  display: none;
}
html[data-layout="sanctuary-stage"] .bottom-nav {
  display: flex;
}
/* Pad main content above mini-bar + bottom-nav */
html[data-layout="sanctuary-stage"] .main > *:last-child {
  padding-bottom: calc(56px + 52px + env(safe-area-inset-bottom));
}
html[data-layout="sanctuary-stage"] .mini-bar {
  bottom: calc(56px + env(safe-area-inset-bottom));
}
html[data-layout="sanctuary-stage"] .topbar {
  background: rgba(9, 11, 16, 0.6);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-bottom: 1px solid rgba(245, 158, 11, 0.12);
  box-shadow: none;
}
html[data-layout="sanctuary-stage"] .player-stage {
  position: relative;
}
html[data-layout="sanctuary-stage"] .player-stage::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 50% at 50% 50%, rgba(245, 158, 11, 0.07), transparent 70%);
  z-index: 0;
}
html[data-layout="sanctuary-stage"] .bottom-nav {
  background: rgba(9, 11, 16, 0.85);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-top: 1px solid rgba(245, 158, 11, 0.12);
}
html[data-layout="sanctuary-stage"] .bottom-nav-btn.active { color: #fbbf24; }
html[data-layout="sanctuary-stage"] .mini-bar-inner {
  background: rgba(9, 11, 16, 0.85);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-top: 1px solid rgba(245, 158, 11, 0.12);
}
html[data-layout="sanctuary-stage"] .brand-mark {
  background: linear-gradient(145deg, #fbbf24, #d97706);
  box-shadow: 0 6px 18px -4px rgba(245, 158, 11, 0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}

/* --- Liturgical Chronicle --------------------------------------------------
 * Light parchment palette with burgundy accent and serif typography.
 * Sidebar kept wider for the editorial column feel.
 * ------------------------------------------------------------------------- */
html[data-layout="liturgical"] {
  --bg: #faf8f5;
  --bg-1: #f2ede6;
  --bg-2: #e8e0d5;
  --bg-3: #ddd5c8;
  --line: #d5ccbc;
  --line-soft: #e0d8cc;
  --text: #1a1208;
  --text-2: #3d3027;
  --text-dim: #8b7060;
  --accent: #8b261d;
  --accent-bright: #a83028;
  --accent-deep: #6b1c14;
  --accent-glow: rgba(139, 38, 29, 0.35);
  --display: Georgia, 'Times New Roman', serif;
  --ui: Georgia, 'Times New Roman', serif;
  --shadow: 0 18px 50px -12px rgba(0, 0, 0, 0.2);
}
html[data-layout="liturgical"] body::before {
  background: radial-gradient(900px 600px at 0% 0%, rgba(139, 38, 29, 0.04), transparent 60%);
}
html[data-layout="liturgical"] body::after { opacity: 0.008; }
/* Keep video player dark */
html[data-layout="liturgical"] #video,
html[data-layout="liturgical"] .video-wrap,
html[data-layout="liturgical"] #videoOverlay { background: #000; }
/* Scrollbar for light theme */
html[data-layout="liturgical"] ::-webkit-scrollbar-thumb { background: var(--bg-2); }
html[data-layout="liturgical"] ::-webkit-scrollbar-thumb:hover { background: var(--bg-3); }
/* Topbar tint */
html[data-layout="liturgical"] .topbar {
  background: linear-gradient(180deg, var(--bg-1), rgba(250,248,245,0.92));
  border-bottom-color: var(--line);
}
/* Mini-bar on light */
html[data-layout="liturgical"] .mini-bar-inner {
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-top-color: var(--line);
}
/* Input / select elements */
html[data-layout="liturgical"] select,
html[data-layout="liturgical"] input[type="text"],
html[data-layout="liturgical"] input[type="search"],
html[data-layout="liturgical"] input[type="number"] {
  color: var(--text);
  background: var(--bg-2);
  border-color: var(--line);
}

/* --- Living Hymnal ---------------------------------------------------------
 * Dark zinc with indigo accent. Clean, technical feel; slightly narrower
 * sidebar gives the main content area more room.
 * ------------------------------------------------------------------------- */
html[data-layout="living-hymnal"] {
  --bg: #09090b;
  --bg-1: #0d0d10;
  --bg-2: #18181b;
  --bg-3: #27272a;
  --line: #3f3f46;
  --line-soft: #27272a;
  --text: #e4e4e7;
  --text-2: #a1a1aa;
  --text-dim: #71717a;
  --accent: #6366f1;
  --accent-bright: #818cf8;
  --accent-deep: #4f46e5;
  --accent-glow: rgba(99, 102, 241, 0.4);
}
html[data-layout="living-hymnal"] body::before {
  background:
    radial-gradient(900px 600px at 18% -10%, rgba(99, 102, 241, 0.08), transparent 60%),
    radial-gradient(700px 500px at 100% 110%, rgba(99, 102, 241, 0.04), transparent 55%);
}
html[data-layout="living-hymnal"] .sidebar {
  background: linear-gradient(180deg, #0d0d10, #09090b);
  border-right: 1px solid #27272a;
}
html[data-layout="living-hymnal"] .nav-item {
  border-radius: 8px;
  padding-left: 18px;
}
html[data-layout="living-hymnal"] .nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  background: #6366f1;
  border-radius: 0 3px 3px 0;
}
html[data-layout="living-hymnal"] .topbar {
  background: #0d0d10;
  border-bottom: 1px solid #27272a;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-layout="living-hymnal"] .mini-bar-inner {
  background: linear-gradient(180deg, #18181b, #0d0d10);
  border-top: 1px solid #27272a;
}
html[data-layout="living-hymnal"] .playlist-item {
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  padding: 8px 10px;
}
html[data-layout="living-hymnal"] .brand-mark {
  background: linear-gradient(145deg, #818cf8, #4f46e5);
  box-shadow: 0 6px 18px -4px rgba(99, 102, 241, 0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}

/* --- Sunday Broadcaster ----------------------------------------------------
 * Near-black with crimson/rose accent for a live-broadcast feel.
 * Prominent top bar with an accent underline.
 * ------------------------------------------------------------------------- */
html[data-layout="broadcaster"] {
  --bg: #050507;
  --bg-1: #0a0a0e;
  --bg-2: #141418;
  --bg-3: #1e1e24;
  --line: #2a2a32;
  --line-soft: #1e1e26;
  --accent: #f43f5e;
  --accent-bright: #fb7185;
  --accent-deep: #e11d48;
  --accent-glow: rgba(244, 63, 94, 0.45);
}
html[data-layout="broadcaster"] body::before {
  background:
    radial-gradient(900px 600px at 18% -10%, rgba(244, 63, 94, 0.09), transparent 60%),
    radial-gradient(700px 500px at 100% 110%, rgba(244, 63, 94, 0.04), transparent 55%);
}
html[data-layout="broadcaster"] .sidebar {
  background: linear-gradient(180deg, #0a0a0e, #050507);
}
html[data-layout="broadcaster"] .topbar {
  position: relative;
  min-height: 58px;
  background: linear-gradient(180deg, #0a0a0e 0%, #050507 100%);
  border-bottom: 2px solid rgba(244, 63, 94, 0.3);
}
html[data-layout="broadcaster"] .topbar::after {
  content: '● LIVE';
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 11px;
  font-weight: 800;
  color: #f43f5e;
  letter-spacing: 0.08em;
  font-family: system-ui, sans-serif;
  pointer-events: none;
}
html[data-layout="broadcaster"] .brand-mark {
  background: linear-gradient(145deg, #fb7185, #e11d48);
  box-shadow: 0 6px 18px -4px rgba(244, 63, 94, 0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}
html[data-layout="broadcaster"] .nav-item.active {
  background: rgba(244, 63, 94, 0.08);
  color: #fb7185;
}
html[data-layout="broadcaster"] .nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  background: #f43f5e;
  border-radius: 0 3px 3px 0;
}
html[data-layout="broadcaster"] .mini-bar-inner {
  background: linear-gradient(180deg, #141418, #0a0a0e);
  border-top: 1px solid rgba(244, 63, 94, 0.15);
}
html[data-layout="broadcaster"] .playlist-item.active {
  background: rgba(244, 63, 94, 0.08);
  border-left: 3px solid #f43f5e;
}

/* --- Contemplative Sanctuary ------------------------------------------------
 * Deep blue-black with teal accent and serif typography. Sidebar collapses
 * and bottom-nav keeps all views accessible.
 * ------------------------------------------------------------------------- */
html[data-layout="contemplative"] {
  --bg: #0a0e14;
  --bg-1: #0d1218;
  --bg-2: #131820;
  --bg-3: #1a2030;
  --line: #1e2840;
  --line-soft: #161e30;
  --accent: #2dd4bf;
  --accent-bright: #5eead4;
  --accent-deep: #0d9488;
  --accent-glow: rgba(45, 212, 191, 0.35);
  --display: Georgia, 'Times New Roman', serif;
}
html[data-layout="contemplative"] body::before {
  background:
    radial-gradient(900px 600px at 50% -20%, rgba(45, 212, 191, 0.07), transparent 60%),
    radial-gradient(700px 500px at 50% 120%, rgba(45, 212, 191, 0.04), transparent 55%);
}
html[data-layout="contemplative"] .app { grid-template-columns: 1fr; }
html[data-layout="contemplative"] .sidebar { display: none; }
html[data-layout="contemplative"] .bottom-nav { display: flex; }
html[data-layout="contemplative"] .mini-bar {
  bottom: calc(56px + env(safe-area-inset-bottom));
}
html[data-layout="contemplative"] .topbar {
  background: transparent;
  border-bottom: 1px solid rgba(45, 212, 191, 0.08);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-layout="contemplative"] .brand,
html[data-layout="contemplative"] .topbar {
  font-family: Georgia, 'Times New Roman', serif;
}
html[data-layout="contemplative"] .player-stage {
  position: relative;
}
html[data-layout="contemplative"] .player-stage::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(45, 212, 191, 0.06), transparent 70%);
  z-index: 0;
}
html[data-layout="contemplative"] .bottom-nav {
  background: rgba(10, 14, 20, 0.9);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-top: 1px solid rgba(45, 212, 191, 0.1);
}
html[data-layout="contemplative"] .bottom-nav-btn.active { color: #5eead4; }
html[data-layout="contemplative"] .mini-bar-inner {
  background: rgba(10, 14, 20, 0.9);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  border-top: 1px solid rgba(45, 212, 191, 0.1);
}
html[data-layout="contemplative"] .playlist-item.active {
  background: rgba(45, 212, 191, 0.06);
  border-left: 2px solid #2dd4bf;
}
html[data-layout="contemplative"] .nav-item.active { color: #5eead4; }
html[data-layout="contemplative"] .brand-mark {
  background: linear-gradient(145deg, #5eead4, #0d9488);
  box-shadow: 0 6px 18px -4px rgba(45, 212, 191, 0.4), inset 0 1px 0 rgba(255,255,255,0.25);
}

/* Grid-column overrides only apply on screens wide enough for an inline sidebar
   (≥861px). Below that the sidebar is position:fixed (out of grid flow) so
   a two-column grid would leave .main stranded in the narrow first column. */
@media (min-width: 861px) {
  html[data-layout="liturgical"] .app { grid-template-columns: 300px 1fr; }
  html[data-layout="living-hymnal"] .app { grid-template-columns: 220px 1fr; }
}


/* ============================================================================
 * Lyrics · chapters · bookmarks panel (Notes in app.js)
 * ========================================================================== */
.notes-panel {
  margin-top: 16px;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.notes-tabs {
  display: flex; align-items: center; gap: 4px;
  padding: 6px 10px 0;
  border-bottom: 1px solid var(--line-soft);
}
.notes-tab {
  background: transparent; border: none; cursor: pointer;
  color: var(--text-dim);
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em;
  padding: 9px 8px 10px;
  border-bottom: 2px solid transparent;
  transition: color 0.16s, border-color 0.16s;
}
.notes-tab:hover { color: var(--text-2); }
.notes-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.notes-count {
  display: inline-block; min-width: 16px; padding: 1px 5px; margin-left: 4px;
  border-radius: 8px; background: var(--bg-3); color: var(--text-2);
  font-size: 9px; letter-spacing: 0; text-align: center;
}
.notes-count:empty { display: none; }
.notes-status {
  margin-left: auto; min-width: 0;
  font-family: var(--mono); font-size: 10px; color: var(--accent-bright);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.notes-pane { padding: 12px 14px 14px; }
.notes-spacer { flex: 1; }

.lyrics-toolbar, .markers-toolbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-bottom: 10px;
}
.lyrics-toolbar .np-btn, .markers-toolbar .np-btn, .lyrics-syncbar .np-btn { padding: 6px 10px; font-size: 12px; }
.lyr-offset {
  display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 2px; background: var(--bg-1);
}
.lyr-off-btn {
  background: transparent; border: none; color: var(--text-2); cursor: pointer;
  font-family: var(--mono); font-size: 11px; padding: 4px 6px; border-radius: 6px;
}
.lyr-off-btn:hover { background: var(--bg-3); color: var(--text); }
.lyr-off-val { font-family: var(--mono); font-size: 11px; color: var(--text-dim); min-width: 38px; text-align: center; }
.lyr-off-val.nonzero { color: var(--accent-bright); }
.lyr-auto { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-2); cursor: pointer; }

.lyrics-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.lyr-tag {
  font-family: var(--mono); font-size: 11px; color: var(--text-2);
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 999px;
  padding: 3px 9px;
}

.lyrics-list {
  position: relative;
  max-height: min(52vh, 460px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px 2px 40vh 2px; /* tail room so the last line can centre */
  scrollbar-width: thin;
}
.lyr-section {
  margin: 14px 0 6px;
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.16em; color: var(--accent);
}
.lyr-section:first-child { margin-top: 2px; }
.lyr-section-time { color: var(--text-dim); font-weight: 400; }
.lyr-line {
  display: flex; gap: 12px; align-items: baseline;
  padding: 6px 8px; border-radius: var(--radius-sm);
  cursor: pointer; color: var(--text-2);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.lyr-line:hover { background: var(--bg-3); }
.lyr-line.untimed { cursor: default; }
.lyr-time { flex: none; width: 38px; font-family: var(--mono); font-size: 10px; color: var(--text-dim); }
.lyr-text { white-space: pre-line; font-size: 15px; line-height: 1.45; }
.lyr-line.active { background: var(--bg-3); color: var(--text); }
.lyr-line.active .lyr-text { font-weight: 700; font-size: 17px; }
.lyr-line.active .lyr-time { color: var(--accent-bright); }
.lyr-cue {
  display: flex; justify-content: space-between; gap: 10px;
  margin: 8px 0; padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px dashed var(--line); color: var(--text-2);
  font-family: var(--mono); font-size: 11px; cursor: pointer;
}
.lyr-cue.soon { border-color: var(--accent); color: var(--text); }
.lyr-cue-in { color: var(--accent-bright); white-space: nowrap; }

.lyrics-syncbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-bottom: 10px; padding: 8px 10px;
  border: 1px solid var(--accent); border-radius: var(--radius-sm);
  background: var(--bg-1);
}
.lyrics-sync-hint { flex: 1 1 180px; min-width: 0; font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lyrics-syncbar .primary-btn { border-color: var(--accent); color: var(--text); background: var(--accent-deep); }
.notes-panel.syncing .lyr-line { cursor: pointer; }
.lyrics-list .sync-ptr { outline: 2px solid var(--accent); outline-offset: -2px; background: var(--bg-3); color: var(--text); }

.notes-empty { padding: 18px 6px; text-align: center; color: var(--text-2); font-size: 13px; }
.notes-empty.small { padding: 8px 4px; text-align: left; font-size: 12px; color: var(--text-dim); }
.notes-empty-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin: 12px 0 8px; }
.notes-empty-hint { font-size: 11px; color: var(--text-dim); }

.marker-chips { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 8px; margin-bottom: 6px; scrollbar-width: thin; }
.marker-chip {
  flex: none; cursor: pointer;
  border: 1px solid var(--line); background: var(--bg-1); color: var(--text-2);
  border-radius: 999px; padding: 5px 11px; font-size: 12px; white-space: nowrap;
  transition: border-color 0.16s, color 0.16s;
}
.marker-chip:hover { color: var(--text); border-color: var(--text-dim); }
.marker-chip.active { border-color: var(--accent); color: var(--text); background: var(--bg-3); }
.marker-chip-time { font-family: var(--mono); font-size: 10px; color: var(--accent-bright); }
.marker-chip.bookmark .marker-chip-time { color: #7ec8ff; }
.markers-section { margin-top: 12px; }
.markers-heading {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-dim);
  margin-bottom: 6px;
}
.markers-scope { font-weight: 400; letter-spacing: 0.04em; text-transform: none; margin-left: 6px; }
.marker-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 6px; border-bottom: 1px solid var(--line-soft);
}
.marker-row:last-child { border-bottom: none; }
.mk-time {
  flex: none; width: 52px; text-align: left; cursor: pointer;
  background: transparent; border: none; padding: 0;
  font-family: var(--mono); font-size: 12px; color: var(--accent-bright);
}
.marker-row[data-kind="bookmark"] .mk-time { color: #7ec8ff; }
.mk-body { flex: 1; min-width: 0; }
.mk-title { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-note { font-size: 11px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-btn {
  flex: none; background: transparent; border: 1px solid transparent; border-radius: 7px;
  color: var(--text-dim); cursor: pointer; padding: 4px 6px; font-size: 12px;
}
.mk-btn:hover { color: var(--text); border-color: var(--line); background: var(--bg-3); }

.seek-markers { position: absolute; left: 0; right: 0; top: 0; height: 0; pointer-events: none; }
.seek-tick {
  position: absolute; top: 2px; width: 2px; height: 10px; margin-left: -1px;
  border-radius: 1px; background: var(--accent-bright); opacity: 0.85;
}
.seek-tick.bookmark { background: #7ec8ff; }

/* Modals opened by the notes panel */
.lyr-editor-help, .modal-text { margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--text-2); }
.lyr-editor-help code { font-family: var(--mono); font-size: 11px; color: var(--text); }
.lyr-editor-note { margin: 0 0 8px; font-size: 12px; color: var(--accent-bright); }
.lyr-editor-text, .mx-text {
  width: 100%; min-height: min(46vh, 360px); resize: vertical; box-sizing: border-box;
  background: var(--bg-1); color: var(--text); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 10px;
  font-family: var(--mono); font-size: 12px; line-height: 1.55;
}
.mx-text { min-height: 180px; }
.lyr-editor-tools { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.mx-inc { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); margin-bottom: 8px; }
.marker-form { display: flex; flex-direction: column; gap: 10px; }
.marker-form label { display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--text-dim); }
.marker-form input {
  background: var(--bg-1); color: var(--text); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 10px; font-size: 14px;
}
.notes-history { display: flex; flex-direction: column; gap: 2px; max-height: 50vh; overflow-y: auto; }
.hist-row { display: flex; align-items: center; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--line-soft); }
.hist-main { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; font-size: 12px; }
.hist-rev { font-family: var(--mono); color: var(--accent-bright); }
.hist-who { color: var(--text); }
.hist-src, .hist-when { color: var(--text-dim); font-size: 11px; }
.hist-live { font-family: var(--mono); font-size: 10px; color: #7ee0a8; }

@media (max-width: 560px) {
  .notes-pane { padding: 10px 10px 12px; }
  .lyr-text { font-size: 14px; }
  .lyr-line.active .lyr-text { font-size: 16px; }
  .lyr-auto { margin-left: auto; }
  .notes-status { display: none; }
}

/* ============================================================================
 * Phone remote (Remote in app.js, server/remote.js)
 * ========================================================================== */
.remote-chip {
  position: fixed; left: 16px; bottom: 18px; z-index: 150;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  background: var(--bg-3); color: var(--text); border: 1px solid var(--line);
  box-shadow: var(--shadow); font-size: 12px; font-weight: 600;
}
.remote-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: #7ee0a8; box-shadow: 0 0 0 3px rgba(126,224,168,0.2); }
body.service-open .remote-chip { bottom: auto; top: 14px; }

.remote-host .rh-pair { display: flex; gap: 16px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.rh-qr { width: 132px; height: 132px; background: #fff; border-radius: 10px; padding: 4px; box-sizing: border-box; }
.rh-label { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); margin: 4px 0; }
.rh-code { font-family: var(--mono); font-size: 34px; font-weight: 700; letter-spacing: 0.08em; color: var(--text); }
.rh-sub { font-size: 12px; color: var(--text-2); margin-top: 4px; max-width: 320px; line-height: 1.45; }
.rh-remote { display: flex; align-items: center; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--line-soft); font-size: 13px; }
.rh-name-row { display: flex; flex-direction: column; gap: 4px; margin-top: 14px; font-size: 11px; color: var(--text-dim); }
.rh-name { background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px; }
.rh-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

.remote-view {
  position: fixed; inset: 0; z-index: 180;
  display: flex; flex-direction: column;
  background: var(--bg);
  padding: max(12px, env(safe-area-inset-top)) 16px max(14px, env(safe-area-inset-bottom));
  overflow-y: auto; overscroll-behavior: contain;
}
body.remote-open { overflow: hidden; }
.rv-top { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.rv-icon {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--text-2);
  font-size: 15px; cursor: pointer;
}
.rv-host { flex: 1; min-width: 0; text-align: center; }
.rv-host-name { font-weight: 700; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rv-status { font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); margin-top: 2px; }
.rv-status.ok { color: #7ee0a8; }

.rv-pair { max-width: 420px; margin: 8vh auto 0; width: 100%; display: flex; flex-direction: column; gap: 12px; }
.rv-pair-title { font-family: var(--display); font-size: 26px; font-weight: 700; }
.rv-pair-help { margin: 0; font-size: 13px; line-height: 1.55; color: var(--text-2); }
.rv-code {
  font-family: var(--mono); font-size: 34px; letter-spacing: 0.2em; text-align: center;
  background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 10px; width: 100%; box-sizing: border-box;
}
.rv-name { background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 11px 12px; font-size: 15px; }
.rv-primary {
  background: var(--accent); color: #fff; border: none; border-radius: var(--radius);
  padding: 14px; font-size: 16px; font-weight: 700; cursor: pointer;
}
.rv-pair-msg { min-height: 1.2em; font-size: 13px; color: var(--accent-bright); text-align: center; }

.rv-control { max-width: 520px; margin: 0 auto; width: 100%; display: flex; flex-direction: column; gap: 14px; }
.rv-now { display: flex; gap: 14px; align-items: center; background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; }
.rv-thumb { width: 88px; height: 50px; object-fit: cover; border-radius: 8px; background: var(--bg-3); flex: none; }
.rv-now-text { min-width: 0; }
.rv-title { font-weight: 700; font-size: 16px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.rv-channel { font-size: 12px; color: var(--text-2); margin-top: 2px; }
.rv-seek input, .rv-volume input { width: 100%; accent-color: var(--accent); }
.rv-times { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 11px; color: var(--text-dim); }
.rv-transport { display: flex; justify-content: center; align-items: center; gap: 22px; }
.rv-tbtn {
  width: 58px; height: 58px; border-radius: 50%; cursor: pointer;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--text); font-size: 20px;
}
.rv-tbtn.rv-play { width: 76px; height: 76px; background: var(--accent); border-color: var(--accent); color: #fff; font-size: 26px; }
.rv-tbtn:active { transform: scale(0.96); }
.rv-volume { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--text-2); }
.rv-volume span:last-child { font-family: var(--mono); font-size: 11px; width: 38px; text-align: right; }
.rv-queue-head { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); }
.rv-queue { display: flex; flex-direction: column; gap: 6px; }
.rv-row {
  display: flex; align-items: center; gap: 10px; padding: 10px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: pointer; touch-action: pan-y; position: relative;
}
.rv-row.dragging { z-index: 2; border-color: var(--accent); box-shadow: var(--shadow); cursor: grabbing; }
.rv-handle { color: var(--text-dim); font-size: 18px; padding: 4px 2px; cursor: grab; touch-action: none; user-select: none; }
.rv-row-text { flex: 1; min-width: 0; }
.rv-row-title { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rv-row-sub { font-size: 11px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rv-row-dur { font-family: var(--mono); font-size: 11px; color: var(--text-dim); }
.rv-row-x { background: transparent; border: none; color: var(--text-dim); font-size: 14px; padding: 6px; cursor: pointer; }
.rv-empty { font-size: 13px; color: var(--text-dim); padding: 10px 2px; }
.rv-queue-hint { font-size: 11px; color: var(--text-dim); text-align: center; }
.rv-actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.rv-action {
  background: var(--bg-2); border: 1px solid var(--line); color: var(--text-2);
  border-radius: var(--radius-sm); padding: 12px 6px; font-size: 13px; cursor: pointer;
}
.rv-action.on { border-color: var(--accent); color: var(--text); }

.rv-add-form { display: flex; gap: 8px; margin-bottom: 10px; }
.rv-add-q { flex: 1; min-width: 0; background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 9px 10px; font-size: 15px; }
.rv-add-results { display: flex; flex-direction: column; gap: 6px; max-height: 55vh; overflow-y: auto; }
.rv-add-item {
  display: flex; gap: 10px; align-items: center; text-align: left; cursor: pointer;
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 6px; color: var(--text);
}
.rv-add-item img { width: 72px; height: 40px; object-fit: cover; border-radius: 6px; flex: none; }
.rv-add-item span { display: flex; flex-direction: column; min-width: 0; font-size: 13px; }
.rv-add-item b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rv-add-item small { color: var(--text-dim); font-size: 11px; }
.rv-add-item.added { border-color: #7ee0a8; }

/* ============================================================================
 * Service mode — lyrics only (Notes.renderService in app.js)
 * ========================================================================== */
.service-mode.lyrics-on .service-meta,
.service-mode.lyrics-on .service-upnext { display: none; }
.service-mode.lyrics-on .service-center {
  max-width: none;
  padding: 8px 0;
  min-height: 0;
  justify-content: stretch;
}
.service-lyrics {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  min-height: 40vh;
}
.sl-list {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  font-family: var(--display);
  /* Soft fade at the top and bottom edges so lines drift in and out. */
  -webkit-mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent);
          mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent);
}
.sl-list::-webkit-scrollbar { display: none; }
.sl-line {
  box-sizing: border-box;
  margin: 0 auto;
  padding: 0.16em 4%;
  width: 100%;
  text-align: center;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.01em;
  white-space: pre-line;
  flex-shrink: 0;
  /* --fit = the size at which THIS line fills one row; others are fractions. */
  font-size: calc(var(--fit, 40px) * 0.48);
  color: var(--text-2);
  opacity: 0.42;
  overflow-wrap: anywhere;
  cursor: pointer;
  border-radius: 18px;
  transition: font-size 0.35s var(--ease), opacity 0.35s var(--ease), color 0.35s var(--ease), background-color 0.35s var(--ease);
}
.sl-line.near { font-size: calc(var(--fit, 40px) * 0.6); opacity: 0.7; }
.sl-line.past { opacity: 0.28; }
.sl-line.active {
  font-size: var(--fit, 40px);
  opacity: 1;
  color: var(--text);
  background-color: color-mix(in srgb, var(--accent) 18%, transparent);
  text-shadow: 0 0 32px var(--accent-glow);
}
.sl-line.untimed { cursor: default; }
/* Plain lyrics (no timings): one shared --fit, every line full size. */
.sl-list.plain .sl-line { font-size: var(--fit, 40px); opacity: 0.92; color: var(--text); }
/* Service mode only: a floor under every lyric size (long lines wrap rather
   than shrink) and breathing room between verses. Keep the floor in step with
   SERVICE_LYRIC_MIN_PX in app.js. */
.service-lyrics .sl-list { display: flex; flex-direction: column; gap: clamp(14px, 3.2vh, 40px); }
.service-lyrics .sl-line { font-size: max(22px, calc(var(--fit, 40px) * 0.48)); }
.service-lyrics .sl-line.near { font-size: max(26px, calc(var(--fit, 40px) * 0.6)); }
.service-lyrics .sl-line.active { font-size: max(30px, var(--fit, 40px)); }
.service-lyrics .sl-list.plain .sl-line { font-size: max(30px, var(--fit, 40px)); }
.sl-empty {
  display: flex; flex-direction: column; gap: 10px; align-items: center;
  font-size: clamp(22px, 4vw, 40px); font-weight: 700; color: var(--text-2);
}
.sl-empty small { font-family: var(--ui); font-size: 16px; font-weight: 500; color: var(--text-dim); }

/* ============================================================================
 * Waveform seek bar (Wave in app.js) — audio-only playback
 * ========================================================================== */
.wave-canvas { display: none; }
.seek-wrap.wave-on .wave-canvas { display: block; width: 100%; height: 46px; }
.seek-wrap.wave-on .seek {
  position: absolute; left: 0; right: 0; top: 0;
  width: 100%; height: 46px; margin: 0;
  opacity: 0; cursor: pointer;
}
.seek-wrap.wave-on .seek-markers { top: -6px; }
.wave-tip {
  position: absolute; top: -26px; transform: translateX(-50%);
  padding: 3px 7px; border-radius: 6px;
  background: var(--bg-3); border: 1px solid var(--line); color: var(--text);
  font-family: var(--mono); font-size: 11px; pointer-events: none; white-space: nowrap;
}
.wave-loud {
  display: block; margin: 6px auto 0; padding: 4px 10px;
  background: transparent; border: 1px solid var(--line); border-radius: 999px;
  color: var(--text-2); font-size: 12px; cursor: pointer;
}
.wave-loud:hover { color: var(--text); border-color: var(--accent); }

/* ============================================================================
 * Stats view (renderStats in app.js)
 * ========================================================================== */
.stats { grid-column: 1 / -1; position: relative; display: flex; flex-direction: column; gap: 16px; padding-bottom: 24px; }
.stats-empty { grid-column: 1 / -1; }
.st-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.st-tile, .st-panel {
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px;
}
.st-label { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); }
.st-big { font-family: var(--mono); font-size: 32px; font-weight: 700; color: var(--text); margin: 6px 0 4px; font-variant-numeric: tabular-nums; }
.st-sub { font-size: 12px; color: var(--text-2); }
.st-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.st-panel-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; font-weight: 700; font-size: 14px; color: var(--text); }
.st-panel-head small { font-weight: 400; font-size: 11px; color: var(--text-dim); text-align: right; }
.st-none { font-size: 13px; color: var(--text-dim); }
.st-bar-row { display: grid; grid-template-columns: minmax(80px, 34%) 1fr 34px; align-items: center; gap: 10px; padding: 5px 0; }
.st-bar-name { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-bar-track { height: 10px; }
.st-bar { display: block; height: 10px; border-radius: 0 4px 4px 0; background: var(--accent); }
.st-bar-row:hover .st-bar { background: var(--accent-bright); }
.st-bar-val { font-family: var(--mono); font-size: 12px; color: var(--text-2); text-align: right; font-variant-numeric: tabular-nums; }
.st-song { display: grid; grid-template-columns: 24px 1fr 96px 34px; align-items: center; gap: 10px; padding: 6px 0; cursor: pointer; border-bottom: 1px solid var(--line-soft); }
.st-song:last-child { border-bottom: none; }
.st-song:hover b { color: var(--accent-bright); }
.st-rank { font-family: var(--mono); font-size: 11px; color: var(--text-dim); }
.st-song-text { display: flex; flex-direction: column; min-width: 0; }
.st-song-text b { font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-song-text small { font-size: 11px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-spark polyline { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.st-heat-wrap { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; }
.st-heat-days { display: grid; grid-template-rows: 14px repeat(7, 14px); row-gap: 3px; font-size: 9px; color: var(--text-dim); font-family: var(--mono); }
.st-heat-days span { line-height: 14px; }
.st-heat-months { display: grid; grid-template-columns: repeat(16, 14px); column-gap: 3px; height: 14px; font-size: 9px; color: var(--text-dim); font-family: var(--mono); white-space: nowrap; margin-bottom: 3px; }
.st-heat { display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, 14px); grid-template-columns: repeat(16, 14px); gap: 3px; }
.st-cell { width: 14px; height: 14px; border-radius: 3px; background: var(--bg-3); }
.st-cell.l1 { background: color-mix(in srgb, var(--accent) 28%, var(--bg-3)); }
.st-cell.l2 { background: color-mix(in srgb, var(--accent) 50%, var(--bg-3)); }
.st-cell.l3 { background: color-mix(in srgb, var(--accent) 74%, var(--bg-3)); }
.st-cell.l4 { background: var(--accent); }
.st-cell.future { background: transparent; border: 1px dashed var(--line); box-sizing: border-box; }
.st-heat .st-cell:hover { outline: 2px solid var(--text); outline-offset: 1px; }
.st-legend { display: flex; align-items: center; gap: 4px; margin-top: 10px; font-size: 11px; color: var(--text-dim); }
.st-legend span:first-child { margin-right: 4px; }
.st-legend span:last-child { margin-left: 4px; }
.st-table { margin-top: 10px; font-size: 12px; color: var(--text-2); }
.st-table summary { cursor: pointer; color: var(--text-dim); }
.st-table table { margin-top: 8px; border-collapse: collapse; }
.st-table td, .st-table th { padding: 3px 12px 3px 0; text-align: left; font-variant-numeric: tabular-nums; }
.st-tip {
  position: absolute; transform: translate(-50%, -100%); pointer-events: none; z-index: 5;
  background: var(--bg-3); border: 1px solid var(--line); color: var(--text);
  padding: 5px 9px; border-radius: 8px; font-size: 12px; white-space: nowrap; box-shadow: var(--shadow);
}

/* ============================================================================
 * Presenter / projector view (Presenter in app.js) — always dark
 * ========================================================================== */
.presenter-view {
  --text: #f7f5f2; --text-2: #c9c8d0; --text-dim: #8a8994; --line: #2a2a33;
  position: fixed; inset: 0; z-index: 420;
  background: #000; color: var(--text);
  overflow: hidden;
}
body.presenter-open { overflow: hidden; }
.pv-list { position: absolute; inset: 4vh 0 8vh 0; }
.presenter-view .sl-line { cursor: default; }
.pv-title {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 0 6vw; font-family: var(--display); font-weight: 800;
  font-size: clamp(32px, 6vw, 96px); line-height: 1.1; color: var(--text);
}
.pv-title small { font-family: var(--ui); font-weight: 500; font-size: clamp(16px, 2vw, 28px); color: var(--text-dim); margin-top: 16px; }
.pv-bar {
  position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: 16px;
  padding: 10px 18px; font-size: 13px; color: var(--text-dim);
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.85)); transition: opacity 0.4s;
}
.pv-status { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pv-hint { font-size: 11px; }
.pv-btn { background: #16161b; color: var(--text); border: 1px solid var(--line); border-radius: 8px; padding: 6px 12px; cursor: pointer; }
.presenter-view.idle { cursor: none; }
.presenter-view.idle .pv-bar { opacity: 0; }
.pv-pair {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(420px, 90vw); display: flex; flex-direction: column; gap: 12px; text-align: center;
  background: #111116; border: 1px solid var(--line); border-radius: 16px; padding: 24px;
}
.pv-pair-title { font-family: var(--display); font-size: 26px; font-weight: 700; }
.pv-pair p { margin: 0; font-size: 13px; color: var(--text-2); line-height: 1.5; }
.pv-pair input {
  font-family: var(--mono); font-size: 32px; letter-spacing: 0.2em; text-align: center;
  background: #000; color: var(--text); border: 1px solid var(--line); border-radius: 12px; padding: 12px;
}
.pv-blank { position: absolute; inset: 0; background: #000; z-index: 5; }
.rh-present { display: flex; gap: 14px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
.rh-qr-sm { width: 96px; height: 96px; }
.rh-present code { font-family: var(--mono); font-size: 11px; word-break: break-all; }

/* Timestamp sharing (Share in app.js) */
.share-moment { display: flex; flex-direction: column; gap: 12px; }
.sm-row { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--text-dim); }
.sm-time { width: 90px; background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 7px 9px; font-family: var(--mono); font-size: 14px; }
.sm-links { display: flex; flex-direction: column; gap: 8px; }
.sm-link { display: grid; grid-template-columns: 64px 1fr auto; gap: 8px; align-items: center; font-size: 12px; color: var(--text-dim); }
.sm-link code { font-family: var(--mono); font-size: 11px; color: var(--text); background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; user-select: all; }
.sm-gif { border-top: 1px solid var(--line-soft); padding-top: 12px; }
.sm-gif-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12px; color: var(--text-dim); }
.sm-gif-controls select { background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px; }
.sm-gif-out { margin-top: 10px; }
.sm-preview { display: block; max-width: 100%; border-radius: 10px; border: 1px solid var(--line); }
.sm-gif-actions { display: flex; gap: 8px; margin-top: 8px; }
.sm-busy, .sm-err { font-size: 13px; color: var(--text-2); }
.sm-err { color: var(--accent-bright); }

/* Sleep timer panel, curtain, equalizer */
.sleep-panel, .eq-panel { display: flex; flex-direction: column; gap: 8px; }
.sp-label { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); margin-top: 6px; }
.sp-chips, .eq-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.sp-chip {
  background: var(--bg-1); color: var(--text-2); border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.sp-chip:hover { color: var(--text); border-color: var(--text-dim); }
.sp-chip.on { color: var(--text); border-color: var(--accent); background: var(--bg-3); }
.sp-note { margin: 6px 0 0; font-size: 11px; line-height: 1.5; color: var(--text-dim); }
.sleep-curtain {
  position: fixed; inset: 0; z-index: 500; background: #000; cursor: pointer;
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 12vh;
}
.sleep-curtain span { color: #666; font-size: 14px; transition: opacity 2s; }
.sleep-curtain.dim span { opacity: 0; }
.eq-bands { display: grid; grid-template-columns: repeat(5, minmax(44px, 1fr)); gap: 8px; margin-top: 8px; }
.eq-band { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 11px; color: var(--text-dim); }
.eq-band input[type=range] { writing-mode: vertical-lr; direction: rtl; width: 44px; height: 130px; accent-color: var(--accent); }
.eq-val { font-family: var(--mono); font-size: 11px; color: var(--text); min-height: 14px; }
.eq-f { font-family: var(--mono); }

/* Touch gestures (Gestures in app.js) */
.player-stage { touch-action: pan-y; }            /* page still scrolls; we get double-tap + pinch */
:fullscreen .player-stage, .player-stage:fullscreen,
body.landscape-fs .player-stage { touch-action: none; } /* fullscreen (real or the iOS landscape one): swipes too */
/* Native fullscreen keeps the ordinary stage's aspect ratio and pane width unless
   all sizing constraints are explicitly reset. This also covers every layout's
   player because fullscreen is a cross-layout surface. */
:is(.player-stage:fullscreen, .player-stage.orientation-fullscreen.orientation-overlay) {
  position: fixed !important;
  inset: 0 !important;
  width: 100dvw !important;
  height: 100dvh !important;
  min-width: 0 !important;
  min-height: 0 !important;
  max-width: none !important;
  max-height: none !important;
  aspect-ratio: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  overflow: hidden !important;
  background: #000 !important;
}
.player-stage.orientation-fullscreen > video {
  flex: none !important;
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  max-height: none !important;
  object-fit: contain;
}
#video { transform-origin: center center; transition: transform 0.05s linear; }
.gesture-hud {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 6;
  min-width: 140px; padding: 12px 16px; border-radius: 14px; text-align: center;
  background: rgba(0, 0, 0, 0.62); color: #fff; pointer-events: none; font-family: var(--ui);
}
.gh-label { font-size: 14px; font-weight: 600; }
.gh-bar { margin-top: 8px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.25); overflow: hidden; }
.gh-bar span { display: block; height: 100%; background: #fff; }
.gh-seek { font-size: 22px; font-weight: 700; }

/* Notes: long personal notes + the 📝 Notes view */
.marker-form textarea {
  background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 9px 10px; font: 14px/1.5 var(--ui); resize: vertical;
}
.mk-note.long { white-space: pre-wrap; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.notes-view { display: flex; flex-direction: column; gap: 12px; padding-bottom: 24px; }
.nv-filter { background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 9px 11px; font-size: 14px; }
.nv-group { background: linear-gradient(180deg, var(--bg-2), var(--bg-1)); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; }
.nv-head { display: flex; flex-direction: column; margin-bottom: 6px; }
.nv-head b { font-size: 14px; color: var(--text); }
.nv-head small { font-size: 11px; color: var(--text-dim); }
.nv-item { display: flex; gap: 10px; width: 100%; text-align: left; background: transparent; border: none; border-top: 1px solid var(--line-soft); padding: 8px 2px; cursor: pointer; color: var(--text-2); }
.nv-item:hover .nv-title { color: var(--accent-bright); }
.nv-time { flex: none; width: 48px; font-family: var(--mono); font-size: 12px; color: var(--accent-bright); }
.nv-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nv-title { font-size: 13px; color: var(--text); }
.nv-note { font-size: 12px; white-space: pre-wrap; color: var(--text-2); }

/* Transcript search tab */
.ts-bar { display: flex; gap: 8px; margin-bottom: 8px; }
.ts-query { flex: 1; min-width: 0; background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px; }
.ts-source { background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 6px 8px; font-size: 12px; }
.ts-info { font-size: 11px; color: var(--text-dim); margin-bottom: 6px; }
.ts-results { max-height: min(46vh, 420px); overflow-y: auto; overscroll-behavior: contain; }
.ts-hit { display: flex; gap: 10px; width: 100%; text-align: left; background: transparent; border: none; border-radius: 8px; padding: 6px; cursor: pointer; color: var(--text-2); font-size: 14px; line-height: 1.4; }
.ts-hit:hover { background: var(--bg-3); color: var(--text); }
.ts-time { flex: none; width: 42px; font-family: var(--mono); font-size: 11px; color: var(--accent-bright); padding-top: 2px; }
.ts-hit mark { background: color-mix(in srgb, var(--accent) 35%, transparent); color: var(--text); border-radius: 3px; padding: 0 1px; }
.sm-bite input { width: 70px; background: var(--bg-1); color: var(--text); border: 1px solid var(--line); border-radius: 8px; padding: 5px 7px; font-family: var(--mono); font-size: 12px; }
.sm-bite-out { margin-top: 10px; }
.sm-audio { width: 100%; }
.ext-panel { display: flex; flex-direction: column; gap: 10px; }
.ext-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.ext-buttons a.np-btn { text-decoration: none; display: inline-flex; align-items: center; }

/* Watch party panel (Party in app.js) */
.party-panel {
  position: fixed; right: 16px; top: 76px; bottom: 96px; width: 340px; z-index: 160;
  display: flex; flex-direction: column; gap: 10px; padding: 12px 14px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow);
}
.party-panel.min { bottom: auto; }
.party-panel.min .pt-body { display: none; }
.pt-head { display: flex; align-items: center; gap: 8px; font-weight: 700; }
.pt-head .rv-icon { width: 30px; height: 30px; font-size: 12px; margin-left: auto; }
.pt-status { font-family: var(--mono); font-size: 10px; color: var(--text-dim); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-body { display: flex; flex-direction: column; gap: 10px; min-height: 0; flex: 1; }
.pt-row { display: flex; gap: 8px; align-items: center; font-size: 12px; color: var(--text-dim); }
.pt-row input, .pt-msg, .pt-name {
  flex: 1; min-width: 0; background: var(--bg-1); color: var(--text); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px;
}
.pt-code { font-family: var(--mono); letter-spacing: 0.2em; text-transform: uppercase; }
.pt-or { text-align: center; font-size: 11px; color: var(--text-dim); }
.pt-share { display: flex; gap: 6px; align-items: center; }
.pt-share code { flex: 1; min-width: 0; font-family: var(--mono); font-size: 11px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-now { font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-members { display: flex; flex-wrap: wrap; gap: 6px; }
.pt-member { font-size: 12px; padding: 3px 9px; border-radius: 999px; background: var(--bg-3); color: var(--text-2); }
.pt-member.me { color: var(--text); border: 1px solid var(--accent); }
.pt-toggle { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); }
.pt-voice { display: flex; align-items: center; gap: 8px; }
.pt-voice .np-btn.on { border-color: #7ee0a8; }
.pt-voice-n { font-size: 11px; color: var(--text-dim); }
.pt-chat { flex: 1; min-height: 80px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; padding: 6px; background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: var(--radius-sm); }
.pt-line { font-size: 13px; color: var(--text-2); line-height: 1.4; overflow-wrap: anywhere; }
.pt-line b { color: var(--text); }
.pt-line.me b { color: var(--accent-bright); }
.pt-sys { font-size: 11px; color: var(--text-dim); text-align: center; }
.pt-send { display: flex; gap: 6px; }
.pt-leave { background: transparent; border: none; color: var(--text-dim); font-size: 12px; cursor: pointer; text-decoration: underline; align-self: center; }
@media (max-width: 720px) {
  /* `bottom: 8px` put the panel's last child — "End the party" — underneath
     the bottom nav and the mini player. --bottom-chrome is measured at runtime
     (SectionRail.placeRail) because either bar can be absent. max-height keeps
     the panel inside the viewport instead of growing off the top. */
  .party-panel {
    left: 8px; right: 8px; width: auto; top: auto;
    /* NEVER trust the measurement alone: take whichever is larger, the value
       SectionRail measured (it also covers the mini player) or a CSS floor of
       one bottom-nav plus the home-indicator inset. A JS value that is stale,
       zero, or from a cached old shell can then no longer hide the panel's
       tail behind the nav — which is what kept eating "End the party". */
    bottom: calc(max(var(--bottom-chrome, 0px), 96px + env(safe-area-inset-bottom)) + 8px);
    height: auto;
    max-height: min(62vh, calc(100vh - max(var(--bottom-chrome, 0px), 96px + env(safe-area-inset-bottom)) - 96px));
    /* Safety net: without this the body's children render OUTSIDE the panel
       box when the measurement is off, and the bottom nav (z-index 310) paints
       over them — which is exactly how "End the party" went missing. Clipping
       here forces the overflow into .pt-body, which scrolls. The fallback is
       deliberately generous (a nav + home indicator) so an unmeasured phone
       errs on the safe side. */
    overflow: hidden;
  }
  .party-panel.min { height: auto; max-height: none; }
  /* Whatever the content, the panel scrolls rather than hiding its own tail. */
  .pt-body { overflow-y: auto; }
  /* The chat box used to take every spare pixel and push the buttons out. */
  .pt-chat { flex: 0 1 auto; max-height: 30vh; }
}
/* Uploads: cover art + badges on cards */
.thumb img.no-art { opacity: 0; }
.thumb:has(img.no-art) { background: linear-gradient(135deg, var(--bg-3), var(--bg-2)); }
.upload-badge {
  position: absolute; left: 4px; bottom: 4px; padding: 1px 6px; border-radius: 6px;
  background: rgba(0, 0, 0, 0.6); color: #fff; font-size: 11px;
}

/* --- Lyrics in place of the video (watch party / sing-along) --------------
   The stage keeps its 16/9 box; the lyrics list fills it and the video is
   hidden rather than unloaded, so playback (and party sync) never stops. */
.player-stage.lyrics-stage > video,
.player-stage.lyrics-stage > .art-fallback { visibility: hidden; }
.stage-lyrics {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 35%, var(--bg-2), #000 78%);
  z-index: 3;
}
.stage-lyrics .sl-list { padding: 0 2%; }
.stage-lyrics-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  gap: 8px;
  justify-content: center;
  padding: 8px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.72));
  opacity: 0;
  transition: opacity 0.18s var(--ease);
}
.stage-lyrics:hover .stage-lyrics-bar,
.stage-lyrics:focus-within .stage-lyrics-bar,
.stage-lyrics.show-bar .stage-lyrics-bar { opacity: 1; }
.stage-lyrics-bar .np-btn { backdrop-filter: blur(6px); }
.stage-lyrics .sl-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; color: var(--text-dim); font-size: 15px; text-align: center; gap: 6px;
}
/* Touch has no hover, so the bar stays visible on phones. */
@media (hover: none) {
  .stage-lyrics-bar { opacity: 1; }
}

/* --- "syncing" spinner beside the Playlists header -----------------------
   Playlists paint from localStorage on the first frame; this says the
   network pass (profile pull, shared-playlist inbox) is still running. */
.sync-spinner {
  width: 12px; height: 12px;
  /* .pl-header is space-between; auto margin keeps the spinner beside the
     label instead of floating in the middle of the row. */
  margin: 0 auto 0 8px;
  flex: none;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-top-color: var(--accent);
  animation: sync-spin 0.7s linear infinite;
}
@keyframes sync-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .sync-spinner { animation-duration: 2.4s; }
}

/* ==========================================================================
   Foldable cards + the mobile section rail
   ========================================================================== */

/* Folding hides a card's body but never its header, so the card stays a
   visible landmark (and a tap target) when collapsed. */
#notesPanel.folded .notes-pane,
#nowPlayingMeta.folded .np-actions,
#relatedPanel.folded .related-list { display: none !important; }
#notesPanel.folded .notes-tabs { border-bottom: 0; margin-bottom: 0; }

.notes-fold {
  margin-left: 6px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-dim);
  border-radius: 8px;
  width: 30px; height: 30px;
  font-size: 13px;
  cursor: pointer;
  flex: none;
  transition: transform 0.16s var(--ease), color 0.16s var(--ease);
}
.notes-fold:hover { color: var(--text); border-color: var(--line); }
#notesPanel.folded .notes-fold { transform: rotate(-90deg); }

/* --- the rail ------------------------------------------------------------ */
.sec-rail {
  position: fixed;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg-1) 84%, transparent);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  backdrop-filter: blur(10px);
}
.sec-rail-btn {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-2);
  font-size: 15px;
  line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  position: relative;
  padding: 0;
  transition: background 0.16s var(--ease), color 0.16s var(--ease);
}
.sec-rail-btn:active { transform: scale(0.94); }
.sec-rail-btn.active {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
/* A folded card's icon is dimmed and marked, so the rail doubles as a map of
   what is currently collapsed. */
.sec-rail-btn.folded { opacity: 0.55; }
.sec-rail-btn.folded::after {
  content: "";
  position: absolute;
  left: 8px; right: 8px; bottom: 6px;
  height: 2px;
  border-radius: 2px;
  background: var(--text-dim);
}
.sec-rail-label {
  position: absolute;
  right: 44px;
  white-space: nowrap;
  background: var(--bg-1);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 12px;
  padding: 4px 9px;
  border-radius: 8px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s var(--ease);
  box-shadow: var(--shadow);
}
.sec-rail-btn.show-label .sec-rail-label { opacity: 1; }

/* Phones only — on desktop the whole page is visible at once. */
@media (min-width: 861px) { .sec-rail { display: none !important; } }
@media (max-width: 860px) {
  /* Sits above the bottom nav and the mini player. Both are position:fixed
     bottom:0 and either can be absent, so SectionRail.placeRail() measures
     them and overrides --rail-bottom; this is only the pre-measure default. */
  .sec-rail {
    top: auto;
    bottom: max(var(--rail-bottom, 0px), calc(96px + env(safe-area-inset-bottom) + 14px));
  }
  /* The mini player is a floating card ABOVE the nav, so when it is on screen
     the rail has to clear both. Keeps the last icon visible even if the JS
     measurement is stale (e.g. the PWA is still on a cached shell). */
  body:has(#miniBar:not(.hidden)) .sec-rail {
    bottom: max(var(--rail-bottom, 0px), calc(186px + env(safe-area-inset-bottom)));
    transform: none;
  }
}

/* P2P: "Get it from a device" next to Retry (plan 017) */
.peer-btn { margin-left: 8px; }

/* Resumable saves: a real progress bar once the size is known, paused rows */
.dl-bar.determinate { animation: none; transform: none; border-radius: 0 2px 2px 0; transition: width 0.4s ease; }
.card.dl-paused .dl-bar { background: var(--text-dim); }
.dl-actions { display: flex; gap: 8px; margin-top: 8px; }
.dl-act {
  height: 32px; padding: 0 12px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--line); background: var(--bg-2); color: var(--text);
  font: 600 12px var(--ui);
}
.dl-act:hover { border-color: var(--accent); }
.dl-act.danger:hover { border-color: #ff5a4f; color: #ff5a4f; }

/* Home screen over a playing video (Search tab): media stays alive, unseen */
.player-pane.home-over video,
.player-pane.home-over #stageLyrics,
.player-pane.home-over #artFallback { visibility: hidden; }
.player-pane.home-over .related-panel { display: none; }
.player-pane.home-over > :not(.player-stage):not(#serviceMode) { display: none !important; }

/* Pending-update icon beside the search box (shown after the update dialog) */
.update-icon-btn {
  flex: none; width: 44px; height: 44px; padding: 0; align-self: center;
  display: grid; place-items: center; cursor: pointer;
  border-radius: 50%; border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-2)); color: var(--accent-bright);
  box-shadow: 0 0 0 0 var(--accent-glow); animation: updPulse 2.4s ease-in-out infinite;
}
.update-icon-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.update-icon-btn.hidden { display: none; }
@keyframes updPulse { 0%, 100% { box-shadow: 0 0 0 0 var(--accent-glow); } 50% { box-shadow: 0 0 0 6px transparent; } }
@media (prefers-reduced-motion: reduce) { .update-icon-btn { animation: none; } }
/* The search box gives up width for the update icon instead of pushing Search off screen */
.search-form { min-width: 0; }
.search-form #searchInput { flex: 1 1 auto; min-width: 0; }

/* iPhone/iPad: no double-tap page zoom (scrolling unaffected) */
html.ios-nozoom, html.ios-nozoom body { touch-action: manipulation; }

/* The last card of a list scrolls clear of the bottom nav + mini player
   (--bottom-chrome is measured in app.js updateBottomChrome). */
#listPane { padding-bottom: calc(var(--bottom-chrome, 0px) + 32px) !important; }

/* Classic-layout SVG nav icons: `hidden` is not reliably honoured on SVG, so
   hide them explicitly everywhere; theme-classic.css shows them in Classic. */
.classic-nav-icon { display: none; }

/* Chapter picker (tap the chapter badge) */
.ch-picker-src { margin: 0 0 8px; font-size: 12.5px; color: var(--text-dim); }
.ch-picker-list { display: flex; flex-direction: column; gap: 4px; max-height: min(60vh, 460px); overflow-y: auto; margin: 0 -4px; padding: 2px 4px; }
.ch-pick {
  display: grid; grid-template-columns: 2.2em 1fr auto; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 8px 12px; border-radius: 12px; text-align: left; cursor: pointer;
  border: 1px solid transparent; background: var(--bg-2); color: var(--text); font: 600 14px var(--ui);
  transition: border-color .15s, background .15s;
}
.ch-pick:hover { border-color: var(--accent); }
.ch-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ch-pick-n { font: 600 12px var(--mono, ui-monospace, monospace); color: var(--text-dim); }
.ch-pick-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-pick-t { font: 500 12.5px var(--mono, ui-monospace, monospace); color: var(--text-dim); font-variant-numeric: tabular-nums; }
.ch-pick.on { background: color-mix(in srgb, var(--accent) 16%, var(--bg-2)); border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.ch-pick.on .ch-pick-n, .ch-pick.on .ch-pick-t { color: var(--accent-bright); }

/* Settings → Offline cache: the saved-videos list folds */
.cache-fold { margin-top: 10px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-1); }
.cache-fold > summary {
  list-style: none; display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 14px;
  cursor: pointer; font-weight: 600; color: var(--text); border-radius: 12px;
}
.cache-fold > summary::-webkit-details-marker { display: none; }
.cache-fold > summary::before {
  content: ""; flex: none; width: 7px; height: 7px; margin-right: 2px;
  border-right: 2px solid var(--text-dim); border-bottom: 2px solid var(--text-dim);
  transform: rotate(-45deg); transition: transform .18s ease;
}
.cache-fold[open] > summary::before { transform: rotate(45deg); }
.cache-fold > summary:hover { background: var(--bg-2); }
.cache-fold > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cache-fold-count { margin-left: auto; font-weight: 500; font-size: 13px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.cache-fold > .cache-list { margin: 0; padding: 4px 10px 10px; }

@media (min-width: 900px) { .modal:has(.eq-panel) { width: min(92vw, 780px); max-width: 780px; } .eq-bands { grid-template-columns: repeat(10, minmax(44px, 1fr)); } }

.lyric-primary { white-space: pre-line; }
.lyric-secondary { display: block; white-space: pre-line; font-size: .62em; font-weight: 450; line-height: 1.2; opacity: .68; margin-top: .15em; }
