/* ==========================================================================
   Monochrome editorial store.
   Grey ground, white content panels, oversized condensed type, and a
   full-bleed grayscale hero with the wordmark multiplied across it.
   ========================================================================== */

:root {
  /* How uploaded artwork is treated. The layout is monochrome by design, but
     a cover is the artist's own work and the thing being sold -- desaturating
     it misrepresents the goods. So artwork keeps its colour by default, and
     the original all-grey look is a switch on the Appearance screen rather
     than something baked into ten separate rules.
     grayscale(0) rather than none, so it composes with other filters. */
  --art-filter: grayscale(0);

  --paper:      #c9cccb;   /* page ground, behind the panels */
  --panel:      #ffffff;   /* content cards */
  --paper-2:    #dcdedd;   /* image placeholders */
  --ink:        #1c1c1c;
  --ink-soft:   #555857;
  --ink-faint:  #8b8e8d;
  --hairline:   #d8dad9;
  --hairline-2: #b6b9b8;
  --white:      #ffffff;

  --shell: 1180px;
  --panel-gap: clamp(.75rem, 1.6vw, 1.5rem);
  --gutter: clamp(1.25rem, 4vw, 4rem);

  --sans: "Helvetica Neue", Helvetica, Arial, "Inter", sans-serif;
  --tight: -0.035em;

  --t-fast: 140ms cubic-bezier(.4, 0, .2, 1);
  --t-slow: 520ms cubic-bezier(.16, 1, .3, 1);
}

/* The original all-grey treatment, kept as an opt-in. */
body.mono-art { --art-filter: grayscale(1); }

/* Off-screen but still read aloud, so the page keeps a heading even when the
   name is not painted across the banner. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

main { flex: 1; }

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--ink); color: var(--panel); }

/* --- Type ---------------------------------------------------------------- */

.eyebrow {
  font-size: .6875rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
  margin: 0 0 1.25rem;
}

.section-title {
  font-size: clamp(2.5rem, 6.5vw, 5rem);
  font-weight: 700;
  letter-spacing: var(--tight);
  text-transform: uppercase;
  line-height: .9;
  margin: 0;
}

.lede { font-size: clamp(1rem, 1.5vw, 1.1875rem); color: var(--ink-soft); max-width: 64ch; }

.shell { max-width: var(--shell); margin: 0 auto; padding-inline: var(--gutter); }
.shell--wide { max-width: 1480px; }

.rule { height: 1px; background: var(--hairline); border: 0; margin: 0; }

/* --- Panels: white cards floating on the grey ground --------------------- */

.panel {
  background: var(--panel);
  margin: var(--panel-gap);
  padding: clamp(2.5rem, 6vw, 5.5rem) clamp(1.5rem, 5vw, 5rem);
}
.panel--tight { padding-block: clamp(1.75rem, 3.5vw, 3rem); }
.panel--flush { padding-inline: 0; }
.panel + .panel { margin-top: 0; }

.panel__inner { max-width: var(--shell); margin: 0 auto; }
.panel--flush .panel__inner { padding-inline: clamp(1.5rem, 5vw, 5rem); }

/* --- Header: overlaid and centred on the hero, solid elsewhere ------------ */

.site-header {
  position: relative;
  z-index: 60;
  padding-block: 1.75rem;
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  position: relative;
  /* Keeps room for the wordmark, which is absolutely positioned and so does
     not push the header open by itself. */
  min-height: 52px;
}

.nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1.25rem, 3.2vw, 3rem);
  flex-wrap: wrap;
}

.nav a {
  font-size: 1.0625rem;
  letter-spacing: .01em;
  font-weight: 500;
  color: var(--ink);
  position: relative;
  padding-block: .25rem;
  transition: opacity var(--t-fast);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--t-fast);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }

/* Overlaid variant, used on the home hero. */
.site-header--overlay {
  position: absolute;
  top: 0; left: 0; right: 0;
  background: transparent;
}
.site-header--overlay .nav a,
.site-header--overlay .wordmark { color: var(--white); text-shadow: 0 1px 14px rgba(0,0,0,.35); }
.site-header--overlay .cart-badge { background: var(--white); color: var(--ink); }

/* Solid variant on inner pages, pinned so the nav and cart count stay
   reachable without scrolling back to the top of a long page. */
.site-header--solid {
  background: var(--panel);
  margin: var(--panel-gap) var(--panel-gap) 0;
  position: sticky;
  top: 0;
}

.wordmark {
  position: absolute;
  left: 0;
  display: flex;
  align-items: center;
  font-weight: 700;
  font-size: .9375rem;
  letter-spacing: .18em;
  text-transform: uppercase;
}
.wordmark img {
  height: 52px;
  width: auto;
  /* Transparent PNG, so no blend tricks are needed to hide a backing plate. */
}

/* The mark is near-black; over the hero photograph the nav is white, so invert
   it to match rather than leaving a dark smudge on the image. */
.site-header--overlay .wordmark img {
  filter: invert(1);
}

@media (max-width: 760px) {
  .wordmark img { height: 40px; }
}

.cart-link { display: inline-flex; align-items: center; gap: .5rem; }
.cart-badge {
  min-width: 20px; height: 20px;
  display: grid; place-items: center;
  padding-inline: 6px;
  background: var(--ink);
  color: var(--panel);
  border-radius: 999px;
  font-size: .625rem;
  font-weight: 700;
}

.nav-toggle {
  display: none;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit;
  font-size: .8125rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 600;
  margin-left: auto;
}

/* --- Hero: full-bleed photograph, wordmark multiplied across it ----------- */

.hero {
  position: relative;
  height: min(100svh, 900px);
  min-height: 520px;
  overflow: hidden;
  background: var(--paper-2);
  margin: var(--panel-gap);
}

/* Edge to edge below desktop. The floating-panel margin frames the artwork
   on a wide screen, but on a tablet or a phone it reads as a stripe of dead
   space down the side and steals width the picture could be using. */
@media (max-width: 1024px) {
  .hero { margin: 0 0 var(--panel-gap); }
}

/* Slides are stacked; only the active one is visible. Opacity rather than
   display, so the change is a fade instead of a jump. */
.hero__slides { position: absolute; inset: 0; }
.hero__slides .hero__bg { opacity: 0; transition: opacity 900ms ease; }
.hero__slides .hero__bg.is-active { opacity: 1; }

/* Pinned to the very bottom, centred. The action bar keeps clear of this
   strip, so the dots never end up under the buy button. */
.hero__dots {
  position: absolute;
  left: 0; right: 0;
  bottom: .7rem;
  z-index: 30;
  display: flex;
  justify-content: center;
  gap: .5rem;
}
.hero__dot {
  width: 8px; height: 8px;
  padding: 0;
  border: 1px solid rgba(255,255,255,.85);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  transition: background var(--t-fast), transform var(--t-fast);
}
.hero__dot.is-active { background: #fff; transform: scale(1.3); }
/* The tap target is bigger than the dot, which is only 8px across. */
.hero__dot::before { content: ""; position: absolute; width: 32px; height: 32px; transform: translate(-12px, -12px); }

@media (prefers-reduced-motion: reduce) {
  .hero__slides .hero__bg { transition: none; }
}

.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 20%;
  /* The shipped image is a full-length studio frame; scaling up crops it to
     the head-and-torso composition the layout is built around. */
  transform: scale(1.22);
  transform-origin: 50% 26%;
  filter: var(--art-filter) contrast(1.03);
}

/* An uploaded banner is somebody's own composition, often with its own type
   and logos already in it. Cropping into it the way the shipped photograph
   needs would cut that off, so a custom banner is shown as framed -- pulled
   slightly right of centre, because a narrow phone crop should keep the
   subject rather than the empty side. */
.hero__bg--custom {
  transform: none;
  object-position: 55% center;
}

/* The wordmark sits low across the image. Multiply keeps it readable over
   the bright areas and lets the dark ones (cap, shadow) swallow it, which is
   what gives the type its woven-into-the-photo look. */
/* Lifted clear of the action bar below. The two used to sit on top of each
   other, which cost the wordmark its impact and made the controls hard to
   read against the letterforms. */
.hero__type {
  position: absolute;
  left: 0; right: 0;
  bottom: clamp(22%, 26vh, 30%);
  display: grid;
  place-items: center;
  mix-blend-mode: multiply;
  pointer-events: none;
}

.hero__name {
  font-size: min(19rem, calc(96vw / (var(--chars, 8) * 0.66)));
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: .8;
  text-transform: uppercase;
  color: #2f2f2f;
  white-space: nowrap;
  margin: 0;
  animation: rise var(--t-slow) both;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* --- Hero actions --------------------------------------------------------- */

/* Its own band along the bottom of the hero. The gradient means the controls
   stay legible whatever part of the photograph sits behind them, without
   putting a hard box over the image. */
/* Gathered to the right rather than spread across the full width. Sleeve art
   almost always carries its logos and credits down the left, and a centred
   bar puts the play button straight through them -- as it did over the MLAB
   mark on the current banner. The right side is also usually the quieter
   half of a portrait, so the controls sit on empty ground. */
.hero__actions {
  position: absolute;
  left: 0; right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: clamp(.75rem, 2vw, 1.5rem);
  /* The bottom value leaves a strip clear for the slider dots. */
  padding: clamp(2.5rem, 6vh, 4.5rem) var(--gutter) clamp(2rem, 3.5vh, 2.75rem);
  /* Shorter and softer than before: enough to carry white text, little
     enough to leave the picture alone. */
  background: linear-gradient(to top, rgba(0, 0, 0, .66) 0%, rgba(0, 0, 0, .28) 45%, rgba(0, 0, 0, 0) 100%);
}

.hero__play {
  width: 62px; height: 62px;
  flex-shrink: 0;
  display: grid; place-items: center;
  border: 0;
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  transition: transform var(--t-fast);
}
.hero__play:hover { transform: scale(1.06); }
.hero__play svg { width: 20px; height: 20px; fill: currentColor; }
.hero__icon-pause { display: none; }
.hero__play.is-playing .hero__icon-play { display: none; }
.hero__play.is-playing .hero__icon-pause { display: block; }

/* Autoplay is blocked until the visitor interacts, so when it is refused the
   control pulses instead of silently doing nothing. */
.hero__play.is-waiting {
  animation: hero-pulse 2s ease-in-out infinite;
}
@keyframes hero-pulse {
  0%, 100% { box-shadow: 0 10px 30px rgba(0,0,0,.35), 0 0 0 0 rgba(255,255,255,.55); }
  50%      { box-shadow: 0 10px 30px rgba(0,0,0,.35), 0 0 0 16px rgba(255,255,255,0); }
}

.hero__nowplaying {
  display: flex;
  flex-direction: column;
  color: var(--white);
  text-shadow: 0 1px 14px rgba(0, 0, 0, .45);
  min-width: 0;
  /* A long title with several featured artists would otherwise stretch back
     across the sleeve; it truncates instead. The full name is one line down
     in the tracklist. */
  max-width: min(34ch, 30vw);
}
.hero__eyebrow {
  font-size: .625rem; letter-spacing: .2em; text-transform: uppercase;
  opacity: .85; font-weight: 600;
}
.hero__track {
  font-size: 1.0625rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.hero__cta { display: flex; gap: .6rem; flex-wrap: wrap; }
/* The buy control is a form now rather than a link, because it charges. The
   wrapper carries no width of its own, so the button lays out exactly as the
   link beside it does. */
.hero__cta form { display: flex; margin: 0; min-width: 0; }
/* .btn--onhero is defined further down, immediately after .btn--ghost --
   the two have equal specificity, so whichever comes last wins. */

@media (max-width: 700px) {
  /* Shaped to the artwork rather than to the screen. Tying the hero to
     viewport height made it a tall narrow window onto a picture that is
     usually square or wide, so most of the image was cropped away and the
     music sat below the fold. A 4:5 frame keeps four fifths of a square
     sleeve's width, reads as a hero rather than a poster, and leaves room
     for the play controls. */
  .hero {
     height: auto;
     aspect-ratio: 4 / 5;
     max-height: 72svh;
     min-height: 400px;
  }

  /* Uploaded artwork is square -- the label delivers it at 1350 or 1365 a
     side -- and a 4:5 frame cut an eighth off each edge of it, which on a
     poster is the festival name down one side and the credits down the
     other. A square frame shows the record sleeve entire: no crop to argue
     about, and no bars beside it either. The shipped photograph keeps 4:5,
     which is the shape it was composed to be cropped to.

     min-height has to go with it, or a narrow phone would force the box
     taller than it is wide and start trimming the sides again. */
  .hero--art {
    aspect-ratio: 1 / 1;
    min-height: 0;
    max-height: none;
  }

  /* A square frame is shorter than a 4:5 one, so the same control bar takes
     a bigger share of it -- 37% against 30%, which is a lot of somebody's
     sleeve to sit a gradient on. Tightened until it costs the artwork no
     more of its height than it did before, so the whole gain from not
     cropping stays with the picture. */
  .hero--art .hero__actions {
    padding-top: 1rem;
    padding-bottom: 1.25rem;
    gap: .35rem;
  }

  /* The controls have to earn their space here. On a shorter hero the old
     bar took nearly half the picture -- 5rem of top padding, oversized
     buttons and a row that wrapped in two -- so the artwork was mostly
     covered by its own furniture. Everything is tightened and the two
     buttons are kept side by side. */
  .hero__actions {
    gap: .45rem;
    padding-top: 1.75rem;
    padding-bottom: 1.9rem;
    justify-content: center;
  }
  .hero__play { width: 46px; height: 46px; }
  .hero__nowplaying { flex: 1 1 auto; max-width: none; }
  .hero__cta { flex: 1 1 100%; justify-content: center; gap: .45rem; }
  .hero__cta .btn {
    flex: 0 1 auto;
    min-width: 0;
    padding: .7rem .85rem;
    font-size: .625rem;
    letter-spacing: .1em;
  }

  /* Edge to edge like the hero. The grey margin beside a white block reads as
     a stray corner on a phone rather than as framing. */
  .panel, .site-header--solid { margin-inline: 0; }
  .hero__type { bottom: clamp(34%, 38vh, 42%); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__play.is-waiting { animation: none; }
}

/* --- Upload progress ------------------------------------------------------ */

.uploadbar { margin-top: 1rem; }
.uploadbar__track { height: 6px; background: var(--hairline); overflow: hidden; }
.uploadbar__fill {
  height: 100%; width: 0;
  background: var(--ink);
  transition: width 180ms linear;
}
.uploadbar__label {
  font-size: .75rem; color: var(--ink-soft); margin-top: .5rem;
  font-variant-numeric: tabular-nums;
}
.uploadbar--failed .uploadbar__fill { background: var(--ink-faint); }
.uploadbar--failed .uploadbar__label { color: var(--ink); font-weight: 700; }

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .625rem;
  padding: .95rem 1.9rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--panel);
  font: inherit;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast);
}
.btn:hover { background: transparent; color: var(--ink); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .45; pointer-events: none; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--hairline-2); }
.btn--ghost:hover { background: var(--ink); color: var(--panel); border-color: var(--ink); }

/* The hero variant of the ghost button, and it must come after .btn--ghost:
   both are single classes, so the later rule wins and the earlier one was
   silently losing -- which left dark ink on a photograph.

   Light ink alone is not enough either. Over a pale area, a white shirt or a
   bright sky, white text on nothing disappears; a dark wash behind the label
   keeps it readable wherever the picture happens to be light, without
   becoming a solid slab. */
.btn--onhero {
  color: var(--white);
  border-color: rgba(255, 255, 255, .7);
  background: rgba(0, 0, 0, .45);
  backdrop-filter: blur(3px);
}
.btn--onhero:hover {
  background: var(--white);
  color: var(--ink);
  border-color: var(--white);
  backdrop-filter: none;
}

.btn--block { width: 100%; }
.btn--sm { padding: .6rem 1.15rem; font-size: .6875rem; letter-spacing: .14em; }

/* --- Sections ------------------------------------------------------------ */

.section { padding-block: clamp(3rem, 7vw, 6rem); }
.section--tight { padding-block: clamp(2rem, 4vw, 3.5rem); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

/* --- Mailing list band --------------------------------------------------- */

.subscribe-band { text-align: center; }
.subscribe-band h2 {
  font-size: clamp(1.375rem, 2.6vw, 1.875rem);
  font-weight: 700;
  letter-spacing: -.01em;
  margin: 0 0 1.5rem;
}
/* --- Search --------------------------------------------------------------- */

/* One rounded field with the magnifier inside it. The form itself is the
   control -- the input and the button are borderless within it -- so there is
   a single thing on screen to look at rather than a box, a button and a
   heading stacked down the page. */
.searchbar {
  display: flex;
  align-items: center;
  gap: .25rem;
  max-width: 560px;
  margin-inline: auto;
  padding: .25rem .9rem .25rem .4rem;
  background: var(--panel);
  border: 1px solid var(--hairline-2);
  border-radius: 999px;
  transition: border-color var(--t-fast);
}
.searchbar:focus-within { border-color: var(--ink); }

.searchbar input {
  /* Shrinkable, so the field never pushes the icon off a narrow screen. */
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  padding: .8rem .2rem;
  border: 0;
  background: transparent;
  color: inherit;
  /* Safari draws a rounded pill and an inner shadow on type=search. */
  -webkit-appearance: none;
  appearance: none;
}
.searchbar input:focus { outline: none; }
.searchbar input::-webkit-search-cancel-button { -webkit-appearance: none; }

.searchbar__go {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast);
}
.searchbar__go:hover { background: var(--ink); color: var(--panel); }
.searchbar:focus-within .searchbar__go { color: var(--ink); }
.searchbar:focus-within .searchbar__go:hover { color: var(--panel); }

.searchbar__icon {
  width: 19px; height: 19px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round;
}

.searchbar--page { margin-inline: 0; max-width: 640px; }

@media (max-width: 560px) {
  /* One row, not three. The button used to drop onto its own full-width line
     and the heading wrapped above it, so a single search field took up most
     of a phone screen before any music appeared. */
  .searchbar { padding-right: .6rem; }

  /* The placeholder already says what this is, so the heading is repetition
     on a small screen. Kept for screen readers, taken out of the layout. */
  .subscribe-band h2 {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
  }
  .subscribe-band { padding-block: 1.1rem; }
}

/* --- Now playing strip + tracklist --------------------------------------- */

.release-block__title {
  font-size: clamp(2.25rem, 6vw, 4.25rem);
  font-weight: 700;
  letter-spacing: var(--tight);
  text-transform: uppercase;
  line-height: .9;
  margin: 0 0 1rem;
}

.nowplaying {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 1.25rem;
  padding-bottom: 1rem;
}

.nowplaying__play {
  width: 58px; height: 58px;
  display: grid; place-items: center;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.nowplaying__play:hover { background: var(--ink); color: var(--panel); }
.nowplaying__play svg { width: 16px; height: 16px; fill: currentColor; }

.nowplaying__title { font-size: 1.0625rem; font-weight: 700; text-transform: uppercase; letter-spacing: .01em; }
.nowplaying__sub { font-size: .9375rem; color: var(--ink-soft); }

.nowplaying__skips { display: flex; gap: .75rem; }
.nowplaying__skip {
  background: none; border: 0; cursor: pointer; color: var(--ink);
  padding: .25rem; transition: opacity var(--t-fast);
}
.nowplaying__skip:hover { opacity: .55; }
.nowplaying__skip svg { width: 22px; height: 22px; fill: currentColor; }

.nowplaying__time { font-size: .9375rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

.progress { height: 5px; background: var(--hairline); cursor: pointer; }
.progress__fill { height: 100%; background: var(--ink-faint); width: 0; }

.tracklist { list-style: none; margin: 0; padding: 0; }

.track {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  padding: 1.05rem .25rem;
  border-bottom: 1px solid var(--hairline);
  cursor: pointer;
  transition: background var(--t-fast);
}
.track:hover { background: #fafafa; }
.track.is-playing { background: #f4f4f4; }

/* The index cell holds the number and a play control stacked in the same box,
   so swapping between them never shifts the row. */
.track__index {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
}

.track__num {
  font-size: .9375rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  transition: opacity var(--t-fast);
}

.track__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  opacity: 0;
  transition: opacity var(--t-fast);
}
.track__play svg { width: 14px; height: 14px; fill: currentColor; }
.track__icon-pause { display: none; }

/* Reveal on hover, on keyboard focus, and while the row is the one playing. */
.track:hover .track__play,
.track__play:focus-visible,
.track.is-playing .track__play { opacity: 1; }
.track:hover .track__num,
.track.is-playing .track__num { opacity: 0; }

.track.is-playing .track__icon-play { display: none; }
.track.is-playing .track__icon-pause { display: block; }

/* Touch devices have no hover, so the control is always visible there. */
@media (hover: none) {
  .track__play { opacity: 1; }
  .track__num { opacity: 0; }
}
.track__title { font-size: .9375rem; }
.track__title b { font-weight: 600; }
.track__time { color: var(--ink-faint); margin-left: .5rem; font-variant-numeric: tabular-nums; }

/* In a chart the rows come from different records, so each one has to say
   whose it is -- on a single release's tracklist that would be repetition. */
.track__from {
  display: block;
  font-size: .75rem;
  color: var(--ink-faint);
  margin-top: .15rem;
}
.track__from:hover { color: var(--ink); text-decoration: underline; }
.track__action { display: flex; align-items: center; gap: .5rem; }

.track__buy {
  min-width: 108px;
  padding: .6rem 1.1rem;
  border: 1px solid var(--hairline-2);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-align: center;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.track__buy:hover { background: var(--ink); color: var(--panel); border-color: var(--ink); }

/* --- Grids / cards ------------------------------------------------------- */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  gap: clamp(1.5rem, 3vw, 2.75rem);
}

.card { display: flex; flex-direction: column; gap: 1rem; height: 100%; }

.card__art { aspect-ratio: 1; background: var(--paper-2); overflow: hidden; position: relative; }
.card__art img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: var(--art-filter);
  transition: transform var(--t-slow);
}
.card:hover .card__art img { transform: scale(1.04); }

.card__flag {
  position: absolute; top: 0; left: 0;
  background: var(--ink); color: var(--panel);
  font-size: .625rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 700;
  padding: .4rem .7rem;
}

.card__title {
  font-size: 1.0625rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: -.01em; margin: 0;
}
.card__meta { font-size: .75rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); }
.card__row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-top: auto; }
.card__price { font-weight: 700; }

/* --- Roster -------------------------------------------------------------- */
/* Artist cards read as people, not products: taller crop, and a name where a
   price would sit. */

.card__byline { font-size: .8125rem; color: var(--ink-soft); margin-top: .35rem; }
.card__byline a { text-decoration: none; }
.card__byline a:hover { text-decoration: underline; }

.roster .card__art--portrait { aspect-ratio: 4 / 5; }

/* Stand-in for a missing photo. Better than an empty grey box, and it keeps
   the roster grid from collapsing before every artist has a press shot. */
.card__initial {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: clamp(3rem, 8vw, 5rem); font-weight: 700;
  letter-spacing: -.04em; text-transform: uppercase;
  color: var(--hairline-2);
  user-select: none;
}

.artist-head {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.artist-head__photo {
  aspect-ratio: 4 / 5; background: var(--paper-2); overflow: hidden; position: relative;
}
.artist-head__photo img { width: 100%; height: 100%; object-fit: cover; filter: var(--art-filter); }

.feature__byline {
  font-size: 1rem; color: var(--ink-soft); margin: -.5rem 0 1.5rem;
}
.feature__byline a { font-weight: 700; color: var(--ink); }

@media (max-width: 760px) {
  .artist-head { grid-template-columns: 1fr; }
}

/* --- Feature (release / product detail) ---------------------------------- */

.feature {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.feature__art { aspect-ratio: 1; background: var(--paper-2); overflow: hidden; }
.feature__art img { width: 100%; height: 100%; object-fit: cover; filter: var(--art-filter); }

.feature__title {
  font-size: clamp(2.25rem, 5vw, 4rem);
  font-weight: 700;
  letter-spacing: var(--tight);
  text-transform: uppercase;
  line-height: .9;
  margin: 0 0 1.25rem;
}

.price { font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; }
.price small { font-size: .75rem; letter-spacing: .16em; font-weight: 600; color: var(--ink-faint); }

/* --- Shows --------------------------------------------------------------- */

.shows { border-top: 1px solid var(--hairline); }

.show {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 1.5rem;
  padding: 1.4rem 0;
  border-bottom: 1px solid var(--hairline);
}
.show__date { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.show__venue { font-weight: 600; }
.show__city { color: var(--ink-soft); font-size: .875rem; letter-spacing: .1em; text-transform: uppercase; }
.show__soldout { font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-faint); font-weight: 700; }

/* --- Photos -------------------------------------------------------------- */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: var(--panel-gap);
}
.photo-grid figure { margin: 0; aspect-ratio: 4 / 5; overflow: hidden; background: var(--paper-2); }
.photo-grid img {
  width: 100%; height: 100%; object-fit: cover;
  filter: var(--art-filter);
  transition: transform var(--t-slow);
}
.photo-grid figure:hover img { transform: scale(1.04); }

/* --- Forms --------------------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 1.25rem; }

.field label {
  font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
}

.field input, .field textarea, .field select {
  font: inherit;
  padding: .85rem 1rem;
  background: var(--panel);
  border: 1px solid var(--hairline-2);
  color: var(--ink);
  border-radius: 0;
  transition: border-color var(--t-fast);
}
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--ink); }
.field .hint { font-size: .75rem; color: var(--ink-faint); }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.25rem; }

.inline-form { display: flex; gap: .75rem; flex-wrap: wrap; }
.inline-form input {
  flex: 1 1 220px; font: inherit; padding: .8rem 1rem;
  border: 1px solid var(--hairline-2); background: var(--panel); border-radius: 0;
}
.inline-form input:focus { outline: none; border-color: var(--ink); }

/* --- Cart / checkout ----------------------------------------------------- */

.layout-split {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.cart-line {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 1.25rem;
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--hairline);
  align-items: center;
}
.cart-line__art { aspect-ratio: 1; background: var(--paper-2); overflow: hidden; }
.cart-line__art img { width: 100%; height: 100%; object-fit: cover; filter: var(--art-filter); }
.cart-line__title { font-weight: 700; text-transform: uppercase; letter-spacing: -.01em; }
.cart-line__meta { font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }

.qty { display: inline-flex; border: 1px solid var(--hairline-2); }
.qty button {
  width: 32px; height: 32px; background: transparent; border: 0; cursor: pointer;
  font: inherit; color: var(--ink); transition: background var(--t-fast), color var(--t-fast);
}
.qty button:hover { background: var(--ink); color: var(--panel); }
.qty span { width: 36px; display: grid; place-items: center; font-variant-numeric: tabular-nums; font-weight: 600; }

.link-quiet {
  font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; background: none; border: 0; padding: 0; cursor: pointer;
  transition: color var(--t-fast);
}
.link-quiet:hover { color: var(--ink); text-decoration: underline; }

.summary { border: 1px solid var(--hairline-2); padding: clamp(1.5rem, 3vw, 2rem); position: sticky; top: 1.5rem; }
.summary__row { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; font-size: .875rem; }
.summary__row--total {
  border-top: 1px solid var(--hairline);
  margin-top: .75rem; padding-top: 1rem;
  font-size: 1.25rem; font-weight: 700;
}

/* --- Notices ------------------------------------------------------------- */

.notice { border: 1px solid var(--ink); padding: 1rem 1.25rem; font-size: .875rem; margin-bottom: 1.5rem; }
.notice--bad { background: var(--ink); color: var(--panel); }

.status-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--ink); display: inline-block; margin-right: .5rem; }
.status-dot--pulse { animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.empty { padding: clamp(3rem, 8vw, 5rem) 0; text-align: center; color: var(--ink-soft); }

.download-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1.125rem 0; border-bottom: 1px solid var(--hairline);
}
.download-row__meta { font-size: .75rem; color: var(--ink-faint); letter-spacing: .1em; text-transform: uppercase; }

/* --- Footer -------------------------------------------------------------- */

.site-footer { background: var(--panel); margin: 0 var(--panel-gap) var(--panel-gap); padding: clamp(2.5rem, 5vw, 4rem) clamp(1.5rem, 5vw, 5rem) 2rem; }

.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 2.5rem;
  margin-bottom: 2.5rem;
  max-width: var(--shell);
  margin-inline: auto;
}
.footer-grid h4 {
  font-size: .6875rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; margin: 0 0 1rem;
}
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.footer-grid a { font-size: .875rem; color: var(--ink-soft); transition: color var(--t-fast); }
.footer-grid a:hover { color: var(--ink); }

.footer-legal {
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: .6875rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint);
  border-top: 1px solid var(--hairline); padding-top: 1.5rem;
  max-width: var(--shell); margin-inline: auto;
}

/* The staff door. Findable without being an invitation -- there is no public
   sign-up, so a prominent link would only mislead customers. */
.footer-signin { color: var(--ink-faint); text-decoration: none; }
.footer-signin:hover { color: var(--ink); text-decoration: underline; }

/* The builder's mark. Kept in its own colours -- it is somebody else's brand,
   and the monochrome treatment applies to the store's own imagery, not to a
   logo that has to stay recognisable. Muted until hovered so it credits
   without competing with the music. */
.powered-by {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--ink-faint);
  opacity: .75;
  transition: opacity var(--t-fast);
}
.powered-by:hover { opacity: 1; }
.powered-by img { height: 26px; width: auto; }

/* --- Test-mode banner ----------------------------------------------------- */

.testbar {
  background: var(--ink);
  color: var(--panel);
  text-align: center;
  padding: .7rem 1rem;
  font-size: .8125rem;
  line-height: 1.4;
  letter-spacing: .01em;
}
.testbar b { letter-spacing: .1em; text-transform: uppercase; }

/* --- Persistent cart status ---------------------------------------------- */

.cartbar {
  position: fixed;
  z-index: 80;
  right: var(--panel-gap);
  bottom: var(--panel-gap);
  animation: cartbar-in var(--t-slow) both;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .4rem;
}
.cartbar[hidden] { display: none; }

/* Deliberately quiet and set apart from Checkout: emptying the cart should be
   findable, never something you hit while reaching for the buy button. */
.cartbar__clear button {
  font: inherit;
  font-size: .6875rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 600;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--ink-soft);
  padding: .25rem .4rem;
}
.cartbar__clear button:hover { color: var(--ink); text-decoration: underline; }

@keyframes cartbar-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.cartbar__inner {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  background: var(--ink);
  color: var(--panel);
  padding: 1.1rem 1.1rem 1.1rem 1.6rem;
  /* A white ring plus a deep shadow so the bar reads as a floating control
     rather than dissolving into whatever content is behind it. */
  box-shadow: 0 0 0 4px var(--panel), 0 18px 44px rgba(0, 0, 0, .42);
  transition: transform var(--t-fast);
}
.cartbar__inner:hover { transform: translateY(-3px); }

.cartbar__icon { display: grid; place-items: center; }
.cartbar__icon svg {
  width: 26px; height: 26px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

.cartbar__text { display: flex; align-items: baseline; gap: .45rem; font-size: 1rem; }
.cartbar__text b { font-size: 1.25rem; }
.cartbar__total {
  padding-left: .85rem;
  margin-left: .35rem;
  border-left: 1px solid color-mix(in srgb, var(--panel) 35%, transparent);
  font-weight: 700;
  font-size: 1.0625rem;
  white-space: nowrap;
}

.cartbar__cta {
  background: var(--panel);
  color: var(--ink);
  padding: .8rem 1.4rem;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* A visible kick when the contents change, so an add registers even when the
   bar was already on screen. */
.cartbar.is-bumped .cartbar__inner { animation: cartbar-bump 480ms cubic-bezier(.2, 1.4, .4, 1); }
@keyframes cartbar-bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.07); }
  100% { transform: scale(1); }
}

/* A pinned bar would otherwise sit on top of the last row of a page. */
body:has(.cartbar:not([hidden])) .site-footer { padding-bottom: 5.5rem; }

@media (max-width: 760px) {
  .cartbar { left: var(--panel-gap); right: var(--panel-gap); bottom: var(--panel-gap); }
  .cartbar__inner { justify-content: space-between; width: 100%; gap: .75rem; }
  .cartbar__total { border-left: 0; padding-left: 0; margin-left: 0; }
  .cartbar__text { flex-direction: column; gap: 0; align-items: flex-start; }
  .cartbar__cta { padding: .8rem 1.1rem; }
}

/* --- Checkout drawer ----------------------------------------------------- */

.drawer-scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(0, 0, 0, .45);
  opacity: 0;
  transition: opacity var(--t-slow);
}
.drawer-scrim.is-open { opacity: 1; }
.drawer-scrim[hidden] { display: none; }

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 100;
  width: min(440px, 100vw);
  display: flex;
}
.drawer[hidden] { display: none; }

.drawer__panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--panel);
  box-shadow: -18px 0 60px rgba(0, 0, 0, .3);
  transform: translateX(100%);
  transition: transform var(--t-slow);
}
.drawer.is-open .drawer__panel { transform: none; }

.drawer__head {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 1.4rem 1.5rem;
  border-bottom: 1px solid var(--hairline);
  flex-shrink: 0;
}
.drawer__title {
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: var(--tight);
  text-transform: uppercase;
  margin: 0;
  flex: 1;
}
.drawer__close, .drawer__back {
  background: none; border: 0; cursor: pointer;
  font-size: 1.75rem; line-height: 1; color: var(--ink-faint);
  padding: 0 .25rem;
  transition: color var(--t-fast);
}
.drawer__back { font-size: 1.25rem; }
.drawer__close:hover, .drawer__back:hover { color: var(--ink); }

/* The body is the only scrolling region, so the total and the pay button
   never leave the screen mid-checkout. */
.drawer__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 1.5rem;
}

.drawer__foot {
  flex-shrink: 0;
  padding: 1.25rem 1.5rem calc(1.25rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--hairline);
  background: var(--panel);
}

.drawer__row { display: flex; justify-content: space-between; gap: 1rem; padding: .3rem 0; font-size: .875rem; }
.drawer__row--total {
  font-size: 1.25rem; font-weight: 700;
  border-top: 1px solid var(--hairline);
  margin-top: .5rem; padding-top: .75rem; margin-bottom: 1rem;
}

.drawer__empty { color: var(--ink-faint); text-align: center; padding: 3rem 0; }
.drawer__lead { font-size: 1.0625rem; margin: 0 0 .5rem; }
.drawer__meta { color: var(--ink-soft); font-size: .875rem; margin: 0; }
.drawer__note { font-size: .75rem; color: var(--ink-faint); margin: .75rem 0 0; text-align: center; }

.drawer__error {
  background: var(--ink); color: var(--panel);
  padding: .8rem 1rem; font-size: .8125rem; margin-bottom: 1.25rem;
}
.drawer__error[hidden] { display: none; }

.drawer__waiting { text-align: center; padding: 2.5rem 0; }
.drawer__waiting .status-dot { width: 12px; height: 12px; margin: 0 0 1.25rem; }

.drawer__download {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .85rem 0; border-bottom: 1px solid var(--hairline); font-size: .875rem;
}

/* Cart lines inside the drawer */
.dline {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) auto;
  gap: .9rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--hairline);
}
.dline__art { aspect-ratio: 1; background: var(--paper-2); overflow: hidden; }
.dline__art img { width: 100%; height: 100%; object-fit: cover; filter: var(--art-filter); }
.dline__title { font-weight: 700; font-size: .875rem; text-transform: uppercase; letter-spacing: -.01em; }
.dline__meta { font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); margin-top: .15rem; }
.dline__foot { display: flex; align-items: center; gap: .9rem; margin-top: .6rem; }
.dline__price { font-weight: 700; font-size: .875rem; white-space: nowrap; }

/* Recommendations */
.drawer__recs { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--hairline); }
.rec {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  gap: .8rem;
  align-items: center;
  padding: .6rem 0;
}
.rec__art { aspect-ratio: 1; background: var(--paper-2); overflow: hidden; }
.rec__art img { width: 100%; height: 100%; object-fit: cover; filter: var(--art-filter); }
.rec__title { font-size: .8125rem; font-weight: 700; text-transform: uppercase; letter-spacing: -.01em; }
.rec__meta { font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); }
.rec__add {
  border: 1px solid var(--hairline-2);
  background: transparent;
  font: inherit; font-size: .625rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  padding: .5rem .7rem; cursor: pointer; white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.rec__add:hover { background: var(--ink); color: var(--panel); border-color: var(--ink); }

body.drawer-open { overflow: hidden; }

@media (max-width: 520px) {
  .drawer { width: 100vw; }
}

/* --- Admin --------------------------------------------------------------- */

.admin-bar { background: var(--ink); color: var(--panel); font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 600; }

/* Wraps rather than overflowing. A fixed-height single row silently pushed
   the last items -- Sign out among them -- off the edge of the viewport with
   no way to reach them, which is a poor thing to do to the way out. */
.admin-bar .shell {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: .5rem 1.5rem; min-height: 46px; padding-block: .6rem;
}
.admin-bar a { opacity: .65; transition: opacity var(--t-fast); }
.admin-bar a:hover, .admin-bar a[aria-current="page"] { opacity: 1; }
/* Pushes the account controls right when there is room, and simply sits at
   the start of the next line when there is not. */
.admin-bar .spacer { margin-left: auto; }
.admin-bar .admin-bar__out { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }

.table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.table th {
  text-align: left; font-size: .625rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600; padding: .75rem .75rem .75rem 0;
  border-bottom: 1px solid var(--ink);
}
.table td { padding: .875rem .75rem .875rem 0; border-bottom: 1px solid var(--hairline); vertical-align: top; }

.tag {
  display: inline-block; font-size: .625rem; letter-spacing: .12em; text-transform: uppercase;
  font-weight: 700; padding: .2rem .5rem; border: 1px solid var(--hairline-2);
}

/* --- Banner list ---------------------------------------------------------- */

.banner-list { display: grid; gap: 1rem; }
.banner-row {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
  border: 1px solid var(--hairline);
  padding: .75rem;
}
.banner-row img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.banner-row__meta { display: grid; gap: .35rem; font-size: .75rem; color: var(--ink-faint); }
.banner-row__meta b { font-size: .8125rem; color: var(--ink); }
.banner-row__actions { display: flex; flex-wrap: wrap; gap: .9rem; margin-top: .25rem; }
.banner-row__actions button { font-size: .75rem; }

@media (max-width: 620px) {
  .banner-row { grid-template-columns: 1fr; }
}

/* --- Pricing a whole record at once --------------------------------------- */

.pricing {
  border: 1px solid var(--ink);
  padding: clamp(1.25rem, 3vw, 2rem);
  margin-bottom: 2.5rem;
}
.pricing__album {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
}

/* --- What is already attached -------------------------------------------- */
/* A file input reads "no file chosen" whether or not something is stored, so
   the admin needs to be told separately what is on file — and warned when it
   is missing. */

.filecard {
  border: 1px solid var(--hairline);
  background: var(--paper-2);
  padding: .7rem .8rem;
  display: grid;
  gap: .6rem;
}
.filecard__row { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }

.filecard__label {
  font-size: .625rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-faint); flex: 0 0 auto; min-width: 84px;
}
.filecard__name {
  font-size: .8125rem; font-weight: 700; word-break: break-all; min-width: 0;
}
.filecard__meta { font-size: .75rem; color: var(--ink-soft); }
.filecard__meta--bad { color: var(--ink); font-weight: 700; }

.filecard audio { height: 32px; }
.tag--solid { background: var(--ink); color: var(--panel); border-color: var(--ink); }

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; }
  .layout-split { grid-template-columns: 1fr; }
  .summary { position: static; }
  .show { grid-template-columns: 1fr auto; gap: .35rem 1rem; }
  .show__city { grid-column: 1 / -1; }
  .nowplaying { grid-template-columns: auto minmax(0, 1fr) auto; }
  .nowplaying__time { display: none; }
}

@media (max-width: 760px) {
  .nav-toggle { display: block; position: absolute; right: 0; }
  .site-header__inner { justify-content: flex-start; }
  .nav {
    position: absolute;
    top: calc(100% + 1rem);
    left: 0; right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--panel);
    padding: 1rem 1.5rem 1.5rem;
    box-shadow: 0 18px 40px rgba(0,0,0,.14);
    display: none;
  }
  .nav.is-open { display: flex; }
  .site-header--overlay .nav a { color: var(--ink); text-shadow: none; }
  .site-header--overlay .cart-badge { background: var(--ink); color: var(--panel); }
  .nav a { font-size: 1.25rem; padding-block: .55rem; }
  .field-row { grid-template-columns: 1fr; }
  .cart-line { grid-template-columns: 64px minmax(0, 1fr); }
  .cart-line > :last-child { grid-column: 1 / -1; }
  .track { grid-template-columns: 1.75rem minmax(0, 1fr); }
  .track__action { grid-column: 1 / -1; justify-content: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
