/* ============================================================
   JOYIA — EPK
   Dark obsidian + restrained neon. Mobile-first.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* base */
  --obsidian:   #0A0A0A;
  --obsidian-2: #0e0e10;
  --ink:        #141417;
  --ink-2:      #1b1b20;
  --line:       rgba(246, 239, 229, 0.10);
  --line-2:     rgba(246, 239, 229, 0.18);

  /* text */
  --cream:      #f6efe5;
  --cream-70:   rgba(246, 239, 229, 0.70);
  --cream-50:   rgba(246, 239, 229, 0.50);
  --cream-32:   rgba(246, 239, 229, 0.32);

  /* neon */
  --pink:   #ff5496;
  --cyan:   #44d9ff;
  --orange: #ff7c20;
  --yellow: #ffd54b;

  /* type */
  --display: "Syne", "Archivo", system-ui, sans-serif;
  --body:    "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* fluid scale */
  --fs-mark:   clamp(3.6rem, 17vw, 15rem);
  --fs-h2:     clamp(2.3rem, 8.2vw, 6.6rem);
  --fs-h3:     clamp(1.4rem, 4vw, 2.3rem);
  --fs-lead:   clamp(1rem, 2.3vw, 1.3rem);
  --fs-body:   clamp(0.98rem, 1.7vw, 1.08rem);
  --fs-micro:  clamp(0.66rem, 1.5vw, 0.76rem);

  /* rhythm */
  --pad:       clamp(1.15rem, 5vw, 4.5rem);
  --sec-y:     clamp(5rem, 13vw, 11rem);
  --maxw:      1320px;
  --r:         14px;
  --r-lg:      22px;

  /* motion */
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
  --ease-io:   cubic-bezier(0.65, 0, 0.35, 1);
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--obsidian);
  color: var(--cream);
  font-family: var(--body);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.6;
  letter-spacing: 0.005em;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body.is-locked { overflow: hidden; }

img, svg, iframe, video { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.03em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

::selection { background: var(--pink); color: #0a0a0a; }

:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- 3. UTILITIES ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

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

.skip-link {
  position: fixed;
  top: 0; left: 50%;
  transform: translate(-50%, -110%);
  z-index: 200;
  padding: 0.7rem 1.3rem;
  background: var(--cream);
  color: #0a0a0a;
  font-size: 0.8rem;
  font-weight: 500;
  border-radius: 0 0 10px 10px;
  transition: transform 0.25s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* film grain */
.grain {
  position: fixed;
  inset: -60%;
  z-index: 3;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>");
  animation: grain 7s steps(6) infinite;
  will-change: transform;
}
@keyframes grain {
  0%, 100% { transform: translate(0, 0); }
  20%  { transform: translate(-3%, 2%); }
  40%  { transform: translate(2%, -3%); }
  60%  { transform: translate(-2%, -2%); }
  80%  { transform: translate(3%, 1%); }
}

/* scroll progress */
.scroll-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 120;
  background: rgba(246, 239, 229, 0.06);
}
.scroll-progress span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--pink), var(--orange) 40%, var(--yellow) 65%, var(--cyan));
  box-shadow: 0 0 14px rgba(255, 84, 150, 0.55);
}

/* ---------- 4. BUTTONS ---------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1.02rem 2.1rem;
  font-family: var(--body);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: 999px;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.4s var(--ease), border-color 0.4s var(--ease),
              transform 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
.btn > span { position: relative; z-index: 2; }

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  transform: translateY(101%);
  transition: transform 0.55s var(--ease);
}

.btn--solid {
  background: var(--cream);
  color: #0a0a0a;
  box-shadow: 0 0 0 rgba(255, 84, 150, 0);
}
.btn--solid::before {
  background: linear-gradient(100deg, var(--pink), var(--orange));
}
.btn--solid:hover, .btn--solid:focus-visible {
  color: #0a0a0a;
  box-shadow: 0 14px 44px -12px rgba(255, 84, 150, 0.7);
}
.btn--solid:hover::before, .btn--solid:focus-visible::before { transform: translateY(0); }

.btn--ghost {
  color: var(--cream);
  border: 1px solid var(--line-2);
  background: rgba(246, 239, 229, 0.02);
  backdrop-filter: blur(6px);
}
.btn--ghost::before { background: var(--cream); }
.btn--ghost:hover, .btn--ghost:focus-visible {
  color: #0a0a0a;
  border-color: var(--cream);
}
.btn--ghost:hover::before, .btn--ghost:focus-visible::before { transform: translateY(0); }

.btn--sm { padding: 0.68rem 1.35rem; font-size: 0.68rem; letter-spacing: 0.13em; }
.btn--lg { padding: 1.2rem 2.6rem; font-size: 0.82rem; }

.btn:active { transform: scale(0.97); }

/* arrow link */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--cream-70);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line-2);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease), gap 0.35s var(--ease);
}
.link-arrow i { font-style: normal; transition: transform 0.35s var(--ease); }
.link-arrow:hover { color: var(--cream); border-color: var(--pink); gap: 0.85rem; }
.link-arrow:hover i { transform: translate(2px, -2px); }

/* ---------- 5. NAV ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: calc(1.05rem + env(safe-area-inset-top, 0px)) var(--pad);
  transition: padding 0.5s var(--ease), background 0.5s var(--ease),
              border-color 0.5s var(--ease), backdrop-filter 0.5s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  padding-block: 0.7rem;
  background: rgba(10, 10, 10, 0.72);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom-color: var(--line);
}

.nav__brand {
  display: flex;
  align-items: center;
  margin-right: auto;
  transition: opacity 0.3s var(--ease);
}
.nav__brand img {
  width: clamp(76px, 9vw, 104px);
  height: auto;
  filter: brightness(1.08);
}
.nav__brand:hover { opacity: 0.72; }

.nav__links { display: none; }

@media (min-width: 900px) {
  .nav__links {
    display: flex;
    gap: 0.35rem;
    margin-right: 1.4rem;
  }
  .nav__links a {
    position: relative;
    padding: 0.5rem 0.95rem;
    font-size: 0.74rem;
    font-weight: 400;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--cream-50);
    border-radius: 999px;
    transition: color 0.3s var(--ease);
  }
  .nav__links a::after {
    content: "";
    position: absolute;
    left: 50%; bottom: 0.18rem;
    width: 3px; height: 3px;
    border-radius: 50%;
    background: var(--pink);
    transform: translate(-50%, 6px) scale(0);
    transition: transform 0.35s var(--ease);
  }
  .nav__links a:hover { color: var(--cream); }
  .nav__links a.is-active { color: var(--cream); }
  .nav__links a.is-active::after { transform: translate(-50%, 0) scale(1); }
}

.nav__cta { display: none; }
@media (min-width: 900px) { .nav__cta { display: inline-flex; } }

/* burger */
.nav__burger {
  position: relative;
  width: 44px; height: 44px;
  display: grid;
  place-content: center;
  gap: 6px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
}
.nav__burger span {
  display: block;
  width: 17px; height: 1.5px;
  background: var(--cream);
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}
.nav__burger[aria-expanded="true"] span:first-child { transform: translateY(3.75px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:last-child  { transform: translateY(-3.75px) rotate(-45deg); }
@media (min-width: 900px) { .nav__burger { display: none; } }

/* mobile menu */
.menu {
  position: fixed;
  inset: 0;
  z-index: 105;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  overflow-y: auto;
  padding: calc(6rem + env(safe-area-inset-top, 0px)) var(--pad) calc(2.5rem + env(safe-area-inset-bottom, 0px));
  background: rgba(8, 8, 9, 0.96);
  backdrop-filter: blur(26px);
}
.menu[hidden] { display: none; }

.menu__inner { display: grid; gap: 0.15rem; }
.menu__inner a {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.35rem 0;
  font-family: var(--display);
  font-size: clamp(1.5rem, 7.5vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--cream);
  opacity: 0;
  transform: translateY(24px);
  transition: color 0.3s var(--ease);
}
.menu__inner a i {
  font-family: var(--body);
  font-style: normal;
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.2em;
  color: var(--pink);
}
.menu__inner a:active { color: var(--pink); }

.menu__foot {
  margin-top: auto;
  padding-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  justify-content: space-between;
  font-size: 0.78rem;
  color: var(--cream-50);
  border-top: 1px solid var(--line);
}

/* ---------- 6. HERO ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 7.5rem 0 clamp(2.5rem, 7vw, 4.5rem);
  overflow: hidden;
  isolation: isolate;
}

.hero__bg { position: absolute; inset: 0; z-index: -1; }

.hero__aurora {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  will-change: transform;
}
.hero__aurora--pink {
  width: 78vw; height: 78vw;
  max-width: 900px; max-height: 900px;
  top: -22%; left: -18%;
  background: radial-gradient(circle at 50% 50%, rgba(255, 84, 150, 0.34), transparent 66%);
  animation: drift1 22s var(--ease-io) infinite alternate;
}
.hero__aurora--cyan {
  width: 68vw; height: 68vw;
  max-width: 820px; max-height: 820px;
  top: 18%; right: -22%;
  background: radial-gradient(circle at 50% 50%, rgba(68, 217, 255, 0.24), transparent 66%);
  animation: drift2 26s var(--ease-io) infinite alternate;
}
.hero__aurora--orange {
  width: 58vw; height: 58vw;
  max-width: 700px; max-height: 700px;
  bottom: -20%; left: 26%;
  background: radial-gradient(circle at 50% 50%, rgba(255, 124, 32, 0.22), transparent 68%);
  animation: drift3 19s var(--ease-io) infinite alternate;
}
@keyframes drift1 { to { transform: translate3d(9%, 7%, 0) scale(1.14); } }
@keyframes drift2 { to { transform: translate3d(-11%, -6%, 0) scale(1.1); } }
@keyframes drift3 { to { transform: translate3d(6%, -9%, 0) scale(1.18); } }

.hero__grid {
  position: absolute;
  inset: 0;
  opacity: 0.4;
  background-image:
    linear-gradient(to right, rgba(246, 239, 229, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(246, 239, 229, 0.045) 1px, transparent 1px);
  background-size: clamp(48px, 9vw, 96px) clamp(48px, 9vw, 96px);
  mask-image: radial-gradient(ellipse 85% 70% at 50% 42%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 85% 70% at 50% 42%, #000 20%, transparent 78%);
}

.hero__plate { position: absolute; inset: 0; }
.hero__plate video {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.28;
  filter: grayscale(0.55) contrast(1.15);
}

.hero__vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 120% 80% at 50% 0%, transparent 30%, rgba(10, 10, 10, 0.55) 100%),
    linear-gradient(to bottom, rgba(10, 10, 10, 0.7) 0%, transparent 22%, transparent 55%, var(--obsidian) 100%);
}

.hero__content {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: clamp(1.4rem, 4vw, 2.4rem);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cream-70);
}
.hero__eyebrow b { color: var(--pink); font-weight: 400; }
.hero__eyebrow .dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--pink);
  box-shadow: 0 0 0 0 rgba(255, 84, 150, 0.6);
  animation: pulse 2.4s var(--ease-io) infinite;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 11px rgba(255, 84, 150, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 84, 150, 0); }
}

/* the JOYIA mark.
   The invert lives on the WRAPPER, never on the <img>: GSAP animates the
   image's own filter during the intro, and an inline filter would replace
   the invert chain and render the black SVG black-on-black. */
.hero__mark {
  margin: 0 0 clamp(1.2rem, 3.5vw, 2rem);
  line-height: 0;
  filter: brightness(1.06)
          drop-shadow(0 0 40px rgba(255, 84, 150, 0.22))
          drop-shadow(0 0 90px rgba(68, 217, 255, 0.12));
}
.hero__mark img {
  width: min(100%, 1040px);
  height: auto;
}
/* Desktop: cap the mark so it never runs under the hero art wall.
   Widths are measured against the rotated frames' bboxes — see the
   HERO PORTRAITS block. Mobile keeps the full-bleed mark. */
@media (min-width: 1100px) { .hero__mark img { width: min(100%, 760px); } }
@media (min-width: 1500px) { .hero__mark img { width: min(100%, 830px); } }

.hero__kinetic {
  font-family: var(--display);
  font-size: clamp(1.15rem, 3.5vw, 2.35rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin-bottom: clamp(0.9rem, 2.4vw, 1.3rem);
  max-width: 24ch;
  /* Four short sentences at 24ch broke 3+1 ("Plays it." orphaned on its own
     line at 1440). `balance` evens the line lengths into 2+2, which also
     matches the phrase rhythm. Unsupported browsers keep the greedy wrap. */
  text-wrap: balance;
}

.hero__sub {
  max-width: 46ch;
  font-size: var(--fs-lead);
  color: var(--cream-70);
  margin-bottom: clamp(1.9rem, 4.5vw, 2.8rem);
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-bottom: clamp(2.2rem, 5vw, 3rem);
}

/* Stat row — the hero's credibility line, so the NUMBER is the object and
   the label is its caption. Previously both sat on one baseline at
   1.05rem/0.8rem, which read as a sentence and buried "15.7M+". Each item is
   now a stacked pair (number over label) in an even 3-up track, so the three
   figures scan as a set at every width.

   No `background-clip: text` gradient on these on purpose: on a wide flex
   item an angled gradient's line ends before the text box does, and trailing
   glyphs ("M+", "K") render at the transparent tail. Solid cream plus a soft
   neon glow gets the same lift with no clipping risk. */
.hero__meta {
  display: grid;
  /* MEASURED (2026-09-16): a 3-up track cannot hold these numbers on a phone.
     "15.7M+" inks 123.2px at its 1.45rem clamp floor, while an even third of
     the content box is 86px at 320px and 109px at 390px — and because the
     cells are `overflow: visible` the glyphs silently ran over the next stat
     instead of being cut, which is worse than a clip. So: one stat per row
     below 560px (number and label on a shared baseline), 3-up only once a
     cell can actually hold a number. Verified fitting 320→1440. */
  grid-template-columns: 1fr;
  justify-content: start;
  gap: 0.75rem clamp(0.75rem, 3vw, 3.2rem);
  padding-top: clamp(1.3rem, 3vw, 1.8rem);
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--cream-50);
  text-transform: uppercase;
  list-style: none;
  margin: 0;
  padding-left: 0;
}
.hero__meta li {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  font-size: clamp(0.6rem, 1.5vw, 0.68rem);
  letter-spacing: 0.18em;
  line-height: 1.25;
  color: var(--cream-50);
}

/* 560px is where an even third of the content box first exceeds the widest
   number's inked width with margin to spare (measured 156.8px vs 123.2px). */
@media (min-width: 560px) {
  .hero__meta { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hero__meta li {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.28rem;
  }
}
.hero__meta b {
  font-family: var(--display);
  font-size: clamp(1.45rem, 4.4vw, 2.05rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--cream);
  margin-right: 0;
  text-shadow: 0 0 26px rgba(255, 84, 150, 0.28);
}

.hero__scroll {
  position: absolute;
  right: var(--pad);
  bottom: clamp(2.5rem, 7vw, 4.5rem);
  display: none;
  align-items: center;
  gap: 0.8rem;
  font-size: 0.62rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--cream-32);
  writing-mode: vertical-rl;
}
.hero__scroll i {
  display: block;
  width: 1px; height: 54px;
  background: linear-gradient(to bottom, var(--pink), transparent);
}
@media (min-width: 1100px) { .hero__scroll { display: flex; } }

/* ---------- 7. MARQUEE ---------- */
.marquee {
  position: relative;
  overflow: hidden;
  user-select: none;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee__track {
  display: flex;
  align-items: center;
  gap: clamp(1.2rem, 3vw, 2.6rem);
  width: max-content;
  will-change: transform;
}
.marquee__track span {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.marquee__track em {
  font-style: normal;
  color: var(--pink);
  opacity: 0.85;
}

.marquee--lg {
  padding-block: clamp(1.4rem, 3.6vw, 2.4rem);
  border-block: 1px solid var(--line);
  background: linear-gradient(to bottom, rgba(255, 84, 150, 0.035), transparent);
}
.marquee--lg .marquee__track span {
  font-size: clamp(1.75rem, 6vw, 4.1rem);
  color: transparent;
  -webkit-text-stroke: 1px rgba(246, 239, 229, 0.45);
  transition: color 0.4s var(--ease), -webkit-text-stroke-color 0.4s var(--ease);
}
.marquee--lg .marquee__track span:hover {
  color: var(--cream);
  -webkit-text-stroke-color: transparent;
}
.marquee--lg .marquee__track em { font-size: clamp(0.85rem, 2vw, 1.4rem); }

.marquee--sm .marquee__track span {
  font-family: var(--body);
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cream-50);
}
.marquee--sm .marquee__track em { font-size: 0.6rem; }
.marquee--sm { padding-block: 1.1rem; border-block: 1px solid var(--line); }

/* ---------- 8. PROOF / STATS ---------- */
.proof { padding-bottom: var(--sec-y); }

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  margin-top: clamp(3rem, 8vw, 5.5rem);
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
@media (min-width: 680px)  { .stats { grid-template-columns: repeat(3, 1fr); } }
/* 6-up only once a cell is genuinely wide enough for "15.7M+" at display size.
   At 1040px the six cells left ~124px of usable width against ~155px of text,
   which cropped the M+/K suffixes. */
@media (min-width: 1200px) { .stats { grid-template-columns: repeat(6, 1fr); } }

.stat {
  position: relative;
  padding: clamp(1.4rem, 3.4vw, 2.3rem) clamp(0.9rem, 1.8vw, 1.25rem);
  background: var(--obsidian);
  transition: background 0.45s var(--ease);
  overflow: hidden;
}
.stat::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--pink), var(--cyan));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.55s var(--ease);
}
.stat:hover { background: var(--ink); }
.stat:hover::after { transform: scaleX(1); }

/* Gradient runs strictly top-to-bottom (180deg) and is sized to the text box.
   An angled gradient here has a horizontal component: on a wide grid cell the
   gradient line ends before the last glyphs, so suffixes like "M+" fell into
   the transparent tail and disappeared against the black. */
.stat__n {
  display: block;
  width: fit-content;
  max-width: 100%;
  font-family: var(--display);
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.04em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--cream);
  background-image: linear-gradient(180deg, var(--cream) 0%, var(--cream) 45%, rgba(246, 239, 229, 0.72) 100%);
  -webkit-background-clip: text;
  background-clip: text;
}

/* Only go transparent where the clip is actually supported, so an
   unsupporting browser keeps solid cream text instead of invisible text. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .stat__n { color: transparent; }
}
.stat__l {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream-50);
}

.support {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  text-align: center;
}
.support__label {
  font-size: var(--fs-micro);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cream-32);
  margin-bottom: 1.1rem;
}
.support__names {
  font-family: var(--display);
  font-size: clamp(1.05rem, 2.9vw, 1.9rem);
  font-weight: 700;
  line-height: 1.45;
  letter-spacing: -0.02em;
  max-width: 24ch;
  margin-inline: auto;
}
.support__names i {
  font-style: normal;
  color: var(--pink);
  opacity: 0.6;
  padding-inline: 0.15em;
}

/* ---------- 9. SECTION SHELL ---------- */
.sec {
  position: relative;
  padding-block: var(--sec-y);
}
.sec + .sec { border-top: 1px solid var(--line); }

.sec__head { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }
.sec__head--row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
}

.sec__num {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: clamp(0.9rem, 2.4vw, 1.4rem);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--pink);
}
.sec__num::before {
  content: "";
  width: clamp(18px, 4vw, 40px);
  height: 1px;
  background: var(--pink);
  opacity: 0.7;
}

.sec__title {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  max-width: 100%;
  overflow-wrap: break-word;
}

/* Split words are inline-block, so a long heading must be allowed to wrap
   between them at narrow widths or it would force horizontal scroll. */
.sec__title .split-word,
.booking__h .split-word,
.hero__kinetic .split-word { max-width: 100%; }

.sec__lead {
  max-width: 54ch;
  margin-top: clamp(1.1rem, 2.6vw, 1.7rem);
  font-size: var(--fs-lead);
  color: var(--cream-70);
}

/* ---------- 10. LISTEN ---------- */
.listen {
  display: grid;
  gap: clamp(1.6rem, 4vw, 2.6rem);
}
@media (min-width: 980px) {
  .listen { grid-template-columns: 1.15fr 1fr; align-items: start; }
}

.player__frame {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink);
  box-shadow: 0 40px 90px -50px rgba(0, 0, 0, 0.9);
}
.player__frame iframe { display: block; border: 0; }

.listen__side { display: grid; gap: clamp(1.6rem, 4vw, 2.4rem); }

.releases { display: grid; gap: 1px; background: var(--line); border-radius: var(--r); overflow: hidden; }
.release {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "tag tag" "h meta";
  gap: 0.4rem 1rem;
  align-items: center;
  padding: clamp(1.05rem, 2.6vw, 1.5rem) clamp(1.1rem, 2.6vw, 1.6rem);
  background: var(--obsidian-2);
  transition: background 0.4s var(--ease), padding-left 0.4s var(--ease);
}
.release:hover { background: var(--ink); padding-left: calc(clamp(1.1rem, 2.6vw, 1.6rem) + 6px); }

.release__tag {
  grid-area: tag;
  justify-self: start;
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.3rem 0.6rem;
  border-radius: 4px;
}
.tag--pink   { background: rgba(255, 84, 150, 0.14); color: var(--pink);   border: 1px solid rgba(255, 84, 150, 0.3); }
.tag--cyan   { background: rgba(68, 217, 255, 0.12); color: var(--cyan);   border: 1px solid rgba(68, 217, 255, 0.28); }
.tag--orange { background: rgba(255, 124, 32, 0.12); color: var(--orange); border: 1px solid rgba(255, 124, 32, 0.28); }

.release h3 {
  grid-area: h;
  font-size: var(--fs-h3);
  text-transform: uppercase;
}
.release p {
  grid-area: meta;
  justify-self: end;
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cream-50);
}

.dsps { display: grid; gap: 0.6rem; }
@media (min-width: 560px) { .dsps { grid-template-columns: 1fr 1fr; } }

.dsp {
  position: relative;
  display: grid;
  gap: 0.15rem;
  padding: 1.05rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: rgba(246, 239, 229, 0.015);
  overflow: hidden;
  transition: border-color 0.4s var(--ease), transform 0.5s var(--ease), background 0.4s var(--ease);
}
.dsp::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--pink);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.45s var(--ease);
}
.dsp__n {
  font-family: var(--display);
  font-size: 1.02rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.dsp__m {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cream-50);
}
.dsp i {
  position: absolute;
  top: 1rem; right: 1.1rem;
  font-style: normal;
  font-size: 0.9rem;
  color: var(--cream-32);
  transition: transform 0.4s var(--ease), color 0.4s var(--ease);
}
.dsp:hover {
  border-color: var(--line-2);
  background: rgba(246, 239, 229, 0.04);
}
.dsp:hover::before { transform: scaleY(1); }
.dsp:hover i { transform: translate(3px, -3px); color: var(--pink); }

/* ---------- 11. WATCH ---------- */
.videos {
  display: grid;
  gap: clamp(0.9rem, 2.4vw, 1.5rem);
}
@media (min-width: 760px) { .videos { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1100px) {
  .videos { grid-template-columns: repeat(3, 1fr); }
  .videos > *:first-child { grid-column: span 2; grid-row: span 2; }
}

.vid {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: clamp(210px, 42vw, 290px);
  padding: clamp(1.1rem, 2.6vw, 1.7rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink);
  cursor: pointer;
  isolation: isolate;
  transition: border-color 0.45s var(--ease), transform 0.6s var(--ease);
}
.videos > *:first-child.vid { min-height: clamp(240px, 52vw, 100%); }

.vid__art {
  position: absolute;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(ellipse at 30% 20%, rgba(255, 84, 150, 0.3), transparent 60%),
    radial-gradient(ellipse at 75% 80%, rgba(68, 217, 255, 0.22), transparent 62%),
    linear-gradient(150deg, #17171b, #0c0c0e);
  transition: transform 0.9s var(--ease), filter 0.6s var(--ease);
}
.vid--b .vid__art {
  background:
    radial-gradient(ellipse at 70% 25%, rgba(255, 124, 32, 0.3), transparent 60%),
    radial-gradient(ellipse at 20% 85%, rgba(255, 213, 75, 0.16), transparent 62%),
    linear-gradient(150deg, #19161a, #0c0c0e);
}
.vid--c .vid__art {
  background:
    radial-gradient(ellipse at 45% 30%, rgba(68, 217, 255, 0.28), transparent 60%),
    radial-gradient(ellipse at 80% 90%, rgba(255, 84, 150, 0.2), transparent 62%),
    linear-gradient(150deg, #14181c, #0c0c0e);
}
.vid::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.88) 8%, rgba(10, 10, 10, 0.2) 55%, transparent);
}
.vid:hover { border-color: var(--line-2); transform: translateY(-4px); }
.vid:hover .vid__art { transform: scale(1.07); filter: saturate(1.25); }

.vid__play {
  position: absolute;
  top: clamp(1.1rem, 2.6vw, 1.7rem);
  right: clamp(1.1rem, 2.6vw, 1.7rem);
  width: 46px; height: 46px;
  display: grid;
  place-content: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.4);
  backdrop-filter: blur(8px);
  font-size: 0.72rem;
  color: var(--cream);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), transform 0.4s var(--ease);
}
.vid:hover .vid__play {
  background: var(--cream);
  border-color: var(--cream);
  color: #0a0a0a;
  transform: scale(1.08);
}

.vid__tag {
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 0.5rem;
}
.vid__t {
  font-size: clamp(1.15rem, 3vw, 1.75rem);
  text-transform: uppercase;
  margin-bottom: 0.35rem;
}
.vid__m {
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  color: var(--cream-50);
}

.vid.is-playing { cursor: default; padding: 0; }
.vid.is-playing > *:not(iframe) { display: none; }
.vid.is-playing iframe { width: 100%; height: 100%; min-height: inherit; border: 0; aspect-ratio: 16 / 9; }

/* ---------- 12. INSTAGRAM ---------- */
.ig { margin-bottom: clamp(3.5rem, 9vw, 6.5rem); }

.ig__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.4rem, 1.4vw, 0.85rem);
}
@media (min-width: 640px) { .ig__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { .ig__grid { grid-template-columns: repeat(6, 1fr); } }

.ig__skeleton {
  aspect-ratio: 1;
  border-radius: var(--r);
  background: linear-gradient(100deg, var(--ink) 25%, var(--ink-2) 50%, var(--ink) 75%);
  background-size: 260% 100%;
  animation: shimmer 1.5s linear infinite;
}
@keyframes shimmer { to { background-position: -160% 0; } }

.ig__item {
  position: relative;
  aspect-ratio: 1;
  display: block;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ink);
  border: 1px solid var(--line);
  transition: transform 0.55s var(--ease), border-color 0.4s var(--ease), z-index 0s;
}
.ig__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.25) contrast(1.04);
  transition: transform 0.75s var(--ease), filter 0.5s var(--ease);
}
.ig__item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.92), rgba(10, 10, 10, 0.1) 55%, transparent);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.ig__cap {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: 0.85rem 0.9rem;
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--cream);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.4s var(--ease), transform 0.5s var(--ease);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ig__badge {
  position: absolute;
  top: 0.55rem; right: 0.55rem;
  z-index: 2;
  padding: 0.22rem 0.45rem;
  border-radius: 5px;
  background: rgba(10, 10, 10, 0.6);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line-2);
  font-size: 0.56rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream-70);
}
.ig__item:hover, .ig__item:focus-visible {
  transform: scale(1.06);
  border-color: rgba(255, 84, 150, 0.45);
  z-index: 3;
}
.ig__item:hover img, .ig__item:focus-visible img {
  transform: scale(1.08);
  filter: grayscale(0) contrast(1.08);
}
.ig__item:hover::after, .ig__item:focus-visible::after { opacity: 1; }
.ig__item:hover .ig__cap, .ig__item:focus-visible .ig__cap { opacity: 1; transform: translateY(0); }

.ig__fallback {
  padding: clamp(2rem, 6vw, 3.5rem);
  text-align: center;
  border: 1px dashed var(--line-2);
  border-radius: var(--r-lg);
  color: var(--cream-50);
  font-size: 0.9rem;
}
.ig__fallback a { color: var(--cyan); border-bottom: 1px solid rgba(68, 217, 255, 0.35); }
.ig__fallback a:hover { color: var(--cream); }

/* ---------- 13. RADIO ---------- */
.radio {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background:
    radial-gradient(ellipse 90% 120% at 12% 0%, rgba(255, 84, 150, 0.14), transparent 62%),
    radial-gradient(ellipse 80% 110% at 90% 100%, rgba(68, 217, 255, 0.1), transparent 60%),
    var(--obsidian-2);
}

.radio__type {
  padding-block: clamp(1rem, 2.6vw, 1.5rem);
  border-bottom: 1px solid var(--line);
  opacity: 0.16;
}
.radio__type .marquee__track span {
  font-size: clamp(2.2rem, 8vw, 5rem);
  text-transform: uppercase;
  letter-spacing: -0.04em;
}
.radio__type .marquee__track em { color: var(--cream); font-size: 1.5rem; }

.radio__body { padding: clamp(1.6rem, 5vw, 3.4rem); }
.radio__kicker {
  font-size: var(--fs-micro);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--yellow);
  margin-bottom: 0.9rem;
}
.radio__h {
  font-size: clamp(1.8rem, 6vw, 3.6rem);
  text-transform: uppercase;
  margin-bottom: 1rem;
}
.radio__p {
  max-width: 56ch;
  color: var(--cream-70);
  font-size: var(--fs-lead);
  margin-bottom: clamp(1.6rem, 4vw, 2.2rem);
}
.radio__links { display: flex; flex-wrap: wrap; gap: 0.7rem; }

/* ---------- 14. ABOUT ---------- */
.bio { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 940px) {
  .bio { grid-template-columns: 0.62fr 1fr; }
}

.bio__rail ul {
  display: grid;
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
.bio__rail li {
  display: grid;
  gap: 0.3rem;
  padding: clamp(0.95rem, 2.2vw, 1.25rem) 0;
  background: var(--obsidian);
}
.bio__rail b {
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--pink);
}
.bio__rail span { font-size: 0.94rem; color: var(--cream-70); }

.bio__short {
  font-size: clamp(1.05rem, 2.5vw, 1.4rem);
  line-height: 1.62;
  color: var(--cream);
  font-weight: 300;
}
.bio__short::first-line { letter-spacing: 0.01em; }

.bio__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  margin-top: clamp(1.5rem, 3.5vw, 2.2rem);
  padding: 0.8rem 1.4rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream-70);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease), background 0.35s var(--ease);
}
.bio__toggle i {
  font-style: normal;
  font-size: 0.8rem;
  color: var(--pink);
  transition: transform 0.45s var(--ease);
}
.bio__toggle:hover {
  color: var(--cream);
  border-color: var(--cream);
  background: rgba(246, 239, 229, 0.04);
}
.bio__toggle[aria-expanded="true"] i { transform: rotate(135deg); }

.bio__full {
  display: grid;
  gap: 1.15rem;
  margin-top: clamp(1.5rem, 3.5vw, 2.2rem);
  padding-top: clamp(1.5rem, 3.5vw, 2.2rem);
  border-top: 1px solid var(--line);
  color: var(--cream-70);
  overflow: hidden;
}
.bio__full[hidden] { display: none; }
.bio__full p:first-child {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2.8vw, 1.6rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--cream);
}

/* ---------- 15. SHOWS ---------- */
.shows {
  display: grid;
  border-top: 1px solid var(--line);
}

.show {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "date venue"
    "date city"
    "note note";
  gap: 0.2rem 1.1rem;
  align-items: center;
  padding: clamp(1.15rem, 3vw, 1.9rem) 0;
  border-bottom: 1px solid var(--line);
  transition: background 0.45s var(--ease);
}
.show::before {
  content: "";
  position: absolute;
  left: calc(var(--pad) * -1);
  right: calc(var(--pad) * -1);
  top: 0; bottom: 0;
  z-index: -1;
  background: linear-gradient(90deg, rgba(255, 84, 150, 0.09), transparent 60%);
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.show:hover::before { opacity: 1; }

.show__date {
  grid-area: date;
  display: grid;
  justify-items: center;
  min-width: clamp(58px, 9vw, 86px);
  padding-right: clamp(0.8rem, 2vw, 1.5rem);
  border-right: 1px solid var(--line);
}
.show__date b {
  font-family: var(--display);
  font-size: clamp(1.7rem, 5vw, 2.9rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
}
.show__date i {
  font-style: normal;
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream-50);
  margin-top: 0.3rem;
}

.show__venue {
  grid-area: venue;
  font-family: var(--display);
  font-size: clamp(1.15rem, 3.6vw, 2.15rem);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  transition: color 0.4s var(--ease);
}
.show:hover .show__venue { color: var(--pink); }

.show__city {
  grid-area: city;
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream-50);
}

.show__note {
  grid-area: note;
  margin-top: 0.5rem;
  font-size: 0.78rem;
  color: var(--cream-70);
}

.show__go { display: none; }

@media (min-width: 860px) {
  .show {
    grid-template-columns: auto 1.5fr 0.9fr 1.2fr auto;
    grid-template-areas: "date venue city note go";
    gap: 1.6rem;
  }
  .show__note { margin-top: 0; text-align: right; }
  .show__go {
    display: block;
    font-size: 1.1rem;
    color: var(--cream-32);
    transition: transform 0.45s var(--ease), color 0.45s var(--ease);
  }
  .show:hover .show__go { transform: translate(4px, -4px); color: var(--pink); }
}

.shows__past-label {
  margin: clamp(2.8rem, 7vw, 4.5rem) 0 1.2rem;
  font-size: var(--fs-micro);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cream-32);
}

/* ---------- 16. BOOKING ---------- */
.sec--booking {
  overflow: hidden;
  text-align: center;
  padding-block: clamp(5.5rem, 15vw, 12rem);
}
.booking__glow {
  position: absolute;
  left: 50%; top: 40%;
  width: min(140vw, 1100px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255, 84, 150, 0.16), rgba(255, 124, 32, 0.06) 40%, transparent 68%);
  filter: blur(40px);
  pointer-events: none;
}
.sec--booking .sec__num { justify-content: center; }

.booking__h {
  font-size: clamp(3rem, 15vw, 11rem);
  line-height: 0.88;
  letter-spacing: -0.05em;
  text-transform: uppercase;
  margin-bottom: clamp(2rem, 5vw, 3rem);
  max-width: 100%;
  overflow-wrap: break-word;
}

.booking__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  margin-bottom: clamp(3.5rem, 9vw, 6rem);
}

.booking__grid {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  text-align: left;
}
@media (min-width: 780px) {
  .booking__grid { grid-template-columns: 1fr 1fr; }
  .bcard--wide { grid-column: span 2; }
}

.bcard {
  padding: clamp(1.5rem, 3.6vw, 2.4rem);
  background: var(--obsidian);
  transition: background 0.45s var(--ease);
}
.bcard:hover { background: var(--obsidian-2); }
.bcard h3 {
  font-size: 0.68rem;
  font-family: var(--body);
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--pink);
  margin-bottom: 1.1rem;
}
.bcard > p { color: var(--cream-70); margin-bottom: 1.1rem; }

.socials {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem 1.2rem;
}
.socials a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.92rem;
  color: var(--cream-70);
  transition: color 0.3s var(--ease);
}
.socials a i { font-style: normal; font-size: 0.72rem; color: var(--cream-32); transition: transform 0.35s var(--ease), color 0.35s var(--ease); }
.socials a:hover { color: var(--cream); }
.socials a:hover i { transform: translate(2px, -2px); color: var(--cyan); }

.sponsors {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.sponsors span {
  padding: 0.55rem 1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cream-50);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease);
}
.sponsors span:hover { color: var(--cream); border-color: var(--line-2); }

/* ---------- 17. FOOTER ---------- */
.foot {
  padding-block: clamp(2.5rem, 6vw, 4rem);
  border-top: 1px solid var(--line);
}
.foot__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem 2rem;
}
.foot__logo {
  width: clamp(96px, 12vw, 140px);
  height: auto;
  filter: brightness(1.05);
  opacity: 0.85;
}
.foot__tag {
  font-family: var(--display);
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--cream-70);
}
.foot__legal { font-size: 0.76rem; color: var(--cream-32); }
.foot__legal a { color: var(--cream-50); }
.foot__legal a:hover { color: var(--cream); }

/* ---------- 18. MOTION PREP / A11Y ---------- */
/* GSAP sets final state; these are pre-paint defaults so nothing flashes. */
.js [data-reveal],
.js [data-split] { will-change: transform, opacity; }

.js [data-reveal] { opacity: 0; transform: translateY(26px); }

/* word masks built by splitWords() in script.js */
.split-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.split-word > span { display: inline-block; will-change: transform; }

/* once GSAP has run, hand control back */
.motion-ready [data-reveal] { opacity: initial; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  .grain { display: none; }
}

/* ============================================================
   19. SOCIAL ICONS
   One sprite, three placements (nav / mobile menu / footer).
   Geometry is stroke-drawn and inherits currentColor, so a single
   colour change drives the whole hover state.
   ============================================================ */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.sicons {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  list-style: none;
}

.sicon {
  position: relative;
  display: grid;
  place-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  color: var(--cream-50);
  transition: color 0.35s var(--ease), background 0.35s var(--ease),
              transform 0.45s var(--ease);
}
.sicon svg {
  width: 19px; height: 19px;
  overflow: visible;
  transition: transform 0.45s var(--ease);
}
.sicon::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid transparent;
  transition: border-color 0.35s var(--ease), box-shadow 0.45s var(--ease);
}

.sicon:hover, .sicon:focus-visible {
  color: var(--cream);
  transform: translateY(-2px);
}
.sicon:hover svg, .sicon:focus-visible svg { transform: scale(1.1); }
.sicon:hover::before, .sicon:focus-visible::before {
  border-color: var(--line-2);
  box-shadow: 0 0 18px -6px rgba(255, 84, 150, 0.55);
}
.sicon:active { transform: translateY(0) scale(0.94); }

/* Per-platform accent on hover — keeps the row monochrome at rest
   so it never competes with the neon headings. */
.sicon[data-tip="Spotify"]:hover,
.sicon[aria-label*="Spotify"]:hover      { color: #5ce08f; }
.sicon[aria-label*="Apple Music"]:hover  { color: var(--pink); }
.sicon[aria-label*="SoundCloud"]:hover   { color: var(--orange); }
.sicon[aria-label*="Beatport"]:hover     { color: var(--yellow); }
.sicon[aria-label*="YouTube"]:hover      { color: #ff5d5d; }
.sicon[aria-label*="Instagram"]:hover    { color: var(--pink); }
.sicon[aria-label*="Komi"]:hover         { color: var(--cyan); }

/* tooltip — desktop only, no layout cost */
.sicon[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  padding: 0.3rem 0.5rem;
  border-radius: 6px;
  background: rgba(10, 10, 10, 0.92);
  border: 1px solid var(--line);
  font-family: var(--body);
  font-size: 0.58rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream-70);
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -4px);
  pointer-events: none;
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .sicon[data-tip]:hover::after { opacity: 1; transform: translate(-50%, 0); }
}

/* nav row: hidden on small screens (the burger menu carries the full set) */
.sicons--nav { display: none; }
@media (min-width: 1100px) {
  .sicons--nav {
    display: flex;
    margin-right: 0.5rem;
    padding-right: 0.7rem;
    border-right: 1px solid var(--line);
  }
  .sicons--nav .sicon { width: 34px; height: 34px; }
  .sicons--nav .sicon svg { width: 17px; height: 17px; }
}

/* mobile menu row */
.sicons--menu {
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: auto;
  padding-top: 2rem;
}
.sicons--menu .sicon {
  width: 44px; height: 44px;
  color: var(--cream-70);
  background: rgba(246, 239, 229, 0.03);
}
.sicons--menu .sicon svg { width: 21px; height: 21px; }
.menu .menu__foot { margin-top: 1.6rem; }

/* footer row */
.sicons--foot {
  flex-wrap: wrap;
  gap: 0.25rem;
  justify-content: center;
  margin-top: clamp(1.6rem, 4vw, 2.4rem);
  padding-top: clamp(1.4rem, 3.5vw, 2rem);
  border-top: 1px solid var(--line);
}
@media (min-width: 640px) { .sicons--foot { justify-content: flex-start; } }
.sicons--foot .sicon { width: 42px; height: 42px; }
.sicons--foot .sicon svg { width: 20px; height: 20px; }

/* icons inside the booking "Follow" list */
.socials a { gap: 0.55rem; }
.socials__i {
  width: 16px; height: 16px;
  flex: 0 0 auto;
  color: var(--cream-32);
  transition: color 0.3s var(--ease), transform 0.4s var(--ease);
}
.socials a:hover .socials__i { color: var(--pink); transform: scale(1.12); }

/* ============================================================
   20. HERO PORTRAITS — tilted editorial cards
   Both are LANDSCAPE masters in 3:2 frames. Matted like framed
   prints (inner hairline + drop shadow) and counter-rotated, so
   the hero reads as an art wall rather than a pasted photo.
   They live behind hero__vignette so the gradient owns the mood.

   LAYER CONTRACT — three transforms, three owners, no collisions:
     .hero__fig        rotate(var(--tilt)) + ambient float  (CSS only)
     .hero__fig__in    load scale, scroll parallax, pointer  (GSAP only)
     .hero__fig img    object-fit crop + its own filter      (CSS only)
   GSAP writes inline transforms, which replace the whole transform
   property. Splitting the tilt onto the outer element is what keeps a
   parallax tween from silently flattening the rotation a breakpoint set.
   ============================================================ */
.hero__figures { position: absolute; inset: 0; pointer-events: none; }

.hero__fig {
  position: absolute;
  margin: 0;
  border-radius: var(--r);
  transform: rotate(var(--tilt, 0deg));
  animation: figFloat var(--float, 13s) var(--ease-io) infinite alternate;
  animation-delay: var(--float-delay, 0s);
}

/* Inner layer: owns the crop, the mat and every JS-driven transform. */
.hero__fig__in {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: inherit;
  border: 1px solid var(--line-2);
  background: var(--ink);
  /* Matted-print feel: hairline inside, soft cast shadow outside, plus a
     faint neon bounce so the frames sit in the aurora instead of on it. */
  box-shadow:
    inset 0 0 0 4px rgba(10, 10, 10, 0.55),
    inset 0 1px 0 0 rgba(246, 239, 229, 0.10),
    0 34px 70px -34px rgba(0, 0, 0, 0.95),
    0 0 90px -40px rgba(255, 84, 150, 0.45);
  will-change: transform;
}
.hero__fig img {
  width: 100%; height: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  filter: grayscale(0.4) contrast(1.06);
}

/* Slow diagonal gallery-light sweep across the glass. Sits above the
   image but inside the frame, and never catches pointer events. */
.hero__fig__sheen {
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(104deg,
    transparent 38%,
    rgba(246, 239, 229, 0.13) 48%,
    rgba(246, 239, 229, 0.02) 56%,
    transparent 64%);
  background-size: 260% 100%;
  background-position: 130% 0;
  animation: figSheen 11s var(--ease-io) infinite;
  animation-delay: var(--sheen-delay, 2s);
}

@keyframes figFloat {
  to { transform: rotate(var(--tilt, 0deg)) translate3d(var(--fx, 0px), var(--fy, -14px), 0); }
}
@keyframes figSheen {
  0%, 62%  { background-position: 130% 0; }
  100%     { background-position: -40% 0; }
}

/* Mobile: two faint frames at the top — the art wall reads even at 360px,
   and both sit clear of the wordmark block that bottom-aligns beneath.

   MEASURED (390x844, 2026-09-16): frame B at `top: 12.4rem` had a bbox
   bottom of 297px while the eyebrow's inked text starts at 277.5px — a real
   113x17px collision that put "SINGER · SONGWRITER · PRODUCER · DJ" on top
   of the portrait and made it unreadable. A rotated frame's visual box is
   its axis-aligned bbox, taller than its layout box, so B is positioned
   against that inflated box. B now lifts into a staggered pair with A
   (bboxes ~111-216 and ~84-237), leaving the whole band above 240px to the
   art and everything below 277px to the type. Re-verify with probe-align.js
   after touching either frame's `top` or `width`. */
.hero__fig--a {
  --tilt: 3.4deg;
  --float: 14s;
  --fy: -13px;
  --fx: -5px;
  /* -0.34 put 11px of the rotated bbox past the right edge, clipping the
     frame's corner against the viewport rather than bleeding softly. */
  top: 5.6rem; right: calc(var(--pad) * -0.12);
  width: min(54vw, 268px);
  opacity: 0.44;
}
.hero__fig--b {
  --tilt: -6.2deg;
  --float: 17s;
  --float-delay: -4s;
  --fy: 11px;
  --fx: 6px;
  --sheen-delay: 6s;
  top: 7.4rem; left: calc(var(--pad) * -0.2);
  width: min(35vw, 152px);
  opacity: 0.26;
}

/* Tablet: pull them apart and open up the centre for the mark. */
@media (min-width: 700px) {
  .hero__fig--a {
    --tilt: 3.8deg;
    top: 8%; right: 3.5%;
    width: min(38vw, 330px);
    opacity: 0.5;
  }
  .hero__fig--b {
    --tilt: -5.4deg;
    top: 34%; left: 3%;
    width: min(24vw, 210px);
    opacity: 0.32;
  }
}

/* Desktop: the art wall gets its own column on the right, and the wordmark
   is capped so the two never share horizontal space.

   MEASURED: at 1440px an uncapped 1040px mark ran 132→1172 while frame A
   started at 949 — a 223x204px overlap that put the "IA" glyphs on top of
   the subject's torso. A rotated frame's visual box is its axis-aligned
   bbox (wider than its layout box), so the frame column is positioned
   against that inflated box, not the nominal width. Re-verify with the
   collision probe after changing either value. */
@media (min-width: 1100px) {
  .hero__fig--a {
    --tilt: 3.6deg;
    --fy: -18px;
    top: 8%; right: 4.5%;
    width: min(27vw, 400px);
    opacity: 0.62;
  }
  /* Overlaps A's lower edge for depth, still clear of the mark column. */
  .hero__fig--b {
    --tilt: -5deg;
    --fy: 14px;
    top: 38%; right: 9.5%;
    left: auto;
    width: min(17.5vw, 258px);
    opacity: 0.44;
  }
}

/* Ultra-wide: widen the spread so the wall breathes at 1500px+. */
@media (min-width: 1500px) {
  .hero__fig--a { top: 7.5%; right: 3.5%; width: min(26vw, 440px); }
  .hero__fig--b { top: 39%; right: 9%; width: min(16vw, 286px); }
}

/* Cursor-reactive depth: JS adds this only on a fine pointer. */
.hero__figures.is-live .hero__fig__in { transition: box-shadow 0.5s var(--ease); }

/* ============================================================
   28. PRESS WALL — tall vertical editorial strip
   Home for the three remaining vertical masters. Full 2:3 frames
   in a staggered row; each column offsets vertically and drifts at
   its own rate (JS), for a gallery-wall rhythm. Events-only gallery
   stays untouched — these never mix.
   ============================================================ */
.press {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.5rem, 1.6vw, 1.1rem);
}
/* Third frame spans both columns on small screens so nothing orphans. */
.press .press__fig:nth-child(3) { grid-column: span 2; }

@media (min-width: 760px) {
  .press { grid-template-columns: repeat(3, 1fr); align-items: start; }
  .press .press__fig:nth-child(3) { grid-column: auto; }
  /* staggered baseline — the gallery-wall rhythm */
  .press .press__fig:nth-child(1) { margin-top: clamp(1.2rem, 3.5vw, 3rem); }
  .press .press__fig:nth-child(3) { margin-top: clamp(0.6rem, 2vw, 1.6rem); }
}

.press__fig {
  position: relative;
  margin: 0;
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--ink);
  will-change: transform;
  transition: border-color 0.45s var(--ease), box-shadow 0.55s var(--ease);
}
.press__fig img {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  filter: grayscale(0.32) contrast(1.05);
  transition: filter 0.6s var(--ease), transform 1s var(--ease);
}
.press__fig::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.72), transparent 52%);
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.press__fig:hover {
  border-color: rgba(255, 84, 150, 0.4);
  box-shadow: 0 30px 60px -34px rgba(255, 84, 150, 0.5);
}
.press__fig:hover img { filter: grayscale(0) contrast(1.08); transform: scale(1.04); }
.press__fig:hover::after { opacity: 1; }

.press__fig figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  padding: 1.6rem 0.9rem 0.8rem;
  font-size: 0.58rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cream-50);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.45s var(--ease), transform 0.5s var(--ease);
}
.press__fig:hover figcaption { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .press__fig figcaption { opacity: 1; transform: none; }
  /* The mat/glow lives on the inner layer now; drop the neon bounce and the
     light sweep, keep the frames legible and completely still. */
  .hero__fig__in { box-shadow: 0 34px 70px -34px rgba(0, 0, 0, 0.95); }
  .hero__fig__sheen { display: none; }
  .hero__fig { animation: none; }
}

/* ============================================================
   21. WATCH — live YouTube cards
   Reuses the .vid shell; the gradient art is swapped for a real
   thumbnail, so hover motion and the gradient scrim carry over.
   ============================================================ */
.sec__hint {
  font-size: var(--fs-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cream-32);
}

.vid__skeleton {
  min-height: clamp(210px, 42vw, 290px);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: linear-gradient(100deg, var(--ink) 25%, var(--ink-2) 50%, var(--ink) 75%);
  background-size: 260% 100%;
  animation: shimmer 1.5s linear infinite;
}
.videos > .vid__skeleton:first-child { min-height: clamp(240px, 52vw, 100%); }

.vid__thumb {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.3) contrast(1.06);
  transition: transform 0.9s var(--ease), filter 0.6s var(--ease);
}
.vid:hover .vid__thumb {
  transform: scale(1.06);
  filter: grayscale(0) contrast(1.1) saturate(1.1);
}

.vid__t--live {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: clamp(1rem, 2.2vw, 1.35rem);
  line-height: 1.16;
}
.videos > .vid:first-child .vid__t--live {
  font-size: clamp(1.15rem, 3vw, 1.75rem);
  -webkit-line-clamp: 3;
}

/* ============================================================
   22. CLIPS — 9:16 performance video tiles
   ============================================================ */
.clips {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.5rem, 1.6vw, 1rem);
}
@media (min-width: 680px)  { .clips { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { .clips { grid-template-columns: repeat(5, 1fr); } }

.clip {
  position: relative;
  aspect-ratio: 9 / 16;
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ink);
  cursor: pointer;
  isolation: isolate;
  transition: border-color 0.4s var(--ease), transform 0.55s var(--ease),
              box-shadow 0.55s var(--ease);
}
.clip video {
  width: 100%; height: 100%;
  object-fit: cover;
  background: var(--ink);
  filter: grayscale(0.25) contrast(1.05);
  transition: filter 0.5s var(--ease), transform 0.8s var(--ease);
}
.clip::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.7) 4%, transparent 45%);
  opacity: 0.9;
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.clip:hover, .clip:focus-visible {
  border-color: rgba(255, 84, 150, 0.45);
  transform: translateY(-4px);
  box-shadow: 0 24px 50px -30px rgba(255, 84, 150, 0.6);
}
.clip:hover video, .clip:focus-visible video { filter: grayscale(0) contrast(1.08); }

.clip__badge {
  position: absolute;
  left: 0.6rem; bottom: 0.6rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream-70);
  transition: color 0.35s var(--ease);
}
.clip:hover .clip__badge { color: var(--cream); }

.clip__play {
  position: absolute;
  top: 50%; left: 50%;
  z-index: 2;
  width: 44px; height: 44px;
  display: grid;
  place-content: center;
  transform: translate(-50%, -50%);
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.45);
  backdrop-filter: blur(6px);
  font-size: 0.66rem;
  color: var(--cream);
  transition: opacity 0.35s var(--ease), background 0.35s var(--ease),
              color 0.35s var(--ease), transform 0.4s var(--ease);
}
.clip:hover .clip__play {
  background: var(--cream);
  color: #0a0a0a;
  border-color: var(--cream);
  transform: translate(-50%, -50%) scale(1.08);
}
.clip.is-playing .clip__play,
.clip.is-playing::after,
.clip.is-playing .clip__badge { opacity: 0; }
.clip.is-playing video { filter: none; }

.clip__mute {
  position: absolute;
  top: 0.55rem; right: 0.55rem;
  z-index: 3;
  width: 30px; height: 30px;
  display: grid;
  place-content: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.55);
  backdrop-filter: blur(6px);
  font-size: 0.62rem;
  color: var(--cream-70);
  opacity: 0;
  transition: opacity 0.3s var(--ease), color 0.3s var(--ease), background 0.3s var(--ease);
}
.clip.is-playing .clip__mute { opacity: 1; }
.clip__mute:hover { color: #0a0a0a; background: var(--cream); }

/* ============================================================
   23. GALLERY — event pics rail + lightbox
   ============================================================ */
.gal {
  position: relative;
  margin-top: clamp(0.5rem, 2vw, 1rem);
}
.gal__rail {
  display: flex;
  gap: clamp(0.5rem, 1.4vw, 0.9rem);
  padding-inline: var(--pad);
  padding-bottom: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
  -webkit-overflow-scrolling: touch;
}
.gal__rail::-webkit-scrollbar { height: 6px; }
.gal__rail::-webkit-scrollbar-track { background: transparent; }
.gal__rail::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border-radius: 999px;
}
.gal__rail::-webkit-scrollbar-thumb:hover { background: var(--pink); }

.gal__item {
  position: relative;
  flex: 0 0 auto;
  width: clamp(190px, 58vw, 340px);
  aspect-ratio: 4 / 5;
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ink);
  scroll-snap-align: start;
  cursor: zoom-in;
  transition: border-color 0.4s var(--ease), transform 0.55s var(--ease);
}
.gal__item:nth-child(3n) { aspect-ratio: 3 / 4; }
.gal__item:nth-child(4n) { aspect-ratio: 1; }

.gal__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.3) contrast(1.05);
  transition: transform 0.8s var(--ease), filter 0.5s var(--ease);
}
.gal__item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.55), transparent 55%);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.gal__item:hover, .gal__item:focus-visible {
  border-color: rgba(68, 217, 255, 0.45);
  transform: translateY(-4px);
}
.gal__item:hover img, .gal__item:focus-visible img {
  transform: scale(1.06);
  filter: grayscale(0) contrast(1.08);
}
.gal__item:hover::after, .gal__item:focus-visible::after { opacity: 1; }

/* Desktop: drop the snap rail for a dense masonry-ish grid. */
@media (min-width: 900px) {
  .gal__rail {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 1fr;
    overflow: visible;
    scroll-snap-type: none;
    max-width: var(--maxw);
    margin-inline: auto;
  }
  .gal__item { width: auto; aspect-ratio: 1; }
  .gal__item:nth-child(3n) { aspect-ratio: 1; }
  .gal__item:nth-child(4n) { aspect-ratio: 1; }
  /* two feature tiles per 12 to break the checkerboard */
  .gal__item:nth-child(12n + 1) { grid-column: span 2; grid-row: span 2; }
  .gal__item:nth-child(12n + 8) { grid-column: span 2; grid-row: span 2; }
}

.gal__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(1.4rem, 3.5vw, 2.2rem);
}
.gal__more {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.8rem 1.4rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream-70);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease), background 0.35s var(--ease);
}
.gal__more i {
  font-style: normal;
  color: var(--cyan);
  transition: transform 0.45s var(--ease);
}
.gal__more:hover {
  color: var(--cream);
  border-color: var(--cream);
  background: rgba(246, 239, 229, 0.04);
}
.gal__more[aria-expanded="true"] i { transform: rotate(135deg); }
.gal__more[hidden] { display: none; }

.gal__credit {
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cream-32);
}

/* lightbox */
.lb {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(6, 6, 7, 0.94);
  backdrop-filter: blur(14px);
}
.lb[hidden] { display: none; }

.lb__stage {
  margin: 0;
  max-width: min(94vw, 1100px);
  max-height: 86svh;
  display: grid;
  gap: 0.9rem;
  justify-items: center;
}
.lb__stage img {
  max-width: 100%;
  max-height: 78svh;
  width: auto; height: auto;
  border-radius: var(--r);
  border: 1px solid var(--line);
  box-shadow: 0 50px 120px -50px rgba(0, 0, 0, 0.95);
}
.lb__count {
  font-size: 0.68rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cream-50);
}

.lb__close {
  position: absolute;
  top: clamp(0.7rem, 2.5vw, 1.6rem);
  right: clamp(0.7rem, 2.5vw, 1.6rem);
  width: 46px; height: 46px;
  display: grid;
  place-content: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--cream-70);
  background: rgba(10, 10, 10, 0.5);
  transition: color 0.3s var(--ease), background 0.3s var(--ease), transform 0.35s var(--ease);
}
.lb__close:hover {
  color: #0a0a0a;
  background: var(--cream);
  transform: rotate(90deg);
}

.lb__nav {
  position: absolute;
  top: 50%;
  width: 50px; height: 50px;
  display: grid;
  place-content: center;
  transform: translateY(-50%);
  border: 1px solid var(--line-2);
  border-radius: 50%;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--cream-70);
  background: rgba(10, 10, 10, 0.5);
  backdrop-filter: blur(8px);
  transition: color 0.3s var(--ease), background 0.3s var(--ease), border-color 0.3s var(--ease);
}
.lb__nav--prev { left: clamp(0.4rem, 2vw, 1.6rem); }
.lb__nav--next { right: clamp(0.4rem, 2vw, 1.6rem); }
.lb__nav:hover {
  color: #0a0a0a;
  background: var(--cream);
  border-color: var(--cream);
}

/* ============================================================
   24. ABOUT — editorial imagery
   Every portrait is framed to its own native orientation: the two
   LANDSCAPE masters live here in 3:2 frames, the five verticals go
   to the hero cards and the press wall (§28). Nothing is cropped
   against its shape.
   ============================================================ */

/* Cinematic full-width band above the bio columns. */
.bio__band {
  position: relative;
  margin: 0 0 clamp(2rem, 5vw, 3.2rem);
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--ink);
}
.bio__band img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: 50% 42%;
  filter: grayscale(0.3) contrast(1.06);
  transition: filter 0.7s var(--ease), transform 1.1s var(--ease);
}
.bio__band:hover img { filter: grayscale(0) contrast(1.08); transform: scale(1.02); }
@media (min-width: 900px) {
  .bio__band img { aspect-ratio: 3 / 2; }
}
.bio__band figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1rem;
  padding: clamp(2.2rem, 6vw, 3.4rem) clamp(1rem, 2.6vw, 1.6rem) clamp(0.8rem, 2vw, 1.1rem);
  background: linear-gradient(to top, rgba(10, 10, 10, 0.9), transparent);
  font-size: 0.64rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.bio__band figcaption span { color: var(--cream-70); }
.bio__band figcaption i { font-style: normal; color: var(--cream-32); }

/* Inline portrait inside the expanded bio. */
.bio__fig {
  position: relative;
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--ink);
}
.bio__fig img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  filter: grayscale(0.28) contrast(1.06);
  transition: filter 0.6s var(--ease), transform 0.9s var(--ease);
}
.bio__fig:hover img { filter: grayscale(0) contrast(1.08); transform: scale(1.03); }
.bio__fig--inline img { aspect-ratio: 3 / 4; object-position: 50% 22%; }

/* ============================================================
   25. SHOWS — whole row is the ticket link
   ============================================================ */
.shows > li { display: grid; }

a.show {
  color: inherit;
  cursor: pointer;
}
a.show:hover .show__go i,
a.show:focus-visible .show__go i { transform: translate(4px, -4px); color: var(--pink); }

.show__go em {
  display: none;
  font-style: normal;
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.show__go i { font-style: normal; }

@media (min-width: 860px) {
  .show__go {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    justify-self: end;
    padding: 0.5rem 0.95rem;
    border: 1px solid transparent;
    border-radius: 999px;
    transition: border-color 0.4s var(--ease), color 0.4s var(--ease),
                background 0.4s var(--ease);
  }
  .show__go em { display: block; }
  a.show:hover .show__go,
  a.show:focus-visible .show__go {
    color: var(--cream);
    border-color: var(--line-2);
    background: rgba(246, 239, 229, 0.04);
  }
}

/* ============================================================
   26. MOTION PREP for the new blocks
   ============================================================ */
.js .clips [data-clip],
.js .gal__item { will-change: transform, opacity; }

@media (prefers-reduced-motion: reduce) {
  .hero__fig img { filter: grayscale(0.4) contrast(1.06); }
  .clip video { filter: none; }
  .gal__rail { scroll-behavior: auto; }
  .yts__rail { scroll-behavior: auto; }
}

/* ============================================================
   27. STAT FIT FIX (6-up row)
   Measured defect: at the 6-column breakpoint "15.7M+" needed
   208px of glyph run against ~137-155px of usable cell width, so
   the M+ suffix was clipped. The cell count is what changed, not
   the type scale, so the value size now tracks viewport width and
   is verified to fit at 1200 / 1440 / 1920.
   ============================================================ */
@media (min-width: 1200px) {
  .stat__n { font-size: clamp(1.25rem, 1.5vw, 1.6rem); }
}

/* Narrow phones: the 2-up stat grid leaves ~138px of usable cell, while
   "15.7M+" ran 145px at the base size. Measured at 375px and 320px. */
@media (max-width: 430px) {
  .stat__n { font-size: clamp(1.25rem, 5.9vw, 1.6rem); }
}

/* Cards carrying a real photographic thumbnail need a heavier scrim than the
   gradient plates did: YouTube stills are often bright and busy exactly where
   the title sits. Scoped to .vid__thumb so gradient-art cards keep their
   lighter treatment. */
.vid:has(.vid__thumb)::after {
  background: linear-gradient(to top,
    rgba(10, 10, 10, 0.95) 0%,
    rgba(10, 10, 10, 0.82) 22%,
    rgba(10, 10, 10, 0.35) 52%,
    rgba(10, 10, 10, 0.08) 100%);
}
/* Fallback for engines without :has() — slightly heavier on every card. */
@supports not selector(:has(*)) {
  .vid::after {
    background: linear-gradient(to top,
      rgba(10, 10, 10, 0.93) 4%,
      rgba(10, 10, 10, 0.5) 42%,
      transparent);
  }
}
.vid__t--live { text-shadow: 0 1px 14px rgba(10, 10, 10, 0.75); }
.vid:has(.vid__thumb) .vid__m { color: var(--cream-70); }

/* ============================================================
   29. LIVE SETS — featured player + horizontal playlist strip

   Layout: one 16:9 feature card carries the current video; the rest
   of the feed becomes a snap-scrolling strip underneath that acts as
   the playlist. Selecting a strip card promotes it into the feature
   and swaps in the iframe — always click-initiated, so nothing ever
   autoplays on load and no audio starts by itself.

   The strip is the scrollable surface on every width (a rail on
   mobile, a wider rail on desktop), so an 8-video feed never turns
   the section into a tall wall of cards.
   ============================================================ */
.yt { position: relative; }
/* These branches all carry a display-setting class, which would beat the
   plain [hidden] attribute — so hiding has to be explicit. */
.yt__skel[hidden], .ytf[hidden], .yts[hidden], [data-yt-static][hidden] { display: none; }

/* Loading state mirrors the final layout (one wide feature over a row of
   strip cards) so the section does not visibly re-flow when data lands. */
.yt__skel {
  display: grid;
  gap: clamp(0.55rem, 1.6vw, 1rem);
  grid-template-columns: repeat(2, 1fr);
}
.yt__skel > .vid__skeleton:first-child {
  grid-column: span 2;
  min-height: 0;
  aspect-ratio: 16 / 9;
}
.yt__skel > .vid__skeleton {
  min-height: 0;
  aspect-ratio: 16 / 9;
  border-radius: var(--r);
}
@media (min-width: 760px) {
  .yt__skel { grid-template-columns: repeat(3, 1fr); }
  .yt__skel > .vid__skeleton:first-child { grid-column: span 3; }
}

/* ---- featured card ---- */
.ytf {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;
  margin-bottom: clamp(1rem, 2.6vw, 1.6rem);
}
.ytf__card {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: inherit;
  cursor: pointer;
  text-align: left;
  background: var(--ink);
}
.ytf__thumb {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.22) contrast(1.06);
  transform: scale(1.01);
  transition: transform 1.1s var(--ease), filter 0.6s var(--ease);
}
.ytf__card:hover .ytf__thumb,
.ytf__card:focus-visible .ytf__thumb {
  transform: scale(1.045);
  filter: grayscale(0) contrast(1.1) saturate(1.08);
}
/* Heavy bottom scrim: YouTube stills are bright exactly where the title sits. */
.ytf__card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(10, 10, 10, 0.94) 0%,
    rgba(10, 10, 10, 0.72) 26%,
    rgba(10, 10, 10, 0.18) 58%,
    rgba(10, 10, 10, 0.04) 100%);
}
.ytf__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: grid;
  gap: 0.45rem;
  padding: clamp(1.1rem, 3.2vw, 2.2rem);
}
.ytf__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--cyan);
}
.ytf__tag::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--pink);
  box-shadow: 0 0 10px rgba(255, 84, 150, 0.8);
}
.ytf__t {
  font-family: var(--display);
  font-size: clamp(1.25rem, 3.6vw, 2.5rem);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--cream);
  text-shadow: 0 2px 22px rgba(10, 10, 10, 0.8);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 30ch;
}
.ytf__m {
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cream-50);
}

/* Centred play affordance on the feature. */
.ytf__play {
  position: absolute;
  top: 50%; left: 50%;
  z-index: 3;
  transform: translate(-50%, -50%);
  width: clamp(56px, 11vw, 82px);
  aspect-ratio: 1;
  display: grid;
  place-content: center;
  border: 1px solid rgba(246, 239, 229, 0.5);
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.34);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  font-size: clamp(0.85rem, 2vw, 1.15rem);
  color: var(--cream);
  transition: transform 0.45s var(--ease), background 0.4s var(--ease),
              border-color 0.4s var(--ease), color 0.4s var(--ease);
}
.ytf__play::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid rgba(255, 84, 150, 0.55);
  opacity: 0;
  transform: scale(1);
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease);
}
.ytf__card:hover .ytf__play,
.ytf__card:focus-visible .ytf__play {
  background: var(--cream);
  border-color: var(--cream);
  color: #0a0a0a;
  transform: translate(-50%, -50%) scale(1.08);
}
.ytf__card:hover .ytf__play::after { opacity: 1; transform: scale(1.3); }

/* Playing state: the iframe takes the whole frame. */
.ytf__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
}
.ytf__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

/* ---- playlist strip ---- */
.yts__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.85rem;
}
.yts__label {
  font-size: var(--fs-micro);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--cream-32);
}
.yts__ctrl { display: none; gap: 0.4rem; }
@media (hover: hover) and (pointer: fine) {
  .yts__ctrl { display: flex; }
}
.yts__btn {
  width: 38px; height: 38px;
  display: grid;
  place-content: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--cream-70);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease),
              background 0.35s var(--ease), transform 0.35s var(--ease);
}
.yts__btn:hover {
  color: #0a0a0a;
  background: var(--cream);
  border-color: var(--cream);
  transform: scale(1.06);
}
.yts__btn:disabled {
  opacity: 0.3;
  cursor: default;
  transform: none;
  color: var(--cream-32);
  background: none;
  border-color: var(--line);
}

/* The scrollable surface. Full-bleed edges are faded with a mask so cards
   dissolve rather than getting cut by the wrapper. */
.yts__rail {
  display: flex;
  gap: clamp(0.55rem, 1.6vw, 1rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.9rem;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
.yts__rail::-webkit-scrollbar { height: 6px; }
.yts__rail::-webkit-scrollbar-track { background: transparent; }
.yts__rail::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 999px; }
.yts__rail::-webkit-scrollbar-thumb:hover { background: var(--pink); }

/* ---- strip card ---- */
.ytc {
  position: relative;
  flex: 0 0 auto;
  width: clamp(208px, 62vw, 300px);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0;
  text-align: left;
  scroll-snap-align: start;
  cursor: pointer;
  background: none;
  transition: transform 0.45s var(--ease);
}
@media (min-width: 760px)  { .ytc { width: clamp(240px, 30vw, 286px); } }
@media (min-width: 1100px) { .ytc { width: 300px; } }

.ytc__art {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ink);
  transition: border-color 0.4s var(--ease), box-shadow 0.5s var(--ease);
}
.ytc__art img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.34) contrast(1.05);
  transition: transform 0.8s var(--ease), filter 0.5s var(--ease);
}
.ytc__art::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 10, 0.62), transparent 58%);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.ytc__play {
  position: absolute;
  top: 50%; left: 50%;
  z-index: 2;
  transform: translate(-50%, -50%) scale(0.86);
  width: 40px; aspect-ratio: 1;
  display: grid;
  place-content: center;
  border: 1px solid rgba(246, 239, 229, 0.42);
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.42);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  font-size: 0.6rem;
  color: var(--cream);
  opacity: 0;
  transition: opacity 0.4s var(--ease), transform 0.45s var(--ease),
              background 0.4s var(--ease), color 0.4s var(--ease);
}
.ytc__t {
  font-size: 0.86rem;
  font-weight: 400;
  line-height: 1.34;
  color: var(--cream-70);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color 0.35s var(--ease);
}
.ytc__m {
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cream-32);
}

.ytc:hover, .ytc:focus-visible { transform: translateY(-4px); }
.ytc:hover .ytc__art, .ytc:focus-visible .ytc__art {
  border-color: rgba(68, 217, 255, 0.45);
  box-shadow: 0 24px 46px -28px rgba(68, 217, 255, 0.45);
}
.ytc:hover .ytc__art img, .ytc:focus-visible .ytc__art img {
  transform: scale(1.07);
  filter: grayscale(0) contrast(1.08);
}
.ytc:hover .ytc__art::after, .ytc:focus-visible .ytc__art::after { opacity: 1; }
.ytc:hover .ytc__play, .ytc:focus-visible .ytc__play {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  background: var(--cream);
  color: #0a0a0a;
}
.ytc:hover .ytc__t, .ytc:focus-visible .ytc__t { color: var(--cream); }

/* Currently in the feature: mark it, and stop advertising it as playable. */
.ytc.is-current .ytc__art {
  border-color: rgba(255, 84, 150, 0.6);
  box-shadow: 0 0 0 1px rgba(255, 84, 150, 0.35), 0 24px 46px -30px rgba(255, 84, 150, 0.5);
}
.ytc.is-current .ytc__t { color: var(--cream); }
.ytc.is-current .ytc__m { color: var(--pink); }
.ytc.is-current .ytc__play { opacity: 0; }

/* Touch has no hover: keep the play glyph visible so the affordance reads. */
@media (hover: none) {
  .ytc__play { opacity: 0.92; transform: translate(-50%, -50%) scale(1); }
  .ytc.is-current .ytc__play { opacity: 0; }
}

/* Narrow screens: the feature card is only ~189px tall at 375px, and the
   overlay text block measured 126px of that (67%) — so a vertically centred
   play button landed inside the title (measured 56x56px overlap) and the
   still's own artwork text read straight through the scrim.

   Fixes, all confined to narrow widths:
     - play button moves to the top-right corner, clear of the text block
       (and matches the .vid__play language used elsewhere on the page)
     - scrim reaches full strength higher up, so busy stills stay legible
     - tighter type + padding so the block occupies less of the card */
@media (max-width: 700px) {
  .ytf__play {
    top: 0.8rem; right: 0.8rem; left: auto;
    transform: none;
    width: 42px;
  }
  .ytf__card:hover .ytf__play,
  .ytf__card:focus-visible .ytf__play { transform: scale(1.06); }
  .ytf__card:hover .ytf__play::after { transform: scale(1.22); }

  .ytf__card::after {
    background: linear-gradient(to top,
      rgba(10, 10, 10, 0.96) 0%,
      rgba(10, 10, 10, 0.9) 42%,
      rgba(10, 10, 10, 0.62) 68%,
      rgba(10, 10, 10, 0.24) 100%);
  }

  .ytf__body { gap: 0.3rem; padding: 0.85rem 1rem; }
  .ytf__tag { font-size: 0.56rem; letter-spacing: 0.18em; }
  .ytf__t { font-size: 1.05rem; line-height: 1.12; max-width: 24ch; }
  .ytf__m { font-size: 0.66rem; }
}

@media (prefers-reduced-motion: reduce) {
  .ytf__thumb, .ytc__art img { transition: none; }
  .ytf__play::after { display: none; }
}

/* ============================================================
   30. POLISH PASS — micro-interactions, rhythm, touch behaviour
   Additive only: every rule here either adds a state that did not
   exist (hover/focus/active) or corrects a measured rhythm problem.
   ============================================================ */

/* ---- keyboard parity ----
   Several card surfaces had hover states but no keyboard equivalent, so
   tabbing through the page showed the focus ring with no card response.
   The ring itself stays: this only matches hover's motion. */
.release:focus-within { background: var(--ink); }
.dsp:focus-visible { border-color: var(--line-2); background: rgba(246, 239, 229, 0.04); }
.dsp:focus-visible::before { transform: scaleY(1); }
.dsp:focus-visible i { transform: translate(3px, -3px); color: var(--pink); }
.press__fig:focus-within figcaption { opacity: 1; transform: translateY(0); }
.show:focus-visible::before { opacity: 1; }
.show:focus-visible .show__venue { color: var(--pink); }
@media (min-width: 860px) {
  .show:focus-visible .show__go { transform: translate(4px, -4px); color: var(--pink); }
}
.socials a:focus-visible { color: var(--cream); }
.socials a:focus-visible i { transform: translate(2px, -2px); color: var(--cyan); }
.link-arrow:focus-visible { color: var(--cream); border-color: var(--pink); }
.link-arrow:focus-visible i { transform: translate(2px, -2px); }

/* ---- stats ----
   The cells already own a top accent bar via .stat::after plus a background
   shift on hover, so this adds only the lift. Two things to respect:
   .stat sets overflow:hidden (a bottom underline would be clipped) and its
   transition lists background — which must be restated here, or this later
   rule would replace it and kill the existing fade. */
.stat { transition: background 0.45s var(--ease), transform 0.45s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .stat:hover { transform: translateY(-3px); }
}

/* Supported-by names: pick each one out on hover instead of a flat block. */
.support__names i { transition: color 0.35s var(--ease); }
.support__names:hover i { color: var(--pink); }

/* ---- listen: the Spotify frame was the one big surface with no response ---- */
.player__frame {
  transition: border-color 0.5s var(--ease), box-shadow 0.6s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .player__frame:hover {
    border-color: var(--line-2);
    box-shadow: 0 40px 90px -46px rgba(0, 0, 0, 0.95),
                0 0 70px -40px rgba(255, 84, 150, 0.4);
  }
}

/* ---- radio card: lift the whole panel, matching every other card ---- */
.radio {
  transition: border-color 0.5s var(--ease), box-shadow 0.6s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .radio:hover {
    border-color: var(--line-2);
    box-shadow: 0 34px 80px -50px rgba(255, 84, 150, 0.45);
  }
}

/* ---- booking cards: accent rail on hover, consistent with .dsp ---- */
.bcard { position: relative; }
.bcard::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: linear-gradient(to bottom, var(--pink), var(--orange));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.5s var(--ease);
}
.bcard:hover::before, .bcard:focus-within::before { transform: scaleY(1); }

/* Sponsor pills: stagger the accent so the row feels alive, not static. */
.sponsors span:hover { background: rgba(246, 239, 229, 0.04); }

/* ---- footer ---- */
.foot__logo { transition: opacity 0.4s var(--ease); }
.foot__logo:hover { opacity: 1; }

/* ---- mobile menu: desktop-style hover cue on pointer devices ---- */
@media (hover: hover) and (pointer: fine) {
  .menu__inner a:hover { color: var(--pink); }
}

/* ---- lightbox: bigger, easier targets and a clearer resting state ---- */
.lb__close, .lb__nav {
  transition: background 0.35s var(--ease), color 0.35s var(--ease),
              border-color 0.35s var(--ease), transform 0.35s var(--ease);
}
.lb__close:hover, .lb__nav:hover { transform: scale(1.08); }
.lb__close:active, .lb__nav:active { transform: scale(0.95); }

/* ---- touch: retire hover-only affordances and tighten tap feedback ----
   On touch, :hover sticks after a tap, leaving cards stuck in their hover
   state. Swap to an :active pulse so feedback is immediate and temporary. */
@media (hover: none) {
  .gal__item:active, .ig__item:active, .ytc:active,
  .clip:active, .press__fig:active { transform: scale(0.985); }
  .gal__item, .ig__item, .ytc, .clip, .press__fig {
    transition: transform 0.18s var(--ease);
  }
  /* Reveal captions/metadata that desktop only shows on hover. */
  .press__fig figcaption { opacity: 0.82; transform: none; }
}

/* ---- spacing rhythm ----
   The gallery rail is full-bleed, so its section needed a slightly tighter
   bottom pad than the text sections to stay on the same visual rhythm. */
.sec--gallery { padding-bottom: clamp(3.5rem, 9vw, 7rem); }
/* Watch sits between two dense sections; give the strip room to breathe. */
.sec--watch .yts { margin-bottom: clamp(0.5rem, 1.5vw, 1rem); }

/* Section rule: fade the divider toward the edges instead of a hard hairline
   spanning the full viewport. */
.sec + .sec { border-top-color: transparent; }
.sec + .sec::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent, var(--line) 18%, var(--line) 82%, transparent);
  pointer-events: none;
}

/* ---- scroll progress: soften the per-frame width jumps ---- */
.scroll-progress span { transition: width 0.12s linear; }
@media (prefers-reduced-motion: reduce) {
  .scroll-progress span { transition: none; }
}

/* ---- anchor offset: the fixed nav was covering section headings on jump ---- */
.sec, .hero { scroll-margin-top: 4.5rem; }

/* ============================================================
   31. HERO LUMINOSITY AT PHONE WIDTHS

   DEFECT: the hero's neon came entirely from .hero__aurora blobs sized in
   vw (78/68/58vw) under filter: blur(90px). At 1440px those are 900/820/700px
   of colour. At 390px they collapse to ~304/265/226px while the blur radius
   stays 90px, so each blob is mostly its own feathered edge; .hero__vignette
   then lays 0.7 black over the top 22% and a full obsidian stop at the
   bottom. Net effect on a phone: the two landscape portraits read flat and
   desaturated against near-black, nothing like the desktop intent.

   FIX, three parts, all mobile-scoped so desktop is untouched:
     a) .hero__wash  — a wide multi-stop neon bloom on `screen`, which can
        only ever ADD light. Sized in % of the hero (not vw), so it does not
        shrink with the viewport the way the blobs did.
     b) scale the aurora blobs up past 100vw and cut their blur, so real
        colour lands inside the frame instead of only the feathered tail.
     c) lighten the vignette's mobile stops and raise portrait opacity +
        saturation, letting the gradient own the mood while the portraits
        stay clearly visible.
   ============================================================ */

/* Inert by default: desktop already has its luminosity. */
.hero__wash { display: none; }

@media (max-width: 700px) {
  .hero__wash {
    display: block;
    position: absolute;
    /* Deliberately bleeds past the hero box on every side — the parent
       clips it (.hero has overflow:hidden), and the overhang keeps the
       brightest part of each stop on-screen rather than at the edge. */
    inset: -12% -22% -6%;
    pointer-events: none;
    /* `screen` adds light and never darkens, so the portraits underneath
       gain luminosity without being tinted into a flat wash. */
    mix-blend-mode: screen;
    opacity: 0.95;
    background:
      radial-gradient(ellipse 62% 44% at 16% 16%,  rgba(255, 84, 150, 0.62), transparent 70%),
      radial-gradient(ellipse 58% 40% at 88% 30%,  rgba(68, 217, 255, 0.50), transparent 72%),
      radial-gradient(ellipse 66% 38% at 50% 74%,  rgba(255, 124, 32, 0.42), transparent 74%),
      radial-gradient(ellipse 40% 26% at 74% 60%,  rgba(255, 213, 75, 0.26), transparent 76%);
    /* One cheap composite layer rather than four animated blobs. */
    animation: washBreathe 18s var(--ease-io) infinite alternate;
  }

  /* (b) Real colour inside the frame: oversize the blobs relative to the
     viewport and cut the blur so they are not all feathered edge. */
  .hero__aurora { filter: blur(56px); }
  .hero__aurora--pink {
    width: 130vw; height: 130vw; max-width: none; max-height: none;
    top: -16%; left: -30%;
    background: radial-gradient(circle at 50% 50%, rgba(255, 84, 150, 0.52), transparent 64%);
  }
  .hero__aurora--cyan {
    width: 118vw; height: 118vw; max-width: none; max-height: none;
    top: 10%; right: -40%;
    background: radial-gradient(circle at 50% 50%, rgba(68, 217, 255, 0.42), transparent 64%);
  }
  .hero__aurora--orange {
    width: 108vw; height: 108vw; max-width: none; max-height: none;
    bottom: -14%; left: 8%;
    background: radial-gradient(circle at 50% 50%, rgba(255, 124, 32, 0.38), transparent 66%);
  }

  /* (c) Let the light through. The bottom obsidian stop has to survive or
     the hero stops blending into the next section, so it is kept and only
     the mid/top stops are lifted. */
  .hero__vignette {
    background:
      radial-gradient(ellipse 130% 74% at 50% 0%, transparent 42%, rgba(10, 10, 10, 0.34) 100%),
      linear-gradient(to bottom,
        rgba(10, 10, 10, 0.46) 0%,
        transparent 26%,
        transparent 62%,
        var(--obsidian) 100%);
  }

  /* The grid was competing with the wash for the same light. */
  .hero__grid { opacity: 0.26; }

  /* Portraits: brighter and less grey, so the neon reads ON them. Desktop
     opacity (0.44 / 0.26) was tuned against a dark backdrop that no longer
     applies once the wash is lit. */
  .hero__fig--a { opacity: 0.72; }
  .hero__fig--b { opacity: 0.52; }
  .hero__fig img {
    filter: grayscale(0.12) contrast(1.1) saturate(1.16) brightness(1.06);
  }
  /* Warm the mat glow to match the lit backdrop. */
  .hero__fig__in {
    box-shadow:
      inset 0 0 0 4px rgba(10, 10, 10, 0.45),
      inset 0 1px 0 0 rgba(246, 239, 229, 0.12),
      0 26px 54px -28px rgba(0, 0, 0, 0.9),
      0 0 70px -26px rgba(255, 84, 150, 0.6);
  }

  /* Keep the wordmark reading against a brighter field. */
  .hero__mark {
    filter: brightness(1.06)
            drop-shadow(0 0 30px rgba(10, 10, 10, 0.5))
            drop-shadow(0 0 60px rgba(10, 10, 10, 0.35));
  }
  .hero__sub, .hero__kinetic { text-shadow: 0 1px 18px rgba(10, 10, 10, 0.6); }
  /* The eyebrow and stat row sit on the brightest part of the wash, and both
     are small caps at low contrast — they need the same scrim the sub and
     kinetic line get, or the lit gradient eats their thin strokes. */
  .hero__eyebrow { text-shadow: 0 1px 14px rgba(10, 10, 10, 0.72); }
  .hero__meta li { text-shadow: 0 1px 12px rgba(10, 10, 10, 0.6); }
}

@keyframes washBreathe {
  to { opacity: 0.66; transform: translate3d(0, -2.5%, 0) scale(1.07); }
}

/* ---- 31b. THE SAME DEFECT, MILDER, ON DESKTOP ----
   MEASURED (2026-09-16, backdrop-only crops, no portraits or type in frame):
   mean luminance of the desktop hero backdrop was 13.9% against 40.3% on
   mobile — the phone got the §31 wash treatment and the desktop never did,
   so the wide layout read as near-monochrome charcoal while the phone read
   neon. The blobs are large enough here (900/820/700px) that they do not need
   resizing; what was missing is additive light between them.

   Reuses .hero__wash (already in the markup, previously inert above 700px)
   rather than adding a layer. Deliberately about half the mobile intensity:
   desktop spreads the same light over ~3.7x the area, and the dark obsidian
   base is the brand — this lifts the field, it does not flood it. */
@media (min-width: 701px) {
  .hero__wash {
    display: block;
    position: absolute;
    inset: -10% -14% -8%;
    pointer-events: none;
    mix-blend-mode: screen;
    opacity: 0.6;
    background:
      radial-gradient(ellipse 52% 46% at 14% 22%, rgba(255, 84, 150, 0.34), transparent 72%),
      radial-gradient(ellipse 48% 42% at 86% 34%, rgba(68, 217, 255, 0.26), transparent 74%),
      radial-gradient(ellipse 54% 38% at 52% 82%, rgba(255, 124, 32, 0.22), transparent 76%);
    animation: washBreathe 24s var(--ease-io) infinite alternate;
  }
  /* The mark sits directly on the lifted field now. */
  .hero__mark {
    filter: brightness(1.06)
            drop-shadow(0 0 40px rgba(255, 84, 150, 0.26))
            drop-shadow(0 0 90px rgba(68, 217, 255, 0.14))
            drop-shadow(0 2px 30px rgba(10, 10, 10, 0.45));
  }
}

/* ============================================================
   32. HERO DEPTH-OF-FIELD PLATES

   Additional images BEHIND the two focal portraits at three blur tiers, so
   the hero has real depth instead of two cards on a gradient.

     .is-near  blur(2px)   scale 1.02  — almost sharp, reads as a third print
     .is-mid   blur(8px)   scale 1.06  — soft shape
     .is-far   blur(20px)  scale 1.12  — pure colour//glow texture

   COST CONTROL (these are decorative, so they must never be expensive):
     - injected by JS after window.load, never in markup
     - capped at 3 (desktop) / 2 (<=700px) by the renderer
     - skipped entirely on save-data / 2g-3g
     - z-index sits under .hero__figures but over the auroras
     - `will-change` is NOT set here: a blurred, animated, composited layer
       with will-change promotes a large texture at blur(20px) and was the
       one thing that measurably cost frames. The drift animation alone is
       enough of a hint for the compositor.
   ============================================================ */
.hero__depth {
  position: absolute;
  inset: 0;
  z-index: -1;            /* behind .hero__figures, above .hero__aurora */
  pointer-events: none;
  overflow: hidden;
}

.hero__dfig {
  position: absolute;
  margin: 0;
  border-radius: var(--r);
  overflow: hidden;
  /* Each plate carries its own tier values via inline custom properties
     written by the renderer, so one rule serves all three. */
  transform: rotate(var(--d-tilt, 0deg)) scale(var(--d-scale, 1));
  opacity: 0;             /* faded in by JS to --d-op after decode */
  transition: opacity 1.4s var(--ease);
  animation: depthDrift var(--d-float, 26s) var(--ease-io) infinite alternate;
  animation-delay: var(--d-delay, 0s);
}
.hero__dfig img {
  width: 100%; height: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  /* The blur tier lives on the <img>, not the frame: blurring the frame
     would also smear its border-radius edge into a grey halo. */
  filter: blur(var(--d-blur, 8px)) grayscale(var(--d-gray, 0.5))
          contrast(1.04) saturate(var(--d-sat, 1.1));
  transform: scale(1.08);  /* hide the blur's transparent edge bleed */
}
/* Tint each plate toward the neon so they read as atmosphere, not photos. */
.hero__dfig::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(140deg,
    rgba(255, 84, 150, 0.22), transparent 52%, rgba(68, 217, 255, 0.18));
  mix-blend-mode: screen;
}

@keyframes depthDrift {
  to {
    transform: rotate(var(--d-tilt, 0deg)) scale(var(--d-scale, 1))
               translate3d(var(--d-x, 2%), var(--d-y, -3%), 0);
  }
}

/* Tiers. Far plates get no border at all — at blur(20px) an edge just reads
   as a grey rectangle outline around a colour smear. */
/* VERIFIED DEFECT (2026-09-16, desktop 1440 capture): with blur(2px) plus a
   hairline border and a cast shadow, the near plate rendered as a hard-edged
   grey RECTANGLE sitting behind the orange portrait — a visible unblended box
   edge, not the depth cue intended. A plate at this opacity cannot also carry
   frame furniture: the border and shadow are what draw the box, since the
   blur only softens the photo INSIDE the frame and never the frame's own
   edge. Border and shadow dropped, blur raised, and every tier is now
   feathered by the shared edge mask below. */
.hero__dfig.is-near {
  --d-blur: 5px;  --d-scale: 1.04; --d-op: 0.3; --d-gray: 0.4; --d-sat: 1.08;
  border: 0;
}
.hero__dfig.is-mid {
  --d-blur: 8px;  --d-scale: 1.06; --d-op: 0.26; --d-gray: 0.5; --d-sat: 1.12;
  border: 0;
}

/* Feather the rectangular tiers into the gradient. `is-far` is already an
   organic blob via border-radius, so it is left alone. Without this, any
   straight plate edge reads as a pasted box the moment it crosses a lighter
   part of the backdrop. */
.hero__dfig.is-near,
.hero__dfig.is-mid {
  -webkit-mask-image: radial-gradient(ellipse 78% 74% at 50% 50%, #000 34%, transparent 82%);
  mask-image: radial-gradient(ellipse 78% 74% at 50% 50%, #000 34%, transparent 82%);
}
.hero__dfig.is-far {
  --d-blur: 20px; --d-scale: 1.12; --d-op: 0.2;  --d-gray: 0.35; --d-sat: 1.25;
  border: 0;
  border-radius: 40% 46% 38% 44%;   /* organic blob, not a photo frame */
}

/* Revealed state — JS adds .is-in once the image has decoded. */
.hero__dfig.is-in { opacity: var(--d-op, 0.26); }

/* Phone: fewer, softer, and pushed to the upper field where the portraits
   sit, so the lower half stays clean for the wordmark + CTAs. The wash
   already supplies the colour down there. */
@media (max-width: 700px) {
  .hero__dfig.is-near { --d-op: 0.26; --d-blur: 3px; }
  .hero__dfig.is-mid  { --d-op: 0.2; }
  .hero__dfig.is-far  { --d-op: 0.16; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__dfig { animation: none; transition: none; }
}

/* ============================================================
   33. CLIPS — HOVER-TO-PREVIEW

   The masters run 17-152MB each (measured), which is why these were
   click-only. Hover play is gated in JS by a dwell timer + a one-at-a-time
   rule; the CSS here only has to make the state legible:

     .is-cued      dwell timer running / data loading  -> spinner ring
     .is-previewing hover playback, muted, will stop on mouseleave
     .is-playing   committed playback after a click (existing behaviour)
   ============================================================ */

/* A cued tile shows progress on the play chip instead of a dead hover. */
.clip.is-cued .clip__play {
  border-color: rgba(255, 84, 150, 0.75);
  border-top-color: transparent;
  animation: clipCue 0.7s linear infinite;
}
@keyframes clipCue {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* Previewing: drop the scrim/chrome so the video reads, but keep the badge
   (a hover preview is transient — the label is still useful context). */
.clip.is-previewing::after { opacity: 0.35; }
.clip.is-previewing .clip__play { opacity: 0; }
.clip.is-previewing video { filter: grayscale(0) contrast(1.06) saturate(1.05); }
.clip.is-previewing .clip__badge { color: var(--cream); }

/* Only a committed (clicked) clip offers audio — a hover preview must not
   invite an unmute it is about to discard on mouseleave. */
.clip.is-previewing:not(.is-playing) .clip__mute { opacity: 0; pointer-events: none; }

/* Preview affordance: a hairline progress bar along the bottom edge so a
   hovered tile clearly reads as "playing a taster", distinct from committed
   playback which hides all chrome. */
.clip__bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 3;
  height: 2px;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(90deg, var(--pink), var(--cyan));
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}
.clip.is-previewing .clip__bar,
.clip.is-playing .clip__bar { opacity: 1; }

/* Touch devices never hover: make sure nothing above leaves a stuck state,
   and keep the tap-to-play affordance fully visible. */
@media (hover: none) {
  .clip.is-cued .clip__play { animation: none; border-color: var(--line-2); }
  .clip__play { opacity: 1; }
}

/* The clips hint swaps copy by input type — hover devices are told about
   hover, touch devices are told about tap. */
.sec__hint__pointer { display: none; }
.sec__hint__touch { display: inline; }
@media (hover: hover) and (pointer: fine) {
  .sec__hint__pointer { display: inline; }
  .sec__hint__touch { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .clip.is-cued .clip__play { animation: none; }
  .clip__bar { transition: none; }
}
