/* 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. */
.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);
  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 {
  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; }
}


/* 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; }

/* ── lyrics ───────────────────────────────────────────────────────────────── */
/* The words are the control. Click them and they become editable in place. */
.lyrics {
  font-size: 17px;
  line-height: 1.9;
  max-width: 56ch;
  white-space: pre-wrap;
  color: var(--text);
  min-height: 72px;
  padding: var(--s3);
  margin: calc(var(--s3) * -1);
  border-radius: var(--r-md);
  cursor: text;
  transition: background var(--fast);
}
.lyrics:hover { background: rgba(255, 255, 255, 0.035); }
.lyrics.empty-words { color: var(--text-3); font-style: italic; }
.lyrics.reading { cursor: default; opacity: 0.85; }

textarea.lyrics-edit {
  font-size: 17px; line-height: 1.9;
  max-width: 56ch; width: 100%;
  min-height: 320px;
  background: var(--bg);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  padding: var(--s3);
  color: var(--text);
  outline: none;
  resize: vertical;
}

.sheet-tabs { display: flex; align-items: center; gap: var(--s1); }
.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;
  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); }

/* 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: 320px; overflow-y: auto; }
.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; }
.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); }

@media (max-width: 720px) {
  .hero { padding-top: var(--s6); }
  .hero-row { flex-direction: column; align-items: flex-start; gap: var(--s4); }
  .version-row { grid-template-columns: 54px 1fr auto; }
  .version-row .when, .version-row .dur { display: none; }
}


/* 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.

   A display you draw on rather than a bank of sliders: drag a node anywhere, add one
   where you need it, and the curve is the sum of what you have made. The analyser sits
   behind the curve so you can see what you are cutting. */

.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(--s3);
  flex-wrap: wrap;
  margin: var(--s4) 0;
}

/* The row of bands under the display, one card each. */
.band-list { display: flex; gap: var(--s2); overflow-x: auto; padding-bottom: var(--s2); }
.band-card {
  flex: none; width: 148px;
  background: var(--surface-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: var(--s3);
  cursor: pointer;
  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: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); }
.band-card .freq { font-family: var(--display); font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
.band-card .nums { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; margin-top: 2px; }
.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;
}

.limiter-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s4) var(--s5);
  margin-top: var(--s3);
}
.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; }

.gr-meter {
  height: 8px; border-radius: var(--r-pill);
  background: var(--elevated);
  overflow: hidden;
}
.gr-meter i {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--accent), var(--warn));
  transition: width 60ms linear;
}

.sound-note {
  margin-top: var(--s4);
  font-size: 12.5px;
  color: var(--text-3);
}


/* 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); }
