/* ClipForge marketing page.

   Design language: instrument, not brochure. The whole story of the product is
   that it refuses. It refuses unlicensed footage per clip, and it refuses to
   render a video that scores below the retention bar. So the page is built like
   a measuring device: near-black neutral canvas, bone ink, one ember accent on
   the parts that are actually running, and numbers set in mono.

   Dials: DESIGN_VARIANCE 7, MOTION_INTENSITY 5, VISUAL_DENSITY 4.

   Radius rule (one system, documented): chips 2px, controls 4px, panels 8px.
   Accent rule: --ember is the only chromatic colour on the page.
   Theme: dark is the brand default. Light is a first-class alternative under
   prefers-color-scheme, driven by the same tokens. No section inverts. */

/* ------------------------------------------------------------- tokens -- */
:root {
  /* dark, the brand default */
  --canvas:        #0b0b0d;
  --surface:       #131316;
  --surface-2:     #191920;
  --surface-sunk:  #08080a;
  --hairline:      #25252c;
  --hairline-firm: #34343d;

  --ink:        #f4f2ef;
  --ink-muted:  #b7b4ae;
  --ink-subtle: #8a8781;

  /* the single accent. --ember fills, --ember-ink is the text-safe variant */
  --ember:      #e2603a;
  --ember-ink:  #ff8a63;
  --ember-wash: rgba(226, 96, 58, .10);
  --ember-edge: rgba(226, 96, 58, .28);
  --on-ember:   #12100e;

  /* Softer than before, matching the reference: pills for chips, 12px for
     controls, 16px for panels. */
  --r-chip: 999px;
  --r-ctrl: 12px;
  --r-panel: 16px;

  --sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;

  --max: 1200px;
  --gutter: 24px;
  --section: clamp(72px, 9vw, 128px);

  --ease: cubic-bezier(.16, 1, .3, 1);
  /* The spring in the reference reads as a slow arrival with a slight
     overshoot. This is the closest a plain transition gets to it. */
  --ease-rise: cubic-bezier(.2, .8, .2, 1);
}

@media (prefers-color-scheme: light) {
  :root {
    --canvas:        #f5f5f4;
    --surface:       #ffffff;
    --surface-2:     #fafaf9;
    --surface-sunk:  #ececeb;
    --hairline:      #e3e3e0;
    --hairline-firm: #c9c9c5;

    --ink:        #141416;
    --ink-muted:  #4c4c50;
    --ink-subtle: #6d6d71;

    --ember:      #e2603a;
    --ember-ink:  #b8431f;
    --ember-wash: rgba(226, 96, 58, .09);
    --ember-edge: rgba(226, 96, 58, .34);
    --on-ember:   #12100e;
  }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 3px;
  border-radius: var(--r-chip);
}

.wrap {
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%) translateY(-200%);
  z-index: 100;
  background: var(--ember);
  color: var(--on-ember);
  font-size: 14px;
  font-weight: 500;
  padding: 10px 18px;
  border-radius: 0 0 var(--r-ctrl) var(--r-ctrl);
  transition: transform .18s var(--ease);
}
.skip-link:focus { transform: translateX(-50%) translateY(0); }

/* --------------------------------------------------------------- type -- */
h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.02em; }

.display-xl { font-size: clamp(38px, 4.4vw, 56px); line-height: 1.06; letter-spacing: -.035em; }
.display-lg { font-size: clamp(32px, 3.9vw, 46px); line-height: 1.10; letter-spacing: -.030em; }
.display-md { font-size: clamp(26px, 2.9vw, 34px); line-height: 1.15; letter-spacing: -.025em; }
.headline   { font-size: clamp(21px, 2.1vw, 26px); line-height: 1.25; letter-spacing: -.020em; }

.lede {
  font-size: clamp(17px, 1.35vw, 19px);
  line-height: 1.5;
  color: var(--ink-muted);
  max-width: 46ch;
  margin: 20px 0 0;
}
.body    { color: var(--ink-muted); margin: 12px 0 0; max-width: 62ch; }
.body-sm { font-size: 14px; line-height: 1.55; }
.subtle  { color: var(--ink-subtle); }
.num     { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Eyebrows are rationed. Two on the whole page, on the retention gate and the
   footage section. Every other section leads with its headline. */
.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ember-ink);
  margin: 0 0 14px;
}

.section-head { max-width: 60ch; margin-bottom: clamp(36px, 4.5vw, 60px); }
.section-head .body { margin-top: 16px; font-size: 17px; }

section { padding: var(--section) 0; }
section + section { padding-top: 0; }

/* ------------------------------------------------------------ buttons -- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  padding: 14px 22px;
  border-radius: var(--r-ctrl);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .18s var(--ease), border-color .18s var(--ease),
              color .18s var(--ease), transform .12s var(--ease);
}
.btn:active { transform: translateY(1px); }

/* Ember fill with a near-black label, about 5.1:1, and identical in both
   themes so the primary action never changes identity between modes. */
.btn-primary { background: var(--ember); color: var(--on-ember); }
.btn-primary:hover { background: #f0714b; }

.btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--hairline-firm);
}
.btn-secondary:hover { border-color: var(--ink-subtle); background: var(--surface); }

.btn-quiet { background: transparent; color: var(--ink-muted); padding: 10px 12px; }
.btn-quiet:hover { color: var(--ink); }

.btn-sm { font-size: 14px; padding: 10px 16px; }

/* ----------------------------------------------------------------- nav -- */
/* A floating bar that contracts into a glass pill once the page has moved.
   The state comes from an IntersectionObserver on a sentinel at the top of the
   document rather than a scroll listener, so the browser reports the crossing
   itself instead of the page recalculating on every frame of every scroll. */
.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  padding: 8px var(--gutter) 0;
  pointer-events: none;
}
.nav-shell {
  display: flex;
  align-items: center;
  gap: 32px;
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  padding: 12px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-panel);
  pointer-events: auto;
  transition: max-width .35s var(--ease), background .35s var(--ease),
              border-color .35s var(--ease), padding .35s var(--ease),
              box-shadow .35s var(--ease);
}
.nav.stuck .nav-shell {
  max-width: 940px;
  padding: 10px 14px 10px 18px;
  background: color-mix(in srgb, var(--canvas) 72%, transparent);
  border-color: var(--hairline);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .28);
}
@supports not (backdrop-filter: blur(1px)) {
  .nav.stuck .nav-shell { background: var(--canvas); }
}

/* Tall enough that the bar only contracts after a real scroll, rather than
   flickering on the first pixel. */
#top-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  height: 64px;
  width: 1px;
  pointer-events: none;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -.02em;
  flex: none;
}
.brand-mark { color: var(--ember); font-size: 13px; line-height: 1; }

.nav-links { display: flex; align-items: center; gap: 26px; margin-left: auto; }
.nav-links a {
  font-size: 14.5px;
  color: var(--ink-muted);
  transition: color .18s var(--ease);
}
.nav-links a:hover { color: var(--ink); }

.nav-actions { display: flex; align-items: center; gap: 8px; flex: none; }

/* ---------------------------------------------------------------- hero -- */
.hero {
  position: relative;
  isolation: isolate;
  padding: clamp(110px, 13vw, 168px) 0 0;
  text-align: center;
  overflow: hidden;
}

/* The page-wide light now lives in backdrop.css. What stays here is the
   vignette, which pulls the canvas back up at the foot of the hero so the
   headline has something solid underneath it. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(125% 125% at 50% 100%,
              transparent 0%, var(--canvas) 78%);
}

.hero-inner { display: flex; flex-direction: column; align-items: center; }
.hero .display-xl { margin-top: 26px; max-width: 18ch; text-wrap: balance; }
.hero .lede { margin-top: 22px; max-width: 52ch; }

/* --- the badge -------------------------------------------------------- */
/* Two arrows in a track twice the visible width. On hover the track slides one
   arrow-width, so the glyph appears to leave and a fresh one take its place. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 5px 5px 5px 16px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.badge:hover { background: var(--surface-2); border-color: var(--hairline-firm); }
.badge-text { font-size: 13.5px; color: var(--ink); }
.badge-rule { width: 1px; height: 16px; background: var(--hairline-firm); }
.badge-arrow {
  display: block;
  width: 24px;
  height: 24px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--canvas);
  color: var(--ember-ink);
  transition: background .3s var(--ease);
}
.badge:hover .badge-arrow { background: var(--surface); }
.badge-arrow svg {
  width: 24px;
  height: 24px;
  padding: 6px;
  float: left;
  transition: transform .5s var(--ease);
}
.badge:hover .badge-arrow svg { transform: translateX(-24px); }

/* --- the buttons ------------------------------------------------------ */
/* The primary sits in a faint shell, which is what gives the reference its
   inset look without a second border on the button itself. */
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 34px;
}
.btn-shell {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--hairline);
  border-radius: calc(var(--r-ctrl) + 3px);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.btn-ghost { background: transparent; color: var(--ink); }
.btn-ghost:hover { background: var(--surface); }

/* --- the framed panel ------------------------------------------------- */
.panel-wrap {
  position: relative;
  margin: clamp(40px, 6vw, 76px) auto 0;
  padding: 0 var(--gutter);
  max-width: calc(var(--max) - 40px);
}
/* Fades the foot of the frame back into the page rather than letting a hard
   edge cut across the glow. */
.panel-fade {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 55%, var(--canvas) 100%);
}
.panel {
  position: relative;
  padding: 14px;
  border: 1px solid var(--hairline);
  border-radius: calc(var(--r-panel) + 6px);
  background: var(--surface);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
}

.stills {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  max-width: 620px;
  margin: 0 auto;
}
.still {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border-radius: var(--r-panel);
  border: 1px solid var(--hairline);
  background: var(--surface-sunk);
}
.still img { width: 100%; height: 100%; object-fit: cover; }

/* The score sits on the middle still because the score is the product, not
   because the image needed a label on it. */
.still-score {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--r-ctrl);
  background: rgba(8, 8, 10, .82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, .12);
  color: #f4f2ef;
}
.still-score b { font-family: var(--mono); font-size: 16px; font-weight: 500; }
.still-score span {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #ff8a63;
}

/* ------------------------------------------------------------- sources -- */
.sources {
  padding: 28px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.sources .wrap {
  display: flex;
  align-items: center;
  gap: clamp(20px, 4vw, 48px);
  flex-wrap: wrap;
}
.sources-label { font-size: 13px; color: var(--ink-subtle); flex: none; margin: 0; }
.sources-logos {
  display: flex;
  align-items: center;
  gap: clamp(24px, 4vw, 44px);
  flex-wrap: wrap;
  margin-left: auto;
}
.sources-logos img {
  height: 20px;
  width: auto;
  opacity: .62;
  transition: opacity .18s var(--ease);
}
.sources-logos img:hover { opacity: 1; }
/* The Simple Icons CDN bakes a prefers-color-scheme query into each SVG, so a
   single request per logo covers both themes. */
@media (prefers-color-scheme: light) {
  .sources-logos img { opacity: .8; }
}

/* --------------------------------------------------------------- steps -- */
/* No cards and no step numbers. Vertical hairlines carry the grouping, and the
   first column is wider so this does not read as three equal tiles. */
.steps {
  display: grid;
  grid-template-columns: 1.25fr 1fr 1fr;
  gap: 0;
  border-top: 1px solid var(--hairline);
}
.step { padding: 32px 34px 0 0; }
.step + .step { padding-left: 34px; border-left: 1px solid var(--hairline); }
.step h3 { font-size: 20px; font-weight: 600; }
.step p { color: var(--ink-muted); margin: 12px 0 0; font-size: 15.5px; }

/* ---------------------------------------------------------------- gate -- */
.gate-grid {
  display: grid;
  grid-template-columns: .82fr 1.18fr;
  gap: clamp(32px, 5vw, 64px);
  align-items: start;
}

.score {
  padding: 30px 32px;
  border-radius: var(--r-panel);
  background: var(--surface);
  border: 1px solid var(--hairline);
}
.score-value {
  font-family: var(--mono);
  font-size: clamp(56px, 7vw, 76px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -.04em;
}
.score-verdict {
  display: inline-flex;
  align-items: center;
  margin-top: 16px;
  padding: 5px 10px;
  border-radius: var(--r-chip);
  background: var(--ember-wash);
  border: 1px solid var(--ember-edge);
  color: var(--ember-ink);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.score-note {
  margin: 18px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-muted);
}
.score-note q { font-style: normal; color: var(--ink); }

/* Six rules in two columns with no per-row hairlines and no filled progress
   tracks. The weight sits at the end of each line in mono. */
.rules {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px clamp(24px, 3vw, 40px);
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
}
.rules li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 0;
}
.rules li span { font-size: 15px; color: var(--ink-muted); }
.rules li b {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-subtle);
  flex: none;
}

/* ------------------------------------------------------------- footage -- */
/* Three cells for three pieces of content: a wide one and a narrow one fill
   the first row, a full-width one closes the second. No empty tiles. */
.bento { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.cell {
  border-radius: var(--r-panel);
  border: 1px solid var(--hairline);
  background: var(--surface);
  padding: 28px;
  overflow: hidden;
}
.cell h3 { font-size: 19px; }
.cell p { color: var(--ink-muted); margin: 10px 0 0; font-size: 15px; }
.cell-wide { grid-column: span 2; }
/* 1 / -1 spans whatever the column count is, so this needs no breakpoint
   overrides of its own. */
.cell-full { grid-column: 1 / -1; }

/* Cell one shows the ranking step rather than a photograph. Sourcing is the
   part of the pipeline nobody can see, and a stock still said nothing about
   it -- three rows with one below the line say the whole thing. */
.cell-rank { padding: 0; display: flex; flex-direction: column; }
.cell-rank .rank { padding: 26px 28px 6px; display: grid; gap: 11px; }
.rank-row {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  font-size: 13px;
}
.rank-bar { height: 6px; border-radius: var(--r-chip); background: var(--surface-sunk); overflow: hidden; }
.rank-bar i { display: block; height: 100%; background: var(--ember); border-radius: inherit; }
.rank-name { color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-num { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
/* The rejected row is the entire point of the panel, so it drops to
   --ink-subtle and no further: 4.6:1 on --surface, still readable. */
.rank-row.is-out .rank-bar i { background: var(--hairline-firm); }
.rank-row.is-out .rank-name,
.rank-row.is-out .rank-num { color: var(--ink-subtle); }
.cell-rank .cell-body { padding: 18px 28px 28px; }

.cell-note {
  background:
    linear-gradient(180deg, var(--ember-wash), transparent 70%),
    var(--surface);
  border-color: var(--ember-edge);
}
.cell-note p + p { margin-top: 12px; }

/* ------------------------------------------------------------- pricing -- */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
.tier {
  display: flex;
  flex-direction: column;
  padding: 28px;
  border-radius: var(--r-panel);
  border: 1px solid var(--hairline);
  background: var(--surface);
}
.tier-featured { border-color: var(--ember-edge); background: var(--surface-2); }

.tier-name {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-muted);
}
.tier-tag {
  padding: 3px 8px;
  border-radius: var(--r-chip);
  background: var(--ember-wash);
  border: 1px solid var(--ember-edge);
  color: var(--ember-ink);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.price { display: flex; align-items: baseline; gap: 6px; margin: 16px 0 22px; }
.price span {
  font-family: var(--mono);
  font-size: 38px;
  font-weight: 500;
  letter-spacing: -.035em;
  line-height: 1;
}
.price small { font-size: 14px; color: var(--ink-subtle); }

.tier .btn { width: 100%; }

.tier ul { list-style: none; margin: 22px 0 0; padding: 0; }
.tier li {
  position: relative;
  padding-left: 24px;
  margin-bottom: 11px;
  font-size: 14.5px;
  color: var(--ink-muted);
}
/* Marks are drawn in CSS rather than pulled in as icon SVGs, because this page
   has no build step to install an icon family into. */
.tier li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 6px;
  width: 5px;
  height: 9px;
  border: solid var(--ember);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(43deg);
}
.tier li.off { color: var(--ink-subtle); }
.tier li.off::before {
  top: 10px;
  left: 1px;
  width: 10px;
  height: 0;
  border-width: 0 0 1.5px 0;
  border-color: var(--hairline-firm);
  transform: none;
}

.pricing-fine { margin: 22px 0 0; font-size: 13.5px; color: var(--ink-subtle); }

/* ----------------------------------------------------------------- faq -- */
.faq { border-top: 1px solid var(--hairline); }
.faq details { border-bottom: 1px solid var(--hairline); }
.faq summary {
  position: relative;
  list-style: none;
  cursor: pointer;
  padding: 22px 44px 22px 0;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -.015em;
  transition: color .18s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--ember-ink); }
.faq summary::before,
.faq summary::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  background: var(--ink-subtle);
  transition: transform .22s var(--ease), opacity .22s var(--ease);
}
.faq summary::before { width: 13px; height: 1.5px; margin-top: -.75px; }
.faq summary::after  { width: 1.5px; height: 13px; margin-top: -6.75px; right: 11.75px; }
.faq details[open] summary::after { transform: rotate(90deg); opacity: 0; }
.faq details p {
  margin: 0 0 24px;
  max-width: 68ch;
  color: var(--ink-muted);
  font-size: 15.5px;
}

/* ----------------------------------------------------------------- cta -- */
.cta-band {
  padding: clamp(48px, 6vw, 72px) clamp(28px, 5vw, 64px);
  border-radius: var(--r-panel);
  border: 1px solid var(--ember-edge);
  background:
    radial-gradient(120% 160% at 12% 0%, var(--ember-wash), transparent 62%),
    var(--surface);
}
.cta-band h2 { max-width: 18ch; }
.cta-band p { color: var(--ink-muted); margin: 14px 0 0; max-width: 46ch; }
.cta-band .btn { margin-top: 30px; }

/* -------------------------------------------------------------- footer -- */
footer {
  margin-top: var(--section);
  padding: 48px 0;
  border-top: 1px solid var(--hairline);
}
footer .wrap { display: flex; gap: 48px; flex-wrap: wrap; justify-content: space-between; }
footer .fine { color: var(--ink-subtle); font-size: 13.5px; max-width: 40ch; margin: 14px 0 0; }
.foot-cols { display: flex; gap: clamp(40px, 7vw, 88px); }
.foot-cols h4 {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-subtle);
  margin-bottom: 14px;
}
.foot-cols ul { list-style: none; margin: 0; padding: 0; }
.foot-cols li { margin-bottom: 9px; }
.foot-cols a { font-size: 14.5px; color: var(--ink-muted); transition: color .18s var(--ease); }
.foot-cols a:hover { color: var(--ink); }

/* -------------------------------------------------------------- motion -- */
/* MOTION_INTENSITY 5. Two effects, both entrances.

   .rise is the hero sequence: lift and unblur, each element a beat behind the
   one above it, so the eye is walked down the page in reading order. The blur
   is what the reference uses instead of a longer fade, and it is why the text
   appears to resolve rather than simply appear.

   .reveal is the same idea for everything below the fold, fired as sections
   arrive. Both are gated behind .js so the page is fully readable when the
   script never runs, and both use IntersectionObserver rather than a scroll
   listener. Nothing loops and nothing hijacks the scroll. */
.js .rise {
  opacity: 0;
  filter: blur(12px);
  transform: translateY(14px);
  animation: rise 1.15s var(--ease-rise) forwards;
}
.js .rise-1 { animation-delay: .10s; }
.js .rise-2 { animation-delay: .20s; }
.js .rise-3 { animation-delay: .30s; }
.js .rise-4 { animation-delay: .42s; }

@keyframes rise {
  to { opacity: 1; filter: blur(0); transform: none; }
}

.js .reveal {
  opacity: 0;
  filter: blur(8px);
  transform: translateY(18px);
  transition: opacity .7s var(--ease-rise), transform .7s var(--ease-rise),
              filter .7s var(--ease-rise);
}
.js .reveal.in { opacity: 1; filter: blur(0); transform: none; }
.js .reveal-d1 { transition-delay: .07s; }
.js .reveal-d2 { transition-delay: .14s; }
.js .reveal-d3 { transition-delay: .21s; }

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

/* ---------------------------------------------------------- responsive -- */
@media (max-width: 1000px) {
  .stills { max-width: 460px; }
  .panel-wrap { max-width: 100%; }

  .gate-grid { grid-template-columns: 1fr; }

  .steps { grid-template-columns: 1fr; border-top: 0; }
  .step { padding: 26px 0; border-top: 1px solid var(--hairline); }
  .step + .step { padding-left: 0; border-left: 0; }

  /* Three cells cannot fill a two-column grid without leaving a hole, so the
     bento drops straight to one column here. */
  .bento { grid-template-columns: 1fr; }
  .cell-wide { grid-column: span 1; }
}

@media (max-width: 760px) {
  :root { --gutter: 18px; }

  .nav-links { display: none; }
  .nav-actions { margin-left: auto; }
  .nav-shell { padding: 10px 14px; gap: 12px; }
  .nav.stuck .nav-shell { max-width: 100%; }

  .hero { padding-top: 96px; }
  .hero-cta { width: 100%; gap: 10px; }
  .btn-shell, .hero-cta .btn { width: 100%; }
  .badge-text { font-size: 12.5px; }
  .stills { gap: 8px; }
  .panel { padding: 8px; }

  .sources .wrap { gap: 18px; }
  .sources-logos { margin-left: 0; gap: 28px; }

  .rules { grid-template-columns: 1fr; gap: 0; }
  .rules li { padding: 9px 0; }

  .bento { grid-template-columns: 1fr; }
  .cell-wide { grid-column: span 1; }

  .tiers { grid-template-columns: 1fr; }

  footer .wrap { flex-direction: column; gap: 36px; }
  .foot-cols { gap: 48px; }
}
