/* ==========================================================================
   soundcloud.alxevt.com
   Layout, type and colour modelled on soundcloud.com's page set.
   ========================================================================== */

:root {
  --orange: #f50;
  --orange-hover: #f70;
  --black: #121212;
  --surface: #fff;
  --page-bg: #f2f2f2;
  --highlight: #f3f3f3;
  --border: #e5e5e5;
  --border-strong: #ccc;
  --text: #333;
  --text-strong: #121212;
  --text-muted: #999;
  --text-dim: #666;
  --link: #333;
  --error: #f30;

  --header-h: 46px;
  --player-h: 74px;
  --content-w: 1240px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell,
    "Noto Sans", "Helvetica Neue", Arial, sans-serif;

  /* Seams for skins (public/skins.css). Each default below is the literal value
     it replaced, so with no skin selected the page renders exactly as before.
     `--font-chrome` is the face used by the player, timings, counts and chips —
     the parts a skin can turn into a board or a printed page without touching
     body copy. */
  --btn-bg: linear-gradient(#fff, #f2f2f2);
  --input-bg: #fff;
  --font-chrome: var(--font);

  --radius: 4px;
  /* The lift under a circular control that floats over content. Its default is
     the literal value it replaced at .carousel__nav, so Classic is unchanged.
     It was declared as `--shadow-card` and consumed nowhere, which meant a dark
     skin's override of it silently did nothing. */
  --shadow-float: 0 1px 6px rgba(0, 0, 0, 0.18);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--page-bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Keep the fixed player from covering the end of every page. */
  padding-bottom: var(--player-h);
}

a { color: var(--link); text-decoration: none; }
a:hover { color: var(--text-strong); }

button {
  font-family: inherit;
  font-size: inherit;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  padding: 0;
}

img { display: block; max-width: 100%; }

/* ---------- header -------------------------------------------------------- */

.sc-header {
  position: sticky;
  top: 0;
  z-index: 60;
  height: var(--header-h);
  background: var(--black);
  border-bottom: 1px solid #000;
}

.sc-header__inner {
  max-width: var(--content-w);
  margin: 0 auto;
  height: 100%;
  padding: 0 12px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.sc-logo {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--orange);
  flex-shrink: 0;
}
.sc-logo:hover { color: var(--orange-hover); }
.sc-logo svg { display: block; }

.sc-nav {
  display: flex;
  align-items: center;
  height: 100%;
}

.sc-nav a {
  color: #ccc;
  font-size: 14px;
  padding: 0 12px;
  line-height: var(--header-h);
  height: 100%;
  white-space: nowrap;
}
.sc-nav a:hover { color: #fff; background: #1d1d1d; }

.sc-search {
  flex: 1;
  max-width: 420px;
  position: relative;
}

.sc-search input {
  width: 100%;
  height: 28px;
  border-radius: var(--radius);
  border: 1px solid #333;
  background: var(--input-bg);
  padding: 0 30px 0 8px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text);
}
.sc-search input:focus {
  outline: none;
  border-color: var(--orange);
}
.sc-search button {
  position: absolute;
  right: 0; top: 0;
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  color: var(--text-muted);
}
.sc-search button:hover { color: var(--text); }

.sc-header__spacer { flex: 1; }

/* At phone width the header holds the logo, the search field and the look
   control, and that is all it has room for. The nav links go: the logo already
   reaches home, and Discover and Tags are one tap from there. Without this the
   look control is pushed past the viewport and takes the whole page's scroll
   width with it. */
@media (max-width: 700px) {
  .sc-nav { display: none; }
  .sc-header__inner { gap: 8px; }
}


/* ---------- header controls (look + preferences) -------------------------- */

/* One row, one shape. The look button and the three preference toggles are the
   same control in different clothes, so they are styled together rather than
   each carrying a copy that can drift. */
.hdr-toggle,
.skin-switch__button {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 9px;
  border-radius: var(--radius);
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: #ccc;
  font-family: var(--font-chrome);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  white-space: nowrap;
}
.hdr-toggle:hover,
.skin-switch__button:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.hdr-toggle svg,
.skin-switch__button svg { width: 15px; height: 15px; flex-shrink: 0; }

/* An engaged preference carries the accent, which is how you can tell at a
   glance which of the four are doing something. */
.hdr-toggle.is-on { color: var(--orange); border-color: var(--orange); }
.hdr-toggle.is-on svg { color: var(--orange); }

/* These two controls were header chrome until CI-0017 moved them into the menu,
   and they kept the header's palette: #ccc on a translucent-white plate, which
   is legible on the near-black header and invisible on the panel, whose ground
   is `--surface` — white in Classic and Day, near-white in Dawn. Only Night hid
   the defect. Inside the panel they take the panel's own tokens. */
.app-menu .hdr-toggle,
.app-menu .skin-switch__button {
  border-color: var(--border-strong);
  background: var(--highlight);
  color: var(--text-dim);
}
.app-menu .hdr-toggle:hover,
.app-menu .skin-switch__button:hover { color: var(--text-strong); border-color: var(--text-muted); }
.app-menu .hdr-toggle.is-on { color: var(--orange); border-color: var(--orange); }

/* Below this the row would push past the viewport, so the labels go and the
   marks carry the meaning — the same trade the nav links already make. */
@media (max-width: 900px) {
  .hdr-toggle span,
  .skin-switch__button span { display: none; }
  .hdr-toggle,
  .skin-switch__button { padding: 0 7px; }
}

/* A track SoundCloud will not serve is hidden unless the listener asks. The
   rule is on the root, so toggling repaints rows already on screen. */
[data-unavailable="hidden"] .track-row.is-unavailable { display: none; }

/* ---------- layout -------------------------------------------------------- */

.sc-main {
  max-width: var(--content-w);
  margin: 0 auto;
  padding: 16px 12px 40px;
}

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 24px;
  align-items: start;
}

@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .layout__aside { display: none; }
}

.section-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
  margin: 0 0 12px;
}

/* ---------- hero (track + playlist) --------------------------------------- */

.hero {
  position: relative;
  background: linear-gradient(135deg, #7a5fff, #f50);
  border-radius: var(--radius);
  overflow: hidden;
  padding: 20px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 20px;
  min-height: 300px;
  color: #fff;
}

@media (max-width: 700px) {
  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero__art { display: none; }
}

/* Blurred artwork behind the hero: this is what gives each track and playlist
   page its own colour without needing to read pixels cross-origin. */
.hero__bg {
  position: absolute;
  inset: -40px;
  background-size: cover;
  background-position: center;
  filter: blur(40px) saturate(1.6);
  opacity: .85;
  z-index: 0;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.15), rgba(0,0,0,.5));
  z-index: 0;
}
.hero > *:not(.hero__bg) { position: relative; z-index: 1; }

.hero__main { display: flex; flex-direction: column; min-width: 0; }

.hero__top { display: flex; gap: 12px; align-items: flex-start; }

.hero__play {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: background .15s;
}
.hero__play:hover { background: var(--orange-hover); }
.hero__play svg { width: 22px; height: 22px; margin-left: 2px; }
.hero__play.is-playing svg { margin-left: 0; }

.hero__titles { min-width: 0; flex: 1; }

.hero__artist {
  display: inline-block;
  background: rgba(0,0,0,.4);
  color: #fff;
  font-size: 14px;
  padding: 3px 8px;
  border-radius: 3px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hero__artist:hover { color: #fff; background: rgba(0,0,0,.55); }

.hero__title {
  display: block;
  background: rgba(0,0,0,.4);
  color: #fff;
  font-size: 18px;
  font-weight: 400;
  padding: 4px 8px;
  border-radius: 3px;
  margin-top: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hero__meta {
  margin-left: auto;
  text-align: right;
  font-size: 12px;
  color: rgba(255,255,255,.75);
  flex-shrink: 0;
}
.hero__genre {
  display: inline-block;
  border: 1px solid rgba(255,255,255,.4);
  border-radius: 3px;
  padding: 1px 6px;
  margin-top: 4px;
}

.hero__wave {
  flex: 1;
  margin-top: 20px;
  min-height: 130px;
  position: relative;
}

.hero__art {
  width: 260px; height: 260px;
  border-radius: var(--radius);
  overflow: hidden;
  background: rgba(0,0,0,.25);
  align-self: start;
  justify-self: end;
}
.hero__art img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- waveform ------------------------------------------------------ */

.waveform {
  position: relative;
  width: 100%;
  height: 130px;
  cursor: pointer;
  touch-action: none;
}
.waveform canvas { display: block; width: 100%; height: 100%; }

.waveform__time {
  position: absolute;
  bottom: -2px;
  font-size: 11px;
  color: rgba(255,255,255,.85);
  background: rgba(0,0,0,.4);
  padding: 1px 4px;
  border-radius: 2px;
  pointer-events: none;
}
.waveform__time--elapsed { left: 0; }
.waveform__time--total { right: 0; }

/* ---------- action bar ---------------------------------------------------- */

.actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 0;
  flex-wrap: wrap;
}

/* Sign-in unavailable on this deployment, so the controls that need an account
   are withheld rather than shown dead. Driven by an attribute on the root that
   public/auth.js keeps current, which lets already-rendered buttons follow the
   session without a re-render. */
[data-auth="off"] .actions [data-like],
[data-auth="off"] .actions [data-repost] { display: none; }

/* ---------- sign-in failure notice ---------------------------------------- */

/* The OAuth callback reports failures by redirecting to /?auth_error=<reason>.
   Nothing read that, so every failure landed the listener on the home page with
   an unexplained query string and no sign that anything had gone wrong. */
.auth-notice {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 12px auto 0;
  max-width: var(--content-w);
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--error);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
}
.auth-notice__close {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 4px;
}
.auth-notice__close:hover { color: var(--text-strong); }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 9px;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  background: var(--btn-bg);
  color: var(--text-dim);
  font-size: 11px;
  white-space: nowrap;
}
.btn:hover { border-color: #999; color: var(--text); }
.btn svg { width: 13px; height: 13px; }
.btn.is-active { color: var(--orange); border-color: var(--orange); }

.actions__stats {
  font-family: var(--font-chrome);
  margin-left: auto;
  display: flex;
  gap: 14px;
  color: var(--text-muted);
  font-size: 12px;
}
.actions__stats span { display: inline-flex; align-items: center; gap: 4px; }
.actions__stats svg { width: 12px; height: 12px; }

/* ---------- tabs ---------------------------------------------------------- */

.tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
  margin: 4px 0 16px;
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tabs a {
  padding: 8px 12px;
  font-size: 14px;
  color: var(--text-dim);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.tabs a:hover { color: var(--text-strong); }
.tabs a.is-active {
  color: var(--orange);
  border-bottom-color: var(--orange);
  font-weight: 500;
}

/* ---------- track rows ---------------------------------------------------- */

.track-list { list-style: none; margin: 0; padding: 0; }

.track-row {
  display: flex;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
  align-items: flex-start;
}
.track-row:last-child { border-bottom: 0; }

.track-row__art {
  display: block;
  position: relative;
  width: 100px; height: 100px;
  flex-shrink: 0;
  background: var(--highlight);
  border-radius: 2px;
  overflow: hidden;
}
.track-row__art img { width: 100%; height: 100%; object-fit: cover; }
/* The whole artwork plays, as on the reference. The button stays as the visible
   affordance and the keyboard-reachable control; this is the mouse target. */
.track-row__art[data-play] { cursor: pointer; }

.track-row__play {
  position: absolute;
  left: 6px; bottom: 6px;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity .12s;
  box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.track-row:hover .track-row__play,
.track-row__play.is-playing { opacity: 1; }
.track-row__play svg { width: 15px; height: 15px; margin-left: 1px; }
.track-row__play.is-playing svg { margin-left: 0; }

.track-row__body { flex: 1; min-width: 0; }

.track-row__head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: baseline;
}

.track-row__artist {
  color: var(--text-muted);
  font-size: 13px;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.track-row__title {
  color: var(--text-strong);
  font-size: 15px;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 1px;
}
.track-row__title:hover { color: var(--orange); }

.track-row__date {
  font-family: var(--font-chrome);
  color: var(--text-muted);
  font-size: 11px;
  white-space: nowrap;
  flex-shrink: 0;
}

.track-row__wave {
  height: 40px;
  margin: 8px 0 6px;
  position: relative;
  cursor: pointer;
}
.track-row__wave canvas { display: block; width: 100%; height: 100%; }

.track-row__stats {
  font-family: var(--font-chrome);
  display: flex;
  gap: 14px;
  color: var(--text-muted);
  font-size: 13px;
}
.track-row__stats span { display: inline-flex; align-items: center; gap: 5px; }
.track-row__stats svg { width: 13px; height: 13px; }

.track-row__context {
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 5px;
  padding-bottom: 6px;
}
.track-row__context svg { width: 12px; height: 12px; }

.track-row.is-current .track-row__title { color: var(--orange); }

/* A track SoundCloud will not serve. The artwork dims and the play control is
   absent rather than present-and-dead, the same posture the sign-in gate takes:
   withhold what cannot work instead of offering it. */
.track-row.is-unavailable .track-row__art { opacity: .45; }
.track-row.is-unavailable .track-row__title { color: var(--text-muted); }
/* The explanation, said in the row. A badge alone tells you something is wrong
   and not what, and a title attribute tells only the people who hover. */
.track-row__notice {
  margin: 6px 0 0;
  padding: 7px 10px;
  border-radius: var(--radius);
  background: var(--highlight);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.45;
}
.track-row__notice strong { color: var(--text-strong); font-weight: 500; }
.track-row__notice a { color: var(--orange); white-space: nowrap; }
.track-row__notice a:hover { text-decoration: underline; }

.track-row__unavailable {
  display: inline-block;
  margin-right: 8px;
  padding: 1px 6px;
  border-radius: 2px;
  background: var(--highlight);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* compact rows (playlist track lists, queue) */

.track-row--compact { padding: 6px 0; align-items: center; }
.track-row--compact .track-row__art { width: 30px; height: 30px; }
.track-row--compact .track-row__play { left: 0; bottom: 0; width: 30px; height: 30px; border-radius: 2px; }
.track-row--compact .track-row__play svg { width: 12px; height: 12px; }
.track-row--compact .track-row__title { font-size: 14px; margin: 0; }
.track-row--compact .track-row__body { display: flex; align-items: center; gap: 8px; }
.track-row--compact .track-row__artist { font-size: 14px; }
.track-row--compact .track-row__artist::after { content: "—"; margin: 0 4px; color: var(--border-strong); }
.track-row__index { color: var(--text-muted); font-size: 12px; width: 22px; text-align: right; flex-shrink: 0; }

/* Add to Next up. Revealed on hover like the queue panel's remove control, but
   never hidden from the keyboard or from a touch device, where no hover exists
   to reveal it with. */
.track-row__queue {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  margin-left: 8px;
  border: 0;
  background: none;
  border-radius: 3px;
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
  transition: color .12s, background .12s;
}
.track-row:hover .track-row__queue,
.track-row__queue:focus-visible { opacity: 1; }
@media (hover: none) { .track-row__queue { opacity: 1; } }
.track-row__queue:hover { color: var(--text-strong); background: var(--highlight); }
.track-row__queue.is-added { opacity: 1; color: var(--orange); }
.track-row--compact .track-row__queue { align-self: center; }
/* Its opposite. Same box, so a row does not reflow when the queue picks the
   track up; the orange says "this one is queued" the way `is-added` does. */
.track-row__queue--remove { color: var(--orange); margin-left: 2px; }
.track-row__queue--remove:hover { color: var(--text-strong); background: var(--highlight); }
.track-row__dur { margin-left: auto; color: var(--text-muted); font-size: 12px; flex-shrink: 0; }

/* ---------- user / playlist cards ----------------------------------------- */

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

.user-card { text-align: center; }
.user-card__avatar {
  display: block;
  width: 100px; height: 100px;
  border-radius: 50%;
  overflow: hidden;
  margin: 0 auto 8px;
  background: var(--highlight);
}
.user-card__avatar img { width: 100%; height: 100%; object-fit: cover; }
.user-card__name {
  display: block;
  color: var(--text-strong);
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-card__name:hover { color: var(--orange); }
.user-card__meta { color: var(--text-muted); font-size: 11px; margin-top: 2px; }

.playlist-card__art {
  display: block;
  position: relative;
  aspect-ratio: 1;
  background: var(--highlight);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 8px;
}
.playlist-card__art img { width: 100%; height: 100%; object-fit: cover; }
.playlist-card__play {
  position: absolute;
  left: 8px; bottom: 8px;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity .12s;
}
.playlist-card:hover .playlist-card__play { opacity: 1; }
.playlist-card__play svg { width: 13px; height: 13px; margin-left: 2px; }
.playlist-card__badge {
  position: absolute;
  right: 6px; top: 6px;
  background: rgba(0,0,0,.6);
  color: #fff;
  font-size: 10px;
  padding: 2px 5px;
  border-radius: 2px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.playlist-card__title {
  display: block;
  color: var(--text-strong);
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.playlist-card__title:hover { color: var(--orange); }
.playlist-card__artist {
  display: block;
  color: var(--text-muted);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- user profile header ------------------------------------------- */

.profile {
  background: linear-gradient(135deg, #444, #1a1a1a);
  border-radius: var(--radius);
  padding: 24px;
  display: flex;
  gap: 20px;
  align-items: center;
  color: #fff;
  margin-bottom: 4px;
}
.profile__avatar {
  width: 140px; height: 140px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: rgba(255,255,255,.1);
}
.profile__avatar img { width: 100%; height: 100%; object-fit: cover; }
.profile__body { min-width: 0; flex: 1; }
.profile__name {
  font-size: 24px;
  font-weight: 500;
  margin: 0 0 4px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.profile__verified { color: var(--orange); display: inline-flex; }
.profile__verified svg { width: 16px; height: 16px; }
.profile__location { color: rgba(255,255,255,.7); font-size: 13px; }
.profile__counts {
  display: flex;
  gap: 24px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.profile__count b { display: block; font-size: 16px; font-weight: 500; }
.profile__count span { font-size: 11px; color: rgba(255,255,255,.7); text-transform: uppercase; letter-spacing: .04em; }

/* ---------- comments ------------------------------------------------------ */

.comment {
  display: flex;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.comment:last-child { border-bottom: 0; }
.comment__avatar {
  display: block;
  width: 32px; height: 32px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--highlight);
}
.comment__avatar img { width: 100%; height: 100%; object-fit: cover; }
.comment__body { min-width: 0; flex: 1; }
.comment__head { font-size: 12px; color: var(--text-muted); }
.comment__author { color: var(--text-dim); }
.comment__author:hover { color: var(--orange); }
.comment__at { color: var(--orange); }
.comment__text { font-size: 14px; color: var(--text); margin-top: 2px; overflow-wrap: anywhere; }

/* ---------- description / tags -------------------------------------------- */

.description {
  font-size: 14px;
  color: var(--text-dim);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 12px 0;
  position: relative;
  /* Generous, then it scrolls. The clamp this replaces was `overflow: hidden`
     with an `.is-expanded` class no script ever set, so anything past 180px was
     in the DOM and unreachable — the third control in this stylesheet drawn for
     a behaviour that was never wired. */
  max-height: 420px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.description::-webkit-scrollbar { width: 8px; }
.description::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}
.description::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }

.tag-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--highlight);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 2px 8px;
  font-size: 12px;
  color: var(--text-dim);
}
.tag:hover { border-color: var(--orange); color: var(--orange); }

/* ---------- states -------------------------------------------------------- */

.state {
  padding: 48px 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: 15px;
}
.state__title { color: var(--text-strong); font-size: 20px; margin-bottom: 6px; }

.spinner {
  width: 22px; height: 22px;
  border: 2px solid var(--border);
  border-top-color: var(--orange);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  margin: 24px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.load-more { display: grid; place-items: center; min-height: 48px; }

/* ---------- bottom mini player -------------------------------------------- */

.player {
  font-family: var(--font-chrome);
  /* The bar's controls size themselves from these four, so the phone override
     below is four numbers rather than four rules. Local to the bar on purpose:
     the `:root` token set is a documented surface with its own gate. */
  --player-btn: 38px;
  --player-icon: 24px;
  --player-play: 52px;
  --player-play-icon: 26px;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 100;
  height: var(--player-h);
  background: var(--black);
  border-top: 1px solid #000;
  color: #ccc;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px;
}

/* Docked on every page, including before anything has been played — the idle
   bar simply reads as unloaded rather than sliding away. */
.player:not(.is-active) .player__scrub,
.player:not(.is-active) .player__time { opacity: .35; }
.player__idle { color: var(--text-muted); font-size: 12px; }
.player.is-active .player__idle { display: none; }

.player__controls { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

.player__btn {
  width: var(--player-btn); height: var(--player-btn);
  display: grid;
  place-items: center;
  color: #ccc;
  border-radius: 3px;
}
.player__btn:hover { color: #fff; }
.player__btn svg { width: var(--player-icon); height: var(--player-icon); }
.player__btn.is-on { color: var(--orange); }
.player__btn[disabled] { opacity: .35; cursor: default; }

.player__play {
  width: var(--player-play); height: var(--player-play);
  border-radius: 50%;
  background: var(--orange);
  color: #fff;
}
.player__play:hover { background: var(--orange-hover); color: #fff; }
/* The play triangle was 18px against every other glyph's 19 — the smallest icon
   in the bar, inside its largest button. It is now the largest, and a little
   larger than the transport glyphs because the triangle's path fills less of its
   box than an arrow's does. */
.player__play svg { width: var(--player-play-icon); height: var(--player-play-icon); margin-left: 3px; }
.player__play.is-playing svg { margin-left: 0; }

.player__time {
  font-family: var(--font-chrome);
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  width: 38px;
  text-align: center;
  flex-shrink: 0;
}

/* The hit area is the full height of the bar; the waveform inside it keeps the
   32px it has always been drawn at. They were the same box, and a click a few
   pixels above or below the drawn band — which still reads as "on the progress
   bar" — fell through to the bar and did nothing. Fifty-seven per cent of the
   control was dead, which is what "click does not work in the mini player"
   meant. Nothing here changes what is painted. */
.player__scrub {
  flex: 1;
  height: 100%;
  min-width: 80px;
  position: relative;
  display: flex;
  align-items: center;
  cursor: pointer;
  touch-action: none;
}
.player__scrub canvas { display: block; width: 100%; height: 32px; }

.player__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 260px;
  flex-shrink: 0;
  min-width: 0;
}
@media (max-width: 760px) {
  .player__meta { width: auto; }
  .player__meta .player__text { display: none; }
}
.player__art {
  width: 44px; height: 44px;
  border-radius: 2px;
  overflow: hidden;
  background: #333;
  flex-shrink: 0;
}
.player__art img { width: 100%; height: 100%; object-fit: cover; }
.player__text { min-width: 0; }
.player__title, .player__artist {
  display: block;
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.player__title { color: #fff; }
.player__title:hover { color: var(--orange); }
.player__artist { color: var(--text-muted); font-size: 11px; }
.player__artist:hover { color: #fff; }

.player__volume { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.player__volume input {
  width: 64px;
  accent-color: var(--orange);
  cursor: pointer;
}
@media (max-width: 900px) { .player__volume input { display: none; } }

/* At phone width the bar cannot hold every control. Volume and the queue
   toggle go first: both are pointer affordances with no touch equivalent (the
   device has its own volume, and the queue is reachable from the page), while
   the transport and the scrubber are what a phone actually needs. */
/* On a phone the bar keeps the sizes it has always had — the growth above is for
   the screens that have room for it — and the artwork joins the volume, the
   queue button and the track text in standing down, which is the rule this bar
   has followed since it was written: at each step the least informative thing
   goes. Before this it did not stand down and was simply clipped, 36px of it
   hanging off the right edge at 390px. */
@media (max-width: 700px) {
  .player {
    gap: 6px;
    padding: 0 8px;
    --player-btn: 32px;
    --player-icon: 20px;
    --player-play: 42px;
    --player-play-icon: 22px;
  }
  .player__controls { gap: 4px; }
  .player__volume,
  .player__meta,
  .player [data-act="queue"] { display: none; }
}

.player__error {
  position: absolute;
  left: 12px; top: -26px;
  background: var(--error);
  color: #fff;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 3px;
}

/* ---------- queue panel --------------------------------------------------- */

.queue {
  position: fixed;
  right: 0;
  bottom: var(--player-h);
  z-index: 99;
  width: 320px;
  max-height: 60vh;
  background: var(--black);
  border: 1px solid #000;
  border-bottom: 0;
  overflow-y: auto;
  display: none;
}
.queue.is-open { display: block; }
/* The head is what sticks now; the title is just its label. */
.queue__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  border-bottom: 1px solid #262626;
  position: sticky;
  top: 0;
  background: var(--black);
  z-index: 1;
}
.queue__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-right: 6px;
  flex-shrink: 0;
  border: 0;
  background: none;
  border-radius: 3px;
  color: var(--text-muted);
  cursor: pointer;
}
.queue__close:hover { color: #fff; background: #262626; }
.queue__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border: 0;
  background: none;
  border-radius: 3px;
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
}
/* Revealed on hover as on the reference, but never hidden from the keyboard or
   from a touch device, where there is no hover to reveal it with. */
.queue__item:hover .queue__remove,
.queue__remove:focus-visible { opacity: 1; }
@media (hover: none) { .queue__remove { opacity: 1; } }
.queue__remove:hover { color: #fff; background: #333; }

.queue__title {
  font-family: var(--font-chrome);
  color: #fff;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: 10px 12px;
}
.queue__item {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 7px 12px;
  cursor: pointer;
  border-bottom: 1px solid #1c1c1c;
}
.queue__item:hover { background: #1d1d1d; }
.queue__item.is-current { background: #1d1d1d; }
.queue__item.is-current .queue__item-title { color: var(--orange); }
.queue__art { width: 26px; height: 26px; border-radius: 2px; overflow: hidden; flex-shrink: 0; background: #333; }
.queue__art img { width: 100%; height: 100%; object-fit: cover; }
.queue__item-body { min-width: 0; flex: 1; }
.queue__item-title, .queue__item-artist {
  display: block;
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.queue__item-title { color: #eee; }
.queue__item-artist { color: var(--text-muted); font-size: 11px; }

/* ---------- app menu ------------------------------------------------------- */

.hdr-menu-slot { position: relative; }
.hdr-menu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 28px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.06);
  color: #ccc;
  cursor: pointer;
}
.hdr-menu:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.app-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 210;
  width: 260px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--shadow-float);
  padding: 6px 0;
}
.app-menu__section { padding: 6px 12px; }
.app-menu__section + .app-menu__section { border-top: 1px solid var(--border); }
.app-menu__title {
  font-family: var(--font-chrome);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-muted);
  margin: 2px 0 8px;
}
.app-menu__row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.app-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  color: var(--text);
  font-size: 14px;
  padding: 7px 2px;
  cursor: pointer;
  border-radius: 3px;
}
.app-menu__item:hover { color: var(--text-strong); background: var(--highlight); }
.app-menu__admin { font-size: 12px; color: var(--text-dim); padding: 2px 2px 6px; }
.app-menu__admin form { display: flex; gap: 6px; margin-bottom: 6px; }
.app-menu__admin input {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--input-bg);
  color: var(--text);
  font-size: 12px;
  padding: 5px 8px;
}
.app-menu__admin button {
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--highlight);
  color: var(--text);
  font-size: 12px;
  padding: 5px 10px;
  cursor: pointer;
}
.app-menu__admin button:hover { color: var(--text-strong); }
.app-menu__admin button[data-admin-deploy] { border-color: var(--orange); color: var(--orange); }
.app-menu__admin-actions { display: flex; gap: 6px; margin: 8px 0 4px; flex-wrap: wrap; }
.app-menu__admin-msg { color: var(--text-muted); margin-top: 4px; overflow-wrap: anywhere; }
.app-menu__about, .app-menu__note {
  font-size: 12px;
  color: var(--text-dim);
  padding: 2px 2px 6px;
  overflow-wrap: anywhere;
}

/* ---------- debug ---------------------------------------------------------- */

/* The single control of ?debug mode. Fixed and central so it cannot be
   mistaken for part of the design; drawn only when the mode is armed. */
.debug-toggle {
  position: fixed;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 300;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface);
  color: var(--text-dim);
  font-family: var(--font-chrome);
  font-size: 11px;
  letter-spacing: .08em;
  padding: 4px 10px;
  cursor: pointer;
}
.debug-toggle.is-on {
  background: #b00020;
  border-color: #b00020;
  color: #fff;
}

/* ---------- discover carousels -------------------------------------------- */

.selection { margin: 0 0 32px; }

.selection__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.selection__title {
  font-size: 18px;
  font-weight: 500;
  color: var(--text-strong);
  margin: 0;
}
.selection__desc {
  color: var(--text-muted);
  font-size: 13px;
  margin: 2px 0 0;
}

.carousel { position: relative; }

.carousel__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 160px;
  /* Without this the cards stretch to the implicit row, and the artwork's
     aspect-ratio then resolves against that stretched height instead of its
     160px width — which collapsed every card to a strip and pushed its title
     outside the scroll box. Sizing to content is what makes the square square. */
  align-items: start;
  gap: 16px;
  overflow-x: auto;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  padding-bottom: 6px;
  /* Hide the native bar; the arrow buttons are the affordance. */
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track > * { scroll-snap-align: start; }

@media (max-width: 600px) {
  .carousel__track { grid-auto-columns: 140px; }
}

.carousel__nav {
  position: absolute;
  top: 50px;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-float);
  display: grid;
  place-items: center;
  color: var(--text);
  opacity: 0;
  transition: opacity .15s;
  z-index: 2;
}
.carousel:hover .carousel__nav { opacity: 1; }
.carousel__nav[disabled] { opacity: 0 !important; pointer-events: none; }
/* -12px, not -14px: `.sc-main` pads by 12, so a 14px overhang put the prev
   arrow two pixels past the left edge of the page and gave every carousel page
   a 2px horizontal scroll between 700px and the content width. Found while
   widening the responsive check past 390px, which is the only width it had ever
   been measured at. */
.carousel__nav--prev { left: -12px; }
.carousel__nav--next { right: -12px; }

/* The arrows hang outside the track by design, which overflows the page once
   the viewport is near the content width. They are a hover affordance anyway —
   touch scrolls the row directly — so below this width they simply go. */
@media (max-width: 700px) {
  .carousel__nav { display: none; }
}
.carousel__nav svg { width: 16px; height: 16px; }

.genre-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.genre-chip {
  font-family: var(--font-chrome);
  border: 1px solid var(--border-strong);
  border-radius: 16px;
  padding: 5px 14px;
  font-size: 13px;
  color: var(--text-dim);
  background: var(--surface);
}
.genre-chip:hover { border-color: var(--orange); color: var(--orange); }
.genre-chip.is-active { background: var(--orange); border-color: var(--orange); color: #fff; }

/* ---------- misc ---------------------------------------------------------- */

.result-count { color: var(--text-muted); font-size: 12px; margin-bottom: 10px; }

.aside-section { margin-bottom: 24px; }
.aside-user {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 8px 0;
}
.aside-user__avatar { display: block; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex-shrink: 0; background: var(--highlight); }
.aside-user__avatar img { width: 100%; height: 100%; object-fit: cover; }
.aside-user__body { min-width: 0; }
.aside-user__name { display: block; color: var(--text-strong); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aside-user__name:hover { color: var(--orange); }
.aside-user__meta { color: var(--text-muted); font-size: 11px; }

/* A control mid-write says so, rather than asserting an outcome it does not
   yet have. Every control that sets `is-busy` is listed here: the action-bar
   buttons, and the two play controls that fetch a list before starting it —
   those two set the class in playList() and had nothing to show for it. */
.btn.is-busy,
.playlist-card__play.is-busy,
.track-row__play.is-busy { opacity: .55; pointer-events: none; }
