/*
 * new fire — dark-first, art-forward.
 *
 * Replaces no.css. Written classless-first for the elements py4web's auth forms
 * and grids emit (which this app doesn't control), then a small set of classes
 * for the release grid that is the actual product.
 *
 * Dark is the default and light is the override rather than the other way
 * round: this is a page of album covers, and they read better against near
 * black. Both themes are driven off the same custom properties, so a colour is
 * only ever defined once.
 */

:root {
  color-scheme: dark light;

  --bg:         #0b0b0f;
  --surface:    #15151c;
  --surface-2:  #1d1d26;
  --border:     #2a2a35;
  --text:       #eceaf1;
  --muted:      #9a97a8;
  --accent:     #ff5c39;
  --accent-ink: #ffffff;
  --shadow:     0 6px 24px rgb(0 0 0 / 0.45);
  --shadow-lift:0 14px 36px rgb(0 0 0 / 0.55);

  --radius:     14px;
  --radius-sm:  9px;
  --container:  1180px;

  --sans: ui-sans-serif, system-ui, -apple-system, "SF Pro Text", "Segoe UI",
          Roboto, Inter, "Helvetica Neue", Arial, sans-serif;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg:         #fbfaf9;
    --surface:    #ffffff;
    --surface-2:  #f3f1ef;
    --border:     #e5e1dd;
    --text:       #17161b;
    --muted:      #6d6a76;
    --accent:     #d93d17;
    --shadow:     0 4px 16px rgb(20 16 12 / 0.08);
    --shadow-lift:0 12px 30px rgb(20 16 12 / 0.14);
  }
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 32px);
}

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

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  min-height: 62px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-weight: 650;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
}
.brand svg { width: 20px; height: 20px; display: block; }
.brand:hover { color: var(--accent); }

.site-nav { display: flex; align-items: center; gap: 4px; }

.site-nav a {
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
}
.site-nav a:hover { color: var(--text); background: var(--surface-2); }

/* Account menu: a <details> so it needs no JavaScript. */
.menu { position: relative; }
.menu > summary {
  list-style: none;
  cursor: pointer;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 0.92rem;
  color: var(--muted);
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { color: var(--text); background: var(--surface-2); }
.menu[open] > summary { color: var(--text); background: var(--surface-2); }
.menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 190px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  display: grid;
  gap: 2px;
}
.menu-panel a { display: block; padding: 8px 10px; border-radius: 6px; }

/* -------------------------------------------------------------- typography */

main { padding-block: 36px 72px; }

h1 {
  font-size: clamp(1.7rem, 3.4vw, 2.3rem);
  letter-spacing: -0.03em;
  line-height: 1.15;
  margin: 0 0 8px;
}
h2 {
  font-size: 1.15rem;
  letter-spacing: -0.015em;
  margin: 40px 0 16px;
}
h2:first-of-type { margin-top: 24px; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-color: var(--accent); }

.lede { color: var(--muted); font-size: 1.02rem; margin: 0 0 28px; max-width: 62ch; }
.muted { color: var(--muted); }
.small { font-size: 0.86rem; }

/* Section heading with something aligned to its right. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.section-head h2 { margin-bottom: 0; }

/* ------------------------------------------------------------ forms/buttons */

input, select, textarea, button { font: inherit; }

input[type="search"], input[type="text"], input[type="email"],
input[type="password"], select, textarea {
  width: 100%;
  padding: 11px 14px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  outline: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
::placeholder { color: var(--muted); }

button, input[type="submit"], .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  font-weight: 550;
  font-size: 0.94rem;
  color: var(--accent-ink);
  background: var(--accent);
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
button:hover, input[type="submit"]:hover, .button:hover { filter: brightness(1.08); }

button.secondary, .button.secondary {
  color: var(--text);
  background: var(--surface-2);
  border-color: var(--border);
}
button.secondary:hover, .button.secondary:hover { border-color: var(--muted); filter: none; }

/* Follow state that is also the unfollow control: reads "Following" at rest and
   "Unfollow" on hover or keyboard focus, so there is no second button and no
   ambiguity about whether the state is clickable. Both labels occupy the same
   grid cell so the button does not resize as it swaps. */
button.following {
  display: grid;
  color: var(--text);
  background: var(--surface-2);
  border-color: var(--border);
}
button.following > span {
  grid-area: 1 / 1;
  text-align: center;
}
button.following .following-action { visibility: hidden; }
button.following:hover, button.following:focus-visible {
  color: #fff;
  background: #c2352f;
  border-color: #c2352f;
  filter: none;
}
button.following:hover .following-state,
button.following:focus-visible .following-state { visibility: hidden; }
button.following:hover .following-action,
button.following:focus-visible .following-action { visibility: visible; }

/* The search bar on the home and search pages. */
.searchbar { display: flex; gap: 10px; max-width: 560px; margin: 0 0 8px; }
.searchbar input { flex: 1; }

/* ---------------------------------------------------------------- filters */

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 24px;
}
.filters select {
  width: auto;
  min-width: 0;
  padding: 8px 30px 8px 12px;
  font-size: 0.86rem;
  border-radius: 999px;
  background: var(--surface);
  /* Native arrow, drawn rather than imported so it follows the theme. */
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: right 14px top 52%, right 9px top 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
.filters select:hover { border-color: var(--muted); }

.filter-clear {
  padding: 8px 12px;
  font-size: 0.86rem;
  color: var(--muted);
  text-decoration: none;
  border-radius: 999px;
}
.filter-clear:hover { color: var(--text); background: var(--surface-2); }

/* --------------------------------------------------------------- notices */

.notice {
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
  margin: 20px 0;
}
.notice strong { color: var(--text); }
.notice.error { border-left-color: #e5484d; }

.empty {
  padding: 56px 24px;
  text-align: center;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

/* ---------------------------------------------------------- release cards */

.release-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
  gap: clamp(16px, 2.2vw, 26px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.release {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.cover {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
  /* The placeholder is the cover's own background, so a cover that 404s at
     render time only has to drop its <img> to reveal it. Roughly a third of
     releases have no front cover in the archive. */
  background:
    radial-gradient(120% 120% at 30% 20%,
      color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
    var(--surface-2);
}
.cover img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.cover-fallback { color: var(--muted); opacity: 0.5; line-height: 0; }
.cover-fallback svg { width: 34px; height: 34px; }
.release:hover .cover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

/* "3 editions" / "EP" — sits over the artwork, bottom-left. */
.badges {
  position: absolute;
  left: 8px;
  bottom: 8px;
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}
.badge {
  padding: 3px 8px;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: 999px;
  color: #fff;
  background: rgb(0 0 0 / 0.62);
  backdrop-filter: blur(6px);
  border: 1px solid rgb(255 255 255 / 0.14);
}

/* Reissues are a different kind of news from a new record, so the badge is a
   different colour from the neutral edition/type ones rather than one more
   grey chip to read past. */
.badge.reissue {
  color: #1b1206;
  background: #f0b429;
  border-color: rgb(0 0 0 / 0.18);
}

.release-title {
  font-size: 0.94rem;
  font-weight: 570;
  line-height: 1.3;
  margin: 0;
  /* Two lines, then ellipsis — cards must stay the same height to grid well. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.release-title a { color: var(--text); text-decoration: none; }
.release-title a:hover { color: var(--accent); text-decoration: underline; }

.release-artist {
  font-size: 0.86rem;
  margin: -4px 0 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.release-artist a { color: var(--muted); text-decoration: none; }
.release-artist a:hover { color: var(--text); text-decoration: underline; }

.release-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  /* No wrapping: a long label name wrapping to a second line made cards in the
     same row end at different heights, which reads as misalignment across the
     grid. The label truncates instead. */
  flex-wrap: nowrap;
  min-width: 0;
  font-size: 0.78rem;
  color: var(--muted);
  margin-top: auto;
  padding-top: 2px;
}
.release-meta .dot { opacity: 0.45; flex: none; }
.release-meta > span:first-child { flex: none; }
.release-meta a, .release-meta > span {
  color: var(--muted);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.release-meta a:hover { color: var(--text); text-decoration: underline; }

/* ------------------------------------------------------- streaming links */

.listen { display: flex; align-items: center; gap: 7px; }
.listen a {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  transition: transform 0.14s ease;
}
.listen a:hover { transform: scale(1.12); border-color: var(--muted); }
.listen img { width: 15px; height: 15px; display: block; object-fit: contain; }

/* -------------------------------------------------------------- label page */

.label-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}
.label-head h1 { margin-bottom: 4px; }

.stats { display: flex; gap: 20px; flex-wrap: wrap; margin: 12px 0 0; padding: 0; list-style: none; }
.stats div { display: grid; gap: 1px; }
.stats dt, .stats .k { font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); }
.stats dd, .stats .v { margin: 0; font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em; }

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  font-size: 0.9rem;
  color: var(--muted);
}
.pagination a {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
}
.pagination a:hover { border-color: var(--accent); color: var(--accent); }

/* ------------------------------------------------------------------ tables */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.93rem;
}
thead th {
  text-align: left;
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  padding: 0 14px 10px;
  border-bottom: 1px solid var(--border);
}
tbody td { padding: 13px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:hover { background: var(--surface); }

/* --------------------------------------------------------------- follow list */

.label-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.label-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.label-list a { color: var(--text); text-decoration: none; font-weight: 550; }
.label-list a:hover { color: var(--accent); }

/* ------------------------------------------------------------------- auth */

.auth-container {
  max-width: 440px;
  margin: 40px auto;
  padding: 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.auth-container label { display: block; margin: 14px 0 6px; font-size: 0.88rem; color: var(--muted); }
.auth-container input[type="submit"], .auth-container button { width: 100%; margin-top: 20px; }

/* py4web appends the sidecar links ("Sign Up", "Lost Password") as bare
   siblings of the submit input inside the same unclassed <div>, with no
   whitespace between them -- so they render as one run of text. Make that div
   a wrapping flex row: the full-width submit keeps the first line to itself
   and the links drop below it, pushed to opposite ends. */
.auth-container form div:has(> input[type="submit"]) {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 14px;
}
.auth-container form div:has(> input[type="submit"]) > input[type="submit"] {
  flex: 0 0 100%;
}
.auth-container a[role="button"] { font-size: 0.88rem; }
/* Fallback for browsers without :has() -- the full-width submit already forces
   the links onto their own line, so all they are missing is a gap. */
.auth-container a[role="button"] + a[role="button"] { margin-left: 14px; }
.py4web-validation-error { display: block; margin-top: 6px; font-size: 0.82rem; color: #e5484d; }

/* ------------------------------------------------------------------ flash */

/* utils.js only builds Bootstrap toast markup when Bootstrap is on the page.
   It isn't, so the fallback branch runs and what actually lands in
   <flash-alerts> is `<div role="alert" class="info"><span class="close">`.
   These rules dress that, not the toast markup in the other branch. */
flash-alerts {
  position: fixed;
  top: 76px;
  right: clamp(16px, 4vw, 32px);
  z-index: 100;
  display: grid;
  gap: 10px;
  width: min(340px, calc(100vw - 32px));
}

flash-alerts [role="alert"] {
  position: relative;
  padding: 13px 38px 13px 15px;
  font-size: 0.92rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  /* Slides in, then takes itself away — the fallback branch has no timer of
     its own and a flash that sits there until clicked outstays its welcome. */
  animation: toast-in 0.22s ease both, toast-out 0.4s ease 6s both;
}
flash-alerts [role="alert"].error,
flash-alerts [role="alert"].danger { border-left-color: #e5484d; }

flash-alerts .close {
  position: absolute;
  top: 9px;
  right: 9px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  color: var(--muted);
  cursor: pointer;
}
flash-alerts .close::before { content: "\00d7"; font-size: 1.25rem; line-height: 1; }
flash-alerts .close:hover { color: var(--text); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(-6px); visibility: hidden; }
}

/* ----------------------------------------------------------------- footer */

.site-footer {
  border-top: 1px solid var(--border);
  padding: 26px 0;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ---------------------------------------------------------------- mobile */

@media (max-width: 620px) {
  .release-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .header-inner { gap: 10px; }
  .site-nav a { padding: 7px 9px; }
  .menu > summary { max-width: 10ch; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
  .release:hover .cover { transform: none; }
}
