/* ==========================================================================
   Stage layout — player beside library on wide screens, stacked below.
   ========================================================================== */
.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
}

@media (min-width: 940px) {
  .stage {
    grid-template-columns: minmax(0, 1fr) 22rem;
    align-items: start;
  }
  /* Library and queue stay in view while the lyrics scroll. */
  .library-panel {
    position: sticky;
    top: calc(var(--header-height) + var(--space-4));
    max-height: calc(100vh - var(--header-height) - var(--space-6));
    overflow-y: auto;
  }
}

.player-panel { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.library-panel { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }

/* The element is the clock and the Web Audio source; the visible controls
   are .transport. Hidden rather than removed so everything wired to it keeps
   working — see the comment beside the audio element in karaoke.html. */
.audio-source { display: none; }

/* ==========================================================================
   Now playing
   ========================================================================== */
.now-playing {
  display: grid;
  grid-template-columns: 11rem minmax(0, 1fr);
  gap: var(--space-5);
  align-items: center;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--surface-raised), var(--surface));
  box-shadow: var(--shadow-2);
}

.now-playing.is-empty { display: block; padding: var(--space-4); background: none; box-shadow: none; }

.now-playing-art { box-shadow: var(--shadow-3); }

.now-playing-meta { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }

.now-playing-title {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}

.now-playing-artist { margin: 0; color: var(--text-dim); font-size: var(--text-md); }
.now-playing-details { margin: 0; color: var(--text-faint); font-size: var(--text-sm); }

@media (max-width: 560px) {
  .now-playing { grid-template-columns: 6rem minmax(0, 1fr); gap: var(--space-4); padding: var(--space-4); }
  .now-playing-title { font-size: var(--text-lg); }
}

/* ==========================================================================
   Transport — replaces the stock <audio controls> widget
   ========================================================================== */
.transport {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.transport-bar {
  display: grid;
  grid-template-columns: auto auto auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
}

.transport-play {
  width: 2.75rem;
  height: 2.75rem;
  min-height: 0;
  padding: 0;
  border-radius: var(--radius-full);
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-size: var(--text-base);
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.transport-play:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.transport-step { font-size: var(--text-sm); }

.transport-time {
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--text-dim);
  min-width: 3ch;
  text-align: center;
}

/* Range inputs give no hook for the filled portion, so the fill is painted
   as a gradient driven by --seek-progress, which the transport updates. */
.transport-seek {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: var(--radius-full);
  background: linear-gradient(
    to right,
    var(--accent) 0 var(--seek-progress, 0%),
    var(--border-strong) var(--seek-progress, 0%) 100%
  );
  cursor: pointer;
}
.transport-seek:disabled { cursor: default; opacity: 0.5; }

.transport-seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 13px;
  height: 13px;
  border-radius: var(--radius-full);
  background: var(--text);
  border: none;
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-fast) var(--ease);
}
.transport-seek:hover::-webkit-slider-thumb { transform: scale(1.2); }

.transport-seek::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: var(--radius-full);
  background: var(--text);
  border: none;
  box-shadow: var(--shadow-1);
}

.transport-status {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-dim);
  text-align: center;
}
.transport-status.is-error { color: var(--danger); }

@media (max-width: 560px) {
  .transport-bar { gap: var(--space-2); padding: var(--space-2); }
  .transport-time { font-size: var(--text-xs); }
}

/* ==========================================================================
   Stem controls — shared by the karaoke (vocals) and drumless (drums)
   tiers; see vocal-control.js and drum-control.js. The pill row/button
   pair backs two different pickers in drum-control.js: the difficulty
   level (both tiers) and the reduce/solo mode (drumless only).
   ========================================================================== */
.controls-row { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }

.control-label {
  color: var(--text-faint);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.stem-status { color: var(--text-dim); font-size: var(--text-sm); }

.stem-pill-row {
  display: flex;
  gap: var(--space-1);
  flex-wrap: wrap;
  padding: var(--space-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
}

.stem-pill-btn {
  min-height: 2rem;
  padding: var(--space-1) var(--space-4);
  border-radius: var(--radius-full);
  border-color: transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--text-sm);
}
.stem-pill-btn:hover:not(:disabled) { background: var(--surface-hover); color: var(--text); }
.stem-pill-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: var(--weight-semibold);
}

.performance-toggle-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: var(--weight-semibold);
}

/* ==========================================================================
   Performance mode — hide the library/queue chrome so the lyrics or drum
   score reads at a glance from stage distance. Album art, transport, and
   the mode/difficulty controls stay put; only the sidebar and the
   below-the-fold sections (suggestions, requests, Apple search) go away.
   ========================================================================== */
body.performance-mode .library-panel,
body.performance-mode .shelf {
  display: none;
}

body.performance-mode .stage {
  grid-template-columns: minmax(0, 1fr);
}

body.performance-mode .lyrics-panel,
body.performance-mode .score-panel {
  height: min(80vh, 60rem);
}

body.performance-mode .lyrics-line {
  font-size: var(--text-2xl);
}

/* ==========================================================================
   Library list
   ========================================================================== */
.library-head { display: flex; gap: var(--space-2); align-items: center; }
.library-head input { flex: 1; }
.library-head button { flex-shrink: 0; }

.track-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 4rem;
}

.track-row {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  border-radius: var(--radius);
  transition: background-color var(--dur) var(--ease);
}

.track-row:hover { background: var(--surface); }
.track-row.is-active { background: var(--accent-dim); }

.track-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1;
  min-width: 0;
  padding: var(--space-2);
  text-align: left;
  background: transparent;
  border-color: transparent;
}
.track-item:hover:not(:disabled) { background: transparent; border-color: transparent; }

.track-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }

.track-title {
  font-weight: var(--weight-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.track-artist {
  font-size: var(--text-sm);
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.track-row.is-active .track-title { color: var(--accent); }

.track-duration {
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  flex-shrink: 0;
}

/* Three bars standing in for a playhead on the row that's playing. */
.track-playing { display: flex; align-items: flex-end; gap: 2px; height: 0.9rem; flex-shrink: 0; }
.track-playing i { width: 3px; background: var(--accent); border-radius: 1px; animation: eq 0.9s var(--ease) infinite alternate; }
.track-playing i:nth-child(1) { height: 40%; animation-delay: -0.2s; }
.track-playing i:nth-child(2) { height: 90%; animation-delay: -0.5s; }
.track-playing i:nth-child(3) { height: 60%; animation-delay: -0.8s; }

@keyframes eq { from { transform: scaleY(0.35); } to { transform: scaleY(1); } }

/* The row already shows what's playing; a static bar is enough when motion
   is unwelcome. */
@media (prefers-reduced-motion: reduce) {
  .track-playing i { animation: none; height: 70%; }
}

.track-queue-btn, .track-delete-btn { opacity: 0; transition: opacity var(--dur) var(--ease); }
.track-row:hover .track-queue-btn,
.track-row:hover .track-delete-btn,
.track-queue-btn:focus-visible,
.track-delete-btn:focus-visible { opacity: 1; }

/* Touch has no hover, so the actions would otherwise be unreachable. */
@media (hover: none) {
  .track-queue-btn, .track-delete-btn { opacity: 1; }
}

/* ==========================================================================
   Up next
   ========================================================================== */
.up-next:not(:empty) {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

.up-next-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: var(--radius);
  background: var(--surface);
}

.up-next-item-btn {
  flex: 1;
  min-width: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0;
  background: transparent;
  border-color: transparent;
  padding: var(--space-2) var(--space-3);
}

.up-next-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-next-artist { display: block; color: var(--text-dim); font-size: var(--text-sm); }

/* ==========================================================================
   Shelves — karaoke picks, request queues, Apple search
   (.shelf itself lives in base.css; the home page uses it too)
   ========================================================================== */
.pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-2);
}

.pick-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.pick-card:hover { background: var(--surface-raised); border-color: var(--border-strong); }
.pick-card.is-owned { border-color: var(--accent-line); }
.pick-card.is-busy { opacity: 0.6; }

.pick-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }

.pick-title {
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pick-artist {
  font-size: var(--text-xs);
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pick-actions { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }
.pick-note { font-size: var(--text-xs); color: var(--accent); }

.queue-list { display: flex; flex-direction: column; gap: var(--space-2); }

.queue-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.queue-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.queue-title { font-weight: var(--weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.queue-artist { font-size: var(--text-sm); color: var(--text-dim); }
.queue-meta { font-size: var(--text-xs); color: var(--text-faint); flex-shrink: 0; }
.queue-actions { display: flex; gap: var(--space-1); flex-shrink: 0; }

#apple-search-section .apple-result-item {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.apple-result-queue-btn { margin-left: auto; flex-shrink: 0; }
.apple-result-queued { margin-left: auto; flex-shrink: 0; color: var(--accent); font-size: var(--text-sm); }

/* ==========================================================================
   Drum score
   The notation counterpart to the lyrics stage: same footprint, same
   scroll-follow behaviour, VexFlow SVG instead of text.
   ========================================================================== */
#view-tabs { display: flex; }

.score-panel {
  position: relative;
  height: min(56vh, 30rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
}

/* No gradient mask here, unlike .lyrics-panel: fading the top and bottom of a
   staff cuts through ledger lines and stems, which reads as a rendering bug
   rather than as depth. */
.score-scroll {
  position: relative;
  height: 100%;
  overflow-y: auto;
  scrollbar-width: none;
}
.score-scroll::-webkit-scrollbar { display: none; }

.score-system {
  position: relative;
  cursor: pointer;
}

/* VexFlow emits raw black; recolour the whole staff through currentColor so
   the notation follows the theme instead of vanishing on a dark background. */
.score-system svg { display: block; }
.score-system svg path,
.score-system svg rect { fill: var(--text); }
.score-system svg text { fill: var(--text); }

.score-highlight {
  position: absolute;
  height: 7.5rem;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  pointer-events: none;
  transition: top 120ms ease, left 120ms ease, width 120ms ease;
}

.score-playhead {
  position: absolute;
  width: 2px;
  height: 7.5rem;
  background: var(--accent);
  pointer-events: none;
  opacity: 0.85;
}

.score-status {
  padding: var(--space-4);
  text-align: center;
}

/* .is-empty sets display:flex, which would otherwise win against the hidden
   attribute the tab control toggles. */
.score-panel[hidden] { display: none; }

.score-panel.is-empty {
  height: auto;
  min-height: 8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
