/* ============ Eyebrow ============ */
.eyebrow {
  display: block;
}
.eyebrow--index { color: var(--accent); }
.eyebrow--label { color: var(--ink-muted); }
.eyebrow--inverse.eyebrow--label { color: var(--ink-inverse-muted); }

/* ============ CTA ============ */
.cta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-7);
}
.cta-row--divided { gap: var(--space-5); }
.cta-row--divided .cta { padding-right: var(--space-7); }
.cta-row--divided .cta + .cta { padding-left: var(--space-7); border-left: 1px solid var(--border-hairline); }
.cta-row--divided.cta-row--inverse .cta + .cta { border-left-color: var(--ink-inverse-muted); }

@media (max-width: 480px) {
  .cta-row--divided { flex-direction: column; align-items: flex-start; gap: var(--space-4); }
  .cta-row--divided .cta { padding-right: 0; }
  .cta-row--divided .cta + .cta { padding-left: 0; border-left: none; }
}

.cta {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-primary);
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease;
}
.cta:hover, .cta:focus-visible { border-bottom-color: currentColor; }
.cta--accent { color: var(--accent); }
.cta--inverse { color: var(--ink-inverse); }

/* Short label CTAs (nav, hero, footer) shouldn't wrap; longer inline links (e.g. the not-ai link line) should */
.cta-row .cta,
.nav__meta .cta {
  white-space: nowrap;
}

/* ============ Nav — floating translucent pills over page content ============ */
.nav {
  position: fixed;
  top: var(--space-5);
  left: var(--space-5);
  right: var(--space-5);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}

.nav__brand {
  display: flex;
  align-items: stretch;
  gap: 0;
}

.nav__logo {
  display: flex;
  align-items: center;
  /* The literal space between "RSI" and the <span> collapses to nothing once the flex
     container turns it into an anonymous flex item — an explicit gap replaces it. */
  gap: 0.25em;
  height: 53px;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 18px;
  color: var(--ink-inverse);
  background: rgba(32, 26, 24, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.14);
  padding-inline: var(--space-5);
  backdrop-filter: blur(10px);
}
.nav__logo span { color: var(--accent); }

/* Plain text, no pill — positioned at the same guide the H2 statements use further down the
   page (max-width: 960px, right-aligned): nav's own box already spans the exact width that
   guide is measured against (viewport minus the two var(--space-5) edges, no extra padding),
   so `left: 100% - 960px` lands the clock's left edge exactly on that column's start. Floored
   at 200px so it can't be pushed under the logo on a narrower desktop viewport — below
   ~1100px the nav's own links+CTA group is wide enough that it collides with that floor too,
   so it hides there instead (see the max-width: 1100px rule further down). */
.nav__clock {
  display: flex;
  align-items: center;
  position: absolute;
  left: max(200px, calc(100% - 960px));
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-inverse-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Below this the links+CTA group is wide enough to reach the 200px floor above, so the clock
   would sit underneath it — hide it here rather than fight for the same space. Separate from
   the 880px breakpoint below, which is about collapsing the links into the mobile toggle. */
@media (max-width: 1100px) {
  .nav__clock { display: none; }
}

.nav__right {
  display: flex;
  align-items: stretch;
  gap: 0;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  background: rgba(32, 26, 24, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.14);
  padding: var(--space-3) var(--space-5);
  backdrop-filter: blur(10px);
}
.nav__links a {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-inverse-muted);
  border-bottom: 1px solid transparent;
}
.nav__links a:hover, .nav__links a:focus-visible { color: var(--ink-inverse); border-bottom-color: var(--ink-inverse); }

.nav__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Same height as .nav__logo (53px) — the two nav chips should match on desktop too. */
  height: 53px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-ink);
  background: var(--accent);
  padding-inline: var(--space-5);
  border: 1px solid var(--accent);
  white-space: nowrap;
}
/* Pink outline on hover, not white — the nav floats over white sections too, where a white
   fill with a white border disappeared into the page. */
.nav__cta:hover { background: var(--ink-inverse); color: var(--surface-hero); border-color: var(--accent); }

.nav__toggle {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.nav__toggle span {
  display: block;
  width: 18px;
  height: 1.5px;
  background: var(--ink-inverse);
}

.nav__backdrop { display: none; }

@media (max-width: 880px) {
  .nav__toggle {
    display: flex;
    /* Same height as .nav__logo (53px) so the two corner chips match — the icon's own
       content is much shorter than the logo's text, so height is set explicitly rather
       than left to padding. */
    height: 53px;
    width: 53px;
    background: rgba(32, 26, 24, 0.72);
    border: 1px solid rgba(255, 255, 255, 0.14);
    backdrop-filter: blur(10px);
  }

  /* the whole links+meta group collapses into one dropdown panel below the bar — animated via
     opacity/transform/visibility rather than the display:none/flex swap this replaced, since
     display can't be transitioned. visibility's own transition-delay keeps it out of layout/
     tab order while closed without cutting the opacity/transform animation short. */
  .nav__right {
    position: absolute;
    top: calc(100% + var(--space-3));
    left: 0;
    right: 0;
    background: rgba(32, 26, 24, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.14);
    backdrop-filter: blur(10px);
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-5);
    padding: var(--space-6) var(--space-5);
    opacity: 0;
    transform: translateY(-8px);
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s;
  }
  .nav.is-open .nav__right {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0s;
  }

  .nav__links {
    background: none;
    border: none;
    padding: 0;
    backdrop-filter: none;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
  }

  .nav__cta { justify-content: center; }

  /* Dims the rest of the page while the menu is open — sits behind the nav's own chips/panel
     (first child in the markup, so later siblings paint over it) but above everything else
     thanks to .nav's z-index:50. Closing by tapping it is wired up in js/main.js. */
  .nav__backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
  }
  .nav.is-open .nav__backdrop {
    opacity: 1;
    pointer-events: auto;
  }
}

/* ============ Section shells ============ */
#why-us, #solutions, #process, #faq, #contact {
  scroll-margin-top: 72px;
}

.section {
  padding-block: var(--space-9);
}
.section--tight { padding-block: var(--space-8); }
.section--inverse { background: var(--surface-hero); color: var(--ink-inverse); }
.section--muted { background: var(--surface-muted); }

.section__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin-bottom: var(--space-8);
  max-width: 820px;
}

/* Rule line — sits 20px below the eyebrow, full screen width (edge to edge, same guide
   as the eyebrow above it — not boxed to the statement's reading width). A fill acts as
   a scrollbar for the pinned text-reveal animation (driven directly from scroll progress in JS). */
.section__rule {
  position: relative;
  width: 100%;
  height: 1px;
  margin-top: 20px;
  margin-bottom: 80px;
  background: var(--border-hairline-muted);
  overflow: hidden;
}
.section__rule-fill {
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
.section--inverse .section__rule { background: var(--ink-inverse-muted); }
/* Same neutral hairline used by the stats block's own rule (03/08), for consistency across
   every eyebrow -> line -> text stack, dark or light background. */
.section--inverse .section__rule--quote { background: var(--border-hairline-muted); }

/* ============ IndexedRow ============ */
/* Divider lines draw in left-to-right, one after another, the first time the list scrolls
   into view (top rule first, then each row's own bottom rule in order) — same scaleX-fill
   technique as .section__rule-fill, just triggered once via IntersectionObserver instead of
   tracked continuously against scroll position. */
.indexed-row-list {
  position: relative;
}
.indexed-row-list::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--border-hairline-muted);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.4s cubic-bezier(0.65, 0, 0.35, 1);
}
.indexed-row-list.is-visible::before { transform: scaleX(1); }
.section--inverse .indexed-row-list::before { background: var(--ink-inverse-muted); }

.indexed-row {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: var(--space-5);
}
.indexed-row::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--border-hairline-muted);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.4s cubic-bezier(0.65, 0, 0.35, 1);
}
.section--inverse .indexed-row::after { background: var(--ink-inverse-muted); }
.indexed-row-list.is-visible .indexed-row::after { transform: scaleX(1); }
.indexed-row-list.is-visible .indexed-row:nth-child(1)::after { transition-delay: 0.28s; }
.indexed-row-list.is-visible .indexed-row:nth-child(2)::after { transition-delay: 0.56s; }
.indexed-row-list.is-visible .indexed-row:nth-child(3)::after { transition-delay: 0.84s; }
.indexed-row-list.is-visible .indexed-row:nth-child(4)::after { transition-delay: 1.12s; }
.indexed-row-list.is-visible .indexed-row:nth-child(5)::after { transition-delay: 1.4s; }
.indexed-row-list.is-visible .indexed-row:nth-child(6)::after { transition-delay: 1.68s; }
.indexed-row-list.is-visible .indexed-row:nth-child(7)::after { transition-delay: 1.96s; }

.indexed-row__main {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  flex: 1;
}
.indexed-row__index {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 500;
  color: var(--accent);
  width: 34px;
  flex-shrink: 0;
  /* optically centered on the title's first capital letter, not the row's line box */
  padding-top: 7px;
}
.indexed-row__body { flex: 1; }
.indexed-row__title { color: var(--ink-primary); }
.section--inverse .indexed-row__title { color: var(--ink-inverse); }
.indexed-row__desc {
  margin-top: var(--space-2);
  color: var(--ink-secondary);
}
.section--inverse .indexed-row__desc { color: var(--ink-inverse-muted); }
.indexed-row__arrow {
  display: inline-block;
  margin-right: var(--space-2);
  color: var(--ink-muted);
}
.indexed-row__num {
  flex-shrink: 0;
  margin-top: 7px;
  font-size: 18px;
  color: var(--accent);
}

/* ============ Solutions — eyebrow/line/heading stack + row table, both edge to edge ============ */
.solutions__header {
  padding-inline: var(--space-5);
  margin-bottom: 50px;
}
.solutions__title {
  max-width: 960px;
  margin-left: auto;
  color: var(--ink-primary);
}
.solutions__rows-wrap {
  /* outer padding only — the ol's own max-width:960/margin-left:auto (from the generic
     .indexed-row-list rule) then lands on the exact same guide as .solutions__title,
     which is padded the same way one level up in .solutions__header */
  padding-inline: var(--space-5);
}

/* ============ Process — same eyebrow/line/heading stack as Solutions, flush against the
   section on the shared var(--space-5) guide, not boxed inside .container ============ */
.process__header {
  padding-inline: var(--space-5);
  margin-bottom: 50px;
}
.process__title {
  max-width: 960px;
  margin-left: auto;
  color: var(--ink-primary);
}
.process-steps-wrap {
  /* outer padding only — .process-steps' own max-width:960/margin-left:auto then lands on
     the exact same guide as .process__title, which is padded the same way one level up */
  padding-inline: var(--space-5);
}
.indexed-row__square {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  /* optically centered on the title's cap-height, not the row's line box */
  margin-top: 17px;
  background: var(--accent);
}

/* ============ QuoteBlock ============ */
.quote-block {
  padding-block: var(--space-9);
}
/* Flush to the same left guide as the nav/hero/why-us content (var(--space-5)), not the
   wider .container padding — and unconstrained in width, so the line and statement both
   run edge to edge instead of sitting in a narrow reading column. */
.quote-block__inner {
  display: flex;
  flex-direction: column;
  padding-inline: var(--space-5);
}
/* Icon particle field in the free space left of the statement (js/main.js sizes and places the
   shapes). Only where that space is wide enough to hold them. */
.quote-block--particles { position: relative; }
.quote-block--particles .quote-block__inner { position: relative; z-index: 1; }
.quote-block__particles {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
@media (max-width: 1199px) {
  .quote-block__particles { display: none; }
}

/* No separate headline here — one flowing statement, sized and weighted the same as the
   why-us statement (block 2), and following that same guide: full-width rule at the left
   edge, but the text itself capped and pushed onto the same right-hand column. */
.quote-block__statement {
  max-width: 960px;
  margin-left: auto;
}

/* Line fill and word opacity are both set directly from scroll position in JS (same
   technique as the why-us statement, block 2) — no CSS transition, the scroll itself
   provides the motion. .word's 20% base opacity matches the why-us statement's own. */
.quote-block__statement .word {
  opacity: 0.2;
}

/* ============ StatBlock ============ */
/* Eyebrow flush at the page's own left guide, statement on the shared right-hand column —
   same stack as the why-us and quote-block headers, just outside .container so it can
   reach that same var(--space-5) edge instead of the grid's wider container padding. */
.stats__header {
  padding-inline: var(--space-5);
  margin-bottom: 50px;
}

/* Left (blank + accent) column is flexible/quiet — no border at all. Right column is the
   bordered 2x2 number grid, held to the same max-width:960 + margin-left:auto guide as the
   statement text above, so its left edge lines up with the text exactly, at any width. */
.stats__grid-row {
  padding-inline: var(--space-5);
  display: flex;
  /* nowrap, not wrap — .stat-grid__side and .stat-grid__numbers together are wider than the
     row at some in-between (tablet-ish) widths, and letting flexbox wrap them on its own
     accidentally re-triggers the exact stacked-column layout the controlled media query
     below is meant to own, at whatever width the content happens to give way — which turned
     out to be as high as ~1025px, not the 720px the query below assumes. Side/numbers just
     shrink instead now; only the explicit query below ever stacks them. */
  flex-wrap: nowrap;
  /* no gap — the accent panel should reach all the way to the numbers grid's own left
     edge (the shared guide), not stop short of it */
  gap: 0;
}
.stat-grid__side {
  flex: 1 1 200px;
  display: flex;
  flex-direction: column;
}
.stat-grid__numbers {
  flex: 0 1 960px;
  max-width: 960px;
  margin-left: auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  /* muted, not the near-black --border-hairline used elsewhere — that read as a proper
     divider against white panels but as a harsh outline against the solid accent pink */
  background: var(--border-hairline-muted);
  border: 1px solid var(--border-hairline-muted);
}
.stat-panel {
  background: var(--surface-page);
  padding: var(--space-6);
  min-height: 220px;
  display: flex;
  flex-direction: column;
  /* label pinned to the top, value pinned to the bottom — the two ends of the cell,
     not grouped together, matching the reference's spacing */
  justify-content: space-between;
}
.stat-panel--page { background: var(--surface-page); }
.stat-panel--accent { background: var(--accent); }
.stat-panel--empty { background: var(--surface-page); }

.stat-panel__value {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(34px, 4vw, 56px);
  line-height: 1;
}
.stat-panel--page .stat-panel__value { color: var(--ink-primary); }
.stat-panel--accent .stat-panel__value { color: var(--accent-ink); }

/* Cursor tilt (js/main.js adds .is-tiltable on mouse/trackpad devices): the tilting panel
   lifts above its neighbours with a shadow, its strength coming in as --tilt-on. */
.stat-panel.is-tiltable {
  position: relative;
  transform-origin: 50% 50%;
  will-change: transform;
}
.stat-panel.is-tilting {
  z-index: 3;
  box-shadow: 0 24px 50px -24px rgba(28, 25, 23, calc(0.35 * var(--tilt-on, 0)));
}

.stat-panel__value-inner {
  display: inline-block;
  /* Left/bottom stays put as js/main.js scales this down into place, so only the top edge
     grows past the number's own box — deliberately NOT clipped (no overflow: hidden on
     .stat-panel__value above): the bottom-row numbers are meant to visibly overlap the row
     above while they're still oversized, exactly like norda.framer.website's own cards. */
  transform-origin: left bottom;
}

.stat-panel__label {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.stat-panel--page .stat-panel__label { color: var(--ink-muted); }
.stat-panel--accent .stat-panel__label { color: var(--accent-ink); opacity: 0.85; }

/* The stat numbers' oversized entrance (2.6x, js/main.js) is meant to overlap the row ABOVE,
   so vertical overflow stays visible — but sideways it ran past the screen edge on phones
   (e.g. "500,000+" at 2.6x in a single 370px column), briefly widening the page enough for
   mobile Safari to allow horizontal scrolling. clip, not hidden: hidden would turn the
   section into a scroll container and force the vertical axis to clip as well. */
.stats { overflow-x: clip; }

@media (max-width: 720px) {
  .stats__grid-row { flex-direction: column; gap: var(--space-5); }
  /* flex: none — stacked in a column, the desktop flex-basis of 960px became a fixed 960px
     HEIGHT, and whatever the four panels didn't fill showed the grid's grey hairline colour
     as a block underneath them. */
  .stat-grid__numbers { max-width: none; margin-left: 0; flex: none; }
  /* .stat-panel--empty is a blank spacer that quietly fills width next to the accent panel
     in the desktop row layout — stacked in a mobile column, that same panel is just a big
     empty box sitting on top of the accent one. Hide it so the accent panel (the real
     content) is what actually follows the intro text. */
  .stat-panel--empty { display: none; }
}
@media (max-width: 480px) {
  .stat-grid__numbers { grid-template-columns: 1fr; }
}

/* ============ FAQ header — same eyebrow/line/heading stack as Process/Solutions ============ */
.faq__header {
  padding-inline: var(--space-5);
  margin-bottom: 50px;
}
.faq__title {
  max-width: 960px;
  margin-left: auto;
  color: var(--ink-primary);
}
.section--inverse .faq__title { color: var(--ink-inverse); }
/* True black, not the warm .section--inverse hero tone the quote-blocks use — .faq-list-wrap's
   own ID/element selectors don't need this, but the section itself is targeted directly so
   only FAQ gets it, not every .section--inverse block on the page. */
#faq.section--inverse { background: var(--surface-inverse); }
.faq-list-wrap {
  /* outer padding only — .faq-list's own max-width:960/margin-left:auto then lands on the
     exact same guide as .faq__title, which is padded the same way one level up */
  padding-inline: var(--space-5);
}

/* ============ FAQ accordion ============ */
/* Rectangles, not the old hairline-divided flat list — each question is its own bordered
   box, titled in caps-lg like Solutions' row titles, but with no accent square. Full width
   edge to edge on the shared guide (not the narrower 960-column the statement text uses) —
   .faq-list-wrap's own padding-inline is the only inset, same as .solutions__rows-wrap. */
.faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.faq-item {
  border: 1px solid var(--border-hairline);
  padding-inline: var(--space-5);
}
.section--inverse .faq-item {
  border-color: rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.04);
}
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: var(--space-5);
  text-align: left;
}
.faq-question__text {
  color: var(--ink-primary);
}
.section--inverse .faq-question__text { color: var(--ink-inverse); }
.faq-toggle {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 20px;
  line-height: 1;
  color: var(--ink-muted);
}
.section--inverse .faq-toggle { color: var(--ink-inverse-muted); }
.faq-question[aria-expanded="true"] .faq-toggle {
  color: var(--accent);
}
.faq-answer {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.2s ease;
}
.faq-answer__inner {
  padding-bottom: var(--space-5);
  max-width: 720px;
  color: var(--ink-secondary);
}
.section--inverse .faq-answer__inner { color: var(--ink-inverse-muted); }
.faq-item.is-open { border-color: var(--accent); }
.faq-item.is-open .faq-answer { max-height: 400px; }

/* ============ Legal pages (Privacy / Terms / Cookie) ============ */
/* Same eyebrow -> line -> title stack as every other section, on the same shared guide as
   every H2 on the site (width:100%/max-width:960/margin-left:auto — lands at the same x as
   the nav clock). A narrower 720px column then sits inside that guide-positioned box for the
   paragraph text (nested, so it can be narrower without shifting off the guide's left edge —
   same trick .faq-answer__inner uses inside .faq-item). */
.legal-page__container {
  padding-inline: var(--space-5);
}
.legal-page__header {
  margin-bottom: 50px;
}
.legal-page__title,
.legal-page__meta,
.legal-page__body {
  width: 100%;
  max-width: 960px;
  margin-left: auto;
}
.legal-page__title {
  color: var(--ink-primary);
}
.legal-page__meta {
  margin-top: var(--space-3);
  color: var(--ink-muted);
}
.legal-page__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}
.legal-page__intro {
  max-width: 720px;
}
.legal-page__section {
  max-width: 720px;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.legal-page__section h2 {
  color: var(--ink-primary);
}
.legal-page__section p,
.legal-page__section li {
  color: var(--ink-secondary);
}
.legal-page__section ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-left: var(--space-5);
  list-style: disc;
}
.legal-page__section a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.legal-page__intro {
  color: var(--ink-secondary);
}

/* ============ Footer ============ */
.footer {
  background: var(--surface-inverse);
  color: var(--ink-inverse);
  overflow: hidden;
}
/* Particle cloud that drifts behind the footer content (js/main.js); pointer-events: none so
   it never gets between the cursor and the links/CTA. */
.footer { position: relative; }
.footer__cloud {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.footer__inner { position: relative; z-index: 1; }
/* Flush at the same var(--space-5) guide as every other section's eyebrow/heading on the
   page (not .container's wider, responsive space-8 pad) — the earlier space-8 version put the
   logo/CTA/nav a full 40px right of where everything else on the page lines up. */
.footer__inner {
  padding-inline: var(--space-5);
  padding-top: var(--space-8);
  padding-bottom: 10px;
}

/* Brand/back-to-top/copyright are pulled out of flow (absolute, left:0) so the CTA
   heading/nav/legal-links next to them can use the page's actual shared guide — the same
   width:100%;max-width:960px;margin-left:auto rule every H2 statement uses elsewhere on the
   site — instead of a fixed grid column that only happens to line up at one viewport width. */
.footer__top {
  position: relative;
  margin-top: 100px;
}
/* On the home page the footer follows the contact section, which is the same dark colour, so
   the two read as one field — there the 100px above (meant to open the dark band after the
   white legal pages) just stacked onto the section's own bottom padding as a big empty gap
   between the form and the footer. */
main:has(> .contact-form:last-child) + .footer .footer__top { margin-top: 0; }
.footer__brand {
  position: absolute;
  left: 0;
  top: 0;
  max-width: 320px;
}
/* No mark, just the tagline — sits flush with the CTA heading's own top (both start at the
   row's top edge: the tagline via this absolute box, the heading as a flex-start-aligned
   item), so the two read as one horizontal line. */
.footer__tagline {
  color: var(--accent);
  line-height: 1.5;
}

/* Heading and button sit side by side in one row (checked against the Figma spec — not
   stacked, as the source reference screenshot's compression made it look). Top-aligned so the
   heading's first line, the button, and the tagline all share the same top row. The button is
   pulled out of flow (js/main.js) onto the same vertical guide as the Contact column below and
   Cookie Policy in the legal row — position:relative here is that absolute box's anchor. */
.footer__cta {
  position: relative;
  width: 100%;
  max-width: 960px;
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
}
.footer__cta-title {
  position: relative;
  top: -5px;
  color: var(--ink-inverse);
}
.footer__cta-btn { display: inline-flex; align-items: stretch; }
.footer__cta-label {
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--surface-hero);
  background: var(--ink-inverse);
  padding: var(--space-3) var(--space-5);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.footer__cta-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  background: var(--accent);
  flex-shrink: 0;
  transition: background-color 0.15s ease;
}
.footer__cta-arrow svg { width: 20px; height: 20px; transition: stroke 0.15s ease; }
/* Two-part swap: the label turns pink/white, the arrow box turns white with a pink icon —
   same pattern on every arrow button on the site (hero, quote-block, footer). */
.footer__cta-btn:hover .footer__cta-label { background: var(--accent); color: var(--ink-inverse); }
.footer__cta-btn:hover .footer__cta-arrow { background: var(--ink-inverse); }
.footer__cta-btn:hover .footer__cta-arrow svg { stroke: var(--accent); }

/* Full-bleed divider between the CTA row and the nav row — 50px clear space above and below
   it (the margins), bleeding past .footer__inner's own side padding the same way the wordmark
   does, so it runs edge to edge rather than stopping at the shared guide. */
.footer__divider {
  /* Full-bleed minus 20px on each side (not all the way to the viewport edge like the
     wordmark) — grey like every other line on the site (var(--ink-inverse-muted) is the
     dark-background equivalent of --border-hairline-muted, same pairing the FAQ item borders
     use). */
  margin-inline: calc(-1 * var(--space-5) + 20px);
  width: calc(100% + (var(--space-5) - 20px) * 2);
  height: 1px;
  margin-top: 50px;
  margin-bottom: 50px;
  background: var(--ink-inverse-muted);
}
.footer__nav-row {
  position: relative;
  padding-top: 0;
  padding-bottom: var(--space-8);
}
.footer__back-to-top {
  position: absolute;
  left: 0;
  top: 0;
  color: var(--ink-inverse-muted);
}
.footer__back-to-top:hover { color: var(--ink-inverse); }
.footer__nav {
  width: 100%;
  max-width: 960px;
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  /* Three vertical guides — Menu flush left (matching the CTA heading and Privacy Policy
     above/below it), then Social, then More — each a fixed 200px from the last. */
  gap: 200px;
}
.footer__nav-group { display: flex; flex-direction: column; gap: var(--space-3); }
.footer__nav-label { color: var(--ink-inverse-muted); }
.footer__nav-group a { color: var(--ink-inverse-muted); }
.footer__nav-group a:hover { color: var(--ink-inverse); }
.footer__nav-static { color: var(--ink-inverse-muted); }
/* Social column with no confirmed profile URLs yet: kept in the layout (it's one of the footer's
   three guides, and js/main.js lines Cookie Policy up under it) but not shown. Drop the class
   and put the links back once real profile URLs are confirmed. */
.footer__nav-group--social-pending { visibility: hidden; }

/* More column: the AI translation note (a few lines of plain text, no page to link to yet),
   then Contact + email in normal flow underneath it. Contact used to be pinned to the About/FAQ
   rows of the Menu column, which only worked while the item above it was a one-line link. */
.footer__nav-group--more-contact { position: relative; min-width: 150px; }
.footer__nav-note { max-width: 300px; }
.footer__nav-contact-label { margin-top: var(--space-3); }

/* Oversized wordmark, filling the row edge to edge on the same guide as everything above it
   (not full viewport bleed) — a fluid vw-based size so it always reads as one continuous
   line regardless of viewport width. */
/* Bleeds past .footer__inner's own side padding to run truly edge to edge (unlike the rest
   of the footer, which stays on the shared guide) — margin/width cancel that padding out
   exactly. font-size is set from JS, measured directly off the rendered text so it always
   spans the full row exactly regardless of copy length or viewport width; the clamp() here
   is only a pre-JS fallback so the line isn't huge/unstyled for an instant on load. */
.footer__wordmark {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  /* Same 20px-each-side rule as .footer__divider — not a full bleed to the viewport edge. */
  margin-inline: calc(-1 * var(--space-5) + 20px);
  width: calc(100% + (var(--space-5) - 20px) * 2);
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(48px, 11vw, 220px);
  line-height: 0.85;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  padding-top: var(--space-7);
  padding-bottom: 10px;
  margin-top: -45px;
}
.footer__wordmark-accent { color: var(--accent); }
.footer__wordmark-rest { color: var(--ink-inverse); }

.footer__bottom {
  position: relative;
  color: var(--ink-inverse-muted);
}
.footer__copyright {
  position: absolute;
  left: 0;
  bottom: 0;
}
.footer__legal {
  position: relative;
  width: 100%;
  max-width: 960px;
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}
/* Same line as the copyright, far right corner — 20px from the true viewport edge (the
   footer's other "always 20px" elements: the divider and the wordmark), not the site's usual
   24px guide, so it sits 4px further out than .footer__legal's own right edge. */
.footer__credit {
  position: absolute;
  right: -4px;
  bottom: 0;
}
.footer__credit-accent { color: var(--accent); }
a.footer__credit-accent { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px; transition: text-decoration-color 0.15s ease; }
a.footer__credit-accent:hover { text-decoration-color: currentColor; }

/* Below the width where .footer__nav's columns wrap onto multiple lines, the measured
   Social/More-column offsets stop meaning anything — js/main.js only applies them above this
   breakpoint, so fall the brand/button/legal-links back to normal stacked flow here. */
@media (max-width: 880px) {
  .footer__brand,
  .footer__back-to-top,
  .footer__copyright {
    position: static;
    margin-bottom: var(--space-5);
  }
  .footer__credit {
    position: static;
    margin-top: var(--space-5);
  }
  .footer__cta-btn,
  .footer__legal a:nth-child(2),
  .footer__legal a:last-child {
    position: static !important;
    transform: none !important;
  }

  /* Temporarily hidden — bring back later. */
  .footer__back-to-top { display: none; }

  /* Nav becomes a 2-column grid: Menu/Social on row 1, More/Legal on row 2 — js/main.js moves
     the actual .footer__legal node into .footer__nav (as the 4th grid item) here, and moves
     .footer__credit/.footer__copyright around .footer__wordmark, only at this breakpoint. */
  .footer__nav {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-6);
    row-gap: var(--space-6);
  }
  .footer__nav-group:nth-child(1) { grid-column: 1; grid-row: 1; }
  .footer__nav-group:nth-child(2) { grid-column: 2; grid-row: 1; }
  .footer__nav-group--more-contact {
    grid-column: 1;
    grid-row: 2;
  }
  /* The More label row-matches Privacy Policy beside it (js/main.js — a mono-label and a
     body-sm link render at slightly different heights, so a shared gap alone doesn't land them
     on the same line). The note and Contact below it just flow. */
  .footer__nav-group--more-contact > * { position: relative; }
  .footer__legal {
    grid-column: 2;
    grid-row: 2;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: var(--space-3);
  }

  /* Design credit sits above the wordmark now (right-aligned), copyright below it (last
     element in the footer) — js/main.js reorders the actual DOM nodes to match. */
  .footer__credit {
    text-align: right;
    /* same size as the copyright line (.body-sm: 14px here, 16px at <=720px below) rather
       than the 18-20px caps-lg it uses on desktop */
    font-size: 14px;
    line-height: 1.5;
  }
  /* Copyright is the very last element now — drop the trailing margin-bottom every other
     static-reset item gets above, so .footer__inner's own 10px padding-bottom is the only
     space left below it. */
  .footer__copyright { margin-bottom: 0; }
}

/* Arrow buttons go full-width on mobile (edge to edge on the shared 10px gutter) — the
   label grows to fill the row, the arrow box stays a fixed 50px square. Same treatment as
   the hero/quote-block buttons in main.css. */
@media (max-width: 720px) {
  .footer__credit { font-size: 16px; }
  .footer__cta-btn { width: 100%; }
  .footer__cta-label { flex: 1; justify-content: center; }
  .footer__cta-arrow { width: 50px; }
  .contact-form__submit { width: 100%; }
  .contact-form__submit-label { flex: 1; justify-content: center; }
  .contact-form__submit-arrow { width: 50px; }
}

/* ============ Contact / Request a Quote ============ */
/* Same eyebrow/line/heading stack as Solutions/Process/Stats/FAQ, flush against the section
   on the shared var(--space-5) guide, not boxed inside .container — the heading itself then
   sits on the narrower 960px guide via margin-left:auto, same as every other section. */
.contact-form__header {
  padding-inline: var(--space-5);
  margin-bottom: 50px;
}
.contact-form__title {
  max-width: 960px;
  margin-left: auto;
  color: var(--ink-inverse);
}
/* Same left-margin/right-guide split as the footer's tagline + CTA row: .contact-form__intro
   pulled out of flow onto the shared var(--space-5) guide (same edge the nav logo sits on),
   so .contact-form__form can use the page's actual 960px content guide — the one "Let us
   cover your next event" itself sits on — without the intro column's width eating into it. */
.contact-form__inner {
  position: relative;
  padding-inline: var(--space-5);
}
.contact-form__intro {
  position: absolute;
  /* .contact-form__inner is both the positioned ancestor and the padded one (unlike the
     footer's two-level split), so the absolute child's containing block is the padding
     edge — left has to restate the guide explicitly rather than relying on the padding. */
  left: var(--space-5);
  top: 0;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.contact-form__lead {
  max-width: 420px;
  color: var(--ink-inverse-muted);
}

.contact-form__method {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.04);
  padding: var(--space-4) var(--space-5);
  margin-top: var(--space-2);
  transition: border-color 0.15s ease;
}
.contact-form__method:hover { border-color: var(--accent); }
.contact-form__method-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--ink-inverse-muted);
}
.contact-form__method-icon svg { width: 18px; height: 18px; }
.contact-form__method-text { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.contact-form__method-title { font-family: var(--font-sans); font-weight: 600; color: var(--ink-inverse); }
.contact-form__method-meta { font-family: var(--font-mono); font-size: 13px; color: var(--ink-inverse-muted); }
.contact-form__method-arrow { display: flex; color: var(--ink-inverse-muted); flex-shrink: 0; transition: color 0.15s ease; }
.contact-form__method-arrow svg { width: 16px; height: 16px; }
.contact-form__method:hover .contact-form__method-arrow { color: var(--accent); }

.contact-form__trust {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-inverse-muted);
  margin-top: var(--space-2);
}
.contact-form__trust-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* ---- form ---- */
.contact-form__form {
  width: 100%;
  max-width: 960px;
  margin-left: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}
.contact-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
.contact-form__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  border: none;
  padding: 0;
  margin: 0;
}
.contact-form__field .mono-label { color: var(--ink-inverse-muted); }
.contact-form__input {
  width: 100%;
  font-family: var(--font-content);
  font-size: 16px;
  color: var(--ink-inverse);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.15);
  padding: var(--space-4) var(--space-5);
  transition: border-color 0.15s ease;
}
.contact-form__input::placeholder { color: var(--ink-inverse-muted); }
.contact-form__input:focus { outline: none; border-color: var(--accent); }
.contact-form__textarea { min-height: 120px; resize: vertical; font-family: var(--font-content); }
/* Native date-picker icon renders dark-on-dark otherwise — color-scheme flips it to the
   light glyph that actually reads against this field's background. */
.contact-form__input[type="date"] { color-scheme: dark; }
/* iOS Safari draws a date input as its own native control: an intrinsic minimum width that
   pushes it past a narrow column, its own height (collapsing further while empty) and the
   value centred. Strip the native look and give it the same box as the text inputs (58px:
   16px text + 2 x 16px padding + borders); the tap still opens the system date picker. */
.contact-form__input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  min-width: 0;
  max-width: 100%;
  height: 58px;
  line-height: 1.5;
  text-align: left;
}
.contact-form__input[type="date"]::-webkit-date-and-time-value {
  text-align: left;
  margin: 0;
}

/* ---- sliders ---- */
/* A plain <input type=range> has no room to show its own value — .contact-form__slider-value
   is a small floating badge js/main.js slides along the track in step with the thumb. */
.contact-form__slider { position: relative; padding-top: 30px; }
.contact-form__slider-value {
  position: absolute;
  top: 0;
  left: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--accent-ink);
  background: var(--accent);
  padding: 3px 8px;
  white-space: nowrap;
}
.contact-form__range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 2px;
  background: rgba(255, 255, 255, 0.2);
  outline: none;
  margin: 10px 0;
}
.contact-form__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ink-inverse);
  border: 2px solid var(--accent);
  cursor: pointer;
}
.contact-form__range::-moz-range-track {
  background: rgba(255, 255, 255, 0.2);
  height: 2px;
}
.contact-form__range::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ink-inverse);
  border: 2px solid var(--accent);
  cursor: pointer;
}
.contact-form__slider-scale {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-inverse-muted);
}

/* ---- radios / checkbox ---- */
.contact-form__radios {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-top: var(--space-2);
}
.contact-form__radio {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  color: var(--ink-inverse-muted);
  font-family: var(--font-content);
}
.contact-form__radio input { accent-color: var(--accent); width: 16px; height: 16px; }
.contact-form__radio:has(input:checked) { color: var(--ink-inverse); }

.contact-form__checkbox {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--ink-inverse-muted);
  font-family: var(--font-content);
  font-size: 14px;
  cursor: pointer;
}
.contact-form__checkbox input { accent-color: var(--accent); width: 16px; height: 16px; margin-top: 2px; flex-shrink: 0; }
.contact-form__checkbox a { color: var(--ink-inverse); text-decoration: underline; text-underline-offset: 2px; }
.contact-form__checkbox a:hover { color: var(--accent); }

/* ---- submit ---- */
.contact-form__submit-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.contact-form__submit { display: flex; align-items: stretch; }
.contact-form__submit-label {
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-inverse);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  padding: var(--space-4) var(--space-6);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.contact-form__submit-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  background: var(--accent);
  border: 1px solid var(--accent);
  flex-shrink: 0;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.contact-form__submit-arrow svg { width: 20px; height: 20px; transition: stroke 0.15s ease; }
/* Same two-part hover swap as every other arrow button on the site. */
.contact-form__submit:hover .contact-form__submit-label { background: var(--accent); border-color: var(--accent); }
.contact-form__submit:hover .contact-form__submit-arrow { background: var(--ink-inverse); border-color: var(--ink-inverse); }
.contact-form__submit:hover .contact-form__submit-arrow svg { stroke: var(--accent); }
/* Phones: every arrow button is the same 44px tall with a 50px arrow box (hero, quote-block
   and 06 CTAs already are). Placed after the base rules above so it actually wins — the
   earlier mobile block's 50px arrow width for this button was being overridden by them. The
   footer label has no border, hence 13px rather than 12px padding to land on the same 44. */
@media (max-width: 720px) {
  .contact-form__submit-label { padding-block: var(--space-3); }
  .contact-form__submit-arrow { width: 50px; }
  .footer__cta-label { padding-block: 13px; }
}
.contact-form__submit:disabled { opacity: 0.5; pointer-events: none; }

.contact-form__status {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-inverse-muted);
}
.contact-form__status.is-success { color: var(--accent); }
.contact-form__status.is-error { color: #ff6b6b; }

/* The intro column (320px) and the form need ~1380px side by side. Wide screens that are
   still short of that: the form (and the heading above it, so they stay on one guide) gives
   up width to the intro instead of sliding underneath it. Below 1100px the intro drops into
   the flow above the form, on the form's own guide, as a lead line + the two contact cards
   side by side. */
@media (min-width: 1101px) {
  .contact-form__title,
  .contact-form__form {
    max-width: min(960px, calc(100% - 320px - var(--space-7)));
  }
}
@media (max-width: 1100px) {
  .contact-form__intro {
    position: static;
    max-width: 960px;
    margin: 0 0 var(--space-8) auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4) var(--space-5);
  }
  .contact-form__lead,
  .contact-form__trust { grid-column: 1 / -1; }
  .contact-form__method { margin-top: 0; }
}
@media (max-width: 600px) {
  .contact-form__row { grid-template-columns: 1fr; }
  .contact-form__intro { grid-template-columns: 1fr; }
}

/* ============ Scroll blur ============ */
/* Fixed band at the bottom of the viewport that progressively blurs whatever page content
   scrolls underneath it — content nearest the true edge blurs the most, fading to fully sharp
   toward the top of the band. Recipe matched from mugenstudio.framer.website's own progressive
   blur (read directly off its computed styles, at both a wide and a narrow viewport): the band
   is 20vh tall (scales with the viewport, not a fixed px height), 8 stacked layers with blur
   doubling from a barely-there 0.0546875px up to 7px — much gentler than this file's previous
   neiden.framer.media recipe (0.3px→20px), which is the "softer" Irina pointed at. Each layer
   fades in AND back out over its own 12.5%-of-band window, overlapping the next layer's fade —
   a "tent" mask, unlike neiden's non-overlapping hand-offs. That topology ghosted on flat
   saturated fills there because two very different blur radii (up to 20px apart) crossfaded
   over the same edge; here the gap between adjacent layers is at most ~3.5px, small enough that
   the same overlap reads as soft rather than doubled. No saturate boost either, matching the
   reference exactly. pointer-events: none throughout so it never intercepts clicks on real
   content. */
.scroll-blur {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 20vh;
  pointer-events: none;
  z-index: 40;
  transition: opacity 0.3s ease;
}
/* Hidden once js/main.js detects there's no more page left to scroll into — the blur reads as
   "more below," which stops being true at the very bottom. */
.scroll-blur.is-hidden { opacity: 0; }
.scroll-blur__layer {
  position: absolute;
  inset: 0;
}
.scroll-blur__layer:nth-child(1) {
  backdrop-filter: blur(0.0546875px);
  -webkit-backdrop-filter: blur(0.0546875px);
  mask-image: linear-gradient(transparent 0%, #000 12.5%, #000 25%, transparent 37.5%);
  -webkit-mask-image: linear-gradient(transparent 0%, #000 12.5%, #000 25%, transparent 37.5%);
}
.scroll-blur__layer:nth-child(2) {
  backdrop-filter: blur(0.109375px);
  -webkit-backdrop-filter: blur(0.109375px);
  mask-image: linear-gradient(transparent 12.5%, #000 25%, #000 37.5%, transparent 50%);
  -webkit-mask-image: linear-gradient(transparent 12.5%, #000 25%, #000 37.5%, transparent 50%);
}
.scroll-blur__layer:nth-child(3) {
  backdrop-filter: blur(0.21875px);
  -webkit-backdrop-filter: blur(0.21875px);
  mask-image: linear-gradient(transparent 25%, #000 37.5%, #000 50%, transparent 62.5%);
  -webkit-mask-image: linear-gradient(transparent 25%, #000 37.5%, #000 50%, transparent 62.5%);
}
.scroll-blur__layer:nth-child(4) {
  backdrop-filter: blur(0.4375px);
  -webkit-backdrop-filter: blur(0.4375px);
  mask-image: linear-gradient(transparent 37.5%, #000 50%, #000 62.5%, transparent 75%);
  -webkit-mask-image: linear-gradient(transparent 37.5%, #000 50%, #000 62.5%, transparent 75%);
}
.scroll-blur__layer:nth-child(5) {
  backdrop-filter: blur(0.875px);
  -webkit-backdrop-filter: blur(0.875px);
  mask-image: linear-gradient(transparent 50%, #000 62.5%, #000 75%, transparent 87.5%);
  -webkit-mask-image: linear-gradient(transparent 50%, #000 62.5%, #000 75%, transparent 87.5%);
}
.scroll-blur__layer:nth-child(6) {
  backdrop-filter: blur(1.75px);
  -webkit-backdrop-filter: blur(1.75px);
  mask-image: linear-gradient(transparent 62.5%, #000 75%, #000 87.5%, transparent 100%);
  -webkit-mask-image: linear-gradient(transparent 62.5%, #000 75%, #000 87.5%, transparent 100%);
}
.scroll-blur__layer:nth-child(7) {
  backdrop-filter: blur(3.5px);
  -webkit-backdrop-filter: blur(3.5px);
  mask-image: linear-gradient(transparent 75%, #000 87.5%, #000 100%);
  -webkit-mask-image: linear-gradient(transparent 75%, #000 87.5%, #000 100%);
}
.scroll-blur__layer:nth-child(8) {
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  mask-image: linear-gradient(transparent 87.5%, #000 100%);
  -webkit-mask-image: linear-gradient(transparent 87.5%, #000 100%);
}
@media (prefers-reduced-motion: reduce) {
  .scroll-blur { transition: none; }
}
