/* ==========================================================================
   DJ SWIRL — stylesheet
   1. tokens     2. base      3. layout    4. sidebar   5. topbar
   6. tracks     7. hero      8. cards     9. player   10. queue
   11. pages    12. states   13. motion   14. responsive
   ========================================================================== */

/* 1. tokens ─────────────────────────────────────────────────────────────── */
:root {
  /* pulled from the DJ Swirl artwork: deep purple + mint */
  --bg:            #0a0810;
  --bg-1:          #100b18;
  --bg-2:          #171021;
  --bg-3:          #1f172c;
  --line:          #2a2038;
  --line-soft:     #1c1528;

  --text:          #f4f1f8;
  --text-2:        #a99fb8;
  --text-3:        #7b7189;

  --accent:        #6ee7d0;   /* mint  — primary action */
  --accent-hi:     #9df2e2;
  --accent-ink:    #05231d;
  --accent-soft:   rgba(110, 231, 208, .13);
  --accent-line:   rgba(110, 231, 208, .38);

  --violet:        #b45cff;   /* purple — brand glow */
  --violet-soft:   rgba(180, 92, 255, .16);

  /* frequency bands, deepest to highest */
  --f-sub:         #7b5cff;   /* subsonic, under 20 Hz */
  --f-20:          #b45cff;   /* 20–24 Hz */
  --f-25:          #5b9dff;   /* 25–29 Hz */
  --f-30:          #22d3ee;   /* 30–34 Hz */
  --f-35:          #3ddc84;   /* 35–39 Hz */
  --f-40:          #ffb03d;   /* 40 Hz and up */

  --warn:          #ffb03d;
  --love:          #ff5d8f;

  --danger:        #ff5f57;

  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;
  --r-xl: 26px;
  --r-full: 999px;

  --rail-w: 250px;
  --dock-h: 112px;
  --topbar-h: 68px;

  /* How much of the screen the phone keeps for itself.
     Installed on an iPhone the page owns every pixel, status bar and Dynamic
     Island included, so anything pinned to an edge has to be told to stay out
     of the way — otherwise the search field sits underneath the clock and the
     battery, looks fine, and cannot be tapped at all. Zero on a desktop, and
     zero on the Androids that have nothing in the way. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  /* What the dock really occupies, for the things that float above it. */
  --dock-space: calc(var(--dock-h) + var(--safe-b));

  --shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --shadow-2: 0 14px 34px -14px rgba(0,0,0,.8);
  --shadow-3: 0 28px 70px -22px rgba(0,0,0,.9);
  --glow:     0 0 40px -6px rgba(180, 92, 255, .45);

  --ease: cubic-bezier(.2, .7, .3, 1);
  --spring: cubic-bezier(.34, 1.4, .5, 1);
  --fast: 130ms var(--ease);
  --base: 240ms var(--ease);

  --font:    "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --display: "Anton", "DM Sans", Impact, sans-serif;
  --mono:    "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* live sub-bass level, written by the player (0 → 1) */
  --bass: 0;
}

/* 2. base ───────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

/* The grey rectangle iOS flashes over whatever you touch. Every control here
   has an :active state of its own, so the flash is only ever noise. */
* { -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}

[hidden] { display: none !important; }

/* Safari on iOS, and nothing else: the callout property has never existed
   anywhere but there, which makes it the honest way to ask. */
@supports (-webkit-touch-callout: none) {
  /* Focus a field smaller than sixteen pixels and iOS zooms the whole page in
     to read it, then leaves you scrolled sideways with the layout broken. The
     only cure is to be sixteen. */
  input, select, textarea { font-size: 16px; }
  /* Momentum scrolling inside the panels, not just on the page. */
  .view, .rail, .queue__list { -webkit-overflow-scrolling: touch; }
}

/* With the grey flash gone, a press has to show somewhere. Only on touch, so a
   mouse still gets hover instead. */
@media (hover: none) {
  .track:active, .card:active, .artist-tile:active, .folder:active { opacity: .72; }
  .btn:active, .icon-btn:active, .chip:active, .tab:active { transform: scale(.96); }
}

h1, h2, h3, h4, p, ol, ul, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button, input { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
svg { display: block; }
img { display: block; max-width: 100%; }

::selection { background: var(--accent); color: var(--accent-ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: fixed; top: calc(10px + var(--safe-t)); left: calc(10px + var(--safe-l)); z-index: 100;
  padding: 10px 16px; border-radius: var(--r);
  background: var(--accent); color: var(--accent-ink); font-weight: 700;
  transform: translateY(-200%);
  transition: transform var(--fast);
}
.skip-link:focus { transform: none; }

* { scrollbar-width: thin; scrollbar-color: var(--bg-3) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: var(--bg-3); border-radius: 99px; border: 3px solid var(--bg);
}
*::-webkit-scrollbar-thumb:hover { background: #2c2140; }

/* 3. layout ─────────────────────────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas: "rail main" "dock dock";
  height: 100dvh;
}

.main {
  position: relative;
  grid-area: main;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background:
    radial-gradient(1100px 460px at 82% -14%, rgba(180,92,255,.16), transparent 62%),
    radial-gradient(720px 360px at 4% -4%, rgba(110,231,208,.07), transparent 60%),
    var(--bg);
}

/* Behind the content and in front of the glow the page already had. It never
   takes a click and it never scrolls: the library moves over a still sky. */
.sky {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 0;
  pointer-events: none;
  --sky-hue: 262;
  --sky-energy: 0;
  background-image:
    radial-gradient(64% 48% at 16% 8%,
      hsla(var(--sky-hue), 82%, 56%, calc(.035 + .085 * var(--sky-energy))), transparent 70%),
    radial-gradient(56% 44% at 88% 82%,
      hsla(calc(var(--sky-hue) + 44), 78%, 54%, calc(.028 + .07 * var(--sky-energy))), transparent 72%);
}
/* The wash behind the stars goes with the motion. The system preference is the
   default; an explicit choice on the page overrides it either way. */
@media (prefers-reduced-motion: reduce) { :root:not([data-motion="full"]) .sky { background-image: none; } }
:root[data-motion="calm"] .sky { background-image: none; }

.view {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 32px 48px;
  scroll-behavior: smooth;
}
.view:focus { outline: none; }

.section { margin-top: 44px; }
.section:first-child { margin-top: 8px; }

.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.section__title {
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-2);
}

.section__count { font-family: var(--mono); font-size: 12px; color: var(--text-3); }

.link-btn { font-size: 13px; font-weight: 700; color: var(--text-2); transition: color var(--fast); }
.link-btn:hover { color: var(--accent); }

/* 4. sidebar ────────────────────────────────────────────────────────────── */
.rail {
  grid-area: rail;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: calc(20px + var(--safe-t)) 16px calc(18px + var(--safe-b)) calc(16px + var(--safe-l));
  background: linear-gradient(180deg, #130c1d, var(--bg-1) 40%);
  border-right: 1px solid var(--line-soft);
  overflow-y: auto;
}

.brand { display: flex; align-items: center; gap: 11px; padding: 0 6px 2px; }
.brand__logo {
  width: 42px; height: 42px; flex: none;
  border-radius: 11px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.06), var(--shadow-1);
  transition: transform var(--base);
}
.brand:hover .brand__logo { transform: rotate(-6deg) scale(1.06); }
.brand__text { display: flex; flex-direction: column; line-height: 1.05; }
.brand__text b { font-family: var(--display); font-size: 20px; letter-spacing: .01em; }
.brand__text i {
  font-style: normal; font-size: 9.5px; font-weight: 700;
  letter-spacing: .24em; text-transform: uppercase; color: var(--accent);
  margin-top: 4px;
}

.nav { display: flex; flex-direction: column; gap: 2px; }

.nav__item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  border-radius: var(--r);
  color: var(--text-2);
  font-weight: 500;
  position: relative;
  transition: color var(--fast), background var(--fast);
}
.nav__item svg { width: 19px; height: 19px; fill: currentColor; flex: none; opacity: .85; }
.nav__item:hover { color: var(--text); background: var(--bg-2); }
.nav__item[aria-current="page"] { color: var(--text); background: var(--bg-2); }
.nav__item[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 3px; height: 18px; margin-top: -9px;
  border-radius: 0 3px 3px 0; background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
}

.rail__section { display: flex; flex-direction: column; gap: 10px; }
.rail__title {
  font-family: var(--display);
  font-size: 12px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-3); padding: 0 12px;
}

.chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 8px; }

.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  font-family: var(--mono);
  font-size: 11.5px; font-weight: 500;
  color: var(--text-2);
  transition: border-color var(--fast), color var(--fast), background var(--fast);
}
.chip:hover { color: var(--text); border-color: #392b4d; }
.chip[aria-pressed="true"] {
  color: var(--text); border-color: transparent;
  background: color-mix(in srgb, var(--chip-color, var(--accent)) 20%, transparent);
}
.chip__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--chip-color, var(--accent)); }
.chip__n { color: var(--text-3); }

/* The extras pick one answer each, so no dot to suggest they stack. */
.chip--plain { gap: 6px; padding: 5px 10px; font-size: 11px; }
.chip--plain[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-line); }
.chip--plain:disabled { opacity: .38; cursor: default; }
.chip--plain:disabled:hover { color: var(--text-2); border-color: var(--line); }
#variant-chips, #format-chips { gap: 6px; }
#format-chips { margin-top: 6px; }

.rail__foot { margin-top: auto; display: flex; flex-direction: column; gap: 12px; padding: 0 10px; }

.status { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-3); }
.status__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-3); flex: none; }
.status__dot[data-state="loading"] { background: var(--warn); animation: pulse 1.4s infinite; }
.status__dot[data-state="ok"] { background: var(--accent); box-shadow: 0 0 10px var(--accent); }
.status__dot[data-state="error"] { background: var(--danger); }

@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }

.rail__legal { font-size: 11px; line-height: 1.5; color: #5d5470; }

/* 5. topbar ─────────────────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  /* Taller by exactly whatever the phone is holding back, and the extra is
     padding rather than height, so the blur reaches up behind the clock while
     the search field and the burger stay below it and stay tappable. */
  height: calc(var(--topbar-h) + var(--safe-t));
  padding: var(--safe-t) calc(32px + var(--safe-r)) 0 calc(32px + var(--safe-l));
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--base);
}
.topbar[data-scrolled="true"] { border-bottom-color: var(--line-soft); }
/* Two classes deep on purpose: `.icon-btn` sets display:grid further down the
   file, and at equal specificity the later rule wins. Without this the burger
   showed on desktop, where the sidebar is already open and pressing it only
   dimmed the screen. */
.topbar__menu.icon-btn { display: none; }

.search { position: relative; flex: 1; max-width: 560px; display: flex; align-items: center; }
.search__icon {
  position: absolute; left: 14px; width: 18px; height: 18px;
  fill: var(--text-3); pointer-events: none; transition: fill var(--fast);
}
.search__input {
  width: 100%; height: 44px;
  padding: 0 40px 0 42px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--fast), background var(--fast), box-shadow var(--fast);
}
.search__input::placeholder { color: var(--text-3); }
.search__input::-webkit-search-cancel-button { display: none; }
.search__input:hover { border-color: #352846; }
.search__input:focus {
  outline: none;
  border-color: var(--accent-line);
  background: var(--bg-3);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.search:focus-within .search__icon { fill: var(--accent); }
.search__clear {
  position: absolute; right: 8px;
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 50%;
  color: var(--text-3);
  transition: color var(--fast), background var(--fast);
}
.search__clear svg { width: 17px; height: 17px; fill: currentColor; }
.search__clear:hover { color: var(--text); background: var(--bg-3); }

.icon-btn {
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  flex: none;
  transition: color var(--fast), background var(--fast), transform var(--fast);
}
.icon-btn svg { width: 19px; height: 19px; fill: currentColor; }
.icon-btn:hover { color: var(--text); background: var(--bg-2); }
.icon-btn:active { transform: scale(.93); }
.icon-btn[aria-pressed="true"] { color: var(--accent); }
.icon-btn:disabled { opacity: .3; pointer-events: none; }

.topbar__shuffle { margin-left: auto; }

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line-soft); margin: 4px 0 22px; }
/* A section straight after the tab bar shouldn't stack both gaps. */
.tabs + .section { margin-top: -6px; }
.tab {
  position: relative; padding: 12px 14px;
  font-size: 14px; font-weight: 700; color: var(--text-3);
  transition: color var(--fast);
}
.tab:hover { color: var(--text-2); }
.tab[aria-selected="true"] { color: var(--text); }
.tab__n {
  margin-left: 7px;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  color: var(--text-3);
}
.tab[aria-selected="true"] .tab__n { color: var(--accent); }
.tab[aria-selected="true"]::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 2px; border-radius: 2px; background: var(--accent);
  box-shadow: 0 0 10px var(--accent);
  animation: slide-in .3s var(--ease);
}
@keyframes slide-in { from { transform: scaleX(.2); opacity: 0 } }

/* 6. tracks ─────────────────────────────────────────────────────────────── */
.tracks { display: flex; flex-direction: column; }

.track {
  display: grid;
  grid-template-columns: 28px 48px minmax(0, 1.7fr) minmax(0, 1fr) 92px 52px 76px;
  align-items: center;
  gap: 14px;
  padding: 8px 12px;
  border-radius: var(--r);
  position: relative;
  transition: background var(--fast);
}
.track + .track { margin-top: 2px; }
.track:hover { background: var(--bg-2); }
.track[data-current="true"] { background: color-mix(in srgb, var(--accent) 8%, transparent); }

/* Versions of one song read as a set: a hairline in the gutter ties the rows
   together, opening at the first cut and closing after the last. */
.track[data-gsize] { position: relative; }
.track[data-gsize]::before {
  content: "";
  position: absolute; left: 8px; top: -6px; bottom: -6px;
  width: 2px; border-radius: 2px;
  background: var(--line-soft);
}
.track[data-gsize][data-gpos="0"]::before { top: 50%; }
.track[data-gsize][data-glast]::before { bottom: 50%; }
/* the tick that ties each row to the line */
.track[data-gsize]::after {
  content: "";
  position: absolute; left: 10px; top: 50%;
  width: 6px; height: 2px; margin-top: -1px;
  border-radius: 2px; background: var(--line-soft);
}
.track[data-gsize]:hover::before, .track[data-gsize]:hover::after { background: var(--line); }

.track__index { font-family: var(--mono); font-size: 12px; color: var(--text-3); text-align: right; }
.track:hover .track__index { opacity: 0; }

.track__play {
  position: absolute; left: 12px;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 50%; color: var(--text);
  opacity: 0;
  transition: opacity var(--fast), transform var(--fast);
}
.track__play svg { width: 15px; height: 15px; fill: currentColor; }
.track:hover .track__play, .track__play:focus-visible { opacity: 1; }
.track__play:hover { transform: scale(1.15); color: var(--accent); }

.track__art { position: relative; width: 48px; height: 48px; flex: none; }

.art {
  width: 100%; height: 100%;
  border-radius: var(--r-sm);
  object-fit: cover;
  background: var(--bg-3);
  box-shadow: var(--shadow-1);
}
.art--empty {
  display: grid; place-items: center;
  font-family: var(--display);
  font-size: 15px; letter-spacing: .04em;
  color: rgba(255,255,255,.8);
  background: linear-gradient(150deg, hsl(var(--h, 280) 46% 26%), hsl(calc(var(--h, 280) + 42) 50% 14%));
}
.art--empty::after { content: attr(data-initials); }

.track__meta { min-width: 0; }
.track__title {
  font-size: 14.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.track[data-current="true"] .track__title { color: var(--accent); }
.track__artist,
.track__source {
  font-size: 12.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.track__artist { margin-top: 1px; }

.track__dur { font-family: var(--mono); font-size: 12px; color: var(--text-3); text-align: right; }

mark {
  background: color-mix(in srgb, var(--accent) 30%, transparent);
  color: inherit; border-radius: 3px; padding: 0 1px;
}

.badge {
  display: inline-flex; align-items: center; justify-content: center;
  height: 24px; padding: 0 9px;
  border-radius: var(--r-sm);
  font-family: var(--mono);
  font-size: 11px; font-weight: 700;
  white-space: nowrap;
}
.badge--freq {
  color: var(--bucket, var(--accent));
  background: color-mix(in srgb, var(--bucket, var(--accent)) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--bucket, var(--accent)) 30%, transparent);
}
.badge--ghost { color: var(--text-3); border: 1px solid var(--line); }
[data-bucket="sub"] { --bucket: var(--f-sub); }
[data-bucket="f20"] { --bucket: var(--f-20); }
[data-bucket="f25"] { --bucket: var(--f-25); }
[data-bucket="f30"] { --bucket: var(--f-30); }
[data-bucket="f35"] { --bucket: var(--f-35); }
[data-bucket="f40"] { --bucket: var(--f-40); }
[data-bucket="unknown"] { --bucket: #6a5f7d; }

.eq { display: flex; align-items: flex-end; gap: 2px; width: 15px; height: 14px; margin-left: auto; }
.eq span { flex: 1; background: var(--accent); border-radius: 1px; animation: eq 900ms ease-in-out infinite; }
.eq span:nth-child(2) { animation-delay: 180ms; }
.eq span:nth-child(3) { animation-delay: 360ms; }
@keyframes eq { 0%, 100% { height: 22% } 50% { height: 100% } }

/* 7. hero ───────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 48px;
  padding: 40px 0 20px;
}

.hero__copy { display: grid; gap: 20px; }

.hero__eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--mono);
  font-size: 11px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--text-3);
}
.hero__eyebrow b { color: var(--accent); font-size: 9px; }

.hero__title {
  font-family: var(--display);
  font-size: clamp(46px, 7.4vw, 104px);
  line-height: .86;
  letter-spacing: .002em;
  text-transform: uppercase;
  margin: -6px 0 0;
}
.hero__title em {
  font-style: normal; display: block;
  background: linear-gradient(96deg, var(--accent) 0%, var(--violet) 62%, var(--accent) 120%);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  animation: sweep 9s var(--ease) infinite;
}
@keyframes sweep { 0%, 100% { background-position: 0% 0 } 50% { background-position: 100% 0 } }

.hero__lead { max-width: 52ch; font-size: 15.5px; line-height: 1.7; color: var(--text-2); }
.hero__actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

/* rotating swirl behind the logo, pulsing with the sub-bass */
.hero__mark {
  position: relative;
  width: clamp(200px, 25vw, 320px);
  height: clamp(200px, 25vw, 320px);
  align-self: center;
  display: grid; place-items: center;
  flex: none;
}
.hero__mark::before,
.hero__mark::after {
  content: ""; position: absolute; inset: -14%;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    rgba(180,92,255,.55), rgba(110,231,208,.28), rgba(180,92,255,.1),
    rgba(110,231,208,.3), rgba(180,92,255,.55));
  filter: blur(26px);
  animation: spin 26s linear infinite;
  opacity: calc(.42 + var(--bass) * .55);
  transform: scale(calc(1 + var(--bass) * .1));
  transition: opacity 90ms linear, transform 90ms linear;
}
.hero__mark::after { animation-direction: reverse; animation-duration: 40s; inset: 2%; filter: blur(34px); }
@keyframes spin { to { transform: rotate(1turn) } }

.hero__logo {
  position: relative;
  width: 100%; height: 100%; object-fit: cover;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3), 0 0 0 1px rgba(255,255,255,.07);
  animation: float 7s ease-in-out infinite;
}
@keyframes float { 0%, 100% { transform: translateY(-6px) } 50% { transform: translateY(6px) } }

.btn {
  display: inline-flex; align-items: center; gap: 9px;
  height: 46px; padding: 0 22px;
  border-radius: var(--r-full);
  font-weight: 700; font-size: 14.5px;
  border: 1px solid transparent;
  transition: transform var(--fast), background var(--fast), border-color var(--fast),
              color var(--fast), box-shadow var(--fast);
}
.btn svg { width: 17px; height: 17px; fill: currentColor; }
.btn:active { transform: scale(.97); }
.btn--primary { background: var(--accent); color: var(--accent-ink); }
.btn--primary:hover { background: var(--accent-hi); box-shadow: 0 0 26px -6px var(--accent); }
.btn--ghost { border-color: var(--line); color: var(--text-2); }
.btn--ghost:hover { border-color: var(--accent-line); color: var(--text); background: var(--bg-2); }

.stats { display: flex; flex-wrap: wrap; gap: 28px; padding-top: 2px; }
.stat b { display: block; font-family: var(--mono); font-size: 21px; font-weight: 700; }
.stat span { font-size: 11px; color: var(--text-3); letter-spacing: .12em; text-transform: uppercase; }

/* 8. cards ──────────────────────────────────────────────────────────────── */
.row { position: relative; }

.rowscroll {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(172px, 1fr);
  gap: 16px;
  overflow-x: auto;
  padding-bottom: 12px;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  /* A visible track is the only thing that says "there is more over there". */
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.rowscroll::-webkit-scrollbar { height: 9px; }
.rowscroll::-webkit-scrollbar-track { background: transparent; }
.rowscroll::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 99px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.rowscroll::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
  background-clip: padding-box;
}

.row__nav {
  position: absolute; top: 34%; z-index: 3;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--text);
  background: rgba(10, 8, 16, .84);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  backdrop-filter: blur(8px);
  opacity: 0; transform: scale(.88);
  transition: opacity var(--fast), transform var(--fast), background var(--fast), color var(--fast);
}
.row__nav svg { width: 18px; height: 18px; fill: currentColor; }
.row__nav--prev { left: -10px; }
.row__nav--next { right: -10px; }
.row:hover .row__nav, .row__nav:focus-visible { opacity: 1; transform: none; }
.row__nav:hover { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.row__nav:active { transform: scale(.92); }

/* A finger already swipes; arrows would only sit on top of the artwork. */
@media (hover: none) {
  .row__nav { display: none; }
}

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(172px, 1fr)); gap: 18px 16px; }

.card {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px;
  border-radius: var(--r-lg);
  background: var(--bg-1);
  border: 1px solid var(--line-soft);
  scroll-snap-align: start;
  transition: background var(--fast), border-color var(--fast), transform var(--base);
}
.card:hover { background: var(--bg-2); border-color: var(--line); transform: translateY(-3px); }
.card__art { position: relative; aspect-ratio: 1; border-radius: var(--r); overflow: hidden; }
.card__art .art { border-radius: 0; }
.card__play {
  position: absolute; right: 10px; bottom: 10px;
  width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--accent-ink);
  box-shadow: var(--shadow-2);
  opacity: 0; transform: translateY(10px) scale(.85);
  transition: opacity var(--base), transform var(--base) ;
}
.card__play svg { width: 18px; height: 18px; fill: currentColor; margin-left: 2px; }
.card:hover .card__play, .card:focus-within .card__play {
  opacity: 1; transform: none; transition-timing-function: var(--spring);
}
.card__title {
  font-size: 14px; font-weight: 700; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card__artist { font-size: 12.5px; color: var(--text-3); }
.card__foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

.artists { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.artist-tile {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px;
  border-radius: var(--r);
  border: 1px solid var(--line-soft);
  background: var(--bg-1);
  transition: background var(--fast), border-color var(--fast), transform var(--fast);
}
.artist-tile:hover { background: var(--bg-2); border-color: var(--line); transform: translateY(-2px); }
.artist-tile__ring {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--display); font-size: 14px;
  background: linear-gradient(150deg, hsl(var(--h,280) 44% 28%), hsl(calc(var(--h,280) + 44) 48% 15%));
}
.artist-tile__meta { min-width: 0; flex: 1; }
.artist-tile__name {
  display: block;
  font-size: 13.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.artist-tile__n {
  display: block;
  font-family: var(--mono); font-size: 11px; color: var(--text-3);
  white-space: nowrap;
}

/* 9. player ─────────────────────────────────────────────────────────────── */
.dock {
  grid-area: dock;
  position: relative;
  background: linear-gradient(180deg, #130c1d, var(--bg-1));
  border-top: 1px solid var(--line-soft);
  /* The home indicator lives in the bottom strip; the controls stay above it. */
  padding: 0 calc(18px + var(--safe-r)) calc(8px + var(--safe-b)) calc(18px + var(--safe-l));
}
.dock[data-active="false"] { opacity: .75; }

.dock__seek { position: relative; height: 14px; margin: 0 -18px; }
.seek {
  position: absolute; inset: 0; width: 100%; height: 16px;
  margin: 0; appearance: none; background: none; cursor: pointer; z-index: 2;
}
.seek::-webkit-slider-thumb {
  appearance: none; width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 4px rgba(10,8,16,.7), 0 0 12px var(--accent);
  opacity: 0; transition: opacity var(--fast);
}
.seek::-moz-range-thumb { width: 13px; height: 13px; border: 0; border-radius: 50%; background: var(--accent); opacity: 0; }
.dock:hover .seek::-webkit-slider-thumb, .seek:focus-visible::-webkit-slider-thumb { opacity: 1; }
.dock:hover .seek::-moz-range-thumb { opacity: 1; }
.seek:disabled { cursor: default; }

.seek__track { position: absolute; left: 0; right: 0; top: 6px; height: 4px; background: var(--bg-3); overflow: hidden; }
.seek__buffer, .seek__fill { position: absolute; inset: 0 auto 0 0; width: 0; transition: width 140ms linear; }
.seek__buffer { background: #2c2140; }
.seek__fill { background: linear-gradient(90deg, var(--violet), var(--accent)); box-shadow: 0 0 14px -2px var(--accent); }

.dock__grid {
  display: grid;
  /* Equal columns either side of the transport, so the play button is dead
     centre of the dock however wide the window is. The sub display shares the
     left one with the track that is playing; the rest of the range shares the
     right one with the volume. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; gap: 16px;
  height: calc(var(--dock-h) - 20px);
}

.now { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 0 1 auto; max-width: 264px; }
.now__art { width: 44px; height: 44px; flex: none; }
.now__meta { min-width: 0; overflow: hidden; }
.now__title { font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; }
.now__title span { display: inline-block; white-space: nowrap; }
.now__title[data-scroll="true"] span { animation: marquee 12s linear infinite; }
@keyframes marquee {
  0%, 12% { transform: translateX(0) }
  88%, 100% { transform: translateX(calc(-100% + 180px)) }
}
.now__artist { font-size: 11.5px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The play button in the middle of the dock, with the clock directly under it —
   the two things you look at while a track is running, in one place. */
.transport { display: grid; justify-items: center; gap: 3px; justify-self: center; }
.transport__row { display: flex; align-items: center; gap: 5px; }
.transport__row .icon-btn { width: 31px; height: 31px; }
.transport__row .icon-btn svg { width: 17px; height: 17px; }

.play-btn {
  display: grid; place-items: center;
  width: 41px; height: 41px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  transition: transform var(--fast), background var(--fast), box-shadow var(--fast);
}
.play-btn svg { width: 17px; height: 17px; fill: currentColor; }
.play-btn:hover { background: var(--accent-hi); transform: scale(1.06); box-shadow: 0 0 30px -6px var(--accent); }
.play-btn:active { transform: scale(.96); }
.play-btn .play-btn__pause { display: none; }
.play-btn[data-playing="true"] .play-btn__play { display: none; }
.play-btn[data-playing="true"] .play-btn__pause { display: block; }
.play-btn__play { margin-left: 3px; }

#btn-repeat { position: relative; }
.repeat-one {
  position: absolute; right: 3px; bottom: 2px;
  font-family: var(--mono); font-size: 9px; font-weight: 700;
  color: var(--accent); display: none;
}
#btn-repeat[data-mode="one"] .repeat-one { display: block; }

.dock__side { display: flex; align-items: center; justify-content: flex-end; gap: 10px; min-width: 0; }

/* One clock either side of the skip buttons. Both are the same width and the
   two of them sit an equal distance out, so the play button stays exactly in
   the middle of the row however many digits the numbers grow. */
.time {
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  min-width: 44px;
  color: var(--text-2);
  padding: 2px 4px; border-radius: 6px;
}
.time--now { text-align: right; }
.time--left { text-align: left; color: var(--text-3); transition: color var(--fast), background var(--fast); }
.time--left:hover { color: var(--text); background: var(--bg-2); }
.time--left[data-mode="left"] { color: var(--accent); }

/* The analyser takes whatever width the dock can spare: the wider it is, the
   more of the ruler fits and the further apart the notes sit. */
.dock__left { display: flex; align-items: center; gap: 12px; min-width: 0; }

.viz {
  flex: 1 1 auto;
  min-width: 120px;
  /* Taller than it needs to be for the notes to read: the difference between
     the loudest bar and the one beside it is only worth drawing if there are
     pixels to draw it in. */
  height: 83px;
  opacity: .95;
}
/* Both displays press right up against the transport and take whatever room is
   left in their column, so the play button sits exactly halfway between them —
   and, because the two columns are equal, exactly in the middle of the dock. */
.viz--low { flex: 1 1 0; min-width: 200px; }
.viz--high { flex: 1 1 0; min-width: 130px; }
@media (max-width: 1240px) {
  .viz { height: 75px; }
  .viz--low { min-width: 160px; }
  .viz--high { min-width: 120px; }
}

.volume { display: flex; align-items: center; gap: 4px; }
.volume__range { width: 88px; height: 20px; appearance: none; background: none; cursor: pointer; }
.volume__range::-webkit-slider-runnable-track {
  height: 4px; border-radius: 99px;
  background: linear-gradient(90deg, var(--accent) var(--fill, 100%), var(--bg-3) var(--fill, 100%));
}
.volume__range::-moz-range-track { height: 4px; border-radius: 99px; background: var(--bg-3); }
.volume__range::-moz-range-progress { height: 4px; border-radius: 99px; background: var(--accent); }
.volume__range::-webkit-slider-thumb {
  appearance: none; margin-top: -4px;
  width: 12px; height: 12px; border-radius: 50%; background: var(--text);
  opacity: 0; transition: opacity var(--fast);
}
.volume__range::-moz-range-thumb { width: 12px; height: 12px; border: 0; border-radius: 50%; background: var(--text); }
.volume:hover .volume__range::-webkit-slider-thumb,
.volume__range:focus-visible::-webkit-slider-thumb { opacity: 1; }

#btn-mute .vol-off { display: none; }
#btn-mute[data-muted="true"] .vol-on { display: none; }
#btn-mute[data-muted="true"] .vol-off { display: block; }

/* 10. queue ─────────────────────────────────────────────────────────────── */
.queue {
  position: fixed; right: calc(16px + var(--safe-r)); bottom: calc(var(--dock-space) + 14px);
  z-index: 40;
  width: min(380px, calc(100vw - 32px - var(--safe-l) - var(--safe-r)));
  /* Never past the status bar: the panel grows upward from the dock. */
  max-height: min(62vh, 560px, calc(100dvh - var(--dock-space) - var(--safe-t) - 40px));
  display: flex; flex-direction: column;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  overflow: hidden;
  animation: rise 220ms var(--spring);
}
@keyframes rise { from { opacity: 0; transform: translateY(14px) scale(.98) } }

.queue__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 12px 12px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.queue__head h2 { font-family: var(--display); font-size: 14px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-2); }
.queue__list { overflow-y: auto; padding: 8px; }

.queue__label {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: 12px 8px 6px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--text-3);
}
.queue__label:first-child { padding-top: 4px; }
.queue__empty { padding: 26px 20px; text-align: center; color: var(--text-3); font-size: 13px; line-height: 1.6; }

.queue__item {
  position: relative;
  display: grid; grid-template-columns: 20px 36px minmax(0,1fr) auto 26px;
  align-items: center; gap: 10px;
  padding: 7px 8px; border-radius: var(--r-sm);
  cursor: pointer; transition: background var(--fast), transform var(--fast), opacity var(--fast);
}
.queue__art { width: 36px; height: 36px; }
.queue__grip {
  font-size: 13px; color: var(--text-3); text-align: center;
  cursor: grab; user-select: none;
  touch-action: none; /* a finger on the handle reorders instead of scrolling */
  transition: color var(--fast);
}
.queue__item:hover .queue__grip { color: var(--text-2); }
/* The row you are holding lifts off the list and follows the pointer; the
   others slide out of the way to show where it will land. */
.queue__list[data-dragging] { cursor: grabbing; user-select: none; }
.queue__list[data-dragging] .queue__item { pointer-events: none; }
.queue__item[data-dragging] {
  z-index: 2;
  background: var(--bg-2);
  box-shadow: 0 12px 28px rgba(0,0,0,.5), 0 0 0 1px var(--line);
  cursor: grabbing;
}
.queue__item[data-dragging] .queue__grip { cursor: grabbing; color: var(--accent); }
.queue__item .art { -webkit-user-drag: none; user-select: none; }
.queue__drop {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--text-3);
  opacity: 0; transition: opacity var(--fast), color var(--fast), background var(--fast);
}
.queue__drop svg { width: 15px; height: 15px; fill: currentColor; }
.queue__item:hover .queue__drop { opacity: 1; }
.queue__drop:hover { color: var(--danger); background: var(--bg-3); }
.queue__item:hover { background: var(--bg-2); }
.queue__item[data-current="true"] { background: var(--accent-soft); }
.queue__n { font-family: var(--mono); font-size: 11px; color: var(--text-3); text-align: right; }
/* A grid, so the two lines are blocks: an inline span ignores text-overflow and
   a long title wraps under the badge instead of ending in an ellipsis. */
.queue__meta { min-width: 0; display: grid; grid-template-rows: auto auto; gap: 1px; }
.queue__title { display: block; font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue__artist { display: block; font-size: 11.5px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue__item .badge { white-space: nowrap; }
/* The tag sits beside the range rather than inside the title, so a long name
   truncates without taking the one word that says what this cut is. */
.queue__tags { display: flex; align-items: center; gap: 6px; }
.queue__tags .tag { margin-left: 0; }

#btn-queue { position: relative; }
#btn-queue[data-count]:not([data-count=""])::after {
  content: attr(data-count);
  position: absolute; top: 1px; right: 1px;
  min-width: 15px; height: 15px; padding: 0 3px;
  display: grid; place-items: center;
  border-radius: 999px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  background: var(--accent); color: var(--accent-ink);
}

/* the right-click menu */
.menu {
  position: fixed; z-index: 95;
  min-width: 196px; padding: 6px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--bg-1);
  box-shadow: 0 18px 44px rgba(0,0,0,.55);
  animation: menu-in .12s var(--ease);
}
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px) } }
.menu__item {
  display: block; width: 100%;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  text-align: left; font-size: 13px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background var(--fast), color var(--fast);
}
.menu__item:hover { background: var(--bg-2); color: var(--text); }
.menu__rule { height: 1px; margin: 5px 6px; border: 0; background: var(--line-soft); }

.scrim { position: fixed; inset: 0; z-index: 30; background: rgba(6,4,10,.65); backdrop-filter: blur(2px); }

/* 11. pages ─────────────────────────────────────────────────────────────── */
.page-head { padding: 34px 0 6px; }
.page-head h1 {
  font-family: var(--display);
  font-size: clamp(38px, 5.6vw, 68px);
  line-height: .95; text-transform: uppercase;
}
.page-head p { margin-top: 12px; color: var(--text-2); max-width: 60ch; }

.statement {
  max-width: 24ch;
  font-size: clamp(23px, 3.1vw, 38px);
  font-weight: 500;
  line-height: 1.24;
  letter-spacing: -.02em;
  color: var(--text);
  margin: 10px 0 34px;
  text-wrap: balance;
}
.statement em {
  font-style: normal;
  background: linear-gradient(100deg, var(--accent), var(--violet));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.statement--wide { max-width: 30ch; }

.photo {
  position: relative;
  margin: 8px 0 10px;
  border-radius: var(--r-xl);
  overflow: hidden;
  border: 1px solid var(--line);
  max-width: 820px;
  box-shadow: var(--shadow-3);
}
.photo img { width: 100%; height: auto; }
.photo figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 40px 22px 18px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .08em;
  text-transform: uppercase; color: #d8d2e2;
  background: linear-gradient(180deg, transparent, rgba(6,4,10,.86));
}

.social { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; max-width: 820px; }
.social__link {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-soft);
  background: var(--bg-1);
  position: relative; overflow: hidden;
  transition: border-color var(--fast), background var(--fast), transform var(--fast);
}
.social__link::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(220px 100px at 12% 0%, var(--brand-color, var(--accent)), transparent 70%);
  opacity: 0; transition: opacity var(--base);
}
.social__link:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--brand-color) 45%, var(--line)); background: var(--bg-2); }
.social__link:hover::after { opacity: .13; }
.social__icon {
  width: 42px; height: 42px; flex: none;
  display: grid; place-items: center;
  border-radius: 12px;
  background: color-mix(in srgb, var(--brand-color) 16%, transparent);
  color: var(--brand-color);
}
.social__icon svg { width: 22px; height: 22px; fill: currentColor; }
.social__meta { min-width: 0; position: relative; }
.social__name { font-weight: 700; font-size: 14.5px; }
.social__handle { font-family: var(--mono); font-size: 12px; color: var(--text-3); }
.social__go { margin-left: auto; color: var(--text-3); transition: transform var(--fast), color var(--fast); position: relative; }
.social__go svg { width: 18px; height: 18px; fill: currentColor; }
.social__link:hover .social__go { color: var(--brand-color); transform: translate(3px, -3px); }

.prose { max-width: 68ch; }
.prose p { color: var(--text-2); line-height: 1.75; margin-bottom: 14px; font-size: 15.5px; }
.prose strong { color: var(--text); font-weight: 700; }

.panels { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin: 22px 0; max-width: 820px; }
.panel {
  padding: 20px; border-radius: var(--r-lg);
  border: 1px solid var(--line-soft); background: var(--bg-1);
  transition: border-color var(--fast), transform var(--fast);
}
.panel:hover { border-color: var(--line); transform: translateY(-2px); }
.panel h3 { font-size: 14.5px; font-weight: 700; margin-bottom: 7px; }
.panel p { font-size: 13.5px; color: var(--text-3); line-height: 1.6; }
.panel__n {
  display: block; font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: .16em; color: var(--accent); margin-bottom: 12px;
}

.callout {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 18px 20px; margin: 24px 0; max-width: 820px;
  border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--bg-1);
}
.callout svg { width: 20px; height: 20px; fill: var(--accent); flex: none; margin-top: 2px; }
.callout p { font-size: 13.5px; color: var(--text-2); line-height: 1.65; }

/* 12. states ────────────────────────────────────────────────────────────── */
.empty { display: grid; place-items: center; gap: 10px; padding: 72px 20px; text-align: center; }
.empty svg { width: 36px; height: 36px; fill: var(--text-3); opacity: .6; }
.empty h2 { font-family: var(--display); font-size: 20px; text-transform: uppercase; }
.empty p { color: var(--text-3); font-size: 14px; max-width: 44ch; }

.notice {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 16px 18px; margin: 18px 0;
  border-radius: var(--r);
  border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--line));
  background: color-mix(in srgb, var(--warn) 7%, transparent);
}
.notice svg { width: 20px; height: 20px; fill: var(--warn); flex: none; margin-top: 2px; }
.notice b { display: block; margin-bottom: 3px; font-size: 14px; }
.notice p { font-size: 13px; color: var(--text-2); line-height: 1.6; }
.notice code { font-family: var(--mono); font-size: 12px; background: var(--bg-2); padding: 1px 5px; border-radius: 4px; }

.skeleton {
  background: linear-gradient(100deg, var(--bg-2) 30%, var(--bg-3) 50%, var(--bg-2) 70%);
  background-size: 220% 100%;
  animation: shimmer 1.4s infinite linear;
  border-radius: var(--r-sm);
}
@keyframes shimmer { from { background-position: 140% 0 } to { background-position: -40% 0 } }

.skeleton-row {
  display: grid; grid-template-columns: 48px minmax(0,1fr) 90px;
  gap: 14px; align-items: center; padding: 8px 12px;
}
.skeleton-row + .skeleton-row { margin-top: 2px; }

.toast {
  position: fixed; left: 50%; bottom: calc(var(--dock-space) + 20px);
  transform: translateX(-50%); z-index: 60;
  padding: 11px 18px;
  border-radius: var(--r-full);
  background: var(--bg-3); border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  font-size: 13.5px; font-weight: 500;
  animation: rise 200ms var(--spring);
}

/* 12b. the live panel ───────────────────────────────────────────────────── */
.nav__item--live[aria-current] svg, .nav__item--live:hover svg { fill: var(--accent); }

.pulse__now {
  display: flex; align-items: center; gap: 30px; flex-wrap: wrap;
  padding: 18px 20px; margin-bottom: 14px;
  background: var(--bg-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
}
.pulse__count b {
  display: block;
  font-family: var(--display); font-size: 44px; line-height: 1;
  color: var(--accent);
}
.pulse__count--soft b { color: var(--text-2); font-size: 30px; }
.pulse__count span {
  display: block; margin-top: 5px;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-3);
}

.pulse__graph { flex: 1 1 220px; min-width: 180px; }
.pulse__graph svg { width: 100%; height: 46px; fill: var(--accent); opacity: .62; }
.pulse__graph-note {
  display: block; margin-top: 4px;
  font-family: var(--mono); font-size: 10.5px; color: var(--text-3);
}

.pulse__row {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) minmax(0, 1.2fr) 52px;
  align-items: center; gap: 14px;
  padding: 10px 12px; border-radius: var(--r);
}
.pulse__row + .pulse__row { margin-top: 2px; }
.pulse__row[data-playing="true"] { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.pulse__tag {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  text-align: center; padding: 4px 0; border-radius: var(--r-sm);
  background: var(--bg-2); color: var(--text-3);
}
.pulse__who b, .pulse__doing b { display: block; font-size: 14px; font-weight: 600; }
.pulse__who span, .pulse__doing span {
  display: block; margin-top: 1px;
  font-size: 11.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pulse__doing b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pulse__track { display: flex; align-items: center; gap: 6px; color: var(--accent); }
.pulse__track svg { width: 13px; height: 13px; fill: currentColor; flex: none; }
.pulse__for { font-family: var(--mono); font-size: 11.5px; color: var(--text-3); text-align: right; }

.pulse__nobody {
  padding: 26px 20px; border-radius: var(--r-lg);
  border: 1px dashed var(--line); text-align: center;
}
.pulse__nobody b { display: block; font-size: 15px; }
.pulse__nobody span { display: block; margin-top: 5px; font-size: 13px; color: var(--text-3); }

.stats--pulse { gap: 30px; padding: 4px 0 18px; }

.pulse__tallies {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.pulse__tally {
  padding: 14px 16px;
  background: var(--bg-1); border: 1px solid var(--line-soft); border-radius: var(--r);
}
.pulse__tally h3 {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 8px;
}
.pulse__tally-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 3px 0; font-size: 13px;
}
.pulse__tally-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pulse__tally-row b { font-family: var(--mono); font-size: 12px; color: var(--text-2); flex: none; }

.pulse__feed { display: flex; flex-direction: column; }
.pulse__event {
  display: grid; grid-template-columns: 52px 68px minmax(0, 1fr);
  gap: 12px; align-items: baseline;
  padding: 6px 12px; border-radius: var(--r-sm);
  font-size: 13px;
}
.pulse__event:nth-child(odd) { background: color-mix(in srgb, var(--bg-2) 60%, transparent); }
.pulse__when { font-family: var(--mono); font-size: 11.5px; color: var(--text-3); }
.pulse__what { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-3); }
.pulse__event[data-kind="play"] .pulse__what { color: var(--accent); }
.pulse__event[data-kind="leave"] .pulse__what { color: var(--text-3); opacity: .7; }
.pulse__where { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 700px) {
  .pulse__now { gap: 20px; padding: 16px; }
  .pulse__count b { font-size: 36px; }
  /* Two lines on a phone: who, then what they are doing under it. */
  .pulse__row {
    grid-template-columns: 40px minmax(0, 1fr) 46px;
    grid-template-areas: "tag who for" ". doing doing";
    row-gap: 4px;
  }
  .pulse__tag { grid-area: tag; }
  .pulse__who { grid-area: who; }
  .pulse__doing { grid-area: doing; }
  .pulse__for { grid-area: for; }
  .pulse__event { grid-template-columns: 48px minmax(0, 1fr); }
  .pulse__what { grid-column: 2; }
  .pulse__where { grid-column: 2; }
}

/* 13. motion ────────────────────────────────────────────────────────────── */
/* staggered entrance for anything rendered into the view */
.track, .card, .artist-tile, .panel, .social__link, .photo, .statement {
  animation: rise-in .5s var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 24ms);
}
@keyframes rise-in { from { opacity: 0; transform: translateY(12px) } }

.hero__copy > * { animation: rise-in .6s var(--ease) backwards; }
.hero__copy > *:nth-child(2) { animation-delay: 60ms; }
.hero__copy > *:nth-child(3) { animation-delay: 120ms; }
.hero__copy > *:nth-child(4) { animation-delay: 180ms; }
.hero__copy > *:nth-child(5) { animation-delay: 240ms; }
.hero__mark { animation: rise-in .8s var(--ease) backwards; animation-delay: 120ms; }

/* 13b. favourites ───────────────────────────────────────────────────────── */
/* A word, not a badge: it says something about the cut, and it should read as
   part of the title rather than competing with the frequency range. */
.tag {
  display: inline-block; vertical-align: 1px;
  margin-left: 6px; padding: 1px 5px;
  border-radius: 5px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  font-family: var(--mono); font-size: 9px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}
.tag[data-variant="Slowed"] { color: #9db4ff; border-color: rgba(157,180,255,.28); }
.tag[data-variant="Sped up"] { color: var(--f-40); border-color: rgba(255,176,61,.28); }
.tag[data-variant="Nightcore"] { color: var(--love); border-color: rgba(255,93,143,.28); }
.tag[data-variant="FLAC"] { color: var(--accent); border-color: var(--accent-line); }
/* The common case says so without asking for attention. */
.tag[data-variant="MP3"], .tag[data-variant="WAV"], .tag[data-variant="M4A"] {
  color: var(--text-3); border-color: var(--line-soft); background: transparent;
}
.card__title .tag, .queue__title .tag { font-size: 8.5px; }

.track__actions { display: flex; justify-content: flex-end; align-items: center; gap: 2px; }

/* Adding to the queue is a hover affordance: present when you reach for it,
   invisible the rest of the time so the list stays a list. */
.queue-add {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  color: var(--text-3);
  opacity: 0;
  transition: opacity var(--fast), color var(--fast), background var(--fast), transform var(--fast);
}
.queue-add svg { width: 18px; height: 18px; fill: currentColor; }
.track:hover .queue-add, .queue-add:focus-visible { opacity: .55; }
.queue-add:hover { opacity: 1; color: var(--accent); background: var(--bg-3); }
.queue-add:active { transform: scale(.9); }
@media (hover: none) { .queue-add { display: none; } }

.fav {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  color: var(--text-3);
  opacity: .45;
  transition: opacity var(--fast), color var(--fast), background var(--fast), transform var(--fast);
}
.fav svg { width: 18px; height: 18px; fill: currentColor; }
.fav .fav__full { display: none; }
.fav[aria-pressed="true"] .fav__full { display: block; }
.fav[aria-pressed="true"] svg:not(.fav__full) { display: none; }
.fav[aria-pressed="true"] { opacity: 1; color: var(--love); }
.track:hover .fav, .card:hover .fav, .fav:focus-visible { opacity: 1; }
.fav:hover { color: var(--love); background: var(--bg-3); transform: scale(1.14); }
.fav:active { transform: scale(.88); }

.fav--float {
  position: absolute; left: 10px; bottom: 10px;
  background: rgba(6,4,10,.62);
  backdrop-filter: blur(6px);
  opacity: 0; transform: translateY(8px);
}
.card:hover .fav--float, .card:focus-within .fav--float,
.fav--float[aria-pressed="true"] { opacity: 1; transform: none; }

.fav--dock { flex: none; opacity: .7; }

/* 13c. artist folders ───────────────────────────────────────────────────── */
.folders {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
  gap: 22px 16px;
}

.folder {
  display: flex; flex-direction: column; gap: 9px;
  animation: rise-in .5s var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 22ms);
}
.folder__tab {
  width: 52%; height: 13px;
  margin-bottom: -1px;
  border: 1px solid var(--line-soft); border-bottom: 0;
  border-radius: 8px 8px 0 0;
  background: hsl(var(--h, 280) 38% 20%);
  transition: background var(--fast);
}
.folder__body {
  position: relative;
  padding: 7px;
  border: 1px solid var(--line-soft);
  border-radius: 0 var(--r-lg) var(--r-lg) var(--r-lg);
  background: linear-gradient(158deg, hsl(var(--h, 280) 32% 17%), var(--bg-1) 72%);
  transition: border-color var(--fast), transform var(--fast), box-shadow var(--fast);
}
.folder:hover .folder__body {
  border-color: var(--line);
  transform: translateY(-3px);
  box-shadow: var(--shadow-2);
}
.folder:hover .folder__tab { background: hsl(var(--h, 280) 46% 30%); }
.folder:focus-visible .folder__body { outline: 2px solid var(--accent); outline-offset: 3px; }

.folder__mosaic {
  display: grid; gap: 3px;
  aspect-ratio: 1;
  border-radius: var(--r-sm); overflow: hidden;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.folder__mosaic[data-cells="0"] { background: hsl(var(--h, 280) 26% 13%); }
.folder__mosaic[data-cells="1"] { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.folder__mosaic[data-cells="2"] { grid-template-rows: 1fr; }
.folder__mosaic[data-cells="3"] .folder__cell:first-child { grid-row: span 2; }

.folder__cell { display: block; overflow: hidden; min-width: 0; min-height: 0; }
.folder__cell .art { width: 100%; height: 100%; border-radius: 0; box-shadow: none; }
.folder__cell .art--empty { font-size: 12px; }
.folder__mosaic[data-cells="1"] .art--empty { font-size: 22px; }

.folder__count {
  position: absolute; right: 13px; bottom: 13px;
  min-width: 24px; height: 21px; padding: 0 7px;
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  border-radius: 999px;
  background: rgba(6,4,10,.74);
  backdrop-filter: blur(6px);
}
.folder__meta { min-width: 0; padding: 0 2px; }
.folder__name {
  display: block; font-size: 13.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.folder:hover .folder__name { color: var(--accent); }
.folder__sub { font-family: var(--mono); font-size: 11px; color: var(--text-3); }

.artist-head {
  display: grid; grid-template-columns: 148px minmax(0, 1fr);
  gap: 24px; align-items: center;
  padding: 22px 0 28px;
}
.artist-head__mosaic { width: 148px; }
.artist-head__mosaic .folder__mosaic { border-radius: var(--r-lg); }
.artist-head__eyebrow {
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-3);
}
.artist-head h1 {
  font-family: var(--display); font-size: clamp(30px, 5vw, 52px);
  line-height: 1; margin: 8px 0 10px;
}
.artist-head__facts { font-size: 13.5px; color: var(--text-2); margin-bottom: 16px; }

/* 13d. account ──────────────────────────────────────────────────────────── */
.rail__account { padding: 0 10px; }
.account {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px;
  border-radius: var(--r);
  border: 1px solid var(--line-soft);
  background: var(--bg-1);
  text-align: left;
  transition: border-color var(--fast), background var(--fast), color var(--fast);
}
.account--out { font-size: 13px; font-weight: 700; color: var(--text-2); }
.account--out:hover { border-color: var(--accent); color: var(--text); background: var(--bg-2); }
.account--out svg { width: 18px; height: 18px; fill: currentColor; opacity: .85; }

.account__avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--display); font-size: 14px;
  background: linear-gradient(150deg, var(--f-20), var(--f-35));
  color: #12071d;
}
.account__meta { min-width: 0; flex: 1; }
.account__name {
  display: block; font-size: 13px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.account__sub {
  display: block;
  font-family: var(--mono); font-size: 10.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.account__out {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--text-3);
  transition: color var(--fast), background var(--fast);
}
.account__out:hover { color: var(--danger); background: var(--bg-3); }
.account__out svg { width: 17px; height: 17px; fill: currentColor; }

/* The same colour that runs through REBASSED in the hero, running through the
   one button on the page that is asking for something. */
.btn--install {
  width: 100%; justify-content: center;
  height: 40px; font-size: 13px;
  color: var(--accent-ink);
  background-image: linear-gradient(96deg, var(--accent) 0%, var(--violet) 62%, var(--accent) 120%);
  background-size: 220% 100%;
  animation: sweep 9s var(--ease) infinite;
  box-shadow: 0 8px 22px rgba(110, 231, 208, .18);
}
@media (prefers-reduced-motion: reduce) { :root:not([data-motion="full"]) .btn--install { animation: none; } }
:root[data-motion="calm"] .btn--install { animation: none; }
.btn--install svg { width: 17px; height: 17px; fill: currentColor; }
.btn--install:hover { filter: brightness(1.07); }

.steps {
  margin: 20px 0 0; padding-left: 20px;
  display: flex; flex-direction: column; gap: 12px;
  font-size: 13.5px; line-height: 1.55; color: var(--text-2);
}
.steps li::marker { color: var(--accent); font-weight: 700; }
.steps b { color: var(--text); }
.hint-icon {
  width: 15px; height: 15px; fill: var(--accent);
  vertical-align: -3px; margin-left: 3px;
}

.rail__bug {
  display: flex; align-items: center; gap: 8px;
  padding: 0 2px;
  font-size: 12px; color: var(--text-3);
  transition: color var(--fast);
}
.rail__bug:hover { color: var(--text-2); }
#motion-btn[aria-pressed="true"] svg { color: var(--accent); }
.rail__bug svg { width: 15px; height: 15px; fill: currentColor; }

/* Small, out of the way, and the one thing to read first when a browser
   insists it is up to date. */
.rail__build {
  align-self: flex-start;
  padding: 2px 7px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-full);
  font-family: var(--mono); font-size: 10px; letter-spacing: .06em;
  color: var(--text-3);
  transition: color var(--fast), border-color var(--fast);
}
.rail__build:hover { color: var(--accent); border-color: var(--accent-line); }

/* 13e. dialogs & forms ──────────────────────────────────────────────────── */
.modal {
  width: min(420px, calc(100vw - 28px));
  padding: 26px 26px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-1);
  color: var(--text);
  box-shadow: 0 30px 90px rgba(0, 0, 0, .62);
}
.modal::backdrop { background: rgba(6, 4, 10, .74); backdrop-filter: blur(3px); }
.modal[open] { animation: modal-in .26s var(--ease); }
@keyframes modal-in { from { opacity: 0; transform: translateY(14px) scale(.97) } }

.modal__close {
  position: absolute; top: 12px; right: 12px;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--text-3);
  transition: color var(--fast), background var(--fast);
}
.modal__close:hover { color: var(--text); background: var(--bg-3); }
.modal__close svg { width: 18px; height: 18px; fill: currentColor; }

.modal__title { font-family: var(--display); font-size: 26px; letter-spacing: .01em; padding-right: 34px; }
.modal__lead { margin-top: 7px; font-size: 13.5px; line-height: 1.6; color: var(--text-2); }
.modal__switch {
  margin-top: 15px; font-size: 13px; color: var(--text-3);
  display: flex; gap: 6px; justify-content: center; align-items: baseline;
}
.modal__fine { margin-top: 16px; font-size: 11.5px; line-height: 1.65; color: var(--text-3); }
.modal__actions { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.modal__actions .btn { flex: 1; justify-content: center; }

.form { display: flex; flex-direction: column; gap: 13px; margin-top: 19px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field__label { font-size: 12px; font-weight: 700; color: var(--text-2); }
.field__label i { font-style: normal; font-weight: 400; color: var(--text-3); }
.field__wrap { position: relative; display: block; }
.field__input--secret { padding-right: 46px; }

.field__peek {
  position: absolute; right: 5px; top: 5px;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: var(--r-sm); color: var(--text-3);
  transition: color var(--fast), background var(--fast);
}
.field__peek:hover { color: var(--text); background: var(--bg-3); }
.field__peek svg { width: 18px; height: 18px; fill: currentColor; }
.field__peek .peek-off { display: none; }
.field__peek[aria-pressed="true"] { color: var(--accent); }
.field__peek[aria-pressed="true"] .peek-on { display: none; }
.field__peek[aria-pressed="true"] .peek-off { display: block; }

.field__input {
  width: 100%;
  height: 44px; padding: 0 13px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--bg-2); color: var(--text);
  font: inherit; font-size: 14px;
  transition: border-color var(--fast), background var(--fast);
}
.field__input::placeholder { color: var(--text-3); }
.field__input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-3);
}
.form__error {
  font-size: 12.5px; line-height: 1.5; color: var(--danger);
  padding: 9px 11px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--danger) 34%, transparent);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.form__submit { width: 100%; justify-content: center; margin-top: 3px; }
.form__submit[data-busy="true"] { opacity: .55; cursor: progress; }

.mailbox {
  margin-top: 17px; padding: 13px 14px;
  border-radius: var(--r-sm);
  border: 1px dashed var(--line);
  background: var(--bg-2);
  font-family: var(--mono); font-size: 14px; text-align: center;
  user-select: all; word-break: break-all;
}

/* 13f. odds and ends ────────────────────────────────────────────────────── */
.photo--square { max-width: 520px; margin-left: auto; margin-right: auto; }
.fineprint {
  margin-top: 24px;
  max-width: 64ch;
  font-size: 11.5px; line-height: 1.75; color: var(--text-3);
}
.empty__actions {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
  margin-top: -10px; padding-bottom: 20px;
}
.offline-note {
  display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
  margin-top: 10px;
  font-size: 12.5px; color: var(--text-3);
}
.offline-note svg { width: 15px; height: 15px; fill: var(--accent); flex: none; }
.offline-note .link-btn { font-size: 12.5px; }
.offline-note--busy svg { animation: pulse 1.3s infinite; }

.contact { display: flex; flex-direction: column; align-items: flex-start; gap: 13px; }
.contact p { font-size: 13.5px; line-height: 1.65; color: var(--text-2); max-width: 58ch; }

/* 13g. full-screen player ───────────────────────────────────────────────── */
.np {
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column;
  gap: 10px;
  padding: calc(10px + var(--safe-t)) calc(20px + var(--safe-r))
           calc(18px + var(--safe-b)) calc(20px + var(--safe-l));
  /* Flat and dark, so the sky behind it is the only thing with any light in
     it. This used to carry a wide purple wash of its own, which fought the
     stars, banded on an OLED and left the panel looking smeared. */
  background: var(--bg);
  transform: translateY(100%);
  transition: transform .3s var(--ease);
  overscroll-behavior: contain;
  touch-action: pan-y;
}
/* The sky fills the panel; everything else stands in front of it. */
.np__sky {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 0;
  pointer-events: none;
}
.np > *:not(.np__sky) { position: relative; z-index: 1; }
.np[data-open="true"] { transform: none; }
body[data-np-open="true"] { overflow: hidden; }

.np__head {
  display: grid; grid-template-columns: 40px 1fr 40px;
  align-items: center;
  flex: none;
}
.np__from {
  text-align: center;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-3);
}

/* The stage takes whatever height is left, and the ring is sized from it. */
.np__stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid; place-items: center;
  margin: 4px 0;
}
.np__viz {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
.np__art {
  position: relative;
  width: min(52vw, 46vh);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .06);
  transform: scale(calc(1 + var(--bass, 0) * .035));
  transition: transform 90ms linear;
}
.np__art .art { width: 100%; height: 100%; border-radius: 50%; box-shadow: none; }
.np__art .art--empty { font-size: 34px; }

.np__meta {
  display: flex; align-items: center; gap: 12px;
  flex: none;
}
.np__text { min-width: 0; flex: 1; }
.np__title {
  font-size: 21px; font-weight: 700; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.np__artist {
  margin-top: 3px;
  font-size: 14px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.np__freq { flex: none; }
.fav--np { width: 44px; height: 44px; opacity: 1; flex: none; }
.fav--np svg { width: 24px; height: 24px; }

/* The seek input is absolutely positioned, so this box has to own the height
   itself or the times land on top of the bar. */
.np__seek { position: relative; flex: none; height: 46px; margin-top: 6px; }
.np__seek .seek { top: 4px; bottom: auto; height: 20px; }
.np__seek .seek__track { top: 12px; height: 5px; border-radius: 99px; }
/* No hover on a touchscreen, so the handle is simply always there. */
.np__seek .seek::-webkit-slider-thumb { opacity: 1; }
.np__seek .seek::-moz-range-thumb { opacity: 1; }
.np__times {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 11.5px; color: var(--text-3);
}

.np__transport {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 4px 4px 0;
  flex: none;
}
.np__transport .icon-btn { width: 46px; height: 46px; }
.np__transport .icon-btn svg { width: 22px; height: 22px; }
.play-btn--big { width: 72px; height: 72px; }
.play-btn--big svg { width: 30px; height: 30px; }

/* It is a phone feature: on a desktop the dock is already the player. */
@media (min-width: 901px) {
  .np { display: none; }
}

@media (max-width: 900px) {
  /* Tapping the strip opens the big player, so say so. */
  .now { cursor: pointer; }
}

/* 14. responsive ────────────────────────────────────────────────────────── */
@media (max-width: 1180px) {
  .track { grid-template-columns: 28px 48px minmax(0,1fr) 92px 52px 76px; }
  .track__source { display: none; }
  .hero { gap: 28px; }
}

@media (max-width: 900px) {
  :root { --dock-h: 76px; --topbar-h: 62px; }

  .app { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "dock"; }

  .rail {
    position: fixed; inset: 0 auto 0 0; z-index: 50;
    width: 268px; transform: translateX(-100%);
    transition: transform var(--base);
    border-right: 1px solid var(--line);
  }
  .app[data-menu="open"] .rail { transform: none; }

  .topbar { padding: var(--safe-t) calc(16px + var(--safe-r)) 0 calc(16px + var(--safe-l)); }
  .topbar__menu.icon-btn { display: grid; }
  .view { padding: 6px calc(16px + var(--safe-r)) 32px calc(16px + var(--safe-l)); }

  .hero { grid-template-columns: minmax(0, 1fr); padding: 22px 0 4px; }
  .hero__mark { width: min(230px, 62vw); justify-self: center; order: -1; }
  .hero__title { font-size: clamp(40px, 13vw, 68px); }
  .stats { gap: 20px; }

  .track { grid-template-columns: 44px minmax(0,1fr) 78px 36px; gap: 10px; padding: 7px 8px; }
  .track__index, .track__dur { display: none; }
  /* The number is the first column on a wide screen and the hairline sits in
     its place. Here the artwork is first, so the line had nowhere to go and
     was being drawn straight across the sleeve. A list that ties rows together
     opens ten pixels of its own — on every row it holds, so the sleeves still
     line up whether or not a particular song has other versions. */
  .tracks[data-tied] .track { padding-left: 18px; }
  .tracks[data-tied] .track__play { left: 18px; }
  .tracks[data-tied] .track[data-gsize]::before { left: 5px; }
  .tracks[data-tied] .track[data-gsize]::after { left: 7px; width: 6px; }
  .track__art { width: 44px; height: 44px; }
  .track__play { left: 8px; width: 44px; height: 44px; border-radius: var(--r-sm); background: rgba(6,4,10,.5); }
  .fav { opacity: 1; width: 36px; height: 36px; }
  .fav--float { opacity: 1; transform: none; }

  .folders { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 18px 12px; }
  .artist-head { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .artist-head__mosaic { width: 118px; }

  .dock {
    padding: 0 calc(12px + var(--safe-r)) calc(8px + var(--safe-b)) calc(12px + var(--safe-l));
  }
  .dock__grid { grid-template-columns: minmax(0,1fr) auto; height: calc(var(--dock-h) - 20px); }
  .dock__side, .viz { display: none; }
  .dock__left { gap: 0; }
  .now__art { width: 44px; height: 44px; }
  .transport { gap: 0; }
  .transport__row { gap: 2px; }
  /* The clock lives in the full-screen player on a phone; the dock is too
     short to carry a second line. */
  .transport .time { display: none; }
  #btn-shuffle, #btn-repeat { display: none; }

  .queue {
    right: calc(8px + var(--safe-r)); left: calc(8px + var(--safe-l));
    width: auto; bottom: calc(var(--dock-space) + 8px);
  }
  .photo { border-radius: var(--r-lg); }
}

@media (max-width: 560px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 14px 12px; }
  .rowscroll { grid-auto-columns: minmax(148px, 1fr); }
  .btn { height: 44px; padding: 0 18px; }
  .social { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) *,
  :root:not([data-motion="full"]) *::before,
  :root:not([data-motion="full"]) *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
:root[data-motion="calm"] *,
:root[data-motion="calm"] *::before,
:root[data-motion="calm"] *::after {
  animation-duration: .01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
  scroll-behavior: auto !important;
}

@media (prefers-contrast: more) {
  :root { --text-2: #d0c9da; --text-3: #a79db6; --line: #40334f; }
}
