/* 00-tokens.css */
/* Tokens.

   Somewhere between a chat app and a music app: the calm surfaces and generous spacing
   of one, the dark ground and green of the other. The neutrals are not grey, they lean
   very slightly green so the accent reads as belonging to the room rather than dropped
   into it.

   Plant green rather than the usual signal green: enough life to mark what is playing,
   not so much that it glows. */

:root {
  --bg:          #0F1311;
  --bg-deep:     #0A0D0B;
  --surface:     #171C19;
  --surface-2:   #1E2521;
  --elevated:    #232B26;
  --hover:       rgba(255, 255, 255, 0.045);
  --pressed:     rgba(255, 255, 255, 0.08);

  --line:        rgba(255, 255, 255, 0.07);
  --line-2:      rgba(255, 255, 255, 0.13);

  --text:        #E8EDE9;
  --text-2:      #9BA8A0;
  --text-3:      #6E7B74;
  --text-on-accent: #08130C;

  --accent:      #54B37A;
  --accent-hi:   #6ECB92;
  --accent-lo:   #3E8B5D;
  --accent-soft: rgba(84, 179, 122, 0.14);
  --accent-line: rgba(84, 179, 122, 0.4);

  --warn:        #D9A441;
  --bad:         #D4685E;

  --font:  "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* "Jong Display" is whatever font has been uploaded in Settings, registered at runtime.
     Orbitron is the openly licensed stand in until one is: geometric and technical, the
     nearest thing to the face this library was designed around that can ship in a repo. */
  --display: "Jong Display", "Orbitron", "Manrope", ui-sans-serif, system-ui, sans-serif;

  /* Round, and unapologetic about it. */
  --r-pill: 999px;
  --r-xl:  20px;
  --r-lg:  16px;
  --r-md:  12px;
  --r-sm:  8px;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 28px; --s7: 40px; --s8: 56px;

  --rail-w: 244px;
  --player-h: 84px;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 8px 24px rgba(0, 0, 0, 0.36);
  --shadow-3: 0 20px 60px rgba(0, 0, 0, 0.5);

  --ease: cubic-bezier(0.22, 0.7, 0.3, 1);
  --fast: 130ms var(--ease);
  --med:  220ms var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  :root { --fast: 1ms linear; --med: 1ms linear; }
  * { animation-duration: 1ms !important; scroll-behavior: auto !important; }
}


/* 10-base.css */
/* Base: the ground, the type, and the things every screen uses. */

* { box-sizing: border-box; }

/* The hidden attribute has to win against the layout.
 *
 * A browser's own stylesheet says [hidden] { display: none }, but that is a user agent
 * rule and any author rule beats it. So .sheet-backdrop { display: grid } quietly turned
 * the hidden attribute off, and the modal backdrop sat over the whole app at 60% black
 * with nothing in it: the page looked dimmed and swallowed every click. The player did
 * the same thing with nothing playing.
 *
 * Anything given a display by its class needs this to stay hideable. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(30px, 5vw, 46px); font-weight: 800; }
h2 { font-size: 21px; }
h3 { font-size: 16px; letter-spacing: -0.01em; }

a { color: inherit; text-decoration: none; }

button, input, textarea, select { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

::selection { background: var(--accent-soft); }

/* Numbers that sit in columns get to line up. */
.num, .dur, .meta-num { font-variant-numeric: tabular-nums; }

.grow { flex: 1; }
.muted { color: var(--text-2); }
.faint { color: var(--text-3); }
.bad-text { color: var(--bad); }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}

.stack { display: flex; flex-direction: column; }
.row { display: flex; align-items: center; gap: var(--s3); }
.row.wrap { flex-wrap: wrap; }

.empty {
  padding: var(--s7) var(--s5);
  text-align: center;
  color: var(--text-2);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-lg);
}
.empty h3 { margin-bottom: var(--s2); color: var(--text); }

/* Scrollbars, quiet but present. */
* { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.16) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border-radius: var(--r-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.24); background-clip: content-box; }
*::-webkit-scrollbar-track { background: transparent; }


/* 20-shell.css */
/* The shell: a rail, a scrolling main column, a docked player. */

.shell {
  display: grid;
  grid-template-columns: var(--rail-w) 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas: "rail main" "player player";
  height: 100dvh;
  gap: var(--s2);
  padding: var(--s2);
}

/* ── rail ─────────────────────────────────────────────────────────────────── */
.rail {
  grid-area: rail;
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--s4) var(--s3) var(--s3);
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  min-height: 0;
  overflow: hidden;
}
.rail-top { display: flex; align-items: center; justify-content: space-between; padding: 0 var(--s2); }
.wordmark {
  font-family: var(--display);
  font-weight: 800;
  font-size: 23px;
  letter-spacing: -0.03em;
}
.wordmark::after {
  content: "";
  display: inline-block;
  width: 7px; height: 7px;
  margin-left: 3px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 3px;
}
/* The rail buttons carry .icon-btn too, and .icon-btn sets display: grid from a later
   file. Two single class rules tie on specificity and file order decides, which is how
   both of these ended up permanently visible on desktop doing nothing. Two classes in the
   selector settles it wherever the files happen to sit. */
.icon-btn.rail-close { display: grid; }   /* always: it is how you put the rail away */
.icon-btn.rail-open { display: none; }
.shell.rail-shut .icon-btn.rail-open { display: grid; }

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav a {
  display: flex; align-items: center; gap: var(--s3);
  padding: 9px var(--s3);
  border-radius: var(--r-pill);
  color: var(--text-2);
  font-weight: 600;
  transition: background var(--fast), color var(--fast);
}
.nav a svg { flex: none; opacity: 0.9; }
.nav a:hover { background: var(--hover); color: var(--text); }
.nav a.on { background: var(--accent-soft); color: var(--accent-hi); }

.rail-section {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 2px;
}
.rail-section .eyebrow { padding: var(--s3) var(--s3) var(--s2); }
.rail-album {
  display: flex; align-items: center; gap: var(--s3);
  padding: 6px var(--s2);
  border-radius: var(--r-md);
  transition: background var(--fast);
}
.rail-album:hover { background: var(--hover); }
.rail-album .cover { width: 38px; height: 38px; border-radius: var(--r-sm); flex: none; }
.rail-album .t { font-weight: 600; font-size: 13px; }
.rail-album .s { font-size: 11.5px; color: var(--text-3); }

.rail-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
}
.rail-version { font-size: 11px; color: var(--text-3); }

.rail-scrim { display: none; }

/* Collapsing the rail on a wide screen: the column goes to nothing and the main panel
   takes the room. This is what the hamburger does when there is no overlay to open.

   Held inside a min-width query rather than left loose. Two class selectors outrank the
   one class rule that gives a phone its single column, so as a bare rule this pinned the
   main column to zero on every phone and collapsed the entire page behind it. */
@media (min-width: 901px) {
  .shell.rail-shut { grid-template-columns: 0 1fr; }
  .shell.rail-shut .rail { display: none; }
}

/* ── main ─────────────────────────────────────────────────────────────────── */
.main {
  grid-area: main;
  background: var(--surface);
  border-radius: var(--r-lg);
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
}

.topbar {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s5);
  flex: none;
  position: sticky; top: 0; z-index: 5;
  background: linear-gradient(var(--surface) 70%, transparent);
}

.search {
  display: flex; align-items: center; gap: var(--s2);
  background: var(--bg);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  padding: 0 var(--s4);
  height: 40px;
  width: min(360px, 46vw);
  color: var(--text-3);
  transition: border-color var(--fast), background var(--fast);
}
.search:focus-within { border-color: var(--accent-line); background: var(--bg-deep); }
.search input {
  background: none; border: 0; outline: none; width: 100%;
  font-size: 13.5px; color: var(--text);
}
.search input::placeholder { color: var(--text-3); }
.search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.update-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}

.view {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--s2) var(--s5) var(--s8);
  scroll-behavior: smooth;
}

.section { margin-top: var(--s7); }
.section:first-child { margin-top: var(--s3); }
.section-head {
  display: flex; align-items: baseline; gap: var(--s3);
  /* Wrapping so a heading with two buttons after it does not run off the side of a
     phone. The spacer pushes them to a second line rather than off the edge. */
  flex-wrap: wrap;
  margin-bottom: var(--s4);
}
.section-head .grow { flex: 1; }

/* ── responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; grid-template-areas: "main" "player"; }
  .rail {
    position: fixed; inset: var(--s2) auto var(--s2) var(--s2);
    width: var(--rail-w); z-index: 40;
    transition: transform var(--med);
    box-shadow: var(--shadow-3);
  }
  /* Narrow: shut means parked off screen rather than gone, so it can slide back. */
  .shell.rail-shut .rail {
    display: flex;
    transform: translateX(calc(-100% - var(--s3)));
  }
  .rail-scrim {
    display: block; position: fixed; inset: 0; z-index: 30;
    background: rgba(0, 0, 0, 0.5);
  }
  .shell.rail-shut .rail-scrim { display: none; }
}


/* 30-controls.css */
/* Controls: round, and pills where a pill says "one of these".

   Three shapes only. A filled green pill for the action a screen is actually for, a
   quiet pill for everything else, and a circle for transport. */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: 38px;
  padding: 0 var(--s5);
  border: 0;
  border-radius: var(--r-pill);
  background: var(--elevated);
  color: var(--text);
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--fast), transform var(--fast), opacity var(--fast);
}
.btn:hover { background: #2A332D; }
.btn:active { transform: scale(0.97); }
.btn[disabled] { opacity: 0.45; cursor: default; transform: none; }

.btn.primary { background: var(--accent); color: var(--text-on-accent); }
.btn.primary:hover { background: var(--accent-hi); }
.btn.ghost { background: transparent; color: var(--text-2); }
.btn.ghost:hover { background: var(--hover); color: var(--text); }
.btn.danger { background: transparent; color: var(--bad); }
.btn.danger:hover { background: rgba(212, 104, 94, 0.12); }
.btn.sm { height: 30px; padding: 0 var(--s4); font-size: 12.5px; }
.btn.lg { height: 46px; padding: 0 var(--s6); font-size: 15px; }

/* Round transport and icon buttons. */
.icon-btn {
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border: 0; border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background var(--fast), color var(--fast), transform var(--fast);
}
.icon-btn:hover { background: var(--hover); color: var(--text); }
.icon-btn:active { transform: scale(0.94); }
.icon-btn.on { color: var(--accent-hi); }
.icon-btn[disabled] { opacity: 0.35; cursor: default; }

.play-btn {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border: 0; border-radius: 50%;
  background: var(--accent);
  color: var(--text-on-accent);
  cursor: pointer;
  box-shadow: var(--shadow-2);
  transition: transform var(--fast), background var(--fast);
}
.play-btn:hover { background: var(--accent-hi); transform: scale(1.05); }
.play-btn:active { transform: scale(0.97); }
.play-btn.sm { width: 38px; height: 38px; box-shadow: none; }

/* Pills: a row where exactly one is chosen. */
.pills { display: flex; gap: var(--s2); flex-wrap: wrap; }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 var(--s4);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-2);
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  transition: background var(--fast), color var(--fast), border-color var(--fast);
}
.pill:hover { background: var(--hover); color: var(--text); }
.pill.on {
  background: var(--accent); border-color: var(--accent); color: var(--text-on-accent);
}
.pill.quiet { border-color: transparent; background: var(--surface-2); }
.pill.quiet.on { background: var(--accent); }

/* A read only tag, not a control. */
.tag {
  white-space: nowrap;        /* "43 waiting" is one thing, never two lines */
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 10px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11.5px; font-weight: 600;
}
.tag.accent { background: var(--accent-soft); color: var(--accent-hi); }
.tag.warn { background: rgba(217, 164, 65, 0.14); color: var(--warn); }

.field {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 10px var(--s4);
  font-size: 14px;
  outline: none;
  transition: border-color var(--fast), background var(--fast);
}
.field:hover { border-color: var(--line-2); }
.field:focus { border-color: var(--accent-line); background: var(--bg-deep); }
textarea.field { min-height: 120px; resize: vertical; line-height: 1.7; }

.switch {
  position: relative; width: 40px; height: 23px; flex: none;
  border-radius: var(--r-pill); border: 0;
  background: var(--elevated);
  cursor: pointer;
  transition: background var(--fast);
}
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--text-2);
  transition: transform var(--fast), background var(--fast);
}
.switch.on { background: var(--accent); }
.switch.on::after { transform: translateX(17px); background: var(--text-on-accent); }

/* Slider used by the limiter and the volume control. */
.range {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 20px; background: none; cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  height: 4px; border-radius: var(--r-pill);
  background: linear-gradient(var(--accent), var(--accent)) 0 / var(--fill, 0%) 100% no-repeat,
              var(--elevated);
}
.range::-moz-range-track { height: 4px; border-radius: var(--r-pill); background: var(--elevated); }
.range::-moz-range-progress { height: 4px; border-radius: var(--r-pill); background: var(--accent); }
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; margin-top: -5px;
  border-radius: 50%; background: var(--text); border: 0;
  box-shadow: var(--shadow-1);
  transition: transform var(--fast);
}
.range::-moz-range-thumb {
  width: 14px; height: 14px; border: 0; border-radius: 50%; background: var(--text);
}
.range:hover::-webkit-slider-thumb { transform: scale(1.18); }

/* A plain row in a settings or folder list. Generic, so it lives with the controls
   rather than inside one screen's stylesheet, which is where it used to be until that
   screen was rewritten out from under it. */
.list-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-md);
  background: var(--surface-2);
  margin-bottom: var(--s2);
}
.list-row .grow { min-width: 0; flex: 1; }

.toast-stack {
  position: fixed; left: 50%; bottom: calc(var(--player-h) + 24px);
  transform: translateX(-50%);
  display: flex; flex-direction: column; gap: var(--s2);
  z-index: 90; pointer-events: none;
}
.toast {
  background: var(--elevated);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  padding: 10px var(--s5);
  font-size: 13.5px; font-weight: 600;
  box-shadow: var(--shadow-2);
  animation: toast-in 220ms var(--ease);
}
.toast.bad { border-color: rgba(212, 104, 94, 0.5); color: #F0A79E; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }


/* 40-library.css */
/* Library and albums: artwork carries the page, song lists stay dense. */

.cover {
  position: relative;
  border-radius: var(--r-md);
  background: var(--surface-2);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  flex: none;
  display: grid;
  place-items: center;
  /* The placeholder letter is sized from the box, not from the inherited font size.
     A percentage font-size resolves against the parent's font size, which made the
     letter six pixels tall on a two hundred pixel cover. */
  container-type: size;
}
/* No artwork yet: a calm two tone built from the title, so a library with nothing
   uploaded still looks like a shelf rather than a row of empty boxes. */
.cover[data-hue] {
  background-image: linear-gradient(150deg,
    hsl(var(--hue) 26% 32%), hsl(calc(var(--hue) + 34) 22% 17%));
}
.cover .letter {
  font-family: var(--display);
  font-weight: 800;
  color: rgba(255, 255, 255, 0.44);
  font-size: 44cqmin;
  line-height: 1;
  letter-spacing: -0.03em;
  user-select: none;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: var(--s4);
}

.album-card {
  padding: var(--s3);
  border-radius: var(--r-lg);
  background: transparent;
  transition: background var(--fast);
  cursor: pointer;
  position: relative;
}
.album-card:hover { background: var(--surface-2); }
.album-card .cover { width: 100%; aspect-ratio: 1; border-radius: var(--r-md); margin-bottom: var(--s3); }
.album-card .t { font-weight: 700; font-size: 14px; }
.album-card .s { font-size: 12.5px; color: var(--text-3); }
.album-card .play-btn {
  position: absolute; right: var(--s5); top: 46%;
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--fast), transform var(--fast);
}
.album-card:hover .play-btn, .album-card:focus-within .play-btn { opacity: 1; transform: none; }

/* ── song rows ────────────────────────────────────────────────────────────── */
.tracks { display: flex; flex-direction: column; }
.track {
  display: grid;
  grid-template-columns: var(--track-cols, 40px 1fr 84px 62px);
  align-items: center;
  gap: var(--s4);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background var(--fast);
}
.track:hover { background: var(--hover); }
.track:active { background: var(--pressed); }
.track .lead { display: grid; place-items: center; width: 40px; }
.track .cover { width: 40px; height: 40px; border-radius: var(--r-sm); }
.track .index { color: var(--text-3); font-size: 13px; font-variant-numeric: tabular-nums; }
.track .title { font-weight: 600; }
.track .sub { font-size: 12.5px; color: var(--text-3); }
.track .dur, .track .ver { color: var(--text-3); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.track .ver { text-align: left; }
.track.playing .title { color: var(--accent-hi); }
.track.playing .index { color: var(--accent-hi); }

/* The equaliser bars that mark the row currently sounding. */
.playing-bars { display: flex; align-items: flex-end; gap: 2px; height: 13px; }
.playing-bars i {
  width: 2.5px; background: var(--accent-hi); border-radius: 1px;
  animation: bars 900ms var(--ease) infinite alternate;
}
.playing-bars i:nth-child(1) { height: 40%; animation-delay: -200ms; }
.playing-bars i:nth-child(2) { height: 90%; animation-delay: -520ms; }
.playing-bars i:nth-child(3) { height: 60%; animation-delay: -80ms; }
@keyframes bars { to { height: 20%; } }
.paused .playing-bars i { animation-play-state: paused; }

.track-head {
  display: grid;
  grid-template-columns: var(--track-cols, 40px 1fr 84px 62px);
  gap: var(--s4);
  padding: 0 var(--s3) var(--s2);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s2);
}

/* ── album page header ────────────────────────────────────────────────────── */
.page-head {
  display: flex; gap: var(--s6); align-items: flex-end;
  padding: var(--s5) 0 var(--s6);
}
.page-head .cover {
  width: clamp(140px, 20vw, 208px);
  aspect-ratio: 1;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
}
.page-head .meta { min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }
.page-head .stats { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; color: var(--text-2); font-size: 13px; }
.page-head .stats .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-3); }
.page-actions { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }

@media (max-width: 700px) {
  .page-head { flex-direction: column; align-items: flex-start; gap: var(--s4); }
  .track { --track-cols: 40px 1fr 56px !important; }
  .track .ver { display: none; }
  .track-head { display: none; }
}


/* 45-renders.css */
/* ── the renders list, and choosing where one goes ────────────────────────── */

.render-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px solid transparent;
  margin-bottom: var(--s2);
  transition: border-color var(--fast), background var(--fast);
}
.render-row:hover { border-color: var(--line); }
.render-row .grow { min-width: 0; flex: 1; display: block; }
/* One that has found its song stays readable but stops asking for attention. */
.render-row.used { opacity: 0.62; }
.render-row.used:hover { opacity: 1; }

.render-name {
  display: block;
  font-weight: 650;
  cursor: text;
  border-bottom: 1px solid transparent;
}
.render-name:hover { border-bottom-color: var(--line-2); }
.render-row .s {
  display: block;
  font-size: 12px;
  color: var(--text-3);
  margin-top: 1px;
}
.render-row .s b { color: var(--text-2); font-weight: 650; }

.icon-btn.play {
  background: var(--elevated);
  color: var(--text);
  flex: none;
}
.icon-btn.play:hover { background: var(--accent); color: var(--text-on-accent); }
.icon-btn.play.sm { width: 30px; height: 30px; }

/* ── picking: a song for a render, or a render for a song ─────────────────── */

.pick-list {
  max-height: 46vh;
  overflow-y: auto;
  margin-top: var(--s2);
  /* Its own scroll, so the sheet keeps its buttons on screen with fifty songs in it. */
  padding-right: 2px;
}

.pick-row {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%;
  padding: var(--s2) var(--s3);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--fast), border-color var(--fast);
}
.pick-row:hover { background: var(--hover); border-color: var(--line); }
.pick-row .grow { min-width: 0; flex: 1; display: block; }
.pick-row .t { display: block; font-weight: 650; }
.pick-row .s { display: block; font-size: 12px; color: var(--text-3); }

.pick-row.new {
  background: var(--accent-soft);
  border-color: var(--accent-line);
}
.pick-row.new:hover { background: rgba(84, 179, 122, 0.2); }
.pick-plus {
  display: grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: 20px; font-weight: 600; line-height: 1;
}

.pick-go {
  flex: none;
  font-size: 12px;
  font-weight: 650;
  color: var(--text-3);
  padding: 5px var(--s3);
  border-radius: var(--r-pill);
  background: var(--elevated);
}
.pick-row:hover .pick-go { background: var(--accent); color: var(--text-on-accent); }

.cover.sm { width: 38px; height: 38px; }

/* ── how many are still waiting, on the rail ──────────────────────────────── */

.nav-badge {
  margin-left: auto;
  min-width: 20px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: 11px;
  font-weight: 700;
  line-height: 19px;
  text-align: center;
}

@media (max-width: 900px) {
  /* On a phone the buttons come off the row rather than squeezing the name to nothing. */
  .render-row { flex-wrap: wrap; }
  .render-row .grow { flex: 1 1 60%; }
  .render-row .btn { flex: 1 1 auto; }
}


/* 50-song.css */
/* The song page.
 *
 * One page, read top to bottom, with no tabs. Everything a song has sits in its own
 * place: the cover, the name, the version, then the words, then the sound, then the
 * renders. Nothing is behind a button that only says what is behind it.
 *
 * The things themselves are the controls. The title is an editable line, not a Rename
 * button. The cover takes a pen when you point at it. The version reads as a version and
 * opens the list when you press it.
 */

/* ── the header ───────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  /* Out past the view's padding, so the artwork reaches the panel edges. */
  margin: calc(var(--s2) * -1) calc(var(--s5) * -1) var(--s6);
  padding: var(--s8) var(--s5) var(--s6);
  isolation: isolate;
  /* The artwork behind this is deliberately larger than the header so the blur has no
     hard edge. Without clipping it here that overhang becomes page width, and the whole
     library scrolls sideways. */
  overflow: hidden;
}

/* The song's own artwork, enormous and out of focus, moving slower than the page.
   It is the only decoration on the page and it is made of the song's own content. */
.hero-art {
  position: absolute;
  inset: -30% -15% -10%;
  z-index: -2;
  background-size: cover;
  background-position: center;
  filter: blur(64px) saturate(170%);
  opacity: 0.5;
  transform: translate3d(0, 0, 0) scale(1.3);
  will-change: transform;
}
.hero-art.flat {
  /* No artwork yet: a wash built from the title, so the page still has a temperature. */
  background-image: radial-gradient(120% 90% at 20% 0%,
      hsl(var(--hue) 40% 28%), transparent 70%),
    radial-gradient(120% 90% at 90% 20%,
      hsl(calc(var(--hue) + 48) 35% 22%), transparent 65%);
  filter: blur(40px);
}
.hero-veil {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--surface) 30%, transparent) 0%,
    color-mix(in srgb, var(--surface) 72%, transparent) 45%,
    var(--surface) 96%);
}

.hero-row { display: flex; gap: var(--s6); align-items: flex-end; }

/* The cover, and the pen that appears on it. */
.cover-edit {
  position: relative;
  width: clamp(132px, 19vw, 208px);
  aspect-ratio: 1;
  border: 0; padding: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  cursor: pointer;
  flex: none;
  background: none;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  transition: transform var(--fast);
}
.cover-edit .cover { width: 100%; height: 100%; border-radius: var(--r-lg); }
.cover-edit:hover { transform: translateY(-2px); }
.cover-pen {
  position: absolute; top: var(--s2); right: var(--s2);
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(10, 13, 11, 0.66);
  backdrop-filter: blur(6px);
  color: #fff;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity var(--fast), transform var(--fast);
}
.cover-edit:hover .cover-pen,
.cover-edit:focus-visible .cover-pen { opacity: 1; transform: none; }

.hero-meta { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--s3); }

/* The name. Bigger and bolder than anything else in the product, because it is the
   thing the page is about. */
.song-title {
  font-family: var(--display);
  font-size: clamp(38px, 6.4vw, 84px);
  font-weight: 900;
  line-height: 0.94;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--text);
  word-break: break-word;
  cursor: text;
  border-radius: var(--r-sm);
  transition: background var(--fast);
}
.song-title:hover { background: rgba(255, 255, 255, 0.05); }
.song-title-input {
  font-family: var(--display);
  font-size: clamp(38px, 6.4vw, 84px);
  font-weight: 900;
  line-height: 0.94;
  letter-spacing: -0.03em;
  width: 100%;
  background: rgba(0, 0, 0, 0.25);
  border: 0;
  border-bottom: 2px solid var(--accent);
  color: var(--text);
  padding: 0;
  outline: none;
}

/* Every name it used to have, the way an account remembers its old handles. */
.also-known {
  position: relative;
  align-self: flex-start;
  font-size: 12.5px;
  color: var(--text-3);
  background: none; border: 0; padding: 2px 0;
  cursor: pointer;
  text-align: left;
}
.also-known:hover { color: var(--text-2); }
.also-known b { font-weight: 600; color: var(--text-2); }
.name-list {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  min-width: 230px;
  background: var(--elevated);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  padding: var(--s2);
  animation: pop 140ms var(--ease);
}
@keyframes pop { from { opacity: 0; transform: translateY(-4px); } }
.name-list li {
  display: flex; justify-content: space-between; gap: var(--s4);
  padding: 6px var(--s3); border-radius: var(--r-sm);
  font-size: 13px;
}
.name-list ul { list-style: none; margin: 0; padding: 0; }
.name-list .when { color: var(--text-3); font-size: 11.5px; white-space: nowrap; }

.hero-line { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.hero-facts { display: flex; align-items: center; gap: var(--s2); color: var(--text-2); font-size: 13.5px; }
.hero-facts .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-3); }
.hero-facts a:hover { color: var(--text); text-decoration: underline; }

/* The version reads as a version and opens the list. Not a button labelled Versions. */
.version-pick {
  display: inline-flex; align-items: center; gap: 7px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  padding: 5px var(--s3) 5px var(--s4);
  font-family: var(--display);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.01em;
  color: var(--text);
  cursor: pointer;
  transition: background var(--fast), border-color var(--fast);
}
.version-pick:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--accent-line); }
.version-pick .caret { opacity: 0.5; }

/* ── the blocks below ─────────────────────────────────────────────────────── */
.block { margin-bottom: var(--s8); scroll-margin-top: var(--s5); }
.block-head {
  display: flex; align-items: center; gap: var(--s3);
  margin-bottom: var(--s4);
}
.block-head h2 {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}
.block-head .grow { flex: 1; }
.block-tools { display: flex; align-items: center; gap: var(--s2); opacity: 0; transition: opacity var(--fast); }
.block:hover .block-tools, .block:focus-within .block-tools { opacity: 1; }

/* ── A and B, in the header ───────────────────────────────────────────────── */
.ab-inline { display: flex; align-items: stretch; gap: var(--s2); flex-wrap: wrap; }
.slot-pick {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--s2);
  min-width: 148px;
  padding: 7px var(--s3) 7px var(--s2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  text-align: left;
  transition: background var(--fast), border-color var(--fast);
}
.slot-pick:hover { background: rgba(255, 255, 255, 0.12); }
.slot-pick .k {
  display: grid; place-items: center;
  width: 22px; height: 22px; flex: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  font-family: var(--display); font-weight: 800; font-size: 11px;
}
.slot-pick .v { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slot-pick .caret { opacity: 0.45; flex: none; }
/* The side you are actually hearing. */
.slot-pick.live { border-color: var(--accent); background: var(--accent-soft); }
.slot-pick.live .k { background: var(--accent); color: var(--text-on-accent); }

.ab-switch {
  display: grid; place-items: center;
  width: 40px; flex: none;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-2);
  cursor: pointer;
  transition: background var(--fast), color var(--fast), transform var(--fast);
}
.ab-switch:hover { background: var(--accent-soft); color: var(--accent-hi); }
.ab-switch:active { transform: scale(0.94); }

/* One menu for both things a slot carries. */
/* Placed on the body rather than inside the header.
   .hero clips its children so the oversized blurred artwork has no hard edge, and that
   clipping took the dropdown with it: the menu opened inside the header and was cut off
   at its bottom edge. Fixed positioning puts it above every stacking context there is. */
.slot-menu {
  position: fixed; z-index: 80;
  min-width: 260px; max-height: 320px; overflow-y: auto;
  background: var(--elevated);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  padding: var(--s2);
  animation: pop 140ms var(--ease);
  cursor: default;
}
.menu-group {
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-3); padding: var(--s3) var(--s3) var(--s2);
}
.menu-row {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  padding: 7px var(--s3);
  border: 0; border-radius: var(--r-sm);
  background: none; color: var(--text-2);
  font-size: 13px; text-align: left; cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.menu-row:hover { background: var(--hover); color: var(--text); }
.menu-row.on { background: var(--accent-soft); color: var(--accent-hi); }
.menu-row .tagline {
  font-family: var(--display); font-weight: 800; font-size: 12px;
  min-width: 30px; flex: none;
}
.menu-row .grow { flex: 1; min-width: 0; }
.menu-row .when { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.menu-row.add { color: var(--text-3); }
.menu-row.add:hover { color: var(--accent-hi); }
/* Taking a render away lives on its row, since the section that used to hold that is
   gone and a render is the only thing that knows which render it is. */
.row-drop {
  display: grid; place-items: center;
  width: 20px; height: 20px; flex: none;
  border: 0; border-radius: 50%;
  background: none; color: var(--text-3);
  cursor: pointer; opacity: 0;
  transition: opacity var(--fast), background var(--fast), color var(--fast);
}
.menu-row:hover .row-drop { opacity: 1; }
.row-drop:hover { background: rgba(212, 104, 94, 0.16); color: var(--bad); }

/* ── lyrics, as cards you move between ───────────────────────────────────── */
.lyric-deck {
  display: flex; align-items: center; gap: var(--s3);
  justify-content: center;
}
.deck-window {
  flex: 1;
  /* Wide enough that a long line of a verse is a line rather than a wrap. The cards are
     the middle of the page, so they get the room the page has. */
  max-width: 940px;
  overflow: hidden;
  border-radius: var(--r-lg);
  touch-action: pan-y;          /* vertical scrolling still belongs to the page */
}
.deck-track { display: flex; will-change: transform; }

.lyric-card {
  flex: 0 0 100%;
  min-width: 100%;
  padding: var(--s6);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  border: 1px solid var(--line);
  opacity: 0.55;
  transform: scale(0.985);
  transition: opacity var(--med), transform var(--med);
}
.lyric-card.on { opacity: 1; transform: none; }
.lyric-card.reading { border-color: var(--accent-line); }
.lyric-card.editing { opacity: 1; transform: none; }

.card-title {
  font-family: var(--display);
  font-size: 22px; font-weight: 800; letter-spacing: -0.02em;
  margin: 0 0 var(--s4);
  color: var(--text);
}
.card-body {
  font-size: 16.5px; line-height: 1.85;
  color: var(--text);
  min-height: 120px;
  cursor: text;
  border-radius: var(--r-sm);
}
.card-body.empty-words { color: var(--text-3); font-style: italic; }

/* Markdown output. Every line is a line: a verse is not a paragraph to be reflowed. */
.md-line { min-height: 1.85em; }
.md-gap { height: 0.9em; }
.card-body h1, .card-body h2, .card-body h3,
.card-body h4, .card-body h5, .card-body h6 {
  font-family: var(--display); font-weight: 700; letter-spacing: -0.01em;
  margin: var(--s4) 0 var(--s2); font-size: 17px; color: var(--text);
}
.card-body ul, .card-body ol { margin: var(--s2) 0; padding-left: var(--s5); }
.card-body blockquote {
  margin: var(--s3) 0; padding-left: var(--s4);
  border-left: 2px solid var(--accent-line); color: var(--text-2);
}
.card-body blockquote p { margin: 0; }
.card-body hr { border: 0; border-top: 1px solid var(--line-2); margin: var(--s4) 0; }
.card-body code {
  font-size: 0.9em; background: var(--bg); padding: 1px 5px; border-radius: var(--r-sm);
}
.card-body a { color: var(--accent-hi); text-decoration: underline; }

textarea.card-edit {
  width: 100%; min-height: 340px;
  font: inherit; font-size: 16px; line-height: 1.85;
  background: var(--bg);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  padding: var(--s4);
  color: var(--text);
  outline: none; resize: vertical;
}
.card-foot { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3); }

.deck-arrow {
  display: grid; place-items: center;
  width: 40px; height: 40px; flex: none;
  border: 1px solid var(--line-2); border-radius: 50%;
  background: var(--surface-2); color: var(--text-2);
  cursor: pointer;
  transition: background var(--fast), color var(--fast), opacity var(--fast);
}
.deck-arrow:hover { background: var(--elevated); color: var(--text); }
.deck-arrow[disabled] { opacity: 0.25; cursor: default; }

.deck-dots { display: flex; justify-content: center; gap: 6px; margin-top: var(--s4); }
.deck-dot {
  width: 7px; height: 7px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--line-2);
  cursor: pointer;
  transition: background var(--fast), width var(--fast);
}
.deck-dot.on { background: var(--accent); width: 22px; border-radius: var(--r-pill); }

/* Looking at an old version is looking, not restoring. */
.time-bar {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s4);
  border-radius: var(--r-md);
  background: rgba(217, 164, 65, 0.1);
  border: 1px solid rgba(217, 164, 65, 0.3);
  font-size: 13px;
}
.time-bar .grow { flex: 1; }

.history-rail {
  display: flex; flex-direction: column; gap: 1px;
  max-height: 300px; overflow-y: auto;
  max-width: 640px; margin: var(--s5) auto 0;
}
.history-entry {
  display: flex; align-items: center; gap: var(--s3);
  padding: 7px var(--s3);
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: 13px; color: var(--text-2);
  transition: background var(--fast), color var(--fast);
}
.history-entry:hover { background: var(--hover); color: var(--text); }
.history-entry.on { background: var(--accent-soft); color: var(--accent-hi); }
.history-entry .when { font-variant-numeric: tabular-nums; }
.history-entry .grow { flex: 1; }
.history-entry .size { color: var(--text-3); font-size: 11.5px; }

/* ── versions ─────────────────────────────────────────────────────────────── */
.ab-bar {
  display: grid; grid-template-columns: 1fr auto 1fr;
  gap: var(--s3); align-items: stretch; margin-bottom: var(--s4);
}
.ab-slot {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  padding: var(--s4) var(--s5);
  cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
  text-align: left;
}
.ab-slot:hover { background: var(--elevated); }
.ab-slot.on { border-color: var(--accent); background: var(--accent-soft); }
.ab-slot .k { font-size: 11px; font-weight: 700; letter-spacing: 0.16em; color: var(--text-3); }
.ab-slot.on .k { color: var(--accent-hi); }
.ab-slot .v { font-family: var(--display); font-size: 22px; font-weight: 800; letter-spacing: -0.02em; }
.ab-slot .d { font-size: 12px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.ab-mid { display: grid; place-items: center; gap: var(--s2); }
.ab-hint { font-size: 11.5px; color: var(--text-3); text-align: center; }

.version-row {
  display: grid;
  grid-template-columns: 62px 1fr 92px 58px auto;
  align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background var(--fast);
}
.version-row:hover { background: var(--hover); }
.version-row.current { background: var(--accent-soft); }
.version-row .n { font-family: var(--display); font-weight: 800; font-size: 15px; }
/* The name the file arrived under. Six renders later it is often the only thing
   that says which session it came out of, so it is the line, not a footnote. */
.version-row .og-name { display: block; font-size: 13.5px; color: var(--text); }
.version-row.current .n { color: var(--accent-hi); }
.version-row .when, .version-row .dur { font-size: 12.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.version-row .acts { display: flex; gap: var(--s1); opacity: 0; transition: opacity var(--fast); }
.version-row:hover .acts, .version-row:focus-within .acts { opacity: 1; }

/* ── artwork strip ────────────────────────────────────────────────────────── */
.art-strip { display: flex; gap: var(--s2); flex-wrap: wrap; }
.art-tile {
  position: relative; width: 92px; height: 92px;
  border-radius: var(--r-md); overflow: hidden; cursor: pointer;
}
.art-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.art-tile .drop {
  position: absolute; inset: auto 0 0 0;
  display: flex; justify-content: center; gap: var(--s1); padding: 4px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
  opacity: 0; transition: opacity var(--fast);
}
.art-tile:hover .drop { opacity: 1; }
.art-tile.is-cover { outline: 2px solid var(--accent); outline-offset: -2px; }
.art-add {
  width: 92px; height: 92px;
  border: 1.5px dashed var(--line-2);
  border-radius: var(--r-md);
  background: none; color: var(--text-3);
  display: grid; place-items: center;
  cursor: pointer;
  transition: border-color var(--fast), color var(--fast);
}
.art-add:hover { border-color: var(--accent); color: var(--accent-hi); }

/* ── phone ────────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  .hero { padding: var(--s6) var(--s4) var(--s5); margin-inline: calc(var(--s4) * -1); }
  .hero-row { flex-direction: column; align-items: flex-start; gap: var(--s4); }
  .cover-edit { width: 132px; }
  .song-title { font-size: clamp(30px, 11vw, 46px); }
  .song-title-input { font-size: clamp(30px, 11vw, 46px); }

  /* A and B go full width and stack, so neither is a squeezed chip. */
  .ab-inline { width: 100%; display: grid; grid-template-columns: 1fr auto 1fr; }
  .slot-pick { min-width: 0; }
  .slot-menu { left: 0; right: auto; min-width: min(280px, 84vw); }
  .slot-pick[data-slot="B"] .slot-menu { left: auto; right: 0; }

  .block { margin-bottom: var(--s7); }
  /* Nothing to hover with on a phone, so the tools are always shown, and they take
     their own line rather than running off the edge of the screen. */
  .block-head { flex-wrap: wrap; }
  .block-tools { opacity: 1; width: 100%; flex-wrap: wrap; }
  .block-head .grow { display: none; }
  .preset-row { width: 100%; }

  /* The deck fills the width and the arrows step aside for the swipe. */
  .deck-arrow { display: none; }
  .deck-window { max-width: none; }
  .lyric-card { padding: var(--s4); }
  .card-title { font-size: 19px; }
  .card-body { font-size: 16px; }
  .deck-dot { width: 9px; height: 9px; }
  .deck-dot.on { width: 26px; }

  .version-row { grid-template-columns: 52px 1fr auto; }
  .version-row .when, .version-row .dur { display: none; }
  .version-row .acts { opacity: 1; }

  .ab-bar { grid-template-columns: 1fr; }
  .ab-mid { padding: var(--s2) 0; }

  .art-tile, .art-add { width: 76px; height: 76px; }
  .time-bar { font-size: 12.5px; }
}


/* 60-player.css */
/* The player: docked, and able to grow into the version comparison workspace. */

.player {
  grid-area: player;
  height: var(--player-h);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 0 var(--s5);
  display: grid;
  grid-template-columns: minmax(180px, 1fr) minmax(280px, 2.2fr) minmax(180px, 1fr);
  align-items: center;
  gap: var(--s4);
}

.now-playing { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
.now-playing .cover { width: 52px; height: 52px; border-radius: var(--r-md); }
.now-playing .t { font-weight: 700; font-size: 13.5px; }
.now-playing .s { font-size: 12px; color: var(--text-3); }

.transport { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
.transport-row { display: flex; align-items: center; gap: var(--s2); }

.scrubber { display: flex; align-items: center; gap: var(--s3); width: 100%; }
.scrubber .t { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; width: 38px; flex: none; }
.scrubber .t.right { text-align: right; }
.bar {
  position: relative; flex: 1; height: 14px;
  display: flex; align-items: center;
  cursor: pointer;
}
.bar .track-line { position: absolute; inset: 5px 0; height: 4px; border-radius: var(--r-pill); background: var(--elevated); }
.bar .fill { position: absolute; left: 0; top: 5px; height: 4px; border-radius: var(--r-pill); background: var(--text-2); }
.bar .knob {
  position: absolute; top: 2px; width: 10px; height: 10px; margin-left: -5px;
  border-radius: 50%; background: var(--text);
  opacity: 0; transition: opacity var(--fast);
}
.bar:hover .fill, .bar.scrubbing .fill { background: var(--accent); }
.bar:hover .knob, .bar.scrubbing .knob { opacity: 1; }
.bar .buffered { position: absolute; left: 0; top: 5px; height: 4px; border-radius: var(--r-pill); background: rgba(255,255,255,0.09); }

.player-right { display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); }
.volume { display: flex; align-items: center; gap: var(--s2); width: 108px; }

/* The A and B chips live in the player, because comparing versions is a thing you do
   while listening rather than a thing you go to a page for. */
.ab-chips { display: flex; gap: 4px; align-items: center; }
.ab-chip {
  min-width: 34px; height: 26px; padding: 0 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text-2);
  font-size: 11.5px; font-weight: 700;
  cursor: pointer;
  transition: background var(--fast), color var(--fast), border-color var(--fast);
}
.ab-chip:hover { border-color: var(--accent-line); color: var(--text); }
.ab-chip.on { background: var(--accent); border-color: var(--accent); color: var(--text-on-accent); }
.ab-chip[disabled] { opacity: 0.4; cursor: default; }

/* ── expanded ─────────────────────────────────────────────────────────────── */
.stage {
  position: fixed; inset: var(--s2) var(--s2) calc(var(--player-h) + var(--s3)) var(--s2);
  z-index: 50;
  background: var(--surface);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  display: flex; flex-direction: column;
  overflow: hidden;
  animation: stage-in 240ms var(--ease);
}
@keyframes stage-in { from { opacity: 0; transform: translateY(18px); } }
.stage-head {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.stage-body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--s5); }
.stage-grid {
  display: grid; grid-template-columns: minmax(220px, 320px) 1fr; gap: var(--s6);
  align-items: start;
}
.stage-grid .cover { width: 100%; aspect-ratio: 1; border-radius: var(--r-lg); box-shadow: var(--shadow-2); }
@media (max-width: 820px) {
  .stage-grid { grid-template-columns: 1fr; }
  .stage-grid .cover { max-width: 220px; }
}

@media (max-width: 760px) {
  .player { grid-template-columns: 1fr auto; grid-template-rows: auto auto; gap: var(--s2) var(--s3); height: auto; padding: var(--s3) var(--s4); }
  .player .transport { grid-column: 1 / -1; order: 3; }
  .player-right .volume { display: none; }
  :root { --player-h: 116px; }
}


/* 70-eq.css */
/* The equaliser and the limiter.
 *
 * Both are displays you work on rather than banks of sliders. The equaliser is a curve
 * you place points on; the limiter is a meter with the two deciding lines drawn on it.
 * Everything that can be dragged with a mouse can be dragged with a thumb, which is why
 * Q lives on a knob rather than only on the scroll wheel.
 */

/* ── presets ──────────────────────────────────────────────────────────────── */
/* A row where one is chosen. This lived in the lyrics stylesheet until that file was
   rewritten around it, at which point the preset names became unstyled default buttons:
   white squares on a dark panel. It belongs next to the thing that uses it. */
.sheet-tabs { display: flex; align-items: center; gap: var(--s1); flex-wrap: wrap; }
.sheet-tab {
  background: none;
  border: 0;
  color: var(--text-3);
  font-size: 13px; font-weight: 600;
  padding: 4px var(--s3);
  border-radius: var(--r-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--fast), background var(--fast);
}
.sheet-tab:hover { color: var(--text); background: var(--hover); }
.sheet-tab.on { color: var(--accent-hi); background: var(--accent-soft); }

.preset-row { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.preset-tools {
  display: inline-flex; align-items: center; gap: 1px;
  margin-left: var(--s2); padding-left: var(--s2);
  border-left: 1px solid var(--line);
}
.icon-btn.tiny { width: 28px; height: 28px; }

/* ── the curve ────────────────────────────────────────────────────────────── */
.eq-wrap {
  position: relative;
  border-radius: var(--r-lg);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  overflow: hidden;
  user-select: none;
  touch-action: none;
}
.eq-canvas { display: block; width: 100%; height: 300px; cursor: crosshair; }
.eq-canvas.dragging { cursor: grabbing; }

.eq-readout {
  position: absolute; top: var(--s3); left: var(--s4);
  display: flex; gap: var(--s4);
  font-size: 11.5px; color: var(--text-3);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.eq-readout b { color: var(--text); font-weight: 600; }

.eq-hint {
  position: absolute; right: var(--s4); bottom: var(--s3);
  font-size: 11px; color: var(--text-3);
  pointer-events: none;
}

.eq-toolbar {
  display: flex; align-items: center; gap: var(--s2);
  flex-wrap: wrap;
  margin: var(--s4) 0;
}

/* ── one card per band, with a knob for Q ─────────────────────────────────── */
.band-list {
  display: flex; gap: var(--s2);
  overflow-x: auto;
  padding-bottom: var(--s2);
  scroll-snap-type: x proximity;
}
.band-card {
  flex: none; width: 156px;
  background: var(--surface-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: var(--s3);
  cursor: pointer;
  scroll-snap-align: start;
  transition: border-color var(--fast), background var(--fast);
}
.band-card:hover { background: var(--elevated); }
.band-card.on { border-color: var(--accent); }
.band-card.off { opacity: 0.45; }
.band-card .head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.band-card .kind {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-3);
}
.band-card .freq {
  font-family: var(--display); font-weight: 800; font-size: 19px;
  letter-spacing: -0.02em; margin-top: 2px;
}
.band-card .freq .unit { font-family: var(--font); font-size: 11px; color: var(--text-3); margin-left: 3px; }
.band-bottom { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-top: 2px; }
.band-card .gain { font-size: 12px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.band-card select {
  width: 100%; margin-top: var(--s2);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 4px 6px; font-size: 11.5px; color: var(--text-2); outline: none;
}
.band-card .band-remove { width: 100%; margin-top: 6px; height: 26px; }

/* Q, as a dial you turn. The wheel still works, but a thumb has no wheel. */
.q-knob {
  position: relative;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  cursor: ns-resize;
  touch-action: none;
  flex: none;
}
.q-knob svg { display: block; }
.q-knob .q-value {
  position: absolute;
  font-size: 9px; font-weight: 700; color: var(--text-2);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.q-knob.turning .q-value, .q-knob:hover .q-value { color: var(--text); }
.q-knob:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 50%; }

.switch.tiny { width: 30px; height: 17px; }
.switch.tiny::after { width: 11px; height: 11px; }
.switch.tiny.on::after { transform: translateX(13px); }

/* ── the limiter ──────────────────────────────────────────────────────────── */
.limiter-head {
  display: flex; align-items: center; gap: var(--s3);
  margin: var(--s7) 0 var(--s3);
}
.limiter-head h3 {
  font-family: var(--display); font-size: 13px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-3);
}
.limiter-head .grow { flex: 1; }
.limiter-nums {
  display: flex; gap: var(--s4);
  font-size: 11.5px; color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.limiter-nums b { color: var(--text-2); font-weight: 600; }

.limiter-wrap {
  position: relative;
  border-radius: var(--r-lg);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  overflow: hidden;
  user-select: none;
  touch-action: none;
}
.limiter-canvas { display: block; width: 100%; height: 180px; }
.limiter-hint {
  position: absolute; right: var(--s4); bottom: var(--s3);
  font-size: 11px; color: var(--text-3); pointer-events: none;
}

.limiter-knobs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s4) var(--s5);
  margin-top: var(--s4);
}
.knob-row { display: flex; flex-direction: column; gap: 4px; }
.knob-row .lab { display: flex; justify-content: space-between; align-items: baseline; }
.knob-row .lab span:first-child { font-size: 12.5px; color: var(--text-2); }
.knob-row .lab b { font-size: 12.5px; font-variant-numeric: tabular-nums; font-weight: 600; }

.sound-note { margin-top: var(--s4); font-size: 12.5px; color: var(--text-3); }

/* ── phone ────────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  .eq-canvas { height: 210px; }
  .limiter-canvas { height: 150px; }
  .eq-hint, .limiter-hint { display: none; }
  .eq-toolbar { gap: 6px; }
  .eq-toolbar .btn { flex: 1 1 auto; }
  /* Cards get wider and snap, so one thumb swipe lands on one band. */
  .band-card { width: 60vw; max-width: 220px; }
  .q-knob { width: 42px; height: 42px; }
  .q-knob svg { width: 42px; height: 42px; }
}


/* 80-sheet.css */
/* Dialogs. One shape, centred, and it closes on Escape or a click outside. */

.sheet-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0, 0, 0, 0.6);
  display: grid; place-items: center;
  padding: var(--s4);
  animation: fade-in 140ms var(--ease);
}
@keyframes fade-in { from { opacity: 0; } }

.sheet {
  width: min(520px, 100%);
  max-height: 84dvh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  padding: var(--s6);
  animation: sheet-in 200ms var(--ease);
}
.sheet.wide { width: min(760px, 100%); }
@keyframes sheet-in { from { opacity: 0; transform: translateY(14px) scale(0.98); } }

.sheet h2 { margin-bottom: var(--s2); }
.sheet .sub { color: var(--text-2); margin-bottom: var(--s5); }
.sheet-fields { display: flex; flex-direction: column; gap: var(--s4); }
.sheet-label { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; color: var(--text-2); font-weight: 600; }
.sheet-foot { display: flex; justify-content: flex-end; gap: var(--s2); margin-top: var(--s6); }

.candidate {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-md);
  background: var(--surface-2);
  margin-bottom: var(--s2);
}
.candidate .grow { min-width: 0; }
.candidate .name { font-weight: 600; font-size: 13.5px; }
.candidate .path { font-size: 11.5px; color: var(--text-3); }
