/* =========================================================
   Lyricon — landing page styles
   ========================================================= */

*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, p, ul, ol, li, figure { margin: 0; padding: 0; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:root{
  --bg:#0B0B0F;
  --bg-1:#101017;
  --bg-2:#16161F;
  --violet:#8B5CF6;
  --violet-deep:#6D28D9;
  --magenta:#DE2AA9;
  --purple:#931ECF;
  --accent-yellow:#F5D046;
  --accent-pink:#FF4FA3;
  --accent-cyan:#4FD1E0;
  --text:rgba(255,255,255,.92);
  --text-2:rgba(255,255,255,.62);
  --text-3:rgba(255,255,255,.58);
  --hairline:rgba(255,255,255,.08);
  --brand-grad:linear-gradient(135deg,var(--magenta),var(--purple));

  --ease: cubic-bezier(.22,1,.36,1);
  --section-pad: clamp(56px, 5vw, 75px);
}

html {
  scroll-behavior: smooth;
  background: var(--bg);
  overflow-x: hidden;
  /* The header is sticky (~77px desktop, ~64px mobile). scroll-padding-top on
     the scrolling container is what fragment navigation actually honours, so
     in-page anchors stop short of the header instead of landing underneath it. */
  scroll-padding-top: 96px;
}

@media (max-width: 700px){
  html{ scroll-padding-top: 80px; }
}

body {
  font-family: 'Geist', system-ui, -apple-system, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  position: relative;
}

/* grain overlay — static, decorative, no network request */
body::after{
  content:"";
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: .045;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.wrap {
  width: 100%;
  max-width: var(--wrap-w, 1200px);
  margin: 0 auto;
  padding: 0 24px;
}

/* The header is sticky (~77px at desktop, ~64px at mobile), so an in-page
   anchor would otherwise land with the section's eyebrow tucked underneath it.
   Offset every anchor target by the header height plus breathing room. */
section[id],
[id="top"]{
  scroll-margin-top: 96px;
}

@media (max-width: 700px){
  section[id],
  [id="top"]{ scroll-margin-top: 80px; }
}

.skip-link{
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--violet-deep);
  color: #fff;
  padding: 12px 20px;
  z-index: 1000;
  border-radius: 0 0 8px 0;
}
.skip-link:focus{ left: 0; }

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

/* =========================================================
   Typography
   ========================================================= */

.eyebrow{
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--violet);
  margin-bottom: 16px;
}

h1, .hero h1 {
  font-size: clamp(2.5rem, 7vw, 5.5rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.05;
  text-wrap: balance;
}
.hero h1 span{ display: inline-block; text-wrap: balance; }

.section-h2{
  font-size: clamp(2rem, 4.5vw, 3.5rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  max-width: 20ch;
}

.body-lg{
  font-size: clamp(1.0625rem, 1.6vw, 1.1875rem);
  font-weight: 400;
  line-height: 1.6;
  color: var(--text-2);
  margin-top: 20px;
  max-width: 46ch;
}

.max-60{ max-width: 60ch; }

.grad-text{
  background: var(--brand-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-sub{
  font-size: clamp(1.0625rem, 1.6vw, 1.1875rem);
  color: var(--text-2);
  line-height: 1.6;
  max-width: 46ch;
  margin-top: 24px;
}

.fine-print{
  font-size: .8125rem;
  color: var(--text-3);
  margin-top: 18px;
  max-width: 42ch;
}

[style*="--i"] { font-feature-settings: "tnum" 1; }
.chip, .price-list li, .step-num { font-feature-settings: "tnum" 1; }

/* =========================================================
   Buttons
   ========================================================= */

.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 26px;
  border-radius: 999px;
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  transition: transform 280ms var(--ease), box-shadow 280ms var(--ease), background 280ms var(--ease), border-color 280ms var(--ease);
  white-space: nowrap;
}

.btn-primary{
  background: var(--brand-grad);
  color: #fff;
}
.btn-primary:hover{ transform: translateY(-1px); }

.btn-glow{
  box-shadow: 0 0 0 1px rgba(255,255,255,.08) inset,
              0 8px 30px -6px rgba(222,42,169,.55),
              0 4px 18px -4px rgba(139,92,246,.45);
}
.btn-glow:hover{
  box-shadow: 0 0 0 1px rgba(255,255,255,.12) inset,
              0 10px 40px -6px rgba(222,42,169,.7),
              0 6px 22px -4px rgba(139,92,246,.6);
}

.btn-ghost{
  background: rgba(255,255,255,.04);
  border: 1px solid var(--hairline);
  color: var(--text);
}
.btn-ghost:hover{ background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.14); }

.btn-nav{
  padding: 10px 20px;
  font-size: .875rem;
}

.btn-lg{
  padding: 17px 34px;
  font-size: 1rem;
  margin-top: 32px;
}

.btn-block{ width: 100%; margin-top: 28px; }

/* =========================================================
   Header / Nav
   ========================================================= */

.site-header{
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid transparent;
  transition: background 300ms var(--ease), border-color 300ms var(--ease), backdrop-filter 300ms var(--ease);
}
.site-header.scrolled{
  background: rgba(11,11,15,.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom-color: var(--hairline);
}

.header-inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
}

.wordmark{
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 11px 4px;
  margin: -11px -4px;
}
.wordmark.small{ padding: 0; margin: 0; }
.wordmark.small{ font-size: 1rem; }
.wordmark .note{
  background: var(--brand-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-size: 1.2em;
}

.nav-menu{ position: relative; display: flex; align-items: center; }
.menu-toggle{
  display: none;
  cursor: pointer;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
}
.menu-lines,
.menu-lines::before,
.menu-lines::after{
  content: "";
  display: block;
  width: 20px;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 200ms var(--ease), opacity 200ms var(--ease);
}
.menu-lines{ position: relative; }
.menu-lines::before{ position: absolute; top: -6px; }
.menu-lines::after{ position: absolute; top: 6px; }

.nav-links{
  display: flex;
  align-items: center;
  gap: 24px;
  font-size: .9375rem;
  color: var(--text-2);
}
.nav-links a:not(.btn){
  display: inline-flex;
  align-items: center;
  padding: 12px 4px;
  margin: -12px -4px;
}
.nav-links a:not(.btn):hover{ color: var(--text); }

/* .nav-links is a plain <nav>, always visible by default (including with
   JavaScript disabled — the hard requirement is that nothing depends on JS
   to be seen). JS only adds .js-enhanced to #nav-menu, which is what turns
   this into a collapsible mobile dropdown; see the max-width:720px block
   and main.js. An earlier <details>/<summary> + display:contents approach
   was dropped: Chromium does not run flex layout on a <details> element's
   children correctly when display:contents is applied to it, which let the
   nav links escape the header's flex box and overflow off-screen. */

/* =========================================================
   Glows / atmosphere
   ========================================================= */

.hero-glow, .section-glow{
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  z-index: 0;
}
.hero-glow-a{
  width: 640px; height: 640px;
  background: radial-gradient(circle, rgba(222,42,169,.35), transparent 70%);
  top: -220px; left: -140px;
}
.hero-glow-b{
  width: 720px; height: 720px;
  background: radial-gradient(circle, rgba(147,30,207,.28), transparent 70%);
  bottom: -320px; right: -220px;
}
.section-glow{
  width: 800px; height: 800px;
  background: radial-gradient(circle, rgba(139,92,246,.18), transparent 70%);
  top: 10%; right: -300px;
}

/* =========================================================
   Hero
   ========================================================= */

.hero{
  position: relative;
  padding: 64px 0 clamp(72px, 9vw, 120px);
  overflow: hidden;
}

.hero-grid{
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: clamp(24px, 5vw, 64px);
  align-items: center;
}

/* >=1276px: give the copy column exactly what's left after the device
   visual takes its own natural (content-based) width, instead of a fixed
   fr split that left the copy column narrower than it needed to be. The
   visual's track can never be narrower than its content, so this column
   pairing can never overlap by construction. The hero's own .wrap is also
   allowed to run wider than the rest of the page's 1200/1280px reading
   width — that extra room is absorbed entirely by the 1fr copy column
   since the visual column is content-sized, not stretched. */
@media (min-width: 1276px){
  /* The hero needs more room than the page's reading width to keep each
     sentence of the H1 on one line — but it must NOT break the page's left
     alignment line. So we keep the content's left edge identical to every
     other .wrap (same --wrap-w maths) and take the extra room on the RIGHT
     only. Anchoring left instead of re-centering is what keeps the eyebrow,
     H1, sub and CTAs flush with the nav wordmark and every section heading. */
  .hero .wrap{
    max-width: none;
    margin: 0;
    padding-left: max(24px, calc((100vw - var(--wrap-w, 1200px)) / 2 + 24px));
    padding-right: 24px;
  }
  .hero-grid{
    grid-template-columns: 1fr auto;
    gap: clamp(20px, 3vw, 44px);
  }
  .hero h1{ font-size: clamp(3.5rem, 4.6vw, 5.5rem); }
}

.hero-ctas{
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 34px;
}

.hero-visual{
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 480px;
}

.hero-ambient{
  position: absolute;
  inset: -10% -10% -10% -10%;
  width: 120%;
  height: 120%;
  object-fit: cover;
  opacity: .16;
  filter: blur(38px) saturate(120%);
  border-radius: 50%;
  z-index: 0;
}

.phone-stack{
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(-40px, -2vw, -10px);
}

.device-frame{
  position: relative;
  border-radius: 5.2%/2.4%;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.14);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.12),
    0 30px 60px -14px rgba(0,0,0,.65),
    0 0 60px -10px rgba(139,92,246,.35);
  background: var(--bg-2);
}
.device-frame img{ width: 100%; height: auto; display: block; }

.device-center{
  width: clamp(190px, 22vw, 280px);
  z-index: 2;
}

.flank{
  width: clamp(96px, 12vw, 150px);
  opacity: .78;
  filter: blur(.4px);
}
.flank-left{ transform: translate(18px,26px) scale(.92) rotate(-4deg); }
.flank-right{ transform: translate(-18px,-14px) scale(.92) rotate(4deg); }

/* 1276–1439px is the tightest band for the hero H1 fix: the flanking
   clip cards are already at (or near) their max size here while the
   available width is at its narrowest, which is exactly what left too
   little room for the H1 to go one-sentence-per-line. Trim only the
   flanks' ceiling a little in this band — the center device (the
   actual "money shot") and every flank/device size at >=1440px are
   untouched, so the protected hero treatment is unchanged there. */
@media (min-width: 1276px) and (max-width: 1439px){
  .flank{ width: clamp(90px, 11vw, 128px); }
}

.clip-frame{
  position: relative;
  aspect-ratio: 9 / 16;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.10);
  background: var(--bg-2);
  box-shadow: 0 20px 40px -12px rgba(0,0,0,.6);
}
.clip-frame video{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: var(--bg-2);
}
.clip-frame.sm{ width: 130px; flex: 0 0 auto; }

/* =========================================================
   Trust strip
   ========================================================= */

.trust-strip{
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  padding: 22px 0;
}
.trust-inner{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 14px;
  text-align: center;
  font-size: .875rem;
  color: var(--text-3);
}
.trust-inner .dot{ color: var(--text-3); }

/* =========================================================
   Sections
   ========================================================= */

.section{
  position: relative;
  padding: var(--section-pad) 0;
  overflow: hidden;
}

.card-grid{
  display: grid;
  gap: 20px;
  margin-top: 56px;
}
.card-grid-3{ grid-template-columns: repeat(3, 1fr); }

.card{
  background: rgba(255,255,255,.03);
  border: 1px solid var(--hairline);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 20px 40px rgba(0,0,0,.5);
  border-radius: 18px;
  padding: 32px 28px;
}
.card h3{
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 12px;
}
.card p{
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.6;
}

/* asymmetric split layout */
.split-grid{
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: clamp(32px, 6vw, 80px);
  align-items: center;
}
.section-split.reverse .split-grid{ grid-template-columns: .85fr 1.15fr; }
.section-split.reverse .split-copy{ order: 2; }
.section-split.reverse .split-visual{ order: 1; }

.split-visual{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
}

.device-med{ width: clamp(200px, 24vw, 280px); }
.center-frame{ margin: 64px auto 0; }

.output-frame{
  width: clamp(120px, 15vw, 170px);
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: 0 20px 44px -14px rgba(0,0,0,.6), 0 0 40px -12px rgba(222,42,169,.3);
  transform: translateY(28px);
}

/* caption demo */
.caption-demo{
  margin-top: 40px;
  padding: 28px 26px;
  background: rgba(255,255,255,.03);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}
.caption-line{
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.5;
  color: var(--text-2);
}
.cw{
  display: inline-block;
  margin-right: .28em;
  animation: word-pop 5.1s calc(var(--i) * 300ms) infinite;
}
@keyframes word-pop{
  0%, 3% { color: var(--text-2); transform: none; }
  6%, 26% { color: var(--accent-yellow); transform: translateY(-1px); }
  30%, 100% { color: var(--text-2); transform: none; }
}

/* chips */
.chip-row{
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 40px;
}
.chip{
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--hairline);
  font-size: .875rem;
  color: var(--text-2);
}

.style-chips{
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}
.style-chip{
  padding: 10px 20px;
  border-radius: 10px;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
  background: var(--bg-2);
  border: 1px solid var(--hairline);
}
.style-chip-yellow{ color: var(--accent-yellow); }
.style-chip-pink{ color: var(--accent-pink); }
.style-chip-white{ color: #fff; }

/* marquee wall */
.marquee-wall{
  margin: 64px 0 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-row{ overflow: hidden; width: 100%; }
/* Density fix: instead of stretching a fixed card count across a forced
   track width (which left voids when there were few cards), each
   .marquee-group holds the clip set repeated enough times to be wider
   than the largest supported viewport (1920px), and the track holds two
   identical copies of that group back to back. Every gap — inside a
   group and between the two groups — is the same 14px, so the whole
   sequence has a single uniform card-to-card pitch of (130px card +
   14px gap) = 144px. With 15 cards per group that pitch repeats exactly
   every 15 * 144px = 2160px, so translateX(-2160px) always realigns on
   an identical frame: the loop is seamless with no jump, at any
   viewport width, and there is never a gap wider than 14px. */
.marquee-track{
  display: flex;
  align-items: center;
  gap: 14px;
  width: max-content;
  animation: marquee-left 110s linear infinite;
}
.marquee-group{
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 0 0 auto;
}
.marquee-row-left .marquee-track{ animation-name: marquee-left; }
.marquee-row-right .marquee-track{ animation-name: marquee-right; }
.marquee-row:hover .marquee-track{ animation-play-state: paused; }

@keyframes marquee-left{
  from{ transform: translateX(0); }
  to{ transform: translateX(-2160px); }
}
@keyframes marquee-right{
  from{ transform: translateX(-2160px); }
  to{ transform: translateX(0); }
}

/* steps */
.steps{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  margin-top: 56px;
  counter-reset: step;
}
.step{
  position: relative;
  padding: 28px 24px 32px;
  background: rgba(255,255,255,.03);
  border: 1px solid var(--hairline);
  border-radius: 18px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
}
.step-num{
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--violet);
  letter-spacing: .02em;
  margin-bottom: 18px;
  font-feature-settings: "tnum" 1;
}
.step h3{
  font-size: 1.0625rem;
  font-weight: 600;
  margin-bottom: 8px;
  letter-spacing: -0.01em;
}
.step p{ color: var(--text-2); font-size: .9375rem; line-height: 1.55; }

/* pricing */
/* Scoped to #pricing only — every other section keeps its left-aligned
   editorial eyebrow + H2. Centering just these two makes the heading
   read as one deliberate moment with the already-centered cards below,
   instead of a left edge that doesn't line up with anything under it. */
#pricing .eyebrow,
#pricing .section-h2{
  text-align: center;
}
#pricing .section-h2{
  margin-left: auto;
  margin-right: auto;
}

/* Groups the two pricing cards with the export-screen proof shot so the
   whole thing centers as one row on wide screens and stacks cleanly on
   narrow ones (see .pricing-proof below for the sub-700px cutoff). */
.pricing-body{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 32px;
  margin-top: 56px;
}

.pricing-grid{
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 32px;
  margin: 0;
  max-width: 920px;
  align-items: stretch;
}
.price-card{
  display: flex;
  flex-direction: column;
  background: rgba(255,255,255,.03);
  border: 1px solid var(--hairline);
  border-radius: 20px;
  padding: 36px 32px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 20px 40px rgba(0,0,0,.5);
}
.price-card h3{
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.price-tagline{
  color: var(--text-2);
  margin-top: 6px;
  font-size: .9375rem;
}
.price-list{
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1 1 auto;
}
.price-list li{
  position: relative;
  padding-left: 24px;
  color: var(--text-2);
  font-size: .9375rem;
  line-height: 1.5;
}
.price-list li::before{
  content: "";
  position: absolute;
  left: 0;
  top: .5em;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--violet);
}
.price-card-pro{
  position: relative;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--bg-2), var(--bg-2)) padding-box,
    var(--brand-grad) border-box;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 24px 60px -12px rgba(222,42,169,.35), 0 20px 40px rgba(0,0,0,.5);
}
.price-card-pro .price-list li::before{ background: var(--brand-grad); }

.pricing-note{
  margin-top: 28px;
  font-size: .8125rem;
  color: var(--text-3);
  max-width: 60ch;
}

/* Real export-screen proof (720p unlocked, 1080p/4K locked) sitting
   beside the cards. Sized well below the cards so it reads as
   supporting evidence, not a third competing column; hidden under
   700px per its own note below rather than cramping the stacked cards. */
.pricing-proof{ flex: 0 0 auto; }
.pricing-proof .device-frame{ width: clamp(150px, 14vw, 190px); }

@media (max-width: 700px){
  .pricing-proof{ display: none; }
}

/* final CTA */
.final-cta{
  text-align: center;
}
.final-cta .wrap{ position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; }
.final-cta .section-h2{ max-width: 18ch; margin: 0 auto; }
.final-cta .body-lg{ margin: 20px auto 0; text-align: center; }

/* footer */
.site-footer{
  border-top: 1px solid var(--hairline);
  padding: 40px 0;
}
.footer-inner{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px 14px;
  text-align: center;
  font-size: .8125rem;
  color: var(--text-3);
}
.footer-inner a{ display: inline-flex; align-items: center; padding: 13px 3px; margin: -13px -3px; }
.footer-inner a:hover{ color: var(--text-2); }
.footer-inner .dot{ color: var(--text-3); }

.footer-note{
  margin-top: 12px;
  text-align: center;
  font-size: .8125rem;
  color: var(--text-3);
}

/* =========================================================
   Motion / reveal
   ========================================================= */

.reveal{
  opacity: 1;
  transform: none;
  filter: none;
}

@media (prefers-reduced-motion: no-preference){
  .reveal{
    opacity: 0;
    transform: translateY(16px);
    filter: blur(6px);
    transition: opacity 600ms var(--ease), transform 600ms var(--ease), filter 600ms var(--ease);
    transition-delay: var(--d, 0ms);
  }
  .reveal.in-view{
    opacity: 1;
    transform: none;
    filter: none;
  }
}

/* NOTE: an animation-timeline:view() scroll-linked variant was evaluated per
   spec but produced unreliable paints (elements reported opacity:1 via
   getComputedStyle yet intermittently failed to composite while scrolled),
   which risks shipping invisible content. The IntersectionObserver-driven
   .in-view toggle above is used universally instead — same restrained
   opacity/translate/blur motion, without the compositor risk. */

/* =========================================================
   Reduced motion
   ========================================================= */

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  .reveal{ opacity: 1 !important; transform: none !important; filter: none !important; }
  .marquee-track{ animation: none !important; }
  .cw{ animation: none !important; }
  .hero-ambient{ display: none; }
}

/* =========================================================
   Responsive
   ========================================================= */

@media (min-width: 1440px){
  :root{ --wrap-w: 1280px; }
}

/* The hero switches to a stacked (single-column) layout at 1275px and
   below — wider than every other section's 980px breakpoint — because
   at the required 1100px checkpoint (and some way past it) there isn't
   room for the device visual to sit beside the copy without either
   shrinking the visual (touching the protected hero treatment) or
   wrapping the H1's second sentence. Stacked, the visual sits full-width
   above the copy (order:-1) and the H1 gets the full wrap width, which
   trivially satisfies both "one line per sentence" and "never overlaps
   the visual" — they're no longer side by side. The side-by-side layout
   takes over at 1276px, where there's enough room for both. */
@media (max-width: 1275px){
  .hero-grid{ grid-template-columns: 1fr; }
  .hero-visual{ min-height: 420px; order: -1; }
}

@media (max-width: 980px){
  .split-grid{ grid-template-columns: 1fr; }
  .section-split.reverse .split-copy,
  .section-split.reverse .split-visual{ order: initial; }
  .split-copy, .split-visual{ order: initial; }
  .card-grid-3{ grid-template-columns: 1fr 1fr; }
  .steps{ grid-template-columns: 1fr 1fr; }
  .pricing-grid{ grid-template-columns: 1fr; max-width: 460px; }
  /* Once the cards themselves stack vertically, keep the proof shot
     stacked fully below both of them too — otherwise it has enough
     horizontal room to float beside the now-narrow card column and
     ends up vertically centered against the whole two-card stack,
     which reads as an accident rather than a layout. */
  .pricing-body{ flex-direction: column; }
}

@media (max-width: 720px){
  .header-inner{ min-height: 68px; flex-wrap: wrap; row-gap: 8px; padding: 12px 0; }
  .menu-toggle{ display: flex; }

  /* No JS: nav-links stay in normal flow and simply wrap under the
     wordmark — never hidden. With JS, #nav-menu gets .js-enhanced and the
     nav becomes a collapsible dropdown, closed until .open is toggled. */
  .nav-menu.js-enhanced .nav-links{
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    background: rgba(16,16,23,.96);
    border: 1px solid var(--hairline);
    border-radius: 14px;
    padding: 12px;
    min-width: 220px;
    box-shadow: 0 20px 50px rgba(0,0,0,.6);
    display: none;
  }
  .nav-menu.js-enhanced.open .nav-links{ display: flex; }

  .nav-links a:not(.btn){ padding: 13px 12px; margin: 0; border-radius: 8px; }
  .nav-links a:not(.btn):hover{ background: rgba(255,255,255,.05); }
  .nav-links .btn-nav{ margin-top: 8px; text-align: center; }

  .card-grid-3{ grid-template-columns: 1fr; }
  .steps{ grid-template-columns: 1fr 1fr; }

  .phone-stack{ transform: scale(.92); }
  .flank{ width: 84px; }

  .split-visual{ gap: 14px; }
  .output-frame{ display: none; }
}

@media (max-width: 480px){
  .wrap{ padding: 0 18px; }
  .hero{ padding-top: 40px; }
  .hero-ctas{ flex-direction: column; align-items: stretch; }
  .hero-ctas .btn{ width: 100%; }
  .steps{ grid-template-columns: 1fr; }
  .caption-line{ font-size: 1.0625rem; }
  .flank{ display: none; }
  .hero-visual{ min-height: 360px; }
}

@media (min-width: 360px) and (max-width: 400px){
  .wrap{ padding: 0 16px; }
}
