/* The Good Foot — Long Beach. One stylesheet, no build step.
   Committed dark palette: the night happens in a red-walled room with the
   lights down, and the flyers have always been ink-on-black. Every colour is
   painted explicitly so nothing borrows a browser default. */

:root {
  --ink:        #100c0a;   /* page ground */
  --ink-2:      #191211;   /* raised band */
  --ink-3:      #241a17;   /* card ground */
  --paper:      #f6ede1;   /* primary text */
  --head:       #ffffff;   /* headings — plain white, no cream cast */
  /* Both of these were too dark against the brown grounds: the old faint
     brown measured 3.2:1 on a card, under the 4.5:1 needed for body text.
     Lightened until every combination clears AA. */
  --paper-dim:  #d0c2b5;   /* secondary text  — 9.8:1 on card ground */
  --paper-faint:#a89889;   /* tertiary / metadata — 6.1:1 on card ground */
  --gold:       #e9b12a;   /* primary accent — 45 label gold */
  --flame:      #dd4620;   /* hot accent — Alex's Bar red */
  --rule:       rgba(246, 237, 225, 0.13);

  --display: 'Anton', 'Arial Narrow', 'Haettenschweiler', sans-serif;
  --body: 'Barlow', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  --wrap: 1120px;
  /* .section and .profile put --pad INSIDE their --wrap box, so their text
     column is --wrap minus that padding. Wrappers that instead sit inside a
     parent already carrying --pad must subtract it to land on the same left
     edge, otherwise they hang --pad further out than every section above. */
  --wrap-inner: calc(var(--wrap) - 2 * var(--pad));
  --pad: clamp(1.15rem, 5vw, 3rem);
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  position: relative;
}

/* The room itself, sitting behind everything. Fixed so it reads as a backdrop
   rather than a scrolling image, and held at 14% with a dark scrim on top —
   enough to feel the crowd, low enough that cream body text keeps its
   contrast. 20% was noticeably too bright under paragraph text. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  background: url('/assets/room.jpg') center / cover no-repeat;
  opacity: 0.168;
  pointer-events: none;
}
/* Residents: the backdrop travels with the page rather than staying pinned. */
body.bg-scroll::before,
body.bg-scroll::after {
  position: absolute;
  inset: 0 0 auto 0;
  min-height: 100%;
  height: auto;
}

body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(16, 12, 10, 0.45), transparent 70%),
    linear-gradient(180deg, rgba(16, 12, 10, 0.35), rgba(16, 12, 10, 0.8));
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
  color: var(--head);
}

p { margin: 0; }
a { color: var(--gold); text-underline-offset: 2px; }
a:focus-visible, button:focus-visible, input:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}
img { max-width: 100%; display: block; }

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

.skip {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -120%);
  background: var(--gold); color: var(--ink); padding: 0.6rem 1rem;
  font-weight: 700; z-index: 100; text-decoration: none;
}
.skip:focus { transform: translate(-50%, 0); }

.eyebrow {
  font-size: 0.74rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold);
}

/* ---------- top bar ---------- */

.topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 1rem;
  padding: 0.8rem var(--pad);
  background: rgba(16, 12, 10, 0.9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}

.brand {
  display: inline-flex; align-items: center; gap: 0.6rem;
  color: var(--paper); text-decoration: none; margin-right: auto;
}
/* Static: with a blank label there is nothing to watch turn, and a moving
   mark in a sticky header is a distraction rather than a flourish. The hero
   record still spins — that one has a label worth reading. */
.brand-mark {
  width: 54px; height: 54px; flex: none;
}
@keyframes spin { to { transform: rotate(360deg); } }
.brand-text {
  font-family: var(--display); text-transform: uppercase;
  font-size: 1.2rem; letter-spacing: 0.03em; line-height: 1;
}
/* The wordmark is the flyer's own lettering, same artwork as the hero, so the
   header matches the logotype instead of approximating it in Anton. Black art
   on alpha, so it inverts to sit on the dark bar. */
.brand-logo {
  display: block; height: 1.15rem; width: auto;
  filter: invert(1);
}
/* Same artwork in the footer, a touch larger since it stands alone there
   rather than sitting beside the record mark. */
.brand-logo-foot { height: 1.45rem; margin-bottom: 0.1rem; }
.brand-sub {
  display: block; font-family: var(--body); font-size: 0.6rem;
  letter-spacing: 0.22em; color: var(--paper-faint); font-weight: 600;
  margin-top: 0.15rem;
  /* Centred under the wordmark above it. The trailing letter-space on the last
     character pushes the line visually right, so it is pulled back by the same
     amount to sit truly centred rather than just text-align centred. */
  text-align: center;
  text-indent: 0.22em;
}

.nav { display: flex; align-items: center; gap: 1.3rem; }
.nav a {
  color: var(--paper-dim); text-decoration: none;
  font-size: 0.8rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.1em;
  transition: color 0.15s ease;
}
/* Several places uppercase their text in CSS, which would turn "DJs" into
   "DJS". This keeps the plural s lowercase wherever it is used. */
.lc { text-transform: lowercase; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--paper); }
.nav a[aria-current="page"] { color: var(--gold); }

.nav-toggle {
  display: none; width: 42px; height: 38px;
  background: none; border: 1px solid var(--rule); border-radius: 3px;
  color: var(--paper); cursor: pointer;
}
.nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
  display: block; width: 18px; height: 2px; background: currentColor;
  margin: 0 auto; position: relative;
}
.nav-toggle-bars::before, .nav-toggle-bars::after { content: ''; position: absolute; left: 0; }
.nav-toggle-bars::before { top: -6px; }
.nav-toggle-bars::after { top: 6px; }

@media (max-width: 880px) {
  .nav-toggle { display: block; }
  .nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--ink-2); border-bottom: 1px solid var(--rule);
    padding: 0.25rem var(--pad) 1rem;
    display: none;
  }
  .nav.is-open { display: flex; }
  .nav a { padding: 0.85rem 0; border-bottom: 1px solid var(--rule); font-size: 0.95rem; }
}

/* ---------- hero ---------- */

.hero {
  position: relative; overflow: hidden;
  padding: clamp(3rem, 10vw, 6.5rem) var(--pad) clamp(2.5rem, 7vw, 4.5rem);
  background:
    radial-gradient(75% 110% at 12% 0%, rgba(221, 70, 32, 0.26), transparent 62%),
    radial-gradient(65% 95% at 96% 25%, rgba(233, 177, 42, 0.15), transparent 64%),
    var(--ink);
}
/* Halftone dots — the texture every soul reissue sleeve has. */
.hero::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0.55;
  background-image: radial-gradient(rgba(246, 237, 225, 0.055) 1px, transparent 1px);
  background-size: 3px 3px;
}
.hero-inner {
  /* One variable drives both the logotype and the record, so "same height" is
     arithmetic rather than eyeballing. */
  --hero-type: clamp(2.6rem, 8.8vw, 6.2rem);

  position: relative; z-index: 1;
  max-width: var(--wrap-inner); margin: 0 auto;
}
.hero-copy { min-width: 0; }

/* Logotype and record are one lockup — the 45 sits immediately to the right of
   GOOD / FOOT!, not out in its own column at the far edge of the hero. */
.hero-lockup {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2.4vw, 1.8rem);
  margin: 1.15rem 0 1.35rem;
}

/* The record turns. A real 45 does 45rpm — 1.3s a revolution — which is
   unwatchable, so this is geared right down. The global reduced-motion rule
   stops it for anyone who asks. */
/* Sized off the headline, not picked by eye: the h1 is
   clamp(2.9rem, 12vw, 8.5rem) over two lines at 0.95 line-height, so its block
   is ~1.9x its font-size. Multiply the same clamp by 1.9 and the record stands
   exactly as tall as GET ON THE GOOD FOOT at every viewport.
   align-self:start plus the top offset lines its top edge up with the h1
   rather than centring it against the whole copy column. */
.hero-record {
  /* The stacked logotype is 1122x596, so its height is width/1.883. At a
     max-width of 3.7x --hero-type that is 1.97x --hero-type — match it and the
     record stands exactly as tall as GOOD / FOOT! at every viewport. */
  width: calc(var(--hero-type) * 1.97);
  flex: none;
}
.hero-record svg {
  width: 100%; height: auto; display: block;
  animation: spin 14s linear infinite;
  transform-origin: 50% 50%;
}


.hero h1 { font-size: var(--hero-type); margin: 1.25rem 0; }

/* The logotype is black artwork off a white flyer, so it is inverted to sit on
   the dark ground. Width is tied to the old type scale, which keeps the hero's
   proportions and the record's 1.9 multiplier intact. */
.hero-logotype {
  margin: 0;
  /* Two lines now, so it needs roughly half the width the single line took. */
  flex: 0 1 calc(var(--hero-type) * 3.7);
  max-width: calc(var(--hero-type) * 3.7);
}
.hero-logotype img {
  display: block; width: 100%; height: auto;
  filter: invert(1);
}
/* nowrap keeps it to exactly two lines, which is what the 1.9 multiplier
   below assumes. If it ever overflows, that is a sizing bug worth seeing. */
.hero h1 .line { display: block; white-space: nowrap; }
.hero h1 .outline {
  color: transparent;
  -webkit-text-stroke: 2px var(--gold);
}

.lede { max-width: 46ch; font-size: clamp(1.02rem, 2vw, 1.22rem); color: var(--paper-dim); }

.hero-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 2rem; }

.btn {
  display: inline-block; padding: 0.8rem 1.5rem; border-radius: 3px;
  text-decoration: none; font-family: var(--body);
  font-weight: 700; font-size: 0.82rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  border: 1px solid transparent; cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.btn-primary { background: var(--gold); color: var(--ink); }
.btn-primary:hover { background: #ffc848; }
.btn-ghost { border-color: var(--rule); color: var(--paper); background: none; }
.btn-ghost:hover { border-color: var(--paper); }

/* ---------- next date panel ---------- */

.nextup {
  position: relative; z-index: 1;
  max-width: var(--wrap-inner); margin: clamp(2rem, 6vw, 3.5rem) auto 0;
  border: 1px solid var(--rule); border-radius: 3px;
  background: rgba(36, 26, 23, 0.72);
  display: grid; grid-template-columns: auto 1fr auto;
  gap: clamp(1rem, 4vw, 2.5rem); align-items: center;
  padding: clamp(1.25rem, 3vw, 1.75rem);
}
.nextup-date { text-align: center; line-height: 1; }
.nextup-month {
  display: block; font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--flame);
}
.nextup-day { display: block; font-family: var(--display); font-size: clamp(3rem, 9vw, 4.6rem); }
.nextup-year { display: block; font-size: 0.75rem; letter-spacing: 0.16em; color: var(--paper-faint); }
.nextup-body h2 { font-size: clamp(1.3rem, 3.5vw, 1.9rem); margin-bottom: 0.4rem; }
.nextup-body p { color: var(--paper-dim); font-size: 0.95rem; }
.nextup-meta { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; margin-top: 0.6rem; }
.nextup-meta span {
  font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--paper-faint); font-weight: 600;
}

@media (max-width: 760px) {
  .nextup { grid-template-columns: auto 1fr; }
  .nextup > .btn { grid-column: 1 / -1; text-align: center; }
}

/* ---------- ticker ---------- */

.ticker { overflow: hidden; border-block: 1px solid var(--rule); background: var(--ink-2); padding: 0.65rem 0; }
.ticker-track { display: flex; width: max-content; animation: roll 57s linear infinite; }

/* Each group is forced to at least a full viewport, so two of them guarantee
   the strip is 200vw and the -50% shift lands exactly one group along. Without
   the min-width the content is narrower than the screen and the marquee
   appears to start from the middle. */
.ticker-group {
  display: flex; align-items: center; gap: 0.85rem;
  flex: 0 0 auto; min-width: 100vw;
  padding-right: 1.5rem;
  justify-content: space-around;
}
/* Each genre sits on its own lit panel — cream ground, dark type, with a warm
   halo so the strip reads as backlit rather than merely inverted. The chips
   separate themselves, which is why there are no bullets in the markup. */
.ticker-group span {
  font-family: var(--display); text-transform: uppercase; white-space: nowrap;
  font-size: 0.95rem; letter-spacing: 0.06em;
  color: #fff;
  padding: 0.3em 1em;
  /* A soft radial pad rather than a filled rectangle — it has no hard edge, so
     it reads as light spilling off the word instead of a box behind it. */
  background: radial-gradient(
    ellipse at center,
    rgba(255, 255, 255, 0.13) 0%,
    rgba(255, 255, 255, 0.05) 45%,
    rgba(255, 255, 255, 0) 75%
  );
  /* The glow proper: the letters emit it. Halved from the first pass. */
  text-shadow:
    0 0 5px rgba(255, 255, 255, 0.48),
    0 0 16px rgba(255, 255, 255, 0.3),
    0 0 38px rgba(255, 255, 255, 0.18);
}
@keyframes roll { to { transform: translateX(-50%); } }

/* ---------- sections ---------- */

.section { max-width: var(--wrap); margin: 0 auto; padding: clamp(3rem, 8vw, 5.5rem) var(--pad); }
.band { background: rgba(25, 18, 17, 0.88); border-block: 1px solid var(--rule); }
.band > .section { padding-block: clamp(3rem, 8vw, 5.5rem); }

.section-head { margin-bottom: 2.25rem; display: flex; flex-direction: column; gap: 0.7rem; }
.section-head h2 { font-size: clamp(2rem, 5.5vw, 3.2rem); }
.section-head p { max-width: 60ch; color: var(--paper-dim); }

.section-foot { margin-top: 2rem; color: var(--paper-dim); font-size: 0.92rem; }

/* ---------- prose ---------- */

.prose { max-width: 66ch; display: flex; flex-direction: column; gap: 1.1rem; }
.prose p { color: var(--paper-dim); }
.prose h3 { font-size: 1.5rem; color: var(--paper); margin-top: 1rem; }
.prose blockquote {
  margin: 0.5rem 0; padding-left: 1.25rem;
  border-left: 3px solid var(--flame);
  font-size: 1.12rem; color: var(--paper); font-style: italic;
}
.prose blockquote cite {
  display: block; margin-top: 0.5rem; font-style: normal;
  font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--paper-faint);
}

/* ---------- dates list ---------- */

.dates { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }

.date-row {
  display: grid; grid-template-columns: 5.5rem 1fr auto;
  gap: 1.5rem; align-items: center;
  padding: 1.35rem 0; border-bottom: 1px solid var(--rule);
}
.date-cell { text-align: center; line-height: 1; }
.date-mon { display: block; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--flame); }
.date-num { display: block; font-family: var(--display); font-size: 2.4rem; }
.date-dow { display: block; font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--paper-faint); }

.date-body h3 { font-size: 1.35rem; margin-bottom: 0.3rem; }
.date-body p { color: var(--paper-dim); font-size: 0.94rem; max-width: 58ch; }

.date-side { text-align: right; }
.tag {
  display: inline-block; padding: 0.28rem 0.7rem; border-radius: 999px;
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.11em; text-transform: uppercase;
  border: 1px solid var(--rule); color: var(--paper-dim); white-space: nowrap;
}
.tag-free { border-color: var(--gold); color: var(--gold); }
.tag-special { border-color: var(--flame); color: var(--flame); }

@media (max-width: 700px) {
  .date-row { grid-template-columns: 4rem 1fr; }
  .date-num { font-size: 1.9rem; }
  .date-side { grid-column: 2; text-align: left; }
}

/* ---------- residents ---------- */

.residents { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.resident {
  background: var(--ink-3); border: 1px solid var(--rule); border-radius: 3px;
  padding: 1.5rem; display: flex; flex-direction: column; gap: 0.6rem;
  text-decoration: none; color: inherit;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.resident:hover { border-color: var(--gold); transform: translateY(-2px); }
/* The card leads with the name in gold. It used to be two-letter initials at
   2.4rem, which is far too big once a full name sits there. */
.resident-name {
  font-family: var(--display); font-size: 1.55rem; line-height: 1.05;
  color: var(--gold); letter-spacing: 0.02em;
  text-transform: uppercase; text-wrap: balance;
}
@media (max-width: 700px) { .resident-name { font-size: 1.7rem; } }
.resident-role {
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--flame);
}
.resident p { font-size: 0.92rem; color: var(--paper-dim); }
.resident-more {
  margin-top: auto; padding-top: 0.9rem; border-top: 1px solid var(--rule);
  font-size: 0.76rem; font-weight: 700; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--gold);
}

/* ---------- DJ profile page ---------- */

.profile {
  max-width: var(--wrap); margin: 0 auto;
  padding: clamp(2.5rem, 7vw, 4.5rem) var(--pad) clamp(2rem, 5vw, 3rem);
  display: grid; grid-template-columns: minmax(0, 1fr) 20rem;
  gap: clamp(1.75rem, 5vw, 3.5rem); align-items: start;
}
/* Block, not flex: a float has no effect on a flex item, so the portrait
   below could never have text wrapping round it while this was a flex column.
   The margin rule reproduces what `gap: 1.35rem` was doing. */
.profile-main { display: block; }
.profile-main > * + * { margin-top: 1.35rem; }
.profile h1 { font-size: clamp(2.4rem, 8vw, 4.75rem); }
/* A bio is reached from the roll call and there was no way back except the
   browser's own button, so the way out sits at the top as well as the foot. */
.profile-back {
  margin: 0 0 1.25rem;
  font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.profile-back a {
  color: var(--gold); text-decoration: none;
  display: inline-block; padding: 0.35rem 0;
}
.profile-back a:hover, .profile-back a:focus-visible { color: var(--paper); }

.profile-role {
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--flame);
}
.profile-main p { color: var(--paper-dim); max-width: 62ch; }

/* Portrait from the February 2025 shoot, dropped in after the opening
   paragraph to break up a long column of text. All four are cropped to the
   same 4:5 so the bios match each other -- two of the originals are landscape
   and two portrait, and at a fixed width that difference was glaring.
   Floated so the text closes around it rather than being cut in half; the
   factbox holds the right side, so this sits left to balance the page. */
.profile-portrait {
  float: left;
  width: min(42%, 250px);
  margin: 0.35rem 1.5rem 1rem 0;
}
.profile-portrait img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--ink-3);
}
.profile-portrait figcaption {
  margin-top: 0.5rem;
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.06em;
  color: var(--paper-faint); line-height: 1.45;
}
/* A pull-quote squeezed into the column beside the picture reads badly, so
   it always starts below it. */
.profile-main blockquote { clear: left; }

@media (max-width: 700px) {
  /* No room to wrap text beside it on a phone: let it run full width between
     the paragraphs instead, which is what the float was standing in for. */
  .profile-portrait {
    float: none; width: 100%; max-width: 340px;
    margin: 1.25rem 0 1.5rem;
  }
}
.profile-main p strong { color: var(--paper); font-weight: 600; }

.factbox {
  background: var(--ink-3); border: 1px solid var(--rule); border-radius: 3px;
  padding: 1.4rem; display: flex; flex-direction: column; gap: 1rem;
  position: sticky; top: 5.5rem;
}
.factbox h2 { font-size: 1rem; letter-spacing: 0.08em; }
.factbox dl { margin: 0; display: flex; flex-direction: column; gap: 0.85rem; }
.factbox dt {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--paper-faint);
}
.factbox dd { margin: 0.15rem 0 0; font-size: 0.94rem; color: var(--paper); }

@media (max-width: 860px) {
  .profile { grid-template-columns: 1fr; }
  .factbox { position: static; }
}

/* ---------- media page ---------- */

.media-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

.media-item {
  background: var(--ink-3); border: 1px solid var(--rule); border-radius: 3px;
  padding: 1.35rem; display: flex; flex-direction: column; gap: 0.55rem;
  text-decoration: none; color: inherit;
  transition: border-color 0.15s ease;
  overflow: hidden;
}
/* The banner is pulled out to the card edges, so it cancels the card padding
   on three sides rather than sitting inside it. */
.media-thumb {
  display: block; margin: -1.35rem -1.35rem 0.35rem;
  border-bottom: 1px solid var(--rule);
  background: var(--ink);
}
.media-thumb img {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  object-fit: cover;
  filter: saturate(0.85) brightness(0.9);
  transition: filter 0.15s ease;
}
.media-item:hover .media-thumb img { filter: none; }
@media (prefers-reduced-motion: reduce) {
  .media-thumb img { transition: none; }
}
.media-item:hover { border-color: var(--gold); }
.media-kind {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gold);
}
.media-item h3 { font-size: 1.1rem; line-height: 1.15; }
.media-item p { font-size: 0.9rem; color: var(--paper-dim); }
.media-src {
  margin-top: auto; padding-top: 0.8rem; border-top: 1px solid var(--rule);
  font-size: 0.76rem; color: var(--paper-faint); letter-spacing: 0.04em;
}

/* ---------- placeholder / editorial note ---------- */

.todo {
  border: 1px dashed var(--gold); border-radius: 3px;
  background: rgba(233, 177, 42, 0.07);
  padding: 1.1rem 1.25rem; display: flex; flex-direction: column; gap: 0.4rem;
}
.todo strong { color: var(--gold); font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; }
.todo p { font-size: 0.92rem; color: var(--paper-dim); margin: 0; }

/* ---------- visit ---------- */

.visit { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(1.75rem, 5vw, 3.5rem); align-items: start; }
.visit address { font-style: normal; font-size: 1.15rem; line-height: 1.45; }
.visit dl { margin: 1.5rem 0 0; display: grid; gap: 0.9rem; }
.visit dt { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--paper-faint); }
.visit dd { margin: 0.2rem 0 0; color: var(--paper-dim); }


@media (max-width: 800px) { .visit { grid-template-columns: 1fr; } }

/* ---------- follow strip ---------- */

.follow {
  padding: clamp(3rem, 8vw, 5rem) var(--pad);
  background: linear-gradient(135deg, var(--flame), #a82f12);
  color: #180b06;
}
.follow-inner { max-width: var(--wrap-inner); margin: 0 auto; display: flex; flex-direction: column; gap: 1.1rem; }
.follow h2 { font-size: clamp(2rem, 5.5vw, 3.2rem); color: #180b06; }
.follow p { max-width: 52ch; color: rgba(24, 11, 6, 0.85); }
.follow-links { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.5rem; }
.follow-links .btn-primary { background: #180b06; color: var(--gold); }
.follow-links .btn-primary:hover { background: #000; }
.follow-links .btn-ghost { border-color: rgba(24, 11, 6, 0.4); color: #180b06; }
.follow-links .btn-ghost:hover { border-color: #180b06; }

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

.footer { border-top: 1px solid var(--rule); padding: 3rem var(--pad); background: var(--ink); }
.footer-inner {
  max-width: var(--wrap-inner); margin: 0 auto;
  display: grid; gap: 1.5rem; grid-template-columns: 1fr auto; align-items: start;
}
.footer-brand p { margin-top: 0.4rem; color: var(--paper-dim); font-size: 0.9rem; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 1.2rem; }
.footer-nav a {
  color: var(--paper-dim); text-decoration: none;
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
}
.footer-nav a:hover { color: var(--paper); }
.footer-fine {
  grid-column: 1 / -1; margin: 0; padding-top: 1.5rem;
  border-top: 1px solid var(--rule); color: var(--paper-faint); font-size: 0.8rem;
}

@media (max-width: 640px) { .footer-inner { grid-template-columns: 1fr; } }


/* ---------- past guest DJs ----------
   A roll call, not a set of profiles — names read better dense and in a grid
   than padded out into cards. */

.guests {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
}

.guest {
  background: var(--ink-3);
  padding: 1rem 1.1rem;
  display: flex; flex-direction: column; gap: 0.15rem;
}

.guest-name {
  font-family: var(--display); text-transform: uppercase;
  font-size: 1.12rem; letter-spacing: 0.01em; line-height: 1.1;
}
.guest-sub { font-size: 0.82rem; color: var(--paper-dim); }
.guest-when {
  margin-top: 0.1rem;
  font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--gold);
}

/* ---------- monthly food vendor ----------
   One panel, not a whole section — it should read as a useful aside next to
   Visit, not compete with the residents. */

.vendor {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1.25rem, 4vw, 2.5rem);
  align-items: center;
  background: var(--ink-3);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--gold);
  border-radius: 3px;
  padding: clamp(1.35rem, 4vw, 2.25rem);
}

.vendor-mark { width: clamp(72px, 14vw, 104px); flex: none; }
.vendor-mark svg { width: 100%; height: auto; display: block; }

.vendor-body { display: flex; flex-direction: column; gap: 0.7rem; }
.vendor-body h2 { font-size: clamp(1.8rem, 5vw, 2.6rem); }
.vendor-body p { color: var(--paper-dim); max-width: 56ch; }

@media (max-width: 620px) {
  .vendor { grid-template-columns: 1fr; justify-items: start; }
}

/* ---------- video ----------
   The play button IS the thumbnail until it is clicked, at which point it is
   replaced in place by the iframe — same box, no layout shift. */

.videos {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.video { display: flex; flex-direction: column; gap: 0.85rem; }

.video-play,
.video iframe {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  border: 1px solid var(--rule); border-radius: 3px;
  background: #000; padding: 0; margin: 0;
}

.video-play { position: relative; cursor: pointer; overflow: hidden; }
.video-play img {
  width: 100%; height: 100%; object-fit: cover;
  /* hqdefault is 4:3 with letterbox bars; crop to the 16:9 frame. */
  transform: scale(1.34);
  transition: transform 0.25s ease, filter 0.25s ease;
  filter: saturate(0.85) brightness(0.82);
}
.video-play:hover img,
.video-play:focus-visible img { transform: scale(1.4); filter: saturate(1) brightness(1); }

.video-badge {
  position: absolute; inset: 0; display: grid; place-items: center;
  pointer-events: none;
}
.video-badge svg {
  width: clamp(52px, 12%, 72px); height: auto;
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, 0.55));
  transition: transform 0.2s ease;
}
.video-play:hover .video-badge svg { transform: scale(1.1); }
/* The Instagram glyph is an outline, so it needs a scrim behind it to stay
   legible over a bright frame -- the YouTube badge is solid and does not. */
.video-badge-ig::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(closest-side, rgba(0,0,0,0.45), rgba(0,0,0,0) 70%);
}
.video-badge-ig svg { position: relative; }
@media (prefers-reduced-motion: reduce) {
  .video-badge svg { transition: none; }
}

.video-meta { display: flex; flex-direction: column; gap: 0.35rem; }
.video-meta h3 { font-size: 1.15rem; line-height: 1.15; }
.video-meta p { font-size: 0.9rem; color: var(--paper-dim); }
.video-src {
  margin-top: 0.15rem;
  font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--paper-faint);
}

/* Instagram gives no thumbnail without a login, so its facade is a drawn card
   rather than a still — and reels are portrait, so the frame changes shape. */
.video-portrait .video-play,
.video-portrait iframe { aspect-ratio: 9 / 16; max-height: 620px; }

.video-face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.9rem;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(221, 70, 32, 0.35), transparent 62%),
    var(--ink-3);
}
.video-face svg { width: 46px; height: 46px; opacity: 0.9; }
.video-face-label {
  font-family: var(--body); font-size: 0.76rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--paper);
}
.video-play:hover .video-face svg { transform: scale(1.08); transition: transform 0.2s ease; }

/* ---------- flyer year index ---------- */

.year-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.year-card a {
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--ink-3); overflow: hidden;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.year-card a:hover, .year-card a:focus-visible {
  border-color: var(--gold); transform: translateY(-3px);
}
.year-card img {
  width: 100%; height: auto; aspect-ratio: 3 / 4;
  object-fit: contain; background: #0b0908; opacity: 0.72;
  transition: opacity 0.15s ease;
}
/* Photos are landscape, so they can fill their tile without losing anything.
   Flyers keep contain, because they are all shapes and get clipped otherwise. */
.year-grid-landscape .year-card img { aspect-ratio: 3 / 2; object-fit: cover; }
.year-card a:hover img { opacity: 1; }
.year-card-meta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  padding: 0.8rem 1rem 0.9rem; border-top: 2px solid var(--gold);
}
.year-card-year { font-family: var(--display); font-size: 1.5rem; line-height: 1; }
/* Most cards are a bare year. A named collection ("2025 Special Photo Shoot")
   is far longer, so it steps down a size and stacks above the count rather
   than fighting it for the same row. */
.year-card-meta:has(.year-card-year.is-long) { flex-direction: column; align-items: flex-start; gap: 0.35rem; }
.year-card-year.is-long { font-size: 1.05rem; line-height: 1.15; }
.year-card-count {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--paper-dim);
}

.year-nav {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--rule);
}
.year-nav a {
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; text-decoration: none;
}
.year-nav a:hover { text-decoration: underline; }

/* ---------- image galleries (flyers + photos) ----------
   One grid serves both; only the aspect ratio differs, since flyers are
   posters and photographs are mostly landscape. */

.shots {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1.25rem;
}
.shots-portrait  { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.shots-landscape { grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); }

.shot a {
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--ink-3); overflow: hidden;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.shot a:hover, .shot a:focus-visible { border-color: var(--gold); transform: translateY(-3px); }

.shot img { width: 100%; height: auto; object-fit: cover; background: #000; display: block; }
/* Flyers are taller than any fixed tile, and a cover crop lopped the date off
   the top and the venue off the bottom. Contain shows the whole sheet; the
   ground colour fills whatever is left over. */
.shots-portrait  .shot img {
  aspect-ratio: 3 / 4; object-fit: contain; background: #0b0908;
}
.shots-landscape .shot img { aspect-ratio: 3 / 2; }

.shot-meta { padding: 0.75rem 1rem 0.85rem; border-top: 2px solid var(--gold); }
.shot-date {
  font-family: var(--display); font-size: 1rem;
  text-transform: uppercase; letter-spacing: 0.02em;
}


/* Year heading inside the dates list — the run spans twelve months, so it
   always crosses at least one new year. */
.year-divider {
  list-style: none;
  padding: 1.5rem 0 0.6rem;
  border-bottom: 1px solid var(--rule);
}
.year-divider:first-child { padding-top: 0; }
.year-divider span {
  font-family: var(--display);
  font-size: 1.15rem;
  letter-spacing: 0.16em;
  color: var(--gold);
}

/* Previous appearances under a guest's most recent one. Plenty are regulars —
   Anthony De La Rosa has eight nights, the Slop Stomp crew return every
   Halloween — so the whole run is worth showing. */
/* "Last appearance", the date, and the "Also" line all sat at different sizes
   (0.6 / 0.68 / 0.7rem). One size for all three; the labels stay distinct by
   weight and tracking instead. */
.guest-label {
  margin-top: 0.45rem;
  font-size: 0.74rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--paper-dim);
}
.guest-prev em {
  font-style: normal; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--paper-dim); margin-right: 0.2rem;
}
.guest-prev {
  margin-top: 0.3rem;
  font-size: 0.74rem;
  line-height: 1.5;
  color: var(--paper-dim);
}

/* ---------- visit map ----------
   OpenStreetMap rather than Google: no API key, no tracking cookie, and it
   renders without a script. The directions link hands off to whichever maps
   app the visitor actually uses. */
.visit-map { display: flex; flex-direction: column; gap: 0.75rem; }
.visit-map iframe {
  width: 100%; aspect-ratio: 4 / 3; border: 1px solid var(--rule);
  border-radius: 3px; background: var(--ink-3); display: block;
}
.visit-map-link {
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; text-decoration: none;
}
.visit-map-link:hover { text-decoration: underline; }

/* ---------- lightbox ---------- */

.shot-open {
  display: flex; flex-direction: column; width: 100%;
  padding: 0; margin: 0; border: 0; background: none;
  color: inherit; font: inherit; text-align: left; cursor: zoom-in;
}
.shot-cap {
  display: block; margin-top: 0.2rem;
  font-family: var(--body); font-size: 0.78rem;
  color: var(--gold); line-height: 1.35;
}

.lightbox {
  /* The lightbox owns its gestures. Without touch-action the browser reads a
     horizontal drag across the picture as a pan/zoom and scales the image
     mid-swipe, which is the bug this replaced. */
  touch-action: none; overscroll-behavior: contain;
  position: fixed; inset: 0; z-index: 200;
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  padding: clamp(0.75rem, 3vw, 2rem);
  background: rgba(8, 6, 5, 0.94);
  backdrop-filter: blur(6px);
}
.lightbox[hidden] { display: none; }

.lb-figure {
  margin: 0; min-width: 0; display: flex; flex-direction: column;
  align-items: center; gap: 0.9rem;
}
.lb-figure img {
  max-width: 100%; max-height: 78vh; width: auto; height: auto;
  object-fit: contain; border-radius: 3px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
  /* Long-press callout and drag-select both fight the swipe on iOS. */
  touch-action: none; -webkit-touch-callout: none;
  -webkit-user-select: none; user-select: none;
  will-change: transform;
}
/* Settle back after a swipe or a released pinch. Suppressed while a finger is
   down so the picture tracks it one-to-one. */
.lb-figure img.is-settling { transition: transform 0.22s ease, opacity 0.22s ease; }
/* Zoom grows from the middle, and the picture must be free to overflow its
   box once magnified or the edges get clipped while panning. */
.lb-figure img { transform-origin: center center; }
.lightbox.is-zoomed .lb-figure { overflow: visible; }
/* While zoomed the caption and hint are in the way -- fade them back. */
.lightbox.is-zoomed figcaption { opacity: 0.25; transition: opacity 0.2s ease; }
.lb-figure figcaption {
  font-size: 0.9rem; color: var(--paper-dim); text-align: center;
  max-width: 60ch;
}
.lb-figure figcaption strong { color: var(--paper); font-weight: 600; }
.lb-count { display: block; margin-top: 0.3rem; font-size: 0.74rem; color: var(--paper-faint); letter-spacing: 0.1em; }

.lightbox button {
  background: rgba(246, 237, 225, 0.08);
  border: 1px solid var(--rule); color: var(--paper);
  border-radius: 3px; cursor: pointer; font-family: var(--body);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.lightbox button:hover { background: rgba(246, 237, 225, 0.18); border-color: var(--paper-dim); }

.lb-prev, .lb-next { width: clamp(38px, 6vw, 52px); height: clamp(56px, 10vh, 84px); font-size: 1.8rem; line-height: 1; }
.lb-close {
  position: absolute; top: clamp(0.75rem, 3vw, 2rem); right: clamp(0.75rem, 3vw, 2rem);
  width: 40px; height: 40px; font-size: 1.5rem; line-height: 1;
}

@media (max-width: 640px) {
  .lightbox { grid-template-columns: 1fr; grid-template-rows: 1fr auto; }
  .lb-prev { grid-row: 2; justify-self: start; }
  .lb-next { grid-row: 2; justify-self: end; }
  .lb-figure { grid-row: 1; }
}

/* Base state first: at equal specificity the later rule wins, so this has to
   sit above the media query that turns the hint on, not below it. */
.lb-hint { display: none; }

/* On a touch screen the arrows are redundant -- you swipe. Keyed off pointer
   type rather than width so a narrow desktop window keeps its buttons. */
@media (hover: none) and (pointer: coarse) {
  .lb-prev, .lb-next { display: none; }
  .lightbox { grid-template-columns: 1fr; }
  .lb-hint {
    display: block; margin-top: 0.55rem;
    font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--paper-faint);
  }
}

/* Sub-headings inside the roll call — former residents, then guests. */
.roll-head {
  font-size: 1.25rem;
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.roll-head:first-of-type { margin-top: 0; padding-top: 0; border-top: 0; }
.roll-intro {
  margin: 0.6rem 0 1.4rem;
  color: var(--paper-dim);
  max-width: 62ch;
  font-size: 0.95rem;
}

/* ---------- jukebox ---------- */

.jb-album {
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--ink-3); margin-bottom: 0.85rem;
}
.jb-album summary {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding: 1rem 1.25rem; cursor: pointer; list-style: none;
}
.jb-album summary::-webkit-details-marker { display: none; }
.jb-album summary::after {
  content: '+'; font-family: var(--display); font-size: 1.3rem;
  color: var(--gold); line-height: 1;
}
.jb-album[open] summary::after { content: '\2013'; }
.jb-ed { font-family: var(--display); font-size: 1.35rem; text-transform: uppercase; }
.jb-meta {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--paper-faint); margin-left: auto;
  padding-right: 0.75rem;
}

.jb-body {
  display: grid;
  grid-template-columns: minmax(160px, 260px) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2rem);
  padding: 0 1.25rem 1.25rem;
  align-items: start;
}
.jb-art { position: sticky; top: 5.5rem; }
.jb-cover {
  width: 100%; aspect-ratio: 1; object-fit: cover; display: block;
  border-radius: 3px; background: #000;
  border: 1px solid var(--rule);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
/* Until a sleeve photo arrives, a plain card stands in rather than a gap. */
.jb-cover-blank {
  display: grid; place-items: center; text-align: center; padding: 1rem;
  background:
    radial-gradient(70% 70% at 30% 20%, rgba(221, 70, 32, 0.28), transparent 60%),
    var(--ink-2);
}
.jb-cover-blank span {
  font-family: var(--display); font-size: clamp(1.1rem, 4vw, 1.8rem);
  text-transform: uppercase; color: var(--paper-dim); line-height: 1;
}
.jb-side { min-width: 0; }
/* The player only appears once something is playing; until then the tracklist
   gets the full column. */
.jb-stage { padding: 0 0 0.9rem; }
.jb-frame { position: relative; }
.jb-frame iframe {
  width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 3px; display: block;
  background: #000;
}
.jb-controls {
  display: flex; align-items: center; gap: 0.4rem;
  padding-top: 0.55rem;
}
.jb-ctl {
  background: var(--ink-3); color: var(--paper);
  border: 1px solid var(--rule); border-radius: 3px;
  font-size: 0.72rem; line-height: 1; padding: 0.42rem 0.6rem;
  cursor: pointer; transition: border-color 0.15s ease, color 0.15s ease;
}
.jb-ctl:hover { border-color: var(--gold); color: var(--gold); }
.jb-now {
  margin-left: 0.45rem; min-width: 0;
  font-size: 0.78rem; color: var(--paper-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.jb-playall {
  margin-top: 0.7rem; width: 100%;
  background: var(--gold); color: var(--ink);
  border: 0; border-radius: 3px; cursor: pointer;
  font-family: var(--display); font-size: 0.86rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.6rem 0.7rem;
  transition: filter 0.15s ease;
}
.jb-playall:hover { filter: brightness(1.1); }

/* Secondary route: hand the playlist off to the phone's own apps. */
.jb-take { display: flex; gap: 0.4rem; margin-top: 0.45rem; }
.jb-take a {
  flex: 1; text-align: center;
  font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0.42rem 0.3rem; border: 1px solid var(--rule); border-radius: 3px;
  color: var(--paper-dim); text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.jb-take a:hover { border-color: var(--gold); color: var(--gold); }

.jb-carry {
  margin-top: 2.5rem; padding: 1.25rem 1.4rem;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--ink-3);
  display: flex; gap: 1.4rem; align-items: flex-start;
  flex-wrap: wrap;
}
.jb-carry-main { flex: 1 1 22rem; min-width: 0; }
.jb-carry strong {
  display: block; font-family: var(--display);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 0.45rem;
}
.jb-carry p { font-size: 0.9rem; color: var(--paper-dim); margin: 0 0 0.55rem; }
.jb-carry-fine { font-size: 0.82rem !important; color: var(--paper-faint) !important; margin: 0 !important; }
.jb-sub {
  flex: 0 0 auto; align-self: center;
  background: var(--flame); color: #fff; text-decoration: none;
  font-family: var(--display); font-size: 0.82rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.7rem 1.1rem; border-radius: 3px;
  transition: filter 0.15s ease;
}
.jb-sub:hover { filter: brightness(1.12); }

.jb-tracks { list-style: none; margin: 0; padding: 0; }
.jb-track {
  display: grid; grid-template-columns: 2rem 1fr auto; gap: 0.75rem;
  align-items: baseline; padding: 0.5rem 0;
  border-top: 1px solid var(--rule);
}
/* Original pressing: year over label, hard right. */
.jb-rel {
  text-align: right; justify-self: end; min-width: 0;
  display: flex; flex-direction: column; gap: 0.1rem;
}
.jb-year {
  display: block; font-size: 0.8rem; font-weight: 700;
  color: var(--paper-dim); font-variant-numeric: tabular-nums;
}
.jb-label {
  display: block; font-size: 0.72rem; color: var(--paper-faint);
  max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Narrow screens: the label is the first thing to go, year stays. */
@media (max-width: 760px) {
  .jb-label { display: none; }
  .jb-year { font-size: 0.82rem; }
}
.jb-n {
  font-size: 0.72rem; font-weight: 700; color: var(--paper-faint);
  font-variant-numeric: tabular-nums;
}
.jb-link { text-decoration: none; color: inherit; display: block; }
.jb-cue:hover .jb-title, .jb-link:hover .jb-title { color: var(--gold); }

/* Tracks are buttons now, so they have to be un-styled back to plain rows. */
.jb-cue {
  display: contents;
  background: none; border: 0; padding: 0; margin: 0;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.jb-cue:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.jb-track.is-playing { background: rgba(233, 177, 42, 0.08); }
.jb-track.is-playing .jb-n { color: var(--gold); }
.jb-track.is-playing .jb-artist { color: var(--gold); }
.jb-track.is-playing .jb-title { color: var(--paper); }
.jb-artist { display: block; font-weight: 600; font-size: 0.94rem; }
.jb-title { display: block; font-size: 0.88rem; color: var(--paper-dim); transition: color 0.15s ease; }
.jb-track.is-check .jb-title { color: var(--flame); font-style: italic; }

@media (max-width: 620px) {
  .jb-body { grid-template-columns: 1fr; }
  .jb-art { position: static; max-width: 260px; }
}

/* Group headings in the jukebox: anniversaries, samplers, specials, live. */
.jb-group {
  font-size: 1.1rem;
  margin: 2.25rem 0 0.9rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
  color: var(--gold);
  letter-spacing: 0.06em;
}
.jb-group:first-child { margin-top: 0; }


/* ---------- add-to-home-screen ---------- */

.install {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem; margin-top: 1.4rem;
}
.install-card {
  background: var(--ink-3); border: 1px solid var(--rule); border-radius: 3px;
  padding: 1.1rem 1.2rem 1.2rem;
}
.install-head { display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.8rem; }
.install-head svg { width: 26px; height: 26px; flex: none; color: var(--gold); }
.install-h {
  display: block; font-family: var(--display); text-transform: uppercase;
  font-size: 1.05rem; letter-spacing: 0.02em; color: var(--head);
}
.install-plat {
  display: block; font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--paper-faint);
}
.install-steps { margin: 0; padding-left: 1.15rem; }
.install-steps li {
  font-size: 0.92rem; line-height: 1.55; color: var(--paper-dim);
  margin-bottom: 0.4rem;
}
.install-steps li::marker { color: var(--gold); font-weight: 700; }
.install-steps b { color: var(--paper); font-weight: 600; }

@media (max-width: 700px) {
  .install { grid-template-columns: 1fr; }
}

/* ---------- mobile type scale ----------
   17px is comfortable on a desktop monitor but reads small at arm's length on
   a phone, so the base steps up and the smaller utility sizes come with it. */
@media (max-width: 700px) {
  body { font-size: 18.5px; }
  .install-steps li { font-size: 0.98rem; }
  .media-item p, .video-meta p { font-size: 0.95rem; }
  .jb-artist { font-size: 1rem; }
  .jb-title { font-size: 0.95rem; }
  .jb-n { font-size: 0.8rem; }
  .guest-label, .guest-prev, .guest-when { font-size: 0.8rem; }
  .guest-sub { font-size: 0.9rem; }
  .media-src, .video-src { font-size: 0.8rem; }
  .shot-cap { font-size: 0.85rem; }
  .jb-take a { font-size: 0.74rem; }
}

.visit-site {
  font-family: var(--body); font-weight: 600; font-size: 0.92rem;
  color: var(--gold); text-decoration: none;
  letter-spacing: 0.02em;
}
.visit-site:hover { text-decoration: underline; }

.visit-sched {
  display: inline-block; margin-left: 0.15rem;
  font-size: 0.85rem; font-weight: 600; color: var(--gold);
  text-decoration: none; white-space: nowrap;
}
.visit-sched:hover { text-decoration: underline; }

/* Street address sits a little below the phone line and opens the map. */
.visit-addr {
  display: block; margin-top: 0.7rem;
  color: inherit; text-decoration: none;
  transition: color 0.15s ease;
}
.visit-addr:hover { color: var(--gold); text-decoration: underline; }

/* Self-hosted reels play natively — same footprint as the facade they replace. */
.video-native {
  display: block; width: 100%; aspect-ratio: 9 / 16;
  background: #000; border-radius: 3px 3px 0 0;
}
.video:not(.video-portrait) .video-native { aspect-ratio: 16 / 9; }

/* Follow links on a guest card. */
.guest-social {
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  margin-top: 0.6rem; padding-top: 0.55rem;
  border-top: 1px solid var(--rule);
}
.guest-social a {
  font-size: 0.74rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--gold); text-decoration: none;
  border: 1px solid var(--rule); border-radius: 3px;
  padding: 0.24rem 0.5rem;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.guest-social a:hover { border-color: var(--gold); background: rgba(233,177,42,0.1); }
@media (max-width: 700px) { .guest-social a { font-size: 0.8rem; } }
