/* ── BASE ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--c-ground);
  color: var(--c-ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--leading-body);
  overflow-x: hidden;
  caret-color: var(--c-accent);
  scrollbar-color: var(--c-surface-2) var(--c-ground);
}

/* Photocopy grain over the whole page: texture, not gloss. Fixed so it costs nothing on scroll. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-dialog) + 2);
  pointer-events: none;
  background: var(--grain);
  opacity: 0.07;
}

::selection { background: var(--c-accent); color: var(--c-ground); }

img, svg, canvas { display: block; max-width: 100%; }
ul { list-style: none; }
/* Pulls a word down so no paragraph ends on one word alone. Headings set their own `balance`. */
p, li { text-wrap: pretty; }
.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

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

:focus-visible {
  outline: 3px solid var(--c-focus);
  outline-offset: 3px;
}
main:focus { outline: none; }

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

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: calc(var(--z-dialog) + 1);
  padding: var(--space-2) var(--space-4);
  background: var(--c-ink);
  color: var(--c-ground);
  font-weight: 600;
  transform: translateY(-200%);
}
.skip-link:focus,
.skip-link:hover { transform: none; color: var(--c-ground); }

/* ── BUTTONS ── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              scale var(--dur-fast) var(--ease-out);
}
/* Every pressable thing answers the press the same way: a slight give, never a jump. */
.btn:active { scale: 0.97; }
.btn[disabled] { opacity: 0.6; cursor: progress; }

/* Ground-colored text on the accent: 5.1:1 at rest, 6.8:1 on hover. */
.btn-primary { background: var(--c-accent); color: var(--c-ground); }
.btn-primary:hover { background: var(--c-accent-hi); color: var(--c-ground); }

.btn-ghost { background: transparent; color: var(--c-ink); border-color: var(--c-line-hi); }
.btn-ghost:hover { border-color: var(--c-ink); color: var(--c-ink); background: var(--c-surface); }

.btn-lg { min-height: 56px; padding-inline: var(--space-6); font-size: var(--step-1); }
.btn-sm { min-height: 44px; padding: var(--space-2) var(--space-5); font-size: var(--step--1); }

.link-button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--c-blue);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}
.link-button:hover { color: var(--c-text); }

/* ── HEADER ── */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: 4rem;
  padding: 0 var(--gutter-tight);
  transition: background-color var(--dur-med) var(--ease-out);
}
.site-header.scrolled { background: var(--c-ground); }

/* The brand takes the free space, so the menu button and links sit hard against the right margin. */
.brand {
  margin-right: auto;
  display: flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-0);
  letter-spacing: 0.04em;
  color: var(--c-ink);
  text-decoration: none;
}
.brand:hover { color: var(--c-accent-text); }
/* Over the hero the wordmark is already huge, so the header brand waits until the page scrolls. */
body:has(.hero) .site-header .brand { transition: opacity var(--dur-med) var(--ease-out), visibility var(--dur-med); }
body:has(.hero) .site-header:not(.scrolled) .brand { opacity: 0; visibility: hidden; }
.nav-links { align-items: center; }
.brand-mark { width: 7.5rem; height: auto; aspect-ratio: 656 / 100; }

.nav-links { display: flex; gap: var(--space-6); }
.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--c-ink);
  font-weight: 600;
  text-decoration: none;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.4em;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-links a:hover { color: var(--c-accent-text); }
.nav-links a.btn-primary,
.nav-links a.btn-primary:hover { color: var(--c-ground); text-decoration: none; }
.nav-links a.active { text-decoration-line: underline; text-decoration-color: var(--c-accent); }

.nav-toggle { display: none; }

/* ── HERO: the name as a monument, over a xeroxed live photo ── */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  overflow: hidden;
  isolation: isolate;
  background: var(--c-ground);
}

/* The live photo, photocopied: grain, no color, crushed contrast. The layer above tints it the
   purple of the band's shirt print. The source is small (1051px), and the treatment hides that. */
.hero-photo {
  position: absolute;
  inset: 0;
  z-index: -3;
  background: var(--grain), url("../images/band/hero-band.jpg") center 30% / cover no-repeat;
  background-size: 180px, cover;
  filter: grayscale(1) contrast(1.45) brightness(0.62);
  -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 96%);
          mask-image: linear-gradient(to bottom, #000 45%, transparent 96%);
}
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  background: var(--c-accent);
  mix-blend-mode: multiply;
}

.starfield {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  opacity: 0.7;
}

.hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--space-7), 8svh, 6rem);
  padding: calc(4rem + var(--space-6)) var(--gutter) clamp(var(--space-8), 14svh, 9rem);
  text-align: center;
}
.hero-name { width: 100%; max-width: 60rem; }

/* The wordmark runs margin to margin. Text over the photo stays in the full ink. */
.hero-wordmark { color: var(--c-ink); line-height: 0; }
.hero-logo { width: 100%; height: auto; aspect-ratio: 656 / 100; }

.hero-tagline {
  margin: var(--space-5) auto 0;
  max-width: 34ch;
  font-size: var(--step-1);
  font-weight: 600;
  line-height: 1.35;
  text-wrap: balance;
}
.hero-pronounce { display: block; margin-top: var(--space-1); font-size: var(--step-0); font-weight: 400; }

.hero-news { width: 100%; max-width: 54rem; }
.hero-headline {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-3);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  text-wrap: balance;
}
.hero-lede { margin: var(--space-4) auto 0; max-width: 36ch; font-size: var(--step-1); line-height: 1.45; }

.hero-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); margin-top: var(--space-6); }
.socials-hero { margin-top: var(--space-5); }

.ridges {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  height: clamp(8rem, 30vh, 18rem);
  pointer-events: none;
}
.ridge {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: translateY(var(--parallax, 0px));
  animation: ridge-rise 1200ms var(--ease-out) both;
}
.ridge-far  { fill: var(--c-surface-2); animation-delay: 100ms; }
.ridge-mid  { fill: var(--c-surface);   animation-delay: 200ms; }
.ridge-near { fill: var(--c-ground);    animation-delay: 300ms; }

/* `from` only, so each element settles on its own resting opacity (the starfield rests at 0.7). */
@keyframes fade-in { from { opacity: 0; } }
@keyframes rise-in { from { opacity: 0; translate: 0 1rem; } }
/* The name comes into focus, like the moon through cloud. */
@keyframes focus-in { from { opacity: 0; filter: blur(12px); scale: 0.98; } }
/* Rise uses `translate` so it composes with the scroll parallax on `transform`. */
@keyframes ridge-rise {
  from { translate: 0 40%; }
  to   { translate: 0 0; }
}

/* Entrance, once per visit: sky, name, then the news line by line. Nothing waits on it; the buttons
   work the moment they're on screen. */
.starfield { animation: fade-in 1600ms var(--ease-out) both; }
.hero-wordmark { animation: focus-in 1100ms var(--ease-out) both; }
.hero-tagline { animation: rise-in var(--dur-reveal) var(--ease-out) 250ms both; }
.hero-news > * { animation: rise-in var(--dur-reveal) var(--ease-out) both; }
.hero-news > :nth-child(1) { animation-delay: 400ms; }
.hero-news > :nth-child(2) { animation-delay: calc(400ms + var(--stagger)); }
.hero-news > :nth-child(3) { animation-delay: calc(400ms + 2 * var(--stagger)); }
.hero-news > :nth-child(4) { animation-delay: calc(400ms + 3 * var(--stagger)); }

/* ── SCROLL REVEAL ──
   main.js tags blocks below the hero with .reveal (or .reveal-group, whose children step in one
   after another) and adds .is-in as each comes into view. Without JavaScript nothing is tagged,
   so nothing is ever hidden. */
.reveal,
.reveal-group > * {
  opacity: 0;
  translate: 0 1.5rem;
  transition: opacity var(--dur-reveal) var(--ease-out), translate var(--dur-reveal) var(--ease-out);
}
.reveal.is-in,
.reveal-group.is-in > * { opacity: 1; translate: none; }
.reveal-group > :nth-child(2) { transition-delay: var(--stagger); }
.reveal-group > :nth-child(3) { transition-delay: calc(2 * var(--stagger)); }
.reveal-group > :nth-child(n + 4) { transition-delay: calc(3 * var(--stagger)); }
/* Children that arrive after the group is in view (the merch tiles load from a file) still step in. */
@starting-style {
  .reveal-group.is-in > * { opacity: 0; translate: 0 1.5rem; }
}
@media print {
  .reveal,
  .reveal-group > * { opacity: 1; translate: none; }
}

/* ── SECTIONS ──
   One centered axis for the whole page. Headings and short copy sit on it; content blocks are
   centered columns sized to what they hold. Spacing follows the 8px grid: tight inside a group,
   generous between groups, widest between sections. */
.section-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(var(--space-8), 9vw, 8rem) var(--gutter);
  text-align: center;
}

.section-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-3);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  text-wrap: balance;
  margin-bottom: var(--space-6);
}
.section-body > :first-child { margin-top: 0; }

.subhead {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-1);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  margin: var(--space-8) 0 var(--space-6);
}

/* Persuasive copy reads in the full ink; muted is for notes. */
.lede {
  max-width: 40ch;
  margin: 0 auto var(--space-7);
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--c-ink);
  text-wrap: balance;
}

.section-action { margin-top: var(--space-7); }

/* A filled panel: the page's one container, kept for the moments that ask something of the visitor. */
.up-next,
.shows-none,
.booking {
  max-width: 40rem;
  margin-inline: auto;
  padding: var(--space-7) var(--space-6);
  background: var(--c-surface);
}
.up-next-title,
.shows-none-title,
.booking-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-2);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  text-wrap: balance;
}
.up-next > * + *,
.shows-none > * + *,
.booking > * + * { margin-top: var(--space-4); }
.up-next .btn,
.booking .btn { margin-top: var(--space-6); }

/* ── MAILING LIST ── a full-width band one tone up, right after the hero. */
.section-signup { background: var(--c-surface); }

.signup {
  display: grid;
  gap: var(--space-5);
  max-width: 30rem;
  margin: 0 auto;
  text-align: left;
}
.field { display: grid; gap: var(--space-2); }
.field label { font-weight: 600; }
.field input[type="email"] {
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
  font: inherit;
  font-size: var(--step-1);
  color: var(--c-ink);
  background: var(--c-ground);
  border: 2px solid var(--c-line-hi);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.field input[type="email"]:hover,
.field input[type="email"]:focus-visible { border-color: var(--c-ink); }
.field input[aria-invalid="true"] { border-color: var(--c-danger); }
.field input:disabled { opacity: 0.6; cursor: not-allowed; }

.field-check { grid-template-columns: auto 1fr; align-items: start; column-gap: var(--space-3); }
.field-check input { width: 1.5rem; height: 1.5rem; margin-top: 0.1rem; accent-color: var(--c-accent); cursor: pointer; }
.field-check label { font-weight: 400; cursor: pointer; }
.field-check .field-error { grid-column: 2; }

.field-error { color: var(--c-danger); font-size: var(--step--1); font-weight: 600; }

/* Messages ease in instead of popping, so the eye catches them without a jolt. */
.field-error,
.signup-status { transition: opacity var(--dur-med) var(--ease-out), translate var(--dur-med) var(--ease-out); }
@starting-style {
  .field-error,
  .signup-status { opacity: 0; translate: 0 -0.25rem; }
}
.field-trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.signup-privacy { color: var(--c-muted); font-size: var(--step--1); }
.signup-privacy a { display: inline-flex; align-items: center; min-height: 44px; }

.signup-submit { display: grid; gap: var(--space-4); }
.signup-submit .btn { width: 100%; min-height: 56px; font-size: var(--step-1); }
.signup-status:empty { display: none; }
.signup-status { padding: var(--space-4); font-weight: 600; text-align: center; }
.signup-status[data-tone="success"] { color: var(--c-success); background: rgba(143, 227, 192, 0.1); }
.signup-status[data-tone="error"] { color: var(--c-danger); background: rgba(255, 143, 163, 0.1); }

/* Signup and cookie settings need JavaScript; hide them rather than show dead controls. */
html:not(.js) #signup,
html:not(.js) [data-open-consent] { display: none; }
.js .nojs-only { display: none; }

/* ── MUSIC ── */
.up-next { margin-bottom: var(--space-8); }

.release-head { container-type: inline-size; }
/* The title scales with its column, so the name always fits on one line. */
.release-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: clamp(2.25rem, 11cqi, 6rem);
  line-height: 1;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  white-space: nowrap;
}
.release-meta { margin-top: var(--space-4); font-size: var(--step-1); font-weight: 600; }
.release-copy { margin-top: var(--space-1); color: var(--c-muted); }

/* The player box keeps the Spotify embed's height before and after loading, so nothing shifts. */
.player { max-width: 40rem; height: 352px; margin: var(--space-7) auto 0; background: var(--c-surface); }
.player-load {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  height: 100%;
  color: var(--c-ink);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.player-load:hover { background: var(--c-surface-2); color: var(--c-ink); }
.player-icon {
  display: grid;
  place-items: center;
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  background: var(--c-accent);
  transition: scale var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.player-icon::before {
  content: '';
  margin-left: 0.3rem;
  border-block: 0.85rem solid transparent;
  border-left: 1.4rem solid var(--c-ground);
}
.player-load:hover .player-icon { background: var(--c-accent-hi); }
.player-load:active .player-icon { scale: 0.94; }
.player-label { margin-top: var(--space-2); font-size: var(--step-1); font-weight: 600; }
.player-note { color: var(--c-muted); font-size: var(--step--1); }
.player-frame { display: block; width: 100%; height: 100%; border: 0; transition: opacity 400ms var(--ease-out); }
/* Held back until Spotify has drawn, so the box goes straight from our panel to the player, no white flash. */
.player-frame:not(.is-ready) { opacity: 0; }

.platform-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  max-width: 40rem;
  margin: var(--space-6) auto 0;
}
.platform-link {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-5);
  color: var(--c-ink);
  background: var(--c-surface);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out), scale var(--dur-fast) var(--ease-out);
}
.platform-link:hover { color: var(--c-ink); background: var(--c-surface-2); }
.platform-link:active { scale: 0.97; }

/* ── SHOWS ── filled rows, a tone up from the ground; no rules. */
.shows-list { display: grid; gap: var(--space-2); max-width: 48rem; margin: 0 auto; }

.show-row {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  background: var(--c-surface);
  text-align: left;
}

/* Day sits above month, poster-style; DOM order stays "month day" for screen readers. */
.show-date { display: flex; flex-direction: column-reverse; align-items: flex-start; gap: var(--space-1); line-height: 1; }
.show-day { font-family: var(--font-display); font-weight: 800; font-stretch: 125%; font-size: var(--step-2); font-variant-numeric: tabular-nums; }
.show-month { font-size: var(--step--1); font-weight: 600; letter-spacing: 0.06em; color: var(--c-accent-text); }

.show-venue { font-size: var(--step-1); font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; text-wrap: balance; }
.show-location { color: var(--c-muted); }

.show-ticket { white-space: nowrap; }
.show-ticket-none { color: var(--c-muted); white-space: nowrap; }
.show-tag {
  padding: var(--space-1) var(--space-3);
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step--1);
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--c-surface-2);
}
.show-tag-sold { background: var(--c-ink); color: var(--c-ground); }
.show-row.is-past { background: transparent; }
.show-row.is-past .show-venue,
.show-row.is-past .show-day { color: var(--c-muted); }

.shows-empty { font-size: var(--step-1); line-height: 1.5; }

/* ── MERCH STRIP ── */
.merch-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6) var(--space-4); max-width: 64rem; margin: 0 auto; }
/* An odd number of products on a phone: the first one leads at full width, so none is left alone. */
.merch-strip > li:first-child:nth-last-child(odd) { grid-column: 1 / -1; }
.merch-strip:empty { display: none; }
.merch-tile { display: grid; gap: var(--space-3); color: var(--c-ink); text-decoration: none; }
.merch-tile-photo { overflow: hidden; background: var(--c-surface); }
.merch-tile img {
  width: 100%;
  aspect-ratio: 1;
  height: auto;
  object-fit: cover;
  transition: scale var(--dur-med) var(--ease-out);
}
/* Only a real pointer gets the zoom; on touch it would stick after the tap. */
@media (hover: hover) and (pointer: fine) {
  .merch-tile:hover img { scale: 1.03; }
}
.merch-tile-photo { transition: scale var(--dur-fast) var(--ease-out); }
.merch-tile:active .merch-tile-photo { scale: 0.98; }
.merch-tile-name { font-weight: 600; line-height: 1.35; text-wrap: balance; }
.merch-tile:hover .merch-tile-name { text-decoration: underline; color: var(--c-ink); }
.merch-tile-note { margin-top: calc(-1 * var(--space-2)); color: var(--c-muted); font-size: var(--step--1); }

/* ── ABOUT ── */
.about-grid { display: grid; gap: var(--space-7); justify-items: center; }
.about-photo { width: 100%; max-width: 64rem; height: auto; }
.about-copy { max-width: 60ch; font-size: var(--step-1); line-height: 1.55; text-wrap: pretty; }
.about-copy p + p { margin-top: var(--space-4); }
.fans-of { color: var(--c-accent-text); font-weight: 600; }

.members {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-7);
  max-width: 64rem;
  margin: 0 auto;
}
/* Three moons: circular portraits with an orbit ring that answers hover and focus. */
.member > img {
  width: min(100%, 9rem);
  height: auto;
  aspect-ratio: 1;
  margin: 0 auto;
  object-fit: cover;
  border-radius: 50%;
  outline: 2px solid var(--c-surface-2);
  outline-offset: 6px;
  transition: outline-color var(--dur-med) var(--ease-out), outline-offset var(--dur-med) var(--ease-out);
}
.member:hover > img,
.member:focus-within > img { outline-color: var(--c-accent); outline-offset: 10px; }
.member-name { margin-top: var(--space-5); font-size: var(--step-1); font-weight: 600; }
.member-role { color: var(--c-muted); }

.socials {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
}
.socials a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  transition: background-color var(--dur-fast) var(--ease-out), scale var(--dur-fast) var(--ease-out);
}
.socials a:hover { background: var(--c-surface-2); }
.socials a:active { scale: 0.94; }
.socials img { width: 22px; height: 22px; filter: invert(1); opacity: 0.9; }
.socials a:hover img { opacity: 1; }
.socials-band a,
.socials-hero a { width: 48px; height: 48px; }
.socials-band img,
.socials-hero img { width: 26px; height: 26px; opacity: 1; }

.booking { margin-top: var(--space-8); }
.booking .booking-address { margin-top: var(--space-3); color: var(--c-muted); font-weight: 600; user-select: all; overflow-wrap: anywhere; }

/* ── FOOTER ──
   The close inverts the page: bone paper, black ink. The ridge rises again and the wordmark ends it. */
.site-footer {
  position: relative;
  margin-top: clamp(6rem, 14vw, 10rem);
  background: var(--c-ink);
  color: var(--c-ground);
  text-align: center;
}
.site-footer a,
.site-footer .link-button { color: var(--c-ground); }
.site-footer a:hover,
.site-footer .link-button:hover { color: var(--c-ground); text-decoration-thickness: 2px; }
.site-footer :focus-visible { outline-color: var(--c-ground); }
.footer-ridge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% - 1px);
  width: 100%;
  height: clamp(5rem, 14vw, 10rem);
  fill: var(--c-ink);
  pointer-events: none;
  transform: scaleX(-1);
}
.footer-inner {
  display: grid;
  justify-items: center;
  gap: var(--space-6);
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-7) var(--gutter) var(--space-6);
}

.moon { display: inline-flex; align-items: center; gap: var(--space-3); max-width: 30rem; font-weight: 600; text-align: left; }
.moon[hidden] { display: none; }
.moon-disc { width: 2.5rem; height: 2.5rem; flex: none; }
.moon-dark { fill: var(--c-ground); stroke: var(--c-ground); stroke-width: 3; }
.moon-lit { fill: var(--c-accent); }

.footer-connect { display: grid; justify-items: center; gap: var(--space-2); }
.footer-booking { font-size: var(--step-1); font-weight: 600; }
.footer-booking a { overflow-wrap: anywhere; }
.site-footer .socials { margin-top: 0; }
.site-footer .socials img { filter: none; opacity: 1; }
.site-footer .socials a:hover { background: rgba(10, 9, 12, 0.1); }

.footer-nav ul { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 var(--space-5); }
.footer-nav a,
.footer-nav .link-button { display: inline-flex; align-items: center; min-height: 44px; font-size: var(--step--1); }
.footer-copy { font-size: var(--step--1); color: var(--c-on-ink-muted); }

/* The wordmark closes the page edge to edge (the SVG on the home page, set type elsewhere). */
.footer-wordmark {
  display: block;
  width: calc(100% - 2 * var(--gutter));
  height: auto;
  aspect-ratio: 656 / 100;
  margin: var(--space-4) auto 0;
  padding-bottom: var(--gutter);
  box-sizing: content-box;
  color: var(--c-ground);
  user-select: none;
}
div.footer-wordmark { aspect-ratio: auto; font-family: var(--font-display); font-weight: 800; font-stretch: 125%; font-size: 15.5vw; line-height: 0.8; text-align: center; white-space: nowrap; overflow: hidden; }
div.footer-wordmark::before { content: 'LVNARY'; }

/* ── CONSENT BANNER + DIALOG ── */
.consent-banner {
  position: fixed;
  left: var(--space-4);
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: var(--z-banner);
  display: grid;
  gap: var(--space-4);
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--space-5);
  background: var(--c-ridge);
  border: 1px solid var(--c-border-hi);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
  transition: opacity 400ms var(--ease-out), translate 400ms var(--ease-out);
}
/* The banner rises from the edge it sits on, so it reads as arriving rather than appearing. */
@starting-style {
  .consent-banner { opacity: 0; translate: 0 1.5rem; }
}
.consent-text { max-width: var(--measure); }

.consent-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 11rem)) auto;
  justify-content: start;
  align-items: center;
  gap: var(--space-3);
}
.consent-actions .link-button { min-height: 44px; margin-left: var(--space-2); justify-self: start; }
@media (max-width: 30rem) {
  .consent-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .consent-actions > :nth-child(n + 3) { grid-column: 1 / -1; margin-left: 0; }
}

/* Accept and Reject share one style so neither is more prominent. */
.consent-choice {
  width: 100%;
  padding-inline: var(--space-4);
  background: var(--c-accent);
  color: var(--c-ground);
}
.consent-choice:hover { background: var(--c-accent-hi); color: var(--c-ground); }

.consent-dialog {
  width: min(36rem, calc(100% - 2 * var(--space-4)));
  max-height: calc(100dvh - 2 * var(--space-4));
  margin: auto;
  padding: 0;
  color: var(--c-text);
  background: var(--c-ridge);
  border: 1px solid var(--c-border-hi);
  border-radius: var(--radius-md);
}
.consent-dialog::backdrop { background: rgba(10, 9, 12, 0.78); }
/* A modal isn't anchored to its trigger, so it grows from its own center. */
.consent-dialog[open],
.consent-dialog[open]::backdrop { transition: opacity 220ms var(--ease-out), scale 220ms var(--ease-out); }
@starting-style {
  .consent-dialog[open] { opacity: 0; scale: 0.96; }
  .consent-dialog[open]::backdrop { opacity: 0; }
}

.consent-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-5) 0;
}
.consent-title { font-family: var(--font-display); font-weight: 400; font-size: var(--step-1); letter-spacing: 0.04em; }
.consent-close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  font-size: var(--step-2);
  line-height: 1;
  color: var(--c-text);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.consent-close:hover { background: var(--c-surface-2); }

.consent-body { display: grid; gap: var(--space-4); padding: var(--space-4) var(--space-5) var(--space-5); }
.consent-note { padding: var(--space-3) var(--space-4); background: var(--c-surface-2); }

.consent-form { display: grid; gap: var(--space-3); }
.consent-option {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-3) 0;
  border-top: 1px solid var(--c-border);
}
.consent-option input { width: 1.25rem; height: 1.25rem; margin-top: 0.2rem; accent-color: var(--c-violet); }
.consent-option input:disabled + label { cursor: not-allowed; }
.consent-option label { display: grid; gap: var(--space-1); cursor: pointer; }
.consent-option-label { font-weight: 600; }
.consent-option-desc { color: var(--c-muted); font-size: var(--step--1); }
.consent-form .consent-actions { padding-top: var(--space-3); border-top: 1px solid var(--c-border); }

/* ── WIDER SCREENS ── */
@media (min-width: 40rem) {
  /* One column per product (three to four), so the strip always spans the row. */
  .merch-strip { grid-template-columns: repeat(var(--tiles, 3), minmax(0, 1fr)); gap: var(--space-6); }
  .merch-strip > li:first-child:nth-last-child(odd) { grid-column: auto; }
  .members { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .up-next,
  .shows-none,
  .booking { padding: var(--space-8) var(--space-7); }
}

/* ── SMALL SCREENS ── */
@media (max-width: 48rem) {
  .js .nav-toggle {
    display: grid;
    place-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    background: none;
    border: 0;
    cursor: pointer;
  }
  .nav-toggle-bar {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--c-ink);
    transition: transform var(--dur-med) var(--ease-out), opacity var(--dur-fast);
  }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .js .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: var(--space-2) var(--gutter) var(--space-6);
    background: var(--c-ground);
    text-align: center;
    /* Drops from the header it hangs off. Closing is quicker than opening: the visitor has
       already chosen, so get out of the way. */
    opacity: 0;
    translate: 0 -0.5rem;
    transition: opacity var(--dur-fast) var(--ease-out), translate var(--dur-fast) var(--ease-out),
                display var(--dur-fast) allow-discrete;
  }
  .js .nav-links.open { display: flex; opacity: 1; translate: none; transition-duration: 220ms; }
  @starting-style {
    .js .nav-links.open { opacity: 0; translate: 0 -0.5rem; }
  }
  .js .nav-links a { font-size: var(--step-1); min-height: 56px; }
  .js .nav-cta { width: min(100%, 22rem); margin-top: var(--space-3); }
  .js .nav-cta .btn { width: 100%; }
  .site-header:has(.nav-links.open) { background: var(--c-ground); }
  /* With the menu open, the brand shows even over the hero. */
  body .site-header:has(.nav-links.open) .brand { opacity: 1; visibility: visible; } /* `body` matches the hiding rule's weight */

  /* Without JS the links stay visible and wrap. */
  html:not(.js) .site-header { position: static; flex-wrap: wrap; height: auto; padding-block: var(--space-3); background: var(--c-ground); }
  html:not(.js) .nav-links { flex-wrap: wrap; gap: var(--space-4); }

  .show-row {
    grid-template-columns: 3.5rem minmax(0, 1fr);
    gap: var(--space-2) var(--space-4);
    padding: var(--space-4);
  }
  .show-ticket,
  .show-ticket-none,
  .show-tag { grid-column: 2; justify-self: start; }

  .lede { font-size: var(--step-0); }
}

/* Phones: main actions span the column so they're easy to hit with a thumb. */
@media (max-width: 30rem) {
  .hero-actions { flex-direction: column; align-items: stretch; width: 100%; max-width: 22rem; margin-inline: auto; }
  .up-next .btn,
  .booking .btn { width: 100%; }
  .player { height: 352px; }
}

/* ── REDUCED MOTION ──
   Reduced, not removed: things still fade so nothing changes abruptly, but nothing travels, scales,
   spins or blurs. All the motion above uses the separate translate and scale properties, so these
   overrides catch it (important declarations outrank animations). */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    translate: none !important;
    scale: none !important;
  }
  .ridge { animation: none; }
  .hero-wordmark { animation-name: fade-in; }
  .nav-toggle-bar { transition: opacity var(--dur-fast); }
}
