/* The Spectrum — one-screen label site
   Palette: black, white and chrome, lit by the spectrum.
   No panels: everything floats in one environment and moves with the cursor.
   One continuous scroll: home, about, and the footer, which slides up over about. */

/* Herokid Expanded is self-hosted. Drop the woff2 files in /fonts with these names
   (or change the two url() lines to match yours). */
@font-face {
  font-family: "Herokid Expanded";
  src: url("../fonts/Herokid-Expanded-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Herokid Expanded";
  src: url("../fonts/Herokid-Expanded-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

:root {
  --bg: #000;
  --ink: #fff;
  --mute: #8d8d94;

  --ease: cubic-bezier(.2, .78, .18, 1);
  /* the one accent colour: blue, from ice to deep */
  --ice: #9ad1ff;
  --sky: #48b4ff;
  --blue: #2a6cff;
  --deep: #1a3dff;
  --blue-text: linear-gradient(90deg, var(--ice), var(--sky) 45%, var(--blue));
  --chrome: linear-gradient(180deg, #fff 0%, #e4e5e8 30%, #85878e 56%, #f1f1f3 76%, #a5a7ad 100%);

  --font-display: "Herokid Expanded", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-text: Inter, "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;

  /* smoothed pointer position, -1..1, written every frame by spectrum.js */
  --mx: 0;
  --my: 0;
  /* centre of the logo in px, where the opening animation lands */
  --hit-x: 50vw;
  --hit-y: 38vh;
  /* the scroll, written every frame by spectrum.js (see 'scroll'): home → roster (--p1), along the
     roster in artists (--pr, of --rn), roster → about (--pa) and about → footer (--p2) */
  --p1: 0;
  --pr: 0;
  --rn: 1;
  --pa: 0;
  --p2: 0;
  /* how much the layers move at their own speeds (parallax): 0 with reduced motion */
  --px: 1;

  color-scheme: dark;
}

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

html, body { height: 100%; overflow: hidden; }
html { background: var(--bg); -webkit-text-size-adjust: 100%; overscroll-behavior: none; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  /* nothing is selectable, cards included: dragging the cursor around must not paint text blue */
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
  cursor: default;
}
img { -webkit-user-drag: none; }

h1, h2, h3, p, dl, dd, ol, ul { margin: 0; padding: 0; }
ol, ul { list-style: none; }
img, canvas { display: block; max-width: 100%; }

:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

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

/* ---------- environment ---------- */

.env {
  position: fixed; inset: 0; z-index: 0;
  width: 100%; height: 100%; max-width: none;
  /* shown if WebGL is unavailable */
  background: radial-gradient(90% 70% at 50% 42%, #17171a 0%, #060607 60%, #000 100%);
}

.stage {
  position: fixed; inset: 0; z-index: 1;
  overflow: hidden;
  pointer-events: none; /* only its buttons and covers take the pointer */
}

/* Anything with .float lives at a depth (--d): it slides against the cursor
   by that depth, bobs on its own clock (--t), and leaves with the scroll
   (--lift) faster the closer it is. */
.float {
  --d: 1;
  --lift: calc(var(--p1) * (-80vh - (var(--d) - .5) * 60vh * var(--px)));
  translate: calc(var(--mx) * var(--d) * -14px) calc(var(--my) * var(--d) * -14px + var(--lift));
  animation: bob var(--t, 8s) ease-in-out var(--delay, 0s) infinite alternate;
  transition: scale .45s var(--ease);
  will-change: translate, transform;
}
@keyframes bob {
  from { transform: translateY(-7px) rotate(-.7deg); }
  to   { transform: translateY(7px) rotate(.7deg); }
}

/* ---------- top bar: on every page ---------- */

.topbar {
  position: fixed; z-index: 5; left: 0; right: 0; top: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 5% 14px;
  background: linear-gradient(180deg, rgba(0, 0, 0, .65), rgba(0, 0, 0, 0));
}
.topbar button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
.tb-logo img { width: 116px; height: auto; }
.tb-links { display: none; }
.tb-cta {
  padding: 10px 18px;
  border-radius: 999px;
  background: #fff; color: #000;
  font-family: var(--font-display); font-weight: 700; font-size: .74rem;
  text-decoration: none; text-transform: lowercase;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
  transition: box-shadow .3s ease, scale .3s var(--ease);
}
.tb-cta:hover, .tb-cta:focus-visible {
  scale: 1.04;
  box-shadow: 0 0 22px -2px rgba(72, 180, 255, .7), 0 6px 18px -6px rgba(42, 108, 255, .8);
}

/* ---------- home ----------
   A loud headline in the middle with the chrome S above it, and floating all around it the
   results, on cards that each glow in their own blue, mixed in with the covers. Behind it all
   a thin blue ring turns slowly over a faint dot grid.
   Scrolling on, it all leaves upward at different speeds: the near cards fastest, the dots
   slowest, while the ring opens out. */

.home-items { position: absolute; inset: 0; pointer-events: none; }

.home-dots {
  position: absolute; inset: 0;
  background: radial-gradient(rgba(255, 255, 255, .16) 1px, transparent 1.6px) 0 0 / 26px 26px;
  -webkit-mask: radial-gradient(75% 65% at 50% 50%, #000 30%, transparent 100%);
          mask: radial-gradient(75% 65% at 50% 50%, #000 30%, transparent 100%);
  opacity: calc(.55 - var(--p1) * .55);
  translate: 0 calc(var(--p1) * (-80vh + 55vh * var(--px)));
}

/* the ring: thin, in blues from ice to deep, with a soft glow under it, turning once a minute */
.home-ring {
  position: absolute; left: 50%; top: 50%;
  width: min(94vw, 60vh); aspect-ratio: 1;
  translate: -50% calc(-50% + var(--p1) * (-80vh + 45vh * var(--px)));
  scale: calc(1 + var(--p1) * .6 * var(--px));
  opacity: calc(1 - var(--p1) * 1.25);
}
.home-ring i {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: conic-gradient(var(--deep), var(--sky), var(--ice), var(--sky), var(--blue), #0d1a66, var(--deep));
  animation: spin 60s linear infinite;
}
.ring-line {
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 calc(100% - 1px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 calc(100% - 1px));
  opacity: .7;
}
.ring-glow {
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 14px), #000 calc(100% - 4px), transparent);
          mask: radial-gradient(farthest-side, transparent calc(100% - 14px), #000 calc(100% - 4px), transparent);
  filter: blur(10px);
  opacity: .35;
}
@keyframes spin { to { rotate: 1turn; } }

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

.hero {
  --lift: calc(var(--p1) * (-80vh + 14vh * var(--px)));
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding-top: 4svh;
  pointer-events: none;
  opacity: calc(1 - var(--p1) * 1.8);
}
.hero-lockup {
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  transform: perspective(900px) rotateY(calc(var(--mx) * 6deg)) rotateX(calc(var(--my) * -4deg));
}
.hero-mark {
  position: relative;
  height: 13svh;
  aspect-ratio: 1029 / 1758;
  margin-bottom: 2.2svh;
  filter: drop-shadow(0 18px 30px rgba(0, 0, 0, .7));
}
.hero-mark > * { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-mark canvas { opacity: 0; }
.hero-mark.is-live canvas { opacity: 1; }
.hero-mark.is-live .hero-mark-fallback { opacity: 0; }
.hero-mark .hero-ghost { opacity: 0; }

.hero-title {
  margin-top: .4svh;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.6rem, 11vw, 3.4rem); line-height: .95; letter-spacing: -.04em;
  text-transform: lowercase;
  color: #fff;
  text-shadow: 0 0 28px rgba(255, 255, 255, .35), 0 0 2px rgba(255, 255, 255, .6);
}
.ht-line { display: block; }
.hero-title em {
  font-style: normal;
  background: var(--blue-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: none;
}
.hero-sub {
  margin-top: 1.8svh;
  color: #a2a2a9;
  font-size: .78rem; letter-spacing: .14em; text-transform: uppercase;
}

/* ---------- results on home ---------- */

.results { position: absolute; inset: 0; z-index: 4; } /* over the covers */
.result {
  position: absolute;
  display: grid; justify-items: start; gap: 2px;
  min-width: 132px;
  padding: 12px 14px 13px;
  border-radius: 16px;
  rotate: var(--r, 0deg);
  background: linear-gradient(160deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .02) 60%), rgba(8, 8, 10, .55);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), inset 0 0 0 1px rgba(255, 255, 255, .1), 0 24px 60px -18px var(--glow), 0 10px 30px -12px #000;
  opacity: calc(var(--o, 1) * (1 - var(--p1) * 1.6));
  pointer-events: auto;
}
/* each card's own colour, glowing out from behind it */
.result::before {
  content: ""; position: absolute; inset: 18% 10%; z-index: -1;
  border-radius: 50%;
  background: var(--glow);
  filter: blur(34px);
  opacity: .45;
}
.result-num {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.7rem; line-height: 1; letter-spacing: -.03em;
  color: #fff;
  text-shadow: 0 0 18px color-mix(in srgb, var(--glow) 70%, transparent);
}
.result-label { color: #b9b9bf; font-size: .66rem; letter-spacing: .06em; text-transform: uppercase; }
.result-song {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 6px;
  color: #fff; font-family: var(--font-display); font-weight: 700; font-size: .7rem; letter-spacing: .02em;
}
.result-cover { width: 26px; height: 26px; border-radius: 5px; overflow: hidden; flex: none; box-shadow: 0 0 0 1px rgba(255, 255, 255, .2); }
.result-cover img { width: 100%; height: 100%; object-fit: cover; }
.result.is-far { --o: .55; filter: blur(1.4px); scale: .82; }
.result:hover { scale: 1.06; }
.result.is-far:hover { --o: 1; filter: none; }

/* phones: the two LUNA BALA cards top, the two big numbers bottom, the far one hidden */
.r1 { left: 5%;  bottom: 13%; }
.r2 { left: 4%;  top: 11%; }
.r3 { right: 4%; top: 15%; }
.r4 { right: 5%; bottom: 10%; }
.r5 { display: none; }
.lbl-long { display: none; }

/* a hint that there is more below */
.scroll-cue {
  position: absolute; left: 50%; bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  translate: -50% 0;
  display: grid; justify-items: center; gap: 8px;
  padding: 6px 14px;
  border: 0; background: none;
  color: #a9a9b0;
  font: inherit; font-size: .6rem; letter-spacing: .3em; text-transform: uppercase;
  opacity: calc(1 - var(--p1) * 5); /* gone as soon as you scroll */
  pointer-events: auto;
  cursor: pointer;
  transition: color .2s ease;
}
.scroll-cue:hover { color: #fff; }
.scroll-cue i {
  position: relative; display: block;
  width: 18px; height: 28px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
}
.scroll-cue i::after {
  content: "";
  position: absolute; left: 50%; top: 6px;
  width: 2px; height: 6px; margin-left: -1px; border-radius: 2px;
  background: #fff;
  animation: cue 1.8s cubic-bezier(.6, 0, .3, 1) infinite;
}
@keyframes cue { from { translate: 0 0; opacity: 1; } to { translate: 0 10px; opacity: 0; } }
.cue-touch { display: none; }
.lite .cue-touch { display: inline; }
.lite .cue-mouse { display: none; }

/* "spectrum" cropped out of the supplied horizontal logo file (no redraw); the footer uses it */
.wordmark {
  --crop: url("../assets/spectrum-logo.webp") 100% 50% / 118.34% auto no-repeat;
  position: relative;
  display: block;
  aspect-ratio: 1690 / 354;
  background: var(--crop);
}
.wordmark::after {
  content: "";
  position: absolute; inset: 0;
  -webkit-mask: var(--crop); mask: var(--crop);
  background: linear-gradient(105deg, transparent 30%, rgba(0, 0, 0, .6) 46%, rgba(0, 0, 0, .1) 54%, transparent 70%) no-repeat;
  background-size: 220% 100%;
  background-position: calc(50% - var(--mx) * 45%) 0;
}
/* ---------- covers on home ----------
   Square cover arts floating in among the result cards, each at its own depth like the cards
   (spectrum.js makes them from data/releases.json, all ten spots). Hover one (tap on touch) and it
   straightens and opens into a glass card: the cover big, the song, the artist and a button that
   opens the song on Spotify. The card is kept on screen (--sx, --sy).
   Spots without a release yet show as a blue sleeve with the S on it.
   Where each spot floats, its size (--ph), depth (--d) and tilt (--tilt) are set per spot below:
   the first releases get the first spots, so the big, near spots come first. */

.home-covers { position: absolute; inset: 0; }
.cover {
  position: absolute; left: 0; top: 0;
  width: 0; height: 0;               /* a point: the cover is centred on it */
  --ph: 52px;
  z-index: 3;
  pointer-events: none;
  opacity: calc(1 - var(--p1) * 1.5);
}
.cover:focus { outline: none; }
.cover.is-open { z-index: 50; animation-play-state: paused; } /* over everything, and it stops bobbing while you read it */
.cover-shell {
  position: absolute; left: 0; top: 0;
  translate: calc(-50% + var(--sx, 0px)) calc(-50% + var(--sy, 0px));
  rotate: var(--tilt, 0deg);
  width: max-content; /* its anchor has no size, so it must not shrink to it */
  display: grid; justify-items: center;
  padding: 0;
  border-radius: calc(var(--ph) * .14);
  pointer-events: auto;
  cursor: pointer;
  transition: padding .45s var(--ease), border-radius .45s var(--ease), translate .45s var(--ease), rotate .45s var(--ease), background-color .3s ease, box-shadow .3s ease;
}
.cover-art {
  position: relative;
  width: var(--ph); height: var(--ph);
  border-radius: calc(var(--ph) * .12);
  overflow: hidden;
  background: #111116;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18), 0 14px 34px -10px #000, 0 12px 40px -14px var(--hue, var(--sky));
  transition: width .45s var(--ease), height .45s var(--ease), border-radius .45s var(--ease), filter .3s ease, opacity .3s ease;
}
.cover-art img { width: 100%; height: 100%; object-fit: cover; }
/* light catching the sleeve, moving with the cursor */
.cover-art::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(calc(125deg + var(--mx) * 25deg), rgba(255, 255, 255, .24), rgba(255, 255, 255, 0) 45%);
}
.cover:focus-visible .cover-shell { outline: 2px solid #fff; outline-offset: 3px; }

/* the card's text: folded away until it opens */
.cover-more {
  display: grid;
  grid-template-rows: 0fr; grid-template-columns: 0fr;
  transition: grid-template-rows .45s var(--ease), grid-template-columns .45s var(--ease);
}
.cover-clip { min-width: 0; min-height: 0; overflow: hidden; }
.cover-body {
  width: 176px; padding-top: 12px;
  display: grid; justify-items: center; gap: 3px;
  text-align: center;
  opacity: 0;
  transition: opacity .2s ease;
}
.cover-title { font-family: var(--font-display); font-weight: 700; font-size: .98rem; line-height: 1.15; overflow-wrap: anywhere; }
.cover-artist { color: #b9c4d6; font-size: .78rem; line-height: 1.35; }
.cover-body .pod-link { margin-top: 9px; }

.cover.is-open .cover-shell {
  padding: 14px 14px 16px;
  border-radius: 24px;
  rotate: 0deg;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, .03) 44%, rgba(255, 255, 255, .08)),
    rgba(14, 18, 30, .6);
  -webkit-backdrop-filter: blur(16px) saturate(1.5) brightness(1.15);
          backdrop-filter: blur(16px) saturate(1.5) brightness(1.15);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .5), inset 0 0 0 1px rgba(255, 255, 255, .12), 0 26px 54px -16px #000, 0 0 50px -16px var(--sky);
}
.cover.is-open .cover-art { width: 148px; height: 148px; border-radius: 14px; }
.cover.is-open .cover-more { grid-template-rows: 1fr; grid-template-columns: 1fr; }
.cover.is-open .cover-body { opacity: 1; transition: opacity .3s ease .15s; }

/* a spot without a release yet, or a release without its cover: a blue sleeve with the S.
   The empty spots do nothing; a release without its cover still opens into its card. */
.cover.is-empty .cover-shell { pointer-events: none; cursor: default; }
.cover:is(.is-empty, .no-art) .cover-art {
  background:
    url("../assets/spectrum-mark.webp") center / auto 46% no-repeat,
    radial-gradient(circle at 30% 18%, color-mix(in srgb, var(--hue) 50%, #fff), var(--hue) 42%, color-mix(in srgb, var(--hue) 35%, #000) 100%);
}

/* phones: around the logo and between the cards */
.home-covers .cover:nth-child(1)  { left: 15%; top: 42%; --ph: 46px; --d: 1.2; --tilt: -6deg; }
.home-covers .cover:nth-child(2)  { left: 85%; top: 40%; --ph: 46px; --d: 1.1; --tilt: 5deg; }
.home-covers .cover:nth-child(3)  { left: 50%; top: 31%; --ph: 36px; --d: .9;  --tilt: 3deg; }
.home-covers .cover:nth-child(4)  { left: 12%; top: 30%; --ph: 28px; --d: .5;  --tilt: -8deg; }
.home-covers .cover:nth-child(5)  { left: 88%; top: 31%; --ph: 32px; --d: .7;  --tilt: 7deg; }
.home-covers .cover:nth-child(6)  { left: 50%; top: 82%; --ph: 40px; --d: 1;   --tilt: -4deg; }
.home-covers .cover:nth-child(7)  { left: 9%;  top: 71%; --ph: 32px; --d: .8;  --tilt: 6deg; }
.home-covers .cover:nth-child(8)  { left: 91%; top: 71%; --ph: 28px; --d: .5;  --tilt: -6deg; }
.home-covers .cover:nth-child(9)  { left: 32%; top: 74%; --ph: 28px; --d: .6;  --tilt: 5deg; }
.home-covers .cover:nth-child(10) { left: 68%; top: 75%; --ph: 28px; --d: .5;  --tilt: -5deg; }
/* the smallest, furthest ones are a little out of focus */
.home-covers .cover:is(:nth-child(4), :nth-child(8), :nth-child(10)) .cover-art { filter: blur(1.2px); opacity: .62; }
.home-covers .cover:is(:nth-child(4), :nth-child(8), :nth-child(10)).is-open .cover-art { filter: none; opacity: 1; }

/* ---------- link pill (the Spotify button on the roster) ---------- */

.pod-link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .16);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), inset 0 0 0 1px rgba(255, 255, 255, .12);
  color: #fff;
  font-weight: 600; font-size: .8rem;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease, color .18s ease;
}
.pod-link:hover, .pod-link:focus-visible { background: #fff; color: #000; }

/* ---------- scroll: home → roster → about → footer ----------
   One continuous position. spectrum.js eases it toward wherever you scroll (wheel, touch, keys)
   and writes it as --p1 (home → roster), --pr (along the roster, in artists: 0 is the first),
   --pa (roster → about) and --p2 (about → footer). Without a roster, --p1 and --pa move together.
   Every layer moves by them at its own speed, so the scene has depth, and everything holds still
   wherever you stop. What cannot be seen is hidden, so it is not drawn. */

.lite .env { translate: 0 calc(var(--p1) * -8vh); scale: calc(1 + var(--p1) * .18); } /* desktop moves the chrome field in the shader instead */

.page { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.page.is-current > * { pointer-events: auto; }
.home-gone .home-items, .pages-off .bg-pages, .roster-off .page-roster,
.about-off .page-about, .footer-off .page-footer { visibility: hidden; }

/* behind the roster and about: a dark veil with soft blue lights. The lights drift sideways
   with the roster and up towards about, slower than the pages (parallax). */
.bg-pages {
  position: fixed; inset: 0; z-index: 1;
  overflow: hidden;
  background: rgba(0, 0, 0, .5);
  opacity: calc(var(--p1) - var(--p2) * .4);
  pointer-events: none;
}
.glow {
  position: absolute;
  width: 62vmax; height: 62vmax;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--c) 52%, transparent), transparent);
  translate:
    calc(var(--pr) * var(--s) * -6vw * var(--px))
    calc(((1 - var(--p1)) * 50vh - var(--pa) * 24vh) * var(--s) * var(--px));
  animation: drift var(--t) ease-in-out infinite alternate;
}
.g1 { --c: var(--blue); --s: .4; --t: 14s; left: -24vmax; top: -26vmax; }
.g2 { --c: var(--sky);  --s: .7; --t: 17s; right: -26vmax; top: -6vmax; width: 50vmax; height: 50vmax; }
.g3 { --c: #3fd0ff;     --s: 1;  --t: 19s; left: -18vmax; bottom: -30vmax; }
.g4 { --c: var(--deep); --s: 1.3; --t: 15s; right: -16vmax; bottom: -32vmax; width: 66vmax; height: 66vmax; }
@keyframes drift { to { transform: translate(6vmax, -4vmax) scale(1.12); } }

/* ---------- roster: one artist at a time ----------
   The page rises in from below like the others, then holds while scrolling moves you sideways
   through the artists: each one comes in from the right and leaves to the left. Every artist is
   three layers moving at their own speeds: the name written huge in outline far behind (slowest),
   the photo, and the name with the Spotify button in front (fastest). --dd is how far an artist
   is from the middle, in artists (1 = the next one, 0 = in view, -1 = gone by), --ad the same
   either way. After the last one, the page moves up and away as about comes in. */

.page-roster {
  overflow: hidden;
  translate: 0 calc((1 - var(--p1)) * 100vh - var(--pa) * 60vh * var(--px));
  opacity: calc(1 - var(--pa) * 1.3);
}
.roster-head {
  position: absolute; left: 0; right: 0; top: calc(78px + env(safe-area-inset-top, 0px));
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.5rem; letter-spacing: -.03em; text-transform: lowercase; text-align: center;
  text-shadow: 0 0 22px rgba(255, 255, 255, .3), 0 0 50px rgba(72, 180, 255, .45);
  /* a small drift to the left over the whole roster, however many artists */
  translate: calc(var(--pr) / var(--rn) * -2vw * var(--px)) calc((1 - var(--p1)) * 12vh * var(--px));
}
.roster-head:focus { outline: none; }

.roster-track { position: absolute; inset: 0; }
.slide {
  --dd: calc(var(--k) - var(--pr));
  --ad: max(var(--dd), calc(var(--dd) * -1));
  position: absolute; inset: 0;
  pointer-events: none;
}
.slide a { pointer-events: auto; }

/* far behind: the name in outline, slowest. Sized to its length (--len, in letters) so a long name
   still fits across the screen, and they cross-fade instead of passing each other: each one is gone
   before the next one shows (never two at once). */
.slide-ghost {
  position: absolute; left: 50%; top: 42%;
  font-family: var(--font-display); font-weight: 700;
  font-size: min(26vw, calc(120vw / var(--len, 6))); line-height: 1; letter-spacing: -.04em; white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(72, 180, 255, .3);
  translate: calc(-50% + var(--dd) * (100vw - 70vw * var(--px))) -50%;
  opacity: clamp(0, 1 - var(--ad) * 2.8, 1);
}
/* the photo */
.slide-photo {
  position: absolute; left: 50%; top: 42%;
  width: min(68vw, 42svh); aspect-ratio: 4 / 5;
  display: grid; place-items: center;
  border-radius: 24px;
  overflow: hidden;
  background: radial-gradient(circle at 50% 22%, color-mix(in srgb, var(--hue) 45%, #fff), var(--hue) 42%, color-mix(in srgb, var(--hue) 30%, #000) 100%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .2), 0 40px 80px -30px #000, 0 30px 90px -30px var(--hue);
  translate: calc(-50% + var(--dd) * (100vw - 30vw * var(--px))) -50%;
  rotate: calc(var(--dd) * 8deg * var(--px));
  scale: calc(1 - var(--ad) * .14 * var(--px));
  opacity: calc(1.25 - var(--ad));
}
.slide-photo img { width: 100%; height: 100%; object-fit: cover; }
.slide-initials {
  font-family: var(--font-display); font-weight: 700; font-size: 4rem; letter-spacing: -.03em;
  color: #fff; text-shadow: 0 6px 30px rgba(0, 0, 0, .35);
}
/* light catching the photo, moving with the cursor */
.slide-photo::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(calc(125deg + var(--mx) * 25deg), rgba(255, 255, 255, .18), rgba(255, 255, 255, 0) 40%);
}
/* in front: the name and the Spotify button, fastest */
.slide-info {
  position: absolute; left: 50%; top: calc(42% + min(68vw, 42svh) * .625 + 22px);
  width: 88vw;
  display: grid; justify-items: center; gap: 12px;
  text-align: center;
  translate: calc(-50% + var(--dd) * (100vw + 25vw * var(--px))) 0;
  opacity: calc(1 - var(--ad) * 1.6);
}
.slide-no { color: var(--sky); font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .72rem; letter-spacing: .14em; }
.slide-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.9rem, 9vw, 2.6rem); line-height: .98; letter-spacing: -.035em;
  overflow-wrap: anywhere;
  text-shadow: 0 0 26px rgba(255, 255, 255, .3);
}
.slide-info .slide-no { display: none; } /* phones: the count at the bottom says it */

/* where you are: 03 / 10 and a bar that fills as you go */
.roster-foot {
  position: absolute; left: 6%; right: 6%; bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 16px;
  opacity: var(--p1);
}
.roster-count { color: #8d97a8; font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .72rem; letter-spacing: .12em; white-space: nowrap; }
.roster-count b { color: #fff; font-weight: 600; }
.roster-bar { flex: 1; height: 2px; border-radius: 2px; background: rgba(255, 255, 255, .14); overflow: hidden; }
.roster-bar i {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--deep), var(--sky), var(--ice));
  transform-origin: 0 50%;
  scale: calc((var(--pr) + 1) / var(--rn, 1)) 1;
}

/* ---------- about: what we do ----------
   The two services on glass cards that each glow in their own two blues. They rise in with the
   scroll (--pa) from further down, slightly turned, one after the other. With the footer up,
   they drift up and dim. */

.page-about {
  --out: calc(1 - var(--p2) * .75); /* dims as the footer comes up */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: calc(64px + env(safe-area-inset-top, 0px)) 6% calc(20px + env(safe-area-inset-bottom, 0px));
  translate: 0 calc((1 - var(--pa)) * 100vh - var(--p2) * 16vh * var(--px));
}
.page-about > * { width: min(100%, 1180px); }

/* "what we do": comes in first, ahead of the cards */
.about-head {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2rem, 9vw, 2.6rem); line-height: 1; letter-spacing: -.035em;
  text-transform: lowercase; text-align: center;
  color: #fff;
  text-shadow: 0 0 26px rgba(255, 255, 255, .35), 0 0 60px rgba(72, 180, 255, .45);
  translate: 0 calc((1 - var(--pa)) * 6vh * var(--px));
  opacity: calc(clamp(0, var(--pa) * 2.2 - .5, 1) * var(--out));
}
.about-head:focus { outline: none; }

.services { display: grid; gap: 14px; margin-top: 3svh; }
.service {
  position: relative; isolation: isolate; overflow: hidden;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "no name" "info info" "tags tags";
  align-items: center; column-gap: 12px;
  padding: 16px 16px 16px 18px;
  border-radius: 22px;
  background:
    linear-gradient(140deg, color-mix(in srgb, var(--c1) 30%, transparent), color-mix(in srgb, var(--c2) 12%, transparent) 55%, rgba(255, 255, 255, .02)),
    rgba(12, 12, 16, .55);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), inset 0 0 0 1px rgba(255, 255, 255, .1), 0 28px 70px -28px var(--c1), 0 10px 30px -14px #000;
  translate: 0 calc((1 - var(--pa)) * (16vh + var(--i) * 14vh) * var(--px));
  rotate: calc((1 - var(--pa)) * var(--tilt, 0deg) * var(--px));
  opacity: calc(clamp(0, var(--pa) * 2.4 - .7 - var(--i) * .3, 1) * var(--out));
  transition: scale .45s var(--ease), box-shadow .4s ease;
}
/* a light in the card's second colour, coming in from the top right corner */
.service::after {
  content: ""; position: absolute; z-index: -1;
  right: -28%; top: -70%; width: 75%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--c2) 42%, transparent), transparent);
  pointer-events: none;
}
.svc-no {
  grid-area: no;
  color: var(--c1);
  font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .7rem; letter-spacing: .1em;
}
.svc-name {
  grid-area: name;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.5rem, 7vw, 1.9rem); line-height: 1.05; letter-spacing: -.03em;
  text-transform: lowercase;
  color: #fff;
}
/* the full stop, in the card's colours */
.svc-name i {
  font-style: normal;
  background: linear-gradient(135deg, var(--c1), var(--c2)); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.svc-info { grid-area: info; padding-top: 6px; }
.svc-title { color: #fff; font-weight: 600; font-size: .9rem; }
.svc-lead { margin-top: 2px; color: #c6c6cd; font-size: .84rem; }
.svc-more { display: none; } /* phones: the short version */
.svc-tags { grid-area: tags; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.svc-tags li {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px 5px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .13);
  color: #ececf0; font-size: .7rem; letter-spacing: .03em;
}
.svc-tags li::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: linear-gradient(135deg, var(--c1), var(--c2));
  box-shadow: 0 0 8px var(--c1);
}
/* under the cards: one way to get in touch, with a blue arrow that keeps nudging down to the footer */
.page-about > .about-cta { width: auto; }
.about-cta {
  display: inline-flex; align-items: center; gap: 12px;
  margin-top: 3.4svh;
  color: #fff; text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; letter-spacing: -.01em;
  text-shadow: 0 0 18px rgba(255, 255, 255, .25);
  translate: 0 calc((1 - var(--pa)) * 40vh * var(--px));
  opacity: calc(clamp(0, var(--pa) * 2.4 - 1.2, 1) * var(--out));
  transition: text-shadow .3s ease;
}
.about-cta-arrow {
  display: inline-block;
  background: var(--blue-text); -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: none;
  animation: nudge 1.6s ease-in-out infinite;
}
@keyframes nudge { 50% { translate: 0 5px; } }
.about-cta:hover, .about-cta:focus-visible { text-shadow: 0 0 22px rgba(72, 180, 255, .85); }
.about-cta:hover .about-cta-arrow, .about-cta:focus-visible .about-cta-arrow { animation-duration: .7s; }

/* ---------- dots: where you are ---------- */

.pager {
  position: fixed; z-index: 4;
  right: 10px; top: 50%; translate: 0 -50%;
  display: grid; gap: 12px;
}
.pager button {
  position: relative;
  width: 6px; height: 6px; padding: 0;
  border: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .3);
  cursor: pointer;
  transition: height .45s var(--ease), background-color .3s ease;
}
.pager button::before { content: ""; position: absolute; inset: -8px -10px; } /* bigger target */
.pager button[aria-current="true"] { height: 22px; background: #fff; }
.pager span {
  position: absolute; right: 18px; top: 50%; translate: 6px -50%;
  color: #fff; font-size: .7rem; white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity .25s ease, translate .25s ease;
}
@media (hover: hover) {
  .pager button:hover span, .pager button:focus-visible span { opacity: 1; translate: 0 -50%; }
}

@media (min-width: 900px) {
  .page-about { padding-top: calc(74px + env(safe-area-inset-top, 0px)); }
  .about-head { font-size: clamp(2.6rem, 4.6vw, 4.4rem); }
  .services { grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 4.5svh; }
  .service {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "no" "name" "info" "tags";
    align-items: start;
    padding: 34px 36px 32px 38px;
    border-radius: 30px;
  }
  .svc-no { font-size: .78rem; }
  .svc-name { margin-top: 2svh; font-size: clamp(2.4rem, 4vw, 4rem); }
  .svc-info { padding-top: 1.4svh; }
  .svc-title { font-size: 1.08rem; }
  .svc-lead { font-size: 1rem; }
  .svc-more { display: block; max-width: 48ch; margin-top: 12px; color: #b2b2ba; font-size: .94rem; line-height: 1.6; }
  .svc-tags { margin-top: 3.4svh; }
  .svc-tags li { font-size: .74rem; }
  .about-cta { margin-top: 4.5svh; font-size: 1.5rem; gap: 14px; }
  @media (hover: hover) {
    .service:hover { scale: 1.015; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), inset 0 0 0 1px rgba(255, 255, 255, .16), 0 34px 90px -26px var(--c1), 0 10px 30px -14px #000; }
  }
  .pager { display: none; } /* the top bar has the links on desktop */
}

/* ---------- footer: the last stop, it slides up over about ----------
   A row of round glass buttons, one per channel (Instagram, Spotify, email, WhatsApp), each lighting
   up blue on hover; the company's details in small print under them; and the text mark, as wide
   as the footer, rising in last and cut by the bottom edge. */

.page.page-footer {
  top: auto; height: min(50svh, 440px);
  z-index: 3;
  display: grid; grid-template-rows: auto auto 1fr;
  padding: 28px 6% 0;
  overflow: hidden;
  border-radius: 28px 28px 0 0;
  background: linear-gradient(180deg, #121215, #050506 55%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 -30px 80px -20px #000;
  translate: 0 calc((1 - var(--p2)) * 104%);
}
.footer-top { display: grid; justify-items: center; gap: 16px; }
.footer-label { color: #8d97a8; font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .62rem; letter-spacing: .26em; text-transform: uppercase; }
.socials { display: flex; justify-content: center; gap: 16px; }
.social {
  display: grid; justify-items: center; gap: 8px;
  color: #9aa4b5; text-decoration: none;
  font-size: .68rem; letter-spacing: .06em;
  transition: color .2s ease;
}
.social-icon {
  display: grid; place-items: center;
  width: 58px; height: 58px;
  border-radius: 50%;
  color: #fff;
  background: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .03));
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .4), inset 0 0 0 1px rgba(255, 255, 255, .12), 0 14px 30px -14px #000;
  transition: translate .35s var(--ease), background-color .3s ease, box-shadow .3s ease;
}
.social-icon svg { width: 24px; height: 24px; }
.social:is(:hover, :focus-visible) { color: #fff; }
.social:is(:hover, :focus-visible) .social-icon {
  translate: 0 -4px;
  background-color: var(--blue);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .5), inset 0 0 0 1px rgba(255, 255, 255, .2), 0 14px 34px -8px var(--sky);
}
.social:focus-visible { outline: none; }
.social:focus-visible .social-icon { outline: 2px solid #fff; outline-offset: 3px; }
.footer-copy { margin-top: 22px; color: #6f7a8c; font-size: .66rem; letter-spacing: .04em; text-align: center; }
/* the text mark, as wide as the footer, rising in last and cut by the bottom edge */
.footer-word {
  align-self: end;
  width: 100%;
  translate: 0 calc(16% + (1 - var(--p2)) * 60% * var(--px));
}

/* ---------- opening animation ----------
   0.10s  a blade of light is drawn across the black
   0.45s  the S comes at the screen out of the blur
   0.87s  impact: flash, shockwave, shake. The shockwave is also in the shader
          and is what reveals the chrome environment behind it (T_HIT in spectrum.js)
   1.0s+  wordmark cuts in, tagline settles, the covers punch in one by one */

.intro-pending .stage, .intro-pending .pager, .intro-pending .topbar { visibility: hidden; }

.intro { position: fixed; inset: 0; z-index: 3; overflow: hidden; pointer-events: none; }
.intro > * { position: absolute; left: var(--hit-x); top: var(--hit-y); opacity: 0; }

.intro-blade {
  width: 160vmax; height: 2px; margin: -1px 0 0 -80vmax;
  background: linear-gradient(90deg, transparent, #fff 18%, #fff 82%, transparent);
  box-shadow: 0 0 20px 2px rgba(255, 255, 255, .85);
}
.intro-flash {
  width: 170vmax; height: 170vmax; margin: -85vmax 0 0 -85vmax;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0, rgba(255, 255, 255, .55) 10%, rgba(255, 255, 255, 0) 52%);
}
.intro-ring {
  width: 28vmin; height: 28vmin; margin: -14vmin 0 0 -14vmin;
  border: 2px solid #fff; border-radius: 50%;
  box-shadow: 0 0 26px rgba(255, 255, 255, .75), inset 0 0 26px rgba(255, 255, 255, .45);
}

.intro-run .intro-blade { animation: blade .99s linear .1s both; }
.intro-run .intro-flash { animation: flash .65s ease-out .85s both; }
.intro-run .intro-ring  { animation: ring .95s cubic-bezier(.1, .7, .2, 1) .87s forwards; }
.intro-run .stage, .intro-run .env { animation: shake .5s linear .87s; }
.intro-run .hero-mark { animation: slam .62s linear .45s backwards; }
.intro-run .hero-ghost { animation: ghost .85s cubic-bezier(.1, .7, .2, 1) .87s forwards; }
.intro-run .hero-ghost + .hero-ghost { animation-delay: .97s; animation-duration: .7s; }
.intro-run .ht-line { animation: word-in .7s cubic-bezier(.16, 1, .3, 1) 1s backwards; }
.intro-run .ht-line + .ht-line { animation-delay: 1.12s; }
.intro-run .hero-sub { animation: tag-in .9s cubic-bezier(.16, 1, .3, 1) 1.3s backwards; }
.intro-run .home-ring { animation: ring-in 1.6s var(--ease) .87s backwards; } /* opens out with the shockwave */
.intro-run .home-dots { animation: fade-in 1.4s ease 1s backwards; }
.intro-run .topbar { animation: fade-in 1s ease 1.6s backwards; }
.intro-run .scroll-cue { animation: rise-in .8s cubic-bezier(.16, 1, .3, 1) 1.55s backwards; }
.intro-run .pager { animation: fade-in 1s ease 2.2s backwards; }
/* everything else punches in from a point, one after another (--in) */
.intro-run .float:not(.hero) {
  animation:
    bob var(--t, 8s) ease-in-out var(--delay, 0s) infinite alternate,
    punch-in .8s cubic-bezier(.2, 1.35, .3, 1) var(--in, 1.3s) backwards;
}

@keyframes blade {
  0%   { opacity: 1; transform: scaleX(0); animation-timing-function: cubic-bezier(.16, 1, .3, 1); }
  35%  { opacity: 1; transform: scaleX(1); }
  78%  { opacity: 1; transform: scaleX(1) scaleY(1); animation-timing-function: ease-out; }
  100% { opacity: 0; transform: scaleX(1.1) scaleY(70); }
}
@keyframes flash {
  0%   { opacity: 0; transform: scale(.3); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.2); }
}
@keyframes ring {
  from { opacity: 1; transform: scale(.2); }
  to   { opacity: 0; transform: scale(9); }
}
@keyframes shake {
  0%, 100% { transform: translate3d(0, 0, 0); }
  10% { transform: translate3d(-16px, 10px, 0); }
  22% { transform: translate3d(13px, -9px, 0); }
  34% { transform: translate3d(-10px, 6px, 0); }
  46% { transform: translate3d(8px, -5px, 0); }
  60% { transform: translate3d(-5px, 3px, 0); }
  74% { transform: translate3d(3px, -2px, 0); }
  88% { transform: translate3d(-1px, 1px, 0); }
}
@keyframes slam {
  0% {
    opacity: 0; transform: scale(3.8);
    filter: blur(22px) brightness(2.6) drop-shadow(0 24px 40px rgba(0, 0, 0, 0));
    animation-timing-function: cubic-bezier(.7, 0, 1, .45);
  }
  68% {
    opacity: 1; transform: scale(.9);
    filter: blur(0) brightness(2) drop-shadow(0 24px 40px rgba(0, 0, 0, .7));
    animation-timing-function: ease-out;
  }
  84% { transform: scale(1.05); }
  100% {
    opacity: 1; transform: scale(1);
    filter: blur(0) brightness(1) drop-shadow(0 24px 40px rgba(0, 0, 0, .7));
  }
}
@keyframes ghost {
  from { opacity: .8; transform: scale(1); }
  to   { opacity: 0; transform: scale(2.4); }
}
@keyframes word-in {
  from { clip-path: inset(0 100% 0 0); transform: translateX(-34px) skewX(-16deg); filter: brightness(3); }
  to   { clip-path: inset(0 -3% 0 0); transform: none; filter: brightness(1); }
}
@keyframes tag-in { from { opacity: 0; letter-spacing: .7em; } }
@keyframes rise-in { from { opacity: 0; transform: translateY(14px); } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes ring-in { from { opacity: 0; scale: .55; } }
@keyframes punch-in { from { scale: 0; } }

/* ---------- short phones ---------- */

@media (max-height: 720px) and (max-width: 899px) {
  .hero-mark { height: 11svh; }
  .hero-title { font-size: 2.4rem; }
  .result { padding: 9px 12px 10px; min-width: 118px; }
  .result-num { font-size: 1.35rem; }
  .page.page-footer { height: 60svh; }
}

/* ---------- desktop ---------- */

@media (min-width: 900px) {
  .float { translate: calc(var(--mx) * var(--d) * -46px) calc(var(--my) * var(--d) * -32px + var(--lift)); }
  @keyframes bob {
    from { transform: translateY(-10px) rotate(-.9deg); }
    to   { transform: translateY(10px) rotate(.9deg); }
  }

  .topbar { padding: 18px 4% 18px; }
  .tb-logo img { width: 132px; }
  .tb-links { display: flex; gap: 34px; position: absolute; left: 50%; translate: -50% 0; }
  .tb-links button { position: relative; color: #b9b9bf; font-size: .86rem; text-transform: lowercase; transition: color .2s ease; }
  .tb-links button:hover, .tb-links button[aria-current="true"] { color: #fff; }
  .tb-links button[aria-current="true"]::after { /* a small blue dot under the current page */
    content: ""; position: absolute; left: 50%; bottom: -10px;
    width: 4px; height: 4px; margin-left: -2px; border-radius: 50%;
    background: var(--sky);
    box-shadow: 0 0 6px rgba(72, 180, 255, .9);
  }
  .tb-cta { padding: 11px 22px; font-size: .8rem; }

  .home-ring { width: min(112vh, 92vw); }
  .hero { padding-top: 3svh; }
  .hero-mark { height: 15svh; }
  .hero-title { font-size: clamp(3rem, 6.4vw, 6.6rem); }
  .hero-sub { font-size: .84rem; }

  .result { min-width: 190px; padding: 16px 20px 17px; border-radius: 18px; }
  .result-num { font-size: 2.6rem; }
  .result-label { font-size: .72rem; }
  .result-song { font-size: .8rem; }
  .result-cover { width: 32px; height: 32px; }
  .r1 { left: 10%; top: 24%; bottom: auto; }
  .r2 { left: auto; right: 10%; top: 21%; }
  .r3 { right: auto; left: 8%; top: 66%; }
  .r4 { right: 8%; top: 64%; bottom: auto; }
  .r5 { display: grid; left: 27%; top: 86%; }
  .lbl-long { display: inline; }
  .lbl-short { display: none; }

  /* where the covers float: around the headline and between the cards */
  .home-covers .cover:nth-child(1)  { left: 20%; top: 52%; --ph: 66px; --d: 1.2; }
  .home-covers .cover:nth-child(2)  { left: 80%; top: 51%; --ph: 62px; --d: 1.1; }
  .home-covers .cover:nth-child(3)  { left: 33%; top: 17%; --ph: 50px; --d: .9; }
  .home-covers .cover:nth-child(4)  { left: 63%; top: 15%; --ph: 36px; --d: .45; }
  .home-covers .cover:nth-child(5)  { left: 93%; top: 47%; --ph: 44px; --d: .7; }
  .home-covers .cover:nth-child(6)  { left: 59%; top: 87%; --ph: 54px; --d: 1; }
  .home-covers .cover:nth-child(7)  { left: 6%;  top: 50%; --ph: 40px; --d: .65; }
  .home-covers .cover:nth-child(8)  { left: 71%; top: 91%; --ph: 34px; --d: .45; }
  .home-covers .cover:nth-child(9)  { left: 16%; top: 92%; --ph: 42px; --d: .8; }
  .home-covers .cover:nth-child(10) { left: 87%; top: 88%; --ph: 32px; --d: .4; }

  /* the roster: the photo left of the middle, the name beside it */
  .roster-head { left: 4%; right: auto; top: calc(88px + env(safe-area-inset-top, 0px)); font-size: 2.4rem; text-align: left; }
  .slide-ghost { top: 52%; font-size: min(19vw, calc(120vw / var(--len, 6))); }
  .slide-photo { left: 33%; top: 52%; width: min(30vw, 46svh); border-radius: 30px; }
  .slide-initials { font-size: 6rem; }
  .slide-info {
    left: 52%; top: 52%; width: 42vw;
    justify-items: start; gap: 16px; text-align: left;
    translate: calc(var(--dd) * (100vw + 25vw * var(--px))) -50%;
  }
  .slide-info .slide-no { display: block; }
  .slide-name { font-size: clamp(3rem, 6.4vw, 6.4rem); }
  .roster-foot { left: 4%; right: 4%; bottom: 30px; }

  .pod-link { font-size: .84rem; }

  .page.page-footer { height: min(58svh, 520px); padding: 40px 5% 0; }
  .footer-top { gap: 22px; }
  .socials { gap: 28px; }
  .social-icon { width: 72px; height: 72px; }
  .social-icon svg { width: 28px; height: 28px; }
  .social { font-size: .74rem; }
  .footer-copy { font-size: .72rem; }
}

/* ---------- lite: phones and touch tablets ----------
   Same layout, opening and scroll, but nothing that has to be redrawn every frame:
   no cursor parallax, no bobbing, no drifting lights. Only the logo keeps
   a slow drift, which the GPU moves as one finished layer. */

.lite .float { translate: 0 var(--lift); animation: none; will-change: auto; }
.lite .hero.float { animation: bob var(--t, 8s) ease-in-out var(--delay, 0s) infinite alternate; will-change: transform; }
.lite .home-ring i, .lite .glow { animation: none; }
.lite .hero-lockup { transform: none; }

.lite.intro-run .float:not(.hero) { animation: punch-in .7s cubic-bezier(.2, 1.35, .3, 1) var(--in, 1.3s) backwards; }
.lite.intro-run .hero-mark { animation-name: slam-lite; }
@keyframes slam-lite {
  0%   { opacity: 0; transform: scale(3.4); animation-timing-function: cubic-bezier(.7, 0, 1, .45); }
  68%  { opacity: 1; transform: scale(.92); animation-timing-function: ease-out; }
  84%  { transform: scale(1.04); }
  100% { opacity: 1; transform: scale(1); }
}

/* ---------- reduced motion: a still scene, no opening ----------
   Scrolling still moves the pages, but as one piece: no layers at their own speeds. */

@media (prefers-reduced-motion: reduce) {
  :root { --px: 0; }
  *, *::before, *::after {
    animation: none !important;
    transition-duration: .001s !important;
  }
  .float { translate: 0 var(--lift); }
  .hero-lockup { transform: none; }
}
