/* lytti.app — landing page styles (from "Lytti Landing v2" design)
   Design system: web/DESIGN.md. Mono UI on warm near-black; the only color
   on the page comes from the records. Display face: Schibsted Grotesk;
   player chrome deliberately stays on the system/SF stack (iOS mimicry). */

:root {
  /* ink on warm near-black (amp-glow, not blue) */
  --bg: oklch(0.16 0.004 84);
  --fg: oklch(0.97 0 0);
  --fg-muted: rgba(255, 255, 255, 0.68);  /* readable secondary text */
  --fg-faint: rgba(255, 255, 255, 0.55);  /* furniture, dim lines (AA at any size) */
  --fg-ghost: rgba(255, 255, 255, 0.38);  /* decorative only, large or aria-hidden */
  --line: rgba(255, 255, 255, 0.10);
  --line-strong: rgba(255, 255, 255, 0.22);

  --font-display: "Schibsted Grotesk", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  --font-ui: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", sans-serif;

  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --t-fast: 140ms;
}

* { box-sizing: border-box; }

html { scroll-padding-bottom: 130px; } /* keep focused elements above the mini player */

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-ui);
  overflow-x: hidden;
}

a { color: var(--fg); }
a:hover { text-decoration-thickness: 2px; }

button {
  font-family: inherit;
  border: none;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.9);
  outline-offset: 3px;
}

@keyframes lyr {
  from { opacity: 0.18; transform: translateY(10px); filter: blur(1px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@keyframes drift {
  0%, 100% { transform: rotate(2deg) translateY(0); }
  50%      { transform: rotate(2deg) translateY(-12px); }
}

.page { position: relative; }

/* ---------- Mini player ---------- */

.mini-player {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  width: min(640px, calc(100vw - 32px));
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 9px;
  background: linear-gradient(175deg, rgba(70,62,86,0.38), rgba(24,20,32,0.42) 45%, rgba(40,34,54,0.34));
  backdrop-filter: blur(36px) saturate(1.9);
  -webkit-backdrop-filter: blur(36px) saturate(1.9);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 26px;
  padding: 12px 16px 14px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.28), inset 0 -1px 1px rgba(255,255,255,0.05), inset 1px 0 0 rgba(255,255,255,0.08), inset -1px 0 0 rgba(255,255,255,0.08);
}
.mini-player::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 26px;
  /* `rgba(255,255,255,0)`, not `transparent`: the keyword is transparent *black*, so the fade runs
     toward black as well as toward nothing and WebKit shows it as a grey cast. */
  background: radial-gradient(ellipse 60% 45% at 22% 0%, rgba(255,255,255,0.14), rgba(255,255,255,0) 60%);
  pointer-events: none;
}
.mini-player__row { display: flex; align-items: center; gap: 14px; }
.mini-player__icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
}
.mini-player__meta { flex: 1; line-height: 1.25; min-width: 0; }
.mini-player__title, .mini-player__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-player__title { font-size: 14px; font-weight: 700; }
.mini-player__sub { font-size: 12px; color: var(--fg-muted); }
.mini-player__soon {
  border: 1px solid var(--line-strong);
  color: var(--fg-muted);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.mini-player__progress { display: flex; align-items: center; gap: 10px; }
.mini-player__time {
  font-size: 10px;
  color: var(--fg-ghost);
  font-variant-numeric: tabular-nums;
}
.mini-player__bar {
  flex: 1;
  height: 3px;
  background: rgba(255,255,255,0.14);
  border-radius: 2px;
  overflow: visible;
  position: relative;
}
.mini-player__fill {
  height: 100%;
  width: 0%;
  background: #fff;
  border-radius: 2px;
  position: relative;
}
.mini-player__knob {
  position: absolute;
  right: -4px;
  top: 50%;
  width: 9px;
  height: 9px;
  background: #fff;
  border-radius: 50%;
  transform: translateY(-50%);
}

/* ---------- Layout ---------- */

.wrap {
  position: relative;
  max-width: 1060px;
  margin: 0 auto;
  padding: 0 28px 160px;
}

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 0;
}
.site-header__brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.site-header__brand:hover { color: var(--fg); }
.site-header__icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
}
.site-header__name { font-family: var(--font-display); font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
.site-header__tag { font-size: 13px; color: var(--fg-faint); }

/* ---------- Shared pieces ---------- */

.glow {
  position: absolute;
  object-fit: cover;
  border-radius: 50%;
  pointer-events: none;
  /* Safari clips `filter: blur()` to the element's own box instead of growing the filter region the
     way Chrome does. Every glow here is a heavy blur meant to bleed *outward*, so in Safari it ended
     as a hard-edged rectangle of blurred artwork sitting around the phone — reported on the lyrics
     verse, and the bigger the glow, the worse it looked.
     Masking the falloff into the element itself makes the difference moot: the edges are already
     transparent, so there is nothing for either engine to cut off visibly. Reproduced the Safari
     behaviour in Chrome with `clip-path: inset(0)` to verify this actually fixes it. */
  -webkit-mask-image: radial-gradient(closest-side, #000 30%, rgba(0, 0, 0, 0) 100%);
  mask-image: radial-gradient(closest-side, #000 30%, rgba(0, 0, 0, 0) 100%);
}

.phone {
  position: relative;
  background: linear-gradient(155deg, #1d1d23, #101014 60%); /* lit top edge, reads as metal */
  border-radius: 46px;
  padding: 10px;
  box-shadow:
    0 2px 6px rgba(0,0,0,0.55),           /* contact */
    0 14px 32px rgba(0,0,0,0.7),          /* key */
    0 40px 90px rgba(0,0,0,0.8),          /* ambient */
    0 0 44px rgba(255,255,255,0.07),      /* silhouette bloom — the actual separator on near-black */
    0 0 0 1px rgba(255,255,255,0.16),     /* bezel ring */
    inset 0 1px 0 rgba(255,255,255,0.10); /* rim light on top bezel */
}
.phone > img, .phone > video {
  display: block;
  width: 100%;
  border-radius: 37px;
}

.cta-button {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fff;
  color: #000;
  border-radius: 999px;
  padding: 15px 30px;
  font-size: 17px;
  font-weight: 700;
  transition: transform var(--t-fast) var(--ease-out);
}
.cta-button:hover { transform: scale(1.03); }
.cta-button--soon {
  background: transparent;
  color: var(--fg-muted);
  border: 1px solid var(--line-strong);
  cursor: default;
}
.cta-button--soon:hover { transform: none; }
.cta-caption { font-size: 13px; color: var(--fg-faint); }

.kicker {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin-bottom: 14px;
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 48px;
  align-items: center;
  padding: 72px 0 48px;
}
/* Diffused past the point of being a picture: at this radius the Currents artwork stops reading as a
   blurred screenshot and becomes a soft violet field. The saturation bump is what keeps it violet —
   blur averages colour toward grey, so heavier blur needs more saturation to hold the record's hue.
   Still content-sourced, which is the rule (DESIGN.md): the colour is the album's, not a UI accent. */
.hero__glow {
  top: -22%;
  right: -8%;
  width: 1150px;
  height: 1150px;
  filter: blur(200px) saturate(2.2);
  opacity: 0.8;
}
.hero__copy { position: relative; display: flex; flex-direction: column; gap: 10px; }
.hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(48px, 6.5vw, 74px);
  line-height: 1.02;
  letter-spacing: -0.025em;
  font-weight: 800;
  text-wrap: balance;
}
.hero__subtitle {
  margin-top: 14px;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fg-faint);
  line-height: 1.3;
  text-wrap: balance;
}
.hero__cta { display: flex; align-items: center; gap: 16px; margin-top: 30px; }
.hero__phone {
  position: relative;
  justify-self: center;
  width: 280px;
  box-shadow:
    0 2px 8px rgba(0,0,0,0.6),
    0 20px 44px rgba(0,0,0,0.75),
    0 55px 110px rgba(0,0,0,0.85),
    0 0 64px rgba(255,255,255,0.09), /* stronger bloom: no ground halo here, and it drifts */
    0 0 0 1px rgba(255,255,255,0.18),
    inset 0 1px 0 rgba(255,255,255,0.12);
  animation: drift 8s ease-in-out infinite;
}

/* ---------- Features track list ---------- */

.features { padding: 150px 0 0; }
.features__head, .roadmap__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 28px;
}
.features__title, .roadmap__title { margin: 0; font-family: var(--font-display); font-size: 40px; letter-spacing: -0.02em; font-weight: 800; }
.features__note, .roadmap__note { font-size: 13px; color: var(--fg-faint); }
.tracklist { display: flex; flex-direction: column; }
.track {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: baseline;
  gap: 16px;
  padding: 18px 14px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
}
.track:hover { background: rgba(255,255,255,0.05); }
.track__n {
  font-size: 15px;
  color: var(--fg-faint);
  font-variant-numeric: tabular-nums;
}
.track__name { line-height: 1.4; }
.track__title { font-size: 17px; font-weight: 600; }
.track__sub { font-size: 14px; color: var(--fg-muted); }
.track__len {
  font-size: 14px;
  color: var(--fg-faint);
  font-variant-numeric: tabular-nums;
}

/* ---------- Roadmap ---------- */

/* Tracklist rows, with two changes that between them stop this reading as a second copy of the
   features list further down the same page:
   1. Each entry carries a full sentence, not a half-line, so the description gets its own grid row
      spanning the full width. Squeezed into a middle column it wrapped to six lines at 390px, where
      that column is only ~185px wide.
   2. No marker column. The features list is numbered 1-6, the FAQ A1-A5 and the feedback 01-05, but
      a roadmap of three has nothing worth counting — the date on the right is what you scan by. */
.roadmap { padding: 150px 0 0; }
.roadmap .track { grid-template-columns: 1fr auto; padding: 22px 14px; row-gap: 0; }
.roadmap .track__title { grid-column: 1; grid-row: 1; }
.roadmap .track__len   { grid-column: 2; grid-row: 1; white-space: nowrap; }
.roadmap .track__sub   { grid-column: 1 / -1; grid-row: 2; }
.roadmap .track__sub {
  display: block;
  margin: 6px 0 0;
  max-width: 58ch;
  line-height: 1.5;
  text-wrap: pretty;
}
/* A roadmap is the one thing on this page that has not shipped, and the site's standing rule is that
   it carries only what has. This line is what buys the exception; do not drop it. */
.roadmap__hedge {
  margin: 22px 0 0;
  padding: 0 14px;
  font-size: 13px;
  color: var(--fg-faint);
}

/* ---------- Lyrics landscape hero ---------- */

.lyrics-hero { position: relative; padding: 170px 0 0; }
.lyrics-hero__glow {
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  width: 900px;
  height: 480px;
  filter: blur(130px) saturate(1.6);
  opacity: 0.4;
}
.lyrics-hero__phone {
  width: 70%;
  margin: 0 auto;
  border-radius: 44px;
  padding: 14px;
  box-shadow:
    0 3px 10px rgba(0,0,0,0.6),
    0 24px 55px rgba(0,0,0,0.75),
    0 70px 140px rgba(0,0,0,0.85),
    0 0 80px rgba(255,255,255,0.08),
    0 0 0 1px rgba(255,255,255,0.16),
    inset 0 1px 0 rgba(255,255,255,0.10);
  transform: rotate(-1.5deg);
}
.lyrics-hero__phone > video { border-radius: 32px; aspect-ratio: 1800 / 828; }

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

.verse {
  position: relative;
  display: grid;
  gap: 64px;
  align-items: center;
  padding: 170px 0 0;
}
.verse--lyrics { grid-template-columns: 1.15fr 1fr; padding-top: 130px; }
.verse--recs { grid-template-columns: 1fr 1fr; }
.verse--library { grid-template-columns: 1fr 1fr; }
.verse__copy { display: flex; flex-direction: column; gap: 8px; }
.verse__line {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.15;
}
.verse__line--dim { color: var(--fg-faint); }
.verse__p {
  margin: 22px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg-muted);
  max-width: 38ch;
  text-wrap: pretty;
}
.verse__art { position: relative; justify-self: center; }
.verse__art-glow {
  inset: -30px;
  width: calc(100% + 60px);
  height: calc(100% + 60px);
  filter: blur(100px) saturate(1.6);
  opacity: 0.4;
}
/* lit ground behind every verse phone, so its dark shadow has something to fall on */
.verse__art::before {
  content: "";
  position: absolute;
  inset: -50px;
  /* See the note on the header gradient: `transparent` is transparent black and greys the fade. */
  background: radial-gradient(ellipse at center, rgba(255,255,255,0.13), rgba(255,255,255,0) 72%);
  border-radius: 50%; /* elliptical paint area, so a mis-rendered fill can never read as a box */
  pointer-events: none;
}
.verse__phone--lyrics { width: 280px; transform: rotate(2deg); }
.verse__phone--lyrics > video { aspect-ratio: 1206 / 2622; }
.verse__phone--recs { width: 270px; border-radius: 44px; transform: rotate(-2deg); }
.verse__phone--recs > img { border-radius: 35px; }
.verse__phone--library { width: 270px; border-radius: 44px; transform: rotate(2deg); }
.verse__phone--library > video { border-radius: 35px; aspect-ratio: 1206 / 2622; }

@supports (animation-timeline: view()) {
  .verse__line--reveal {
    animation: lyr linear both;
    animation-timeline: view();
    animation-range: entry 60% cover 35%;
  }
  .verse__line--reveal.reveal-2 { animation-range: entry 65% cover 40%; }
  .verse__line--reveal.reveal-3 { animation-range: entry 70% cover 45%; }
}

/* ---------- FAQ (liner notes) ---------- */

.faq {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 72px;
  align-items: start;
  padding: 190px 0 0;
}
.faq__copy { display: flex; flex-direction: column; gap: 18px; }
.faq__copy .kicker { margin-bottom: 0; }
.faq__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 52px;
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-weight: 800;
}
.faq__sub {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--fg-faint);
}
.faq__list { display: flex; flex-direction: column; }
.faq__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
  padding-bottom: 14px;
}
.faq__item { border-bottom: 1px solid var(--line); }
.faq__q {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: baseline;
  gap: 18px;
  padding: 22px 14px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
  cursor: pointer;
  border-radius: 4px;
  list-style: none;
  transition: background var(--t-fast) var(--ease-out);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { background: rgba(255,255,255,0.06); }
.faq__q::after {
  content: "+";
  flex: none;
  font-weight: 500;
  font-size: 24px;
  color: var(--fg-faint);
}
.faq__item[open] > .faq__q::after { content: "\2212"; }
.faq__n {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  opacity: 0.5;
}
.faq__a {
  margin: 0;
  /* 66px = row padding (14) + number column (34) + gap (18): answers align under the question text */
  padding: 0 14px 24px 66px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg-muted);
  max-width: 54ch;
  text-wrap: pretty;
}
.faq__a a { color: var(--fg); }

/* ---------- Feedback ---------- */

.feedback {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 72px;
  align-items: start;
  padding: 190px 0 0;
  position: relative;
}

/* The one section that asks the visitor for something, lifted off the flat background so it stops
   weighing the same as everything above it. A white veil, not a hue — the page's only colour comes
   from album art (DESIGN.md), and a tinted band here would be the streaming-brand accent the whole
   design avoids. Same material as the glass mini-player, so it reads as part of the system.
   Both ends stop at rgba(255,255,255,0), never the `transparent` keyword: `transparent` is
   transparent *black*, so the fade would run toward black and WebKit renders a grey cast.
   The 100vw full-bleed is only safe because `body { overflow-x: hidden }` is set above; without it
   this adds a horizontal scrollbar on desktop. */
.feedback::before {
  content: "";
  position: absolute;
  z-index: -2;
  top: 60px;       /* inside the 190px top padding, so the fade-in happens in empty space */
  bottom: -150px;  /* out under the wrap's 140px bottom padding, well below the last field */
  left: 50%;
  margin-left: -50vw;
  width: 100vw;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(255,255,255,0)     0%,
    rgba(255,255,255,0.030) 22%,
    rgba(255,255,255,0.038) 68%,
    rgba(255,255,255,0)   100%);
}
/* The colour comes from a record, the way every other glow on this page does — Arc de Soleil's
   "Lumin Rain", picked for its range: deep violet with a warm amber halo, so the wash is not one flat
   purple. Choosing a violet in CSS instead would be exactly the UI accent hue the design removed;
   sourcing it from a sleeve is the rule, not an exception to it. The source is 600px and heavily
   compressed on purpose — blurred by 200px it carries nothing but colour.
   The band above stays underneath it (z-index -2 vs -1) doing the structural work: the glow is a soft
   blob, the band is what gives the section an edge to fade in and out of. */
.feedback__glow {
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  width: min(130vw, 1250px);
  height: 760px;
  /* object-position pulls the sample up into the sleeve's violet field: a wide box cropping the
     middle of a square cover lands on the amber halo, which washed out mauve rather than purple */
  object-position: 50% 14%;
  /* Tuned to sit in the same register as the rest of the page rather than to look good alone. The
     sleeve is far more saturated than the app screenshots the other glows use, so at the hero's
     saturate(2.2)/0.8 it measured a vivid plum: 87 from --bg with 50 points of spread between its
     channels, against the hero's 97/19 and the lyrics glow's 48/10. Loudness here was chroma, not
     brightness — hence the low saturate rather than a lower opacity alone. Now 46/14. */
  filter: blur(200px) saturate(1.3);
  opacity: 0.36;
  z-index: -1;
}
.feedback__copy { display: flex; flex-direction: column; gap: 18px; }
.feedback__copy .kicker { margin-bottom: 0; }
.feedback__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 52px;
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-weight: 800;
}
.feedback__sub {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--fg-faint);
}
.feedback__form { display: flex; flex-direction: column; }
.feedback__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
  padding-bottom: 14px;
}
.reason {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 22px 18px;
  border-bottom: 1px solid rgba(255,255,255,0.1);
  cursor: pointer;
  background: transparent;
  color: var(--fg-muted);
  border-radius: 4px;
  transition: background var(--t-fast) var(--ease-out);
  text-align: left;
  width: 100%;
}
.reason:hover { background: rgba(255,255,255,0.06); }
.reason.is-picked { background: #fff; color: #000; }
.reason.is-picked:hover { background: #fff; }
.reason__n { font-size: 12px; font-variant-numeric: tabular-nums; opacity: 0.5; }
.reason__label { font-size: 20px; font-weight: 700; letter-spacing: -0.01em; }
.feedback__saved {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 4px;
  font-size: 13px;
  color: var(--fg-muted);
}
.feedback__saved-check {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  color: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 800;
}
.feedback__detail { display: flex; flex-direction: column; gap: 14px; margin-top: 44px; }
.feedback__detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.feedback__detail-title { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; }
.feedback__optional {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.feedback__field-label { font-size: 13px; color: var(--fg-faint); margin-top: 4px; }
.feedback__note, .feedback__email {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 12px;
  font-size: 15px;
  color: var(--fg);
  font-family: inherit;
}
.feedback__note { padding: 16px; resize: vertical; }
.feedback__email { padding: 14px 16px; }
.feedback__note:focus-visible, .feedback__email:focus-visible {
  outline: none;
  border-color: rgba(255,255,255,0.5);
  box-shadow: 0 0 0 3px rgba(255,255,255,0.15);
}
.feedback__send {
  align-self: flex-start;
  background: #fff;
  color: #000;
  border-radius: 999px;
  padding: 13px 28px;
  font-size: 15px;
  font-weight: 700;
  transition: transform var(--t-fast) var(--ease-out);
}
.feedback__send:hover { transform: scale(1.03); }
.feedback__thanks { font-size: 15px; font-weight: 600; color: var(--fg-muted); }
[hidden] { display: none !important; }

/* ---------- Up next CTA ---------- */

.up-next {
  padding: 190px 0 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 26px;
}
.up-next__kicker { font-family: var(--font-display); font-size: 20px; font-weight: 800; color: var(--fg-faint); }
.up-next__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(44px, 6vw, 68px);
  line-height: 1.04;
  letter-spacing: -0.025em;
  font-weight: 800;
  max-width: 16ch;
  text-wrap: balance;
}
.up-next__cta { display: flex; align-items: center; gap: 16px; margin-top: 8px; }

/* ---------- Footer ---------- */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px 22px;
  margin-top: 110px;
  padding-top: 26px;
  border-top: 1px solid rgba(255,255,255,0.1);
  font-size: 13px;
  color: var(--fg-faint);
}
.site-footer__by { display: flex; align-items: baseline; gap: 8px; }
.site-footer__by a { color: inherit; text-decoration: none; }
.site-footer__by a:hover { color: var(--fg); text-decoration: underline; }
.site-footer__sep { opacity: 0.4; }
.site-footer__links { display: flex; gap: 22px; }
.site-footer__links a { color: var(--fg-faint); text-decoration: none; }
.site-footer__links a:hover { color: var(--fg); text-decoration: underline; }

/* ---------- Privacy page ---------- */

.prose { max-width: 68ch; padding: 40px 0 0; }
.prose h1 {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: clamp(38px, 5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-weight: 800;
}
.prose .updated { font-size: 14px; color: var(--fg-faint); margin-bottom: 36px; }
.prose h2 {
  margin: 44px 0 12px;
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: -0.01em;
  font-weight: 800;
}
.prose p { margin: 0 0 16px; font-size: 15px; line-height: 1.7; color: var(--fg-muted); }
.prose a { color: var(--fg); }
/* Release notes page (generated from RELEASES.md): h2 per release, date under it, h3 per theme. */
.prose h3 {
  margin: 22px 0 6px;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: -0.005em;
  font-weight: 700;
}
.prose .release-date { font-size: 13px; color: var(--fg-faint); margin: -6px 0 14px; }

/* ---------- Responsive ---------- */

@media (max-width: 820px) {
  .wrap { padding: 0 20px 140px; }
  .site-header__tag { display: none; }
  .hero,
  .verse--lyrics, .verse--recs, .verse--library,
  .faq, .feedback {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .faq { padding-top: 130px; }
  .faq__title { font-size: clamp(38px, 10vw, 52px); }
  .faq__sub { font-size: clamp(28px, 8vw, 38px); }
  .hero { padding-top: 40px; }
  .hero__phone { justify-self: center; }
  /* Scaled to the viewport, not left at the desktop size: a 1150px wash on a 390px screen stops
     being a glow behind the phone and becomes a flat purple page, which takes the near-black
     identity with it — and the phone's separation depends on light against dark (DESIGN.md).
     Capped as well as scaled: `vw` alone grows to 1190px at the 820px end of this query, i.e. wider
     than the desktop value on a narrower screen, which brings the flat-page problem straight back. */
  .hero__glow {
    right: -40%;
    width: min(155vw, 760px);
    height: min(155vw, 760px);
    opacity: 0.68;
  }
  .verse--library .verse__art { order: 1; }
  .verse { padding-top: 120px; }
  .verse--lyrics { padding-top: 100px; }
  .features { padding-top: 110px; }
  .features__title { font-size: 32px; }
  .roadmap { padding-top: 110px; }
  .roadmap__title { font-size: 32px; }
  .roadmap .track { gap: 12px; }
  .verse__line { font-size: clamp(28px, 8vw, 38px); }
  .feedback { padding-top: 130px; }
  .feedback::before { top: 40px; }  /* the top padding shrinks here too */
  /* scaled and capped like the hero glow: a 1250px wash on a 390px screen stops being a glow and
     turns the section flat purple — which is exactly what happened to the hero (DESIGN.md) */
  .feedback__glow { width: min(150vw, 620px); height: 460px; opacity: 0.3; }
  .feedback__title { font-size: clamp(38px, 10vw, 52px); }
  .feedback__sub { font-size: clamp(28px, 8vw, 38px); }
  .up-next { padding-top: 130px; }
  .lyrics-hero { padding-top: 110px; }
  .lyrics-hero__phone { width: 100%; padding: 10px; }
  .lyrics-hero__glow { width: 100vw; height: 320px; }
  .up-next__cta, .hero__cta { flex-wrap: wrap; }
  .hero__title { font-size: clamp(28px, 8.3vw, 48px); }
  .hero__subtitle { font-size: clamp(19px, 5.5vw, 26px); }
  .up-next__title { font-size: clamp(28px, 8vw, 44px); }
  .hero__cta .cta-caption, .up-next__cta .cta-caption { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__phone { animation: none; }
  .verse__line--reveal { animation: none !important; }
  .cta-button, .feedback__send { transition: none; }
}
