/* Community mixes.

   Layout: a browsable shelf of community mixes above a persistent player dock,
   like a listening post in a record shop. Single dark theme by choice - this is
   a night-time product and it should look the same at 2am on any device.

   Taken from play-prototype.html. Anything added since is marked. */

:root {
  --ink:        #0A0C16;
  --surface:    #131728;
  --surface-2:  #1C2138;
  --line:       #262C45;
  --text:       #ECEDF6;
  --muted:      #9AA0BE;
  --accent:     #A78BFA;
  --accent-dim: rgba(167, 139, 250, 0.14);
  --accent-ink: #14102A;

  --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --font-body: 'Familjen Grotesk', system-ui, -apple-system, sans-serif;

  color-scheme: dark;
}

* { box-sizing: border-box; }

/* The page is a fixed frame, not a document: the title, the moods and the player
   stay put and only the mixes move. dvh rather than vh so a phone's collapsing
   address bar does not leave the player hanging off the bottom of the screen. */
html { height: 100%; }
body {
  margin: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* the fixed upper frame: brand bar, title, mood chips */
.head {
  flex: 0 0 auto;
  background: var(--ink);
  border-bottom: 1px solid var(--line);
  padding-top: env(safe-area-inset-top, 0px);
}
.head-inner {
  max-width: 1120px;
  margin: 0 auto;
  padding-inline: 20px;
}

/* the only part of the page that moves */
.scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Setting one axis to auto makes the other compute to auto too, which raised a
     horizontal scrollbar under the grid. Nothing here is meant to scroll
     sideways, so that axis is closed explicitly. */
  overflow-x: hidden;
  overscroll-behavior: contain;
}

img { max-width: 100%; }
[hidden] { display: none !important; }

.wrap {
  max-width: 1120px;
  margin: 0 auto;
  padding-inline: 20px;
  padding-block: 18px 28px;
}

/* ---------- header ---------- */
.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-block: 14px;
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand svg { display: block; }
.brand b {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 400;
  letter-spacing: 0.01em;
}
.btn {
  display: inline-block;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  padding: 10px 18px;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
}
.btn:hover { border-color: var(--accent); }
.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.btn-primary:hover { background: #B9A2FB; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- hero ----------
   The prototype set a 30ch measure against a 60px display face, which on a wide
   screen wrapped the heading onto five lines and pushed the mixes themselves
   below the fold. The mixes are the point of the page, so the heading now runs
   the full width of the grid, and the sentence under it does too, so both sit on
   one line on a desktop instead of wrapping into a block. */
.hero { padding-block: 18px 26px; max-width: none; }
.hero h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(30px, 4.6vw, 50px);
  line-height: 1.08;
  margin: 0;
  text-wrap: balance;
}
.hero h1 em { font-style: italic; color: var(--accent); }
.hero p { color: var(--muted); margin: 10px 0 0; font-size: 16px; max-width: none; }

/* ---------- filters and pager ---------- */
.filterbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 18px;
}
.filters { display: flex; flex-wrap: wrap; gap: 8px; }

.pager { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pager-label {
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  min-width: 9ch;
  text-align: center;
}
.pager-btn {
  font-family: inherit;
  font-size: 17px;
  line-height: 1;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.pager-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pager-btn:disabled { opacity: .35; cursor: default; }
.chip {
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  padding: 7px 15px;
  cursor: pointer;
}
.chip[aria-pressed="true"] {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------- mix grid ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 14px;
}
.card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  text-align: left;
  font-family: inherit;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 18px;
  cursor: pointer;
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease, transform .18s ease;
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); }
.card[data-current="true"] { border-color: var(--accent); background: var(--surface-2); }
.card h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 23px;
  line-height: 1.15;
}
.by { color: var(--muted); font-size: 13px; margin-top: 3px; }

/* The sounds in a mix, as a plain run of names. A row per sound made a mix of
   twelve sounds three times the height of a mix of three, and the grid looked
   ragged; the levels are in the panel where there is room to read them.
   Cut off after three lines so every card stays the same shape. */
.layers {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.card-foot { display: flex; align-items: center; justify-content: space-between; margin-top: auto; }
.mood {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.play-dot {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--accent-dim);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}

/* added: shown when the library is empty or unreachable */
.notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 18px;
  color: var(--muted);
  margin: 0;
}

/* ---------- player dock ---------- */
.dock {
  flex: 0 0 auto;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.dock-inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 12px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.transport {
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: var(--accent-ink);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}
/* added: the loading state while the loops are fetched and decoded */
.transport[data-busy="true"] { cursor: progress; }
.transport[data-busy="true"] svg { animation: mixes-pulse 1s ease-in-out infinite; }
@keyframes mixes-pulse { 50% { opacity: .35; } }

.now { min-width: 0; flex-grow: 1; }
.now strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 19px;
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.now span { font-size: 12.5px; color: var(--muted); }

/* "More mixes by @someone" under the meta line; a real link, so it also opens
   the narrowed list in a new tab */
.more-by {
  display: block;
  font-size: 12.5px; color: var(--accent); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.more-by:hover { text-decoration: underline; }
.more-by[hidden] { display: none; }

/* the chip that shows, and clears, a one-person filter */
.chip-by[hidden] { display: none; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.panel {
  border-top: 1px solid var(--line);
  max-width: 1120px;
  margin: 0 auto;
  padding: 20px;
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 28px;
  max-height: 52vh;
  overflow-y: auto;
}
.panel h4 {
  margin: 0 0 12px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.mixer { display: flex; flex-direction: column; gap: 12px; }
.lane { display: grid; grid-template-columns: 84px minmax(0, 1fr) 38px; align-items: center; gap: 12px; }
.lane .nm { font-size: 13.5px; }
.lane .track { height: 6px; border-radius: 3px; background: var(--ink); overflow: hidden; }
.lane .track i { display: block; height: 100%; border-radius: 3px; background: var(--accent); }
.lane .pct { font-size: 12px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
/* added: a layer that would not load says so instead of just being quiet */
.lane[data-failed="true"] .nm { color: var(--muted); text-decoration: line-through; }

.locked {
  display: flex; align-items: center; gap: 13px; width: 100%;
  margin-top: 18px; text-align: left; font-family: inherit;
  background: transparent; border: 1px dashed var(--line);
  border-radius: 14px; padding: 15px; cursor: pointer; color: inherit;
  text-decoration: none;
  transition: border-color .18s ease;
}
.locked:hover { border-color: var(--accent); }
.locked strong { display: block; font-size: 14px; margin-bottom: 3px; }
.locked em { font-style: normal; font-size: 12.5px; color: var(--muted); }
.locked .ic {
  width: 34px; height: 34px; border-radius: 10px; background: var(--accent-dim);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.box.flash { border-color: var(--accent); }

.aside { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.box {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px;
}
.share-url {
  display: block;
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--muted);
  background: var(--ink);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 10px;
  margin-bottom: 10px;
  overflow-x: auto;
  white-space: nowrap;
}
.qr {
  width: 96px; height: 96px;
  border: 2px dashed var(--line);
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--muted);
  flex-shrink: 0;
}
.qr-row { display: flex; gap: 16px; align-items: center; }
.qr-row p { margin: 0; font-size: 13px; color: var(--muted); }
.qr-row strong { display: block; color: var(--text); font-size: 14.5px; margin-bottom: 4px; }

.nudge {
  position: fixed;
  left: 16px; right: 16px;
  bottom: calc(86px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 14px;
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 480px;
  margin-inline: auto;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .45);
}
.nudge p { margin: 0; font-size: 13.5px; font-weight: 500; flex-grow: 1; }
.nudge .btn {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: #fff;
  padding: 8px 14px;
  font-size: 13px;
}
.nudge .x {
  background: none; border: 0; color: var(--accent-ink);
  cursor: pointer; font-size: 18px; line-height: 1; padding: 4px;
}

/* Added: the card a listening limit leaves behind once the mix has faded. It
   sits where the nudge does and blocks nothing - it is a sign-off, not a wall. */
.limit {
  position: fixed;
  left: 16px; right: 16px;
  bottom: calc(86px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  max-width: 440px;
  margin-inline: auto;
  background: var(--surface-2);
  border: 1px solid var(--accent);
  border-radius: 16px;
  padding: 18px 20px 20px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .55);
}
.limit h4 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 24px;
  line-height: 1.15;
  margin: 0 28px 6px 0;
}
.limit p { margin: 0 0 16px; color: var(--muted); font-size: 14px; }
.limit-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.limit .x {
  position: absolute; top: 10px; right: 10px;
  background: none; border: 0; color: var(--muted);
  cursor: pointer; font-size: 20px; line-height: 1; padding: 6px;
}
.limit .x:hover { color: var(--text); }

/* Added: marks a mix, or a layer in the mixer, that uses premium sounds */
.premium-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  color: var(--accent);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  vertical-align: 1px;
}

/* Added: the site's cookie notice, in this page's colours. The library's own
   stylesheet is loaded first and these win on order. Raised clear of the dock. */
.cc-window {
  font-family: var(--font-body) !important;
  font-size: 13.5px;
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .45);
}
.cc-window.cc-floating { max-width: 22rem; padding: 16px 18px; }
.cc-window.cc-bottom { bottom: calc(86px + env(safe-area-inset-bottom, 0px)); }
.cc-link { color: var(--text); opacity: 1; padding: 0; }
.cc-link:hover { color: var(--accent); }
.cc-window .cc-btn {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--accent-ink);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  padding: 7px 16px;
}
.cc-window .cc-btn:hover { background: #B9A2FB; color: var(--accent-ink); }
.cc-compliance { justify-content: flex-start; }
/* on a phone the bottom of the screen is the dock and the limit card, so the
   notice goes to the top, over the brand bar, until it is dismissed */
@media (max-width: 720px) {
  .cc-window.cc-floating.cc-bottom {
    top: calc(8px + env(safe-area-inset-top, 0px));
    bottom: auto;
    left: 8px; right: 8px;
    margin: 0;
    max-width: none;
  }
}

@media (max-width: 720px) {
  /* on a phone the chips need the whole width, so the pager drops below them */
  .filterbar { flex-wrap: wrap; gap: 10px; }
  .pager { margin-left: auto; }
  .panel { grid-template-columns: minmax(0, 1fr); gap: 22px; max-height: 58vh; }
  /* on a phone the mixes go straight to the top: the headline and intro are
     hidden from view but kept for screen readers and search engines (the h1 is
     the page's only heading), so they are clipped rather than display:none */
  .hero { padding-block: 0; }
  .hero h1, .hero p {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .dock-inner { padding: 10px 16px; }
  .wrap { padding-inline: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
