/* ── The opening page ──────────────────────────────────────────
   The app's own stylesheets are not loaded here; only tokens.css, so the
   accent, the greys and the type stack stay in one place. Everything in this
   file is scoped under .lp for the same reason.

   The values are read off the reference with getComputedStyle rather
   than eyeballed from a screenshot: a 65px fixed header over a 1280px column
   with 32px gutters, sections on a 96px vertical rhythm, and one hairline —
   rgba(255,255,255,0.08) — doing all of the dividing. The copy is ours; what
   is borrowed is the measure. */

.lp {
  --lp-max: 1280px;
  --lp-gutter: 32px;
  --lp-hairline: rgba(255, 255, 255, 0.08);
  --lp-card: rgba(10, 10, 12, 0.6);
  --lp-fill: rgba(20, 20, 23, 0.5);
  background: var(--page);
  height: auto;
}

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

/* ── Header ────────────────────────────────────────────────────
   Fixed, transparent, and separated from the page by the hairline alone —
   no fill and no blur, which is why the hero's glow reads through it. */
.lp-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 50;
  block-size: 65px;
  border-block-end: 1px solid var(--lp-hairline);
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}

.lp-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-inline-size: var(--lp-max);
  block-size: 64px;
  margin-inline: auto;
  padding-inline: var(--lp-gutter);
}

.lp-brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.176px;
  text-decoration: none;
}

.lp-brand__mark {
  inline-size: 24px;
  block-size: 24px;
  fill: var(--accent);
}

.lp-nav {
  display: flex;
  align-items: center;
  gap: 28px;
}

.lp-nav a {
  color: var(--text);
  font-size: 16px;
  font-weight: 400;
  letter-spacing: -0.176px;
  text-decoration: none;
  opacity: 0.72;
  transition: opacity 0.16s var(--ease-out, ease);
}

.lp-nav a:hover {
  opacity: 1;
}

/* .lp-nav a is the more specific selector, so without this the button in the
   header inherited the nav's colour: white text on a white pill, a control
   with no visible label. */
.lp-nav .lp-btn {
  color: #000;
  opacity: 1;
}

/* ── Buttons ───────────────────────────────────────────────────
   The primary is the page's only solid white surface, which is what makes it
   read as the one thing to press. */
.lp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 32px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--text);
  color: #000;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.176px;
  text-decoration: none;
  transition: transform 0.16s var(--ease-out, ease), opacity 0.16s var(--ease-out, ease);
}

.lp-btn:hover {
  transform: translateY(-1px);
  opacity: 0.92;
}

.lp-btn--small {
  padding: 8px 20px;
  font-size: 14px;
  opacity: 1;
}

.lp-btn--quiet {
  padding: 14px 28px;
  border: 1px solid var(--lp-hairline);
  background: var(--lp-fill);
  color: var(--text);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.lp-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-block-start: 36px;
}

.lp-actions--centre {
  justify-content: center;
}

/* ── Hero ──────────────────────────────────────────────────────
   160px of top padding is what clears the fixed header and still leaves the
   heading sitting high in the fold. */
.lp-hero {
  position: relative;
  overflow: hidden;
  padding: 160px var(--lp-gutter) 96px;
}

/* Two washes on a black page, the same trick the app uses: without them the
   background reads as flat rather than dark. */
.lp-hero__glow {
  position: absolute;
  inset-block-start: -300px;
  inset-inline-start: 50%;
  inline-size: 1500px;
  block-size: 980px;
  translate: -50% 0;
  /* Three washes, not two: the pair that sit high and wide, and a dimmer one
     centred behind the heading so the type sits on colour rather than on a
     hole between two lights. */
  background:
    radial-gradient(closest-side, var(--bg-glow-1), transparent 72%) 26% 34% / 58% 66% no-repeat,
    radial-gradient(closest-side, var(--bg-glow-2), transparent 72%) 74% 26% / 54% 62% no-repeat,
    radial-gradient(closest-side, #fb2c5a1f, transparent 70%) 50% 58% / 70% 55% no-repeat;
  filter: blur(30px);
  pointer-events: none;
}

/* The reference sets its hero flush left because a collage of album art
   occupies the right half. We have no such art, and left-aligned text beside
   600px of nothing reads as a layout that failed to load — so ours is
   centred, which is the same page with the missing half removed. */
.lp-hero__inner {
  position: relative;
  max-inline-size: 900px;
  margin-inline: auto;
  text-align: center;
}

.lp-hero__inner .lp-lead {
  margin-inline: auto;
}

.lp-hero__inner .lp-actions {
  justify-content: center;
}

.lp-pill {
  display: inline-flex;
  align-items: center;
  padding: 6px 16px;
  border: 1px solid var(--lp-hairline);
  border-radius: var(--radius-pill);
  background: var(--lp-fill);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.176px;
}

.lp-h1 {
  margin: 24px 0 0;
  font-size: 72px;
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--text);
}

.lp-lead {
  max-inline-size: 576px;
  margin: 24px 0 0;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1.625;
  letter-spacing: -0.176px;
}

/* ── Sections ──────────────────────────────────────────────── */
.lp-section {
  max-inline-size: var(--lp-max);
  margin-inline: auto;
  padding: 96px var(--lp-gutter);
  scroll-margin-block-start: 80px;
}

.lp-section__head {
  text-align: center;
  margin-block-end: 48px;
}

.lp-eyebrow {
  display: block;
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}

.lp-h2 {
  max-inline-size: 720px;
  margin: 16px auto 0;
  font-size: 48px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--text);
}

.lp-h2--large {
  font-size: 60px;
  max-inline-size: 800px;
}

.lp-section__lead {
  max-inline-size: 620px;
  margin: 20px auto 0;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1.625;
}

/* ── Feature cards ─────────────────────────────────────────── */
.lp-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.lp-card {
  padding: 28px;
  border: 1px solid var(--lp-hairline);
  border-radius: 24px;
  background: var(--lp-card);
}

.lp-card__icon {
  inline-size: 22px;
  block-size: 22px;
  color: var(--accent);
}

.lp-card__title {
  margin: 16px 0 0;
  font-size: 18px;
  font-weight: 600;
  line-height: 28px;
  letter-spacing: -0.176px;
  color: var(--text);
}

.lp-card__body {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.625;
}

.lp-card__body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--text);
}

/* ── Screens ─────────────────────────────────────────────────
   The phone overlaps the desktop shot's lower-left corner, so the two read as
   one picture of one app rather than as two unrelated images. */
.lp-shots {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 32px;
}

.lp-shot {
  margin: 0;
  line-height: 0;
}

.lp-shot img {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

.lp-shot--desktop {
  flex: 0 1 820px;
  border: 1px solid var(--lp-hairline);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.9);
}

.lp-shot--phone {
  flex: 0 0 200px;
  border: 1px solid var(--lp-hairline);
  border-radius: 34px;
  overflow: hidden;
  box-shadow: 0 30px 60px -25px rgba(0, 0, 0, 0.9);
}

/* ── Numbers ─────────────────────────────────────────────────
   Four claims that are all zero, which is the point of them. */
.lp-stats {
  padding: 40px var(--lp-gutter);
}

.lp-stats__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  max-inline-size: 960px;
  margin-inline: auto;
}

.lp-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 24px 8px;
  border: 1px solid var(--lp-hairline);
  border-radius: 20px;
  background: var(--lp-card);
  text-align: center;
}

.lp-stat__value {
  color: var(--accent);
  font-size: 48px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1.2px;
}

.lp-stat__unit {
  font-size: 24px;
  letter-spacing: -0.6px;
}

.lp-stat__label {
  color: var(--text-muted);
  font-size: 14px;
  letter-spacing: -0.176px;
}

/* ── Close ─────────────────────────────────────────────────── */
.lp-cta {
  padding: 112px var(--lp-gutter);
  text-align: center;
}

.lp-note {
  margin: 20px 0 0;
  color: var(--text-dim);
  font-size: 14px;
  letter-spacing: -0.176px;
}

/* ── Footer ────────────────────────────────────────────────── */
.lp-footer {
  border-block-start: 1px solid var(--lp-hairline);
  padding: 56px var(--lp-gutter);
}

.lp-footer__inner {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 32px;
  max-inline-size: var(--lp-max);
  margin-inline: auto;
}

.lp-footer__blurb {
  max-inline-size: 380px;
  margin: 16px 0 0;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.6;
}

.lp-footer__links {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.lp-footer__links h4 {
  margin: 0 0 2px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.176px;
  color: var(--text);
}

.lp-footer__links a {
  color: var(--text-muted);
  font-size: 14px;
  text-decoration: none;
}

.lp-footer__links a:hover {
  color: var(--text);
}

/* ── Narrow screens ────────────────────────────────────────────
   The same 768px breakpoint the app uses, so the two never disagree about
   what counts as a phone. The type comes down because 72px over a 390px
   screen is five characters a line. */
@media (max-width: 767.98px) {
  .lp {
    --lp-gutter: 20px;
  }

  .lp-nav a:not(.lp-btn) {
    display: none;
  }

  /* The header's call to action is 36 tall on a desktop, which is a cursor
     size. It is the only control on the page up here, so it can simply grow
     rather than needing a hidden hit area. */
  .lp-nav .lp-btn {
    padding-block: 12px;
  }

  .lp-hero {
    padding-block: 120px 64px;
  }

  .lp-h1 {
    font-size: 40px;
    letter-spacing: -0.02em;
  }

  .lp-lead {
    font-size: 16px;
  }

  .lp-section {
    padding-block: 64px;
  }

  .lp-h2 {
    font-size: 32px;
  }

  .lp-h2--large {
    font-size: 36px;
  }

  .lp-section__lead {
    font-size: 16px;
  }

  .lp-cards {
    grid-template-columns: 1fr;
  }

  /* Side by side, each shot would be under 180px wide. Stacked, the phone
     sits under the desktop at a size where the layout is still legible. */
  .lp-shots {
    flex-direction: column;
    align-items: center;
    gap: 24px;
  }

  .lp-shot--phone {
    flex: 0 0 auto;
    inline-size: 170px;
  }

  .lp-stats__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .lp-cta {
    padding-block: 80px;
  }

  .lp-footer__inner {
    grid-template-columns: 1fr 1fr;
  }

  .lp-footer__about {
    grid-column: 1 / -1;
  }
}

/* ── Motion ────────────────────────────────────────────────────
   The page is about a music player, so the one animated thing that earns its
   place is the one the app actually does: it takes its colour from the
   artwork and the colour moves. Everything else here is arrival — content
   appearing where it will sit, never sliding in from off screen.

   All of it is gated on `.js`, set by an inline script before this file
   paints. With JavaScript off nothing is hidden, so the page is complete and
   static rather than blank. */

html {
  scroll-behavior: smooth;
}

/* ── The wash ─────────────────────────────────────────────────
   Two colours, the same two the app uses behind a cover, breathing slowly
   enough that you notice it only if you stay. */
@keyframes lp-drift {
  0%, 100% { scale: 1; opacity: 0.85; }
  50%      { scale: 1.08; opacity: 1; }
}

.lp-hero__glow {
  animation: lp-drift 34s var(--ease-in-out) infinite;
}

/* ── The load sequence ─────────────────────────────────────────
   One orchestrated moment at the top of the page, in reading order. */
@keyframes lp-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.js .lp-hero__inner > * {
  animation: lp-rise 800ms var(--ease-out) both;
}

.js .lp-hero__inner .lp-pill    { animation-delay: 40ms; }
.js .lp-hero__inner .lp-h1      { animation-delay: 120ms; }
.js .lp-hero__inner .lp-lead    { animation-delay: 220ms; }
.js .lp-hero__inner .lp-actions { animation-delay: 320ms; }

/* ── Arrival ───────────────────────────────────────────────────
   Sections come in once, on the way past. Cards inside a grid carry a
   stagger from their index, so a row assembles instead of blinking on. */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--ease-out),
              transform 700ms var(--ease-out);
}

.js .reveal .lp-card,
.js .reveal .lp-stat,
.js .reveal .lp-shot {
  opacity: 0;
  transform: translateY(12px);
}

.js .reveal.is-in .lp-card,
.js .reveal.is-in .lp-stat,
.js .reveal.is-in .lp-shot {
  opacity: 1;
  transform: none;
  transition: opacity 600ms var(--ease-out) var(--stagger, 0ms),
              transform 600ms var(--ease-out) var(--stagger, 0ms);
}

/* ── Header ────────────────────────────────────────────────────
   Transparent over the wash, and it takes its surface only once the page has
   moved — so the two are never competing for the same few pixels. The border
   keeps its width and loses its colour, because the height is measured. */
.lp-header {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-block-end-color: transparent;
  transition: background 300ms var(--ease-out), border-color 300ms var(--ease-out);
}

.lp-header.is-scrolled {
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-block-end-color: var(--lp-hairline);
}

/* ── The pill's meter ──────────────────────────────────────────
   Three bars, the app's own visualiser in miniature. It is the first thing
   on the page and it says "music player" before the heading does. */
.lp-eq {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  block-size: 10px;
  margin-inline-end: 9px;
}

.lp-eq i {
  inline-size: 2px;
  block-size: 100%;
  border-radius: 1px;
  background: var(--accent);
  transform-origin: bottom;
  scale: 1 0.35;
  animation: lp-eq 1.1s var(--ease-in-out) infinite;
}

.lp-eq i:nth-child(2) { animation-delay: 0.18s; }
.lp-eq i:nth-child(3) { animation-delay: 0.36s; }

@keyframes lp-eq {
  0%, 100% { scale: 1 0.35; }
  50%      { scale: 1 1; }
}

/* ── Cards ─────────────────────────────────────────────────────
   The same bright top edge the app's glass surfaces carry, so the page and
   the product look like one thing. */
.lp-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent 40%), var(--lp-card);
  transition: border-color 250ms var(--ease-out), transform 250ms var(--ease-out);
}

.lp-card:hover {
  border-color: rgba(255, 255, 255, 0.16);
  transform: translateY(-2px);
}

.lp-shot--desktop,
.lp-shot--phone {
  transition: transform 400ms var(--ease-out);
}

.lp-shots:hover .lp-shot--desktop {
  transform: translateY(-3px);
}

/* ── Keyboard ──────────────────────────────────────────────────
   Motion is no excuse for losing the focus ring. */
.lp-btn:focus-visible,
.lp-brand:focus-visible,
.lp-nav a:focus-visible,
.lp-footer__links a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-pill);
}

/* ── Asked to sit still ────────────────────────────────────────
   Nothing above is load-bearing, so all of it simply stops. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .js .lp-hero__inner > *,
  .lp-hero__glow,
  .lp-eq i {
    animation: none;
  }

  .js .reveal,
  .js .reveal .lp-card,
  .js .reveal .lp-stat,
  .js .reveal .lp-shot {
    opacity: 1;
    transform: none;
  }

  /* The arrival transitions outrank the plain selectors above, so they need
     their own kill — otherwise a section revealed after the switch still
     spends 700ms getting there. */
  .js .reveal.is-in,
  .js .reveal.is-in .lp-card,
  .js .reveal.is-in .lp-stat,
  .js .reveal.is-in .lp-shot {
    transition: none;
  }

  .lp-card,
  .lp-shot--desktop,
  .lp-shot--phone,
  .lp-header {
    transition: none;
  }

  .lp-card:hover,
  .lp-shots:hover .lp-shot--desktop {
    transform: none;
  }
}
