/* Rules that cannot live with the component they affect.

   The knob rule covers the player bar and the now-playing view in one
   selector list, so it has to load after both. The hidden guard has to
   outrank every display rule in the project. Everything else that used to
   sit here has moved to the file for the thing it styles. */

/* ─ Bars carry no dot ─────────────────────────────────────────
   The reference notes for v1.7: "It's a clean bar with no dot on it, matching the
   progress bar." Confirmed in a screenshot of it mid-playback — the
   filled portion just ends. The knob stays for grabbing, so it fades
   in on hover and while dragging rather than sitting there always. */

.player__track-knob,
.player__vol-knob,
.now-playing__track-knob,
.np-vol-slider__knob {
  opacity: 0;
  transition: opacity 0.15s var(--ease-out);
}

.player__track-bar:hover .player__track-knob,
.player__vol-bar:hover .player__vol-knob,
.now-playing__track-bar:hover .now-playing__track-knob,
.np-vol-slider:hover .np-vol-slider__knob,
.is-scrubbing .player__track-knob,
.is-scrubbing .now-playing__track-knob,
.is-scrubbing .player__vol-knob,
.is-scrubbing .np-vol-slider__knob {
  opacity: 1;
}

/* Lyric selection mode, for the copy action. */
.now-playing__lyrics.is-selecting .np-lyric-line {
  cursor: pointer;
  filter: none;
}

.np-lyric-line--picked {
  color: var(--text) !important;
  filter: none !important;
}

.np-lyric-action.is-active {
  background: rgba(255, 255, 255, 0.24);
  color: var(--text);
}


/* ── Muted ────────────────────────────────────────────────────
   Both Volume buttons shipped with the icon and no handler: the keyboard
   'm' muted, clicking did nothing. Now that they work, the icon has to show
   which state it is in — waves for sound, a stroke through for silence. */
.vol-slash {
  display: none;
}

.is-muted .vol-wave {
  display: none;
}

.is-muted .vol-slash {
  display: inline;
}

.player__vol-bar.is-muted {
  opacity: 0.4;
}

/* ── Ask ─────────────────────────────────────────────────────
   Naming a playlist went through window.prompt and deleting one through
   window.confirm: chrome-coloured boxes with the browser's own typography,
   landing on top of a UI that is otherwise entirely ours. This is the same
   question asked in the app's own voice. One dialog serves all three, so a
   fourth question cannot invent a fourth look. */
.ask-scrim {
  position: fixed;
  inset: 0;
  /* Above the now-playing sheet at 1000, the same as the toast. ask() appends
     to document.body, so the two compare directly in the root stacking
     context — and "+ New playlist…" is reachable from the sheet's own overflow
     menu, where at 300 the dialog was invisible and its buttons unclickable
     with only Escape to get out. */
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.ask {
  inline-size: min(380px, 100%);
  border-radius: var(--radius-tile, 20px);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ask__title {
  font-size: 17px;
  line-height: 24px;
  font-weight: 600;
  color: var(--text);
}

.ask__body {
  font-size: 14px;
  line-height: 20px;
  color: var(--text-muted);
}

.ask__input {
  margin-block-start: 8px;
  block-size: 38px;
  border-radius: 10px;
  padding-inline: 12px;
  font: inherit;
  font-size: 15px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid var(--glass-border);
}

/* A soft ring rather than a hard accent outline: this is the only field in
   the app, and a 2px ring made it the loudest thing on a screen whose whole
   point is the question above it. */
.ask__input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}

/* The affirmative answer has to be findable without reading both buttons. */
.ask__go {
  background: var(--accent);
  color: #fff;
}

.ask__go:hover {
  background: color-mix(in srgb, var(--accent) 88%, #fff);
}

.ask__row {
  margin-block-start: 16px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

@media (prefers-reduced-motion: no-preference) {
  .ask-scrim { animation: ask-in 140ms var(--ease-out); }
  @keyframes ask-in { from { opacity: 0; } to { opacity: 1; } }
}

/* Shuffle and repeat used to set an inline colour from three different places,
   two of which found their button by an aria-label that state now changes.
   One class, set in one function, is what the state looks like. */
.player__icon-btn.is-on,
.np-btn.is-on {
  color: var(--accent);
}

/* ── Focus ───────────────────────────────────────────────────
   The same ring was written out eight times across four files, and two whole
   files — the now-playing sheet and every album and artist button — had none
   at all, so tabbing through them left no trace of where you were. One rule
   covers everything focusable instead.

   :where() keeps this at zero specificity, so the two controls that need a
   different ring (the tab bar, which is clipped, and the ask field) still win
   without having to fight it. */
:where(a[href], area, button, input, select, textarea, summary,
       [tabindex]:not([tabindex="-1"]), [role="button"], [role="link"],
       [contenteditable="true"]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Asked to sit still ────────────────────────────────────────
    Every animation and transition in the app views goes inert under
    prefers-reduced-motion. The per-component guards keep their own fallbacks
    (the marquee keeps its ellipsis, the sheet its visibility sequencing);
    this is the backstop for the rest — toasts, sidebar, hover lifts,
    entrances — and for anything added later that forgets its own. The
    ratified exceptions need no carve-out: sub-200ms colour fades, the linear
    scrubber, the lyric blur and the visibility delay are already nothing to
    a reader who asked for none. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Read out, never drawn. Not display:none and not visibility:hidden — both
   take it out of the accessibility tree, which is the whole point of it. */
.a11y-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
