/* ============================================================
   ACG Align
   Brand strategy and design. Casablanca.
   "Become the standard."
   ============================================================ */

/* ---------- 1. Tokens ---------- */

:root {
  /* Brand core */
  --white:        #FFFFFF;
  --navy:         #040F36;
  --grey:         #979797;
  --black:        #00030B;
  --blue:         #103FEA;
  /* On dark surfaces the accent is white. #103FEA is reserved for light
     surfaces and primary actions, where it has the contrast to carry text. */
  --accent-dark:  #FFFFFF;

  /* Surfaces. The site runs dark: black is the page, and the lifted surface
     carries the alternating band rhythm. */
  --paper:        #00030B;
  --paper-2:      #070C1C;
  --paper-3:      #0C1226;

  /* Ink on the dark page */
  --ink:          rgba(255, 255, 255, .96);
  --ink-80:       rgba(255, 255, 255, .74);
  --ink-62:       rgba(255, 255, 255, .60);
  --ink-45:       rgba(255, 255, 255, .44);
  --rule:         rgba(255, 255, 255, .14);
  --rule-soft:    rgba(255, 255, 255, .07);

  /* The nav pill: dark frosted glass, not a light card. Header text (white)
     stays one colour whether the bar is flat or the pill has formed. */
  --pill:         rgba(8, 11, 22, .62);
  --pill-border:  rgba(255, 255, 255, .09);
  /* Used only by the mobile dropdown panel below, which is its own solid
     light surface and is unaffected by the header pill going dark. */
  --pill-ink:     #00030B;

  --hdr-h:        3rem;   /* the bar's resting height, for content offset */
  --ease-pill:    cubic-bezier(.22, 1, .28, 1);
  /* How far each side of the bar draws in when the pill appears. Both
     edges move, so the wordmark closes in with everything else. */
  --hdr-pad-x:    clamp(1.1rem, 1.9vw, 2rem);  /* .hdr__in's own padding-inline */
  --pill-inset:   clamp(.75rem, 4.5vw, 4.5rem);
  --pill-inset-y: 0px;
  --pill-gap:     14px;   /* breathing room between the pill's cap and its content */
  /* The right end is capped by the CTA, which is the same height and radius
     as the bar, so it nests into the cap with no gap at all. Below the nav
     breakpoint the hamburger sits there instead and the gap comes back. */
  --pill-gap-end: 0px;
  --nav-in:       640ms;   /* pill closing in */
  --nav-out:      300ms;   /* returning to the flat bar */

  /* Ink on dark */
  --on-dark:      rgba(255, 255, 255, .96);
  --on-dark-70:   rgba(255, 255, 255, .70);
  --on-dark-48:   rgba(255, 255, 255, .48);
  --rule-dark:    rgba(255, 255, 255, .16);
  --rule-dark-soft: rgba(255, 255, 255, .08);

  /* Type */
  /* One typeface for the whole site: headings, body, interface, and the
     wordmark all read as Inter. */
  --display: "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --body:    "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --logo:    "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* "ACG" is set in Alexandria SemiBold wherever it appears, including
     mid-sentence; "Align" always stays Inter Regular beside it. */
  --acg:     "Alexandria", "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --t-display: clamp(3.25rem, 9.2vw, 8.25rem);
  --t-h1:      clamp(2.6rem,  6.4vw, 5.5rem);
  --t-h2:      clamp(2rem,    4.1vw, 3.5rem);
  --t-h3:      clamp(1.375rem, 2.1vw, 1.875rem);
  --t-lead:    clamp(1.125rem, 1.55vw, 1.5rem);
  --t-body:    1.0625rem;
  --t-small:   .9375rem;
  --t-micro:   .75rem;

  /* Rhythm */
  --gutter:    clamp(1.25rem, 4vw, 3.5rem);
  --max:       1360px;
  --measure:   62ch;
  --section:   clamp(5rem, 11vw, 10.5rem);

  /* Motion */
  --ease:      cubic-bezier(.16, 1, .3, 1);
  --ease-ui:   cubic-bezier(.32, .72, 0, 1);
  /* The entrance curve. --ease is an expo-out: almost all of its travel is
     spent in the first third, which is right for a UI response but makes a
     reveal look like it has already happened. This one leaves gently and
     settles gently, so the whole duration is visible. */
  --ease-in-out: cubic-bezier(.34, .12, .2, 1);
  --fast:      170ms;
  --mid:       460ms;
}

/* ---------- 2. Reset ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-body);
  line-height: 1.62;
  font-weight: 400;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: .98;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }

a {
  color: inherit;
  text-decoration: none;
}

::selection { background: var(--blue); color: #fff; }

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

/* ---------- 3. Layout ---------- */

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

section { position: relative; }

.band { padding-block: var(--section); }
.band--tight { padding-block: clamp(3.5rem, 7vw, 6.5rem); }

/* Lifted brand panel: the navy to blue gradient, against the flat black page */
.dark {
  background: var(--black);
  color: var(--on-dark);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.dark::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 95% at 88% -12%, rgba(16, 63, 234, .58) 0%, rgba(16, 63, 234, .16) 34%, transparent 66%),
    radial-gradient(80% 70% at 100% 0%, rgba(16, 63, 234, .34) 0%, transparent 60%),
    linear-gradient(168deg, var(--navy) 0%, var(--black) 62%);
  z-index: -2;
}
.dark h1, .dark h2, .dark h3 { color: var(--on-dark); }
.dark .lede, .dark p { color: var(--on-dark-70); }
.dark .rule { background: var(--rule-dark); }

/* Hairline */
.rule { height: 1px; background: var(--rule); border: 0; width: 100%; }

/* ---------- 4. Typography utilities ---------- */

.eyebrow {
  font-family: var(--body);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-45);
  line-height: 1.4;
  margin: 0;
}
.dark .eyebrow { color: var(--on-dark-48); }

.display { font-size: var(--t-display); }
.h1 { font-size: var(--t-h1); }
.h2 { font-size: var(--t-h2); }
.h3 { font-size: var(--t-h3); letter-spacing: -.025em; line-height: 1.12; }

.lede {
  font-size: var(--t-lead);
  line-height: 1.48;
  letter-spacing: -.015em;
  color: var(--ink-80);
  max-width: 34ch;
  font-weight: 400;
}
.lede--wide { max-width: 46ch; }

.body-copy { max-width: var(--measure); color: var(--ink-80); }
.body-copy + .body-copy { margin-top: 1.1em; }
.dark .body-copy { color: var(--on-dark-70); }

.num {
  font-family: var(--display);
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--blue);
  line-height: 1;
}

.accent { color: var(--blue); }
.dark .accent { color: var(--accent-dark); }

/* Section header: index rail + title */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.dark .sec-head { border-top-color: var(--rule-dark); }
.sec-head__title { max-width: 20ch; }
.sec-head__aside { color: var(--ink-62); max-width: 42ch; align-self: end; }
.dark .sec-head__aside { color: var(--on-dark-70); }

@media (min-width: 900px) {
  .sec-head {
    grid-template-columns: 7rem minmax(0, 1.05fr) minmax(0, .85fr);
    gap: 2.5rem;
    align-items: start;
  }
}

/* Lead variant, used by the home page's own section heads. Two children
   rather than three (no eyebrow), so the 7rem rail track goes with it,
   and the title is matched to .soar__title's size and weight instead of
   the default h2: on this page each section opens with a full headline
   rather than a labelled sub-section. Must stay after the base rule
   above, which it overrides at equal specificity. */
.sec-head--lead .sec-head__title { font-size: clamp(2.1rem, 5.6vw, 6rem); font-weight: 400; }
@media (min-width: 900px) {
  .sec-head--lead { grid-template-columns: minmax(0, 1.05fr) minmax(0, .85fr); }
}

/* ---------- 5. Buttons and links ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .85em;
  font-family: var(--body);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: -.005em;
  padding: 1.05em 1.75em;
  border: 1px solid transparent;
  border-radius: 100px;
  cursor: pointer;
  transition: background var(--fast) var(--ease-ui),
              color var(--fast) var(--ease-ui),
              border-color var(--fast) var(--ease-ui),
              transform var(--fast) var(--ease-ui);
  will-change: transform;
}
.btn__arrow {
  display: inline-block;
  transition: transform var(--fast) var(--ease-ui);
}
.btn:hover .btn__arrow { transform: translateX(4px); }
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--blue); color: #fff; }
.btn--primary:hover { background: #0B31C4; }

.btn--light { background: #fff; color: var(--black); }
.btn--light:hover { background: rgba(255, 255, 255, .86); }

.btn--ghost { border-color: var(--rule); color: var(--ink); }
.btn--ghost:hover { border-color: var(--white); background: var(--white); color: var(--black); }
.dark .btn--ghost { border-color: var(--rule-dark); color: var(--on-dark); }
.dark .btn--ghost:hover { background: #fff; color: var(--black); border-color: #fff; }

/* Underline link */
.ulink {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  font-size: var(--t-small);
  font-weight: 500;
  padding-bottom: .35em;
  border-bottom: 1px solid var(--rule);
  transition: border-color var(--fast) var(--ease-ui), color var(--fast) var(--ease-ui);
}
.ulink:hover { border-bottom-color: var(--blue); color: var(--blue); }
.ulink__arrow { transition: transform var(--fast) var(--ease-ui); }
.ulink:hover .ulink__arrow { transform: translateX(4px); }
.dark .ulink { border-bottom-color: var(--rule-dark); }
.dark .ulink:hover { border-bottom-color: var(--accent-dark); color: var(--accent-dark); }

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.75rem;
}

/* ---------- 6. Header ---------- */

/* Flat and transparent over the page at rest. Past the scroll threshold the
   same bar closes into a floating light pill.

   Both edges draw in by --pill-inset, so the wordmark travels with the nav
   rather than sitting still while everything else moves. Contents move on
   transforms and the pill moves on its own insets, all on one clock, so the
   bar reads as a single object closing and nothing in the header reflows. */

.hdr {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding-block: clamp(.55rem, 1.1vw, .9rem);
  padding-inline: clamp(.75rem, 2.2vw, 1.5rem);
  pointer-events: none;
}

/* The track holds the page column. */
.hdr__track {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
}

/* The bar's own layout never changes between the two states. The closing
   motion is carried entirely by transforms on the contents and by the pill's
   own insets, so nothing in here reflows, no text re-wraps mid-transition,
   and the border radius stays circular (which a scaleX would not). */
.hdr__in {
  position: relative;
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--hdr-pad-x);
  /* No fixed height. The CTA is the tallest thing in the bar, so the bar and
     therefore the pill come out exactly as thick as the button. */
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  pointer-events: auto;
}

/* The pill itself. Sits behind the bar's content. */
.hdr__in::before {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  border-radius: 100px;
  background: var(--pill);
  border: 1px solid var(--pill-border);
  -webkit-backdrop-filter: saturate(160%) blur(28px);
  backdrop-filter: saturate(160%) blur(28px);
  opacity: 0;
  box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
  /* Closing: short and direct, matching the contents. */
  transition:
    top var(--nav-out) var(--ease-ui),
    right var(--nav-out) var(--ease-ui),
    bottom var(--nav-out) var(--ease-ui),
    left var(--nav-out) var(--ease-ui),
    opacity 160ms var(--ease-ui),
    box-shadow var(--nav-out) var(--ease-ui);
  z-index: -1;
  pointer-events: none;
}
.hdr.is-stuck .hdr__in::before {
  top: var(--pill-inset-y);
  right: calc(var(--pill-inset) + var(--hdr-pad-x) - var(--pill-gap-end));
  bottom: var(--pill-inset-y);
  left: calc(var(--pill-inset) + var(--hdr-pad-x) - var(--pill-gap));
  opacity: 1;
  box-shadow: 0 18px 50px -22px rgba(0, 0, 0, .8);
  transition:
    top var(--nav-in) var(--ease-pill),
    right var(--nav-in) var(--ease-pill),
    bottom var(--nav-in) var(--ease-pill),
    left var(--nav-in) var(--ease-pill),
    opacity 200ms var(--ease-ui),
    box-shadow var(--nav-in) var(--ease-pill);
}

/* Wordmark: heavy "ACG" + light "Align", matching the ACG Align logotype */
.brand {
  display: inline-flex;
  align-items: baseline;
  gap: .3em;
  font-family: var(--logo);
  font-size: 1.25rem;
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--ink);
}
.acg, .brand__acg {
  font-family: var(--acg);
  font-weight: 600;
  letter-spacing: -.01em;
}
.algn, .brand__div {
  font-family: var(--body);
  font-weight: 400;
  letter-spacing: -.02em;
}
.brand__div { transition: color var(--fast) var(--ease-ui); }
/* No hover colour change in the header: the wordmark stays put on both
   the flat bar and the frosted pill. The footer keeps its own hover below. */
.ftr .brand { color: var(--on-dark); }
.ftr .brand:hover .brand__div { color: var(--blue); }

/* The pill is dark glass, so header text needs no colour flip: it reads
   white against the flat bar and white against the pill alike. Only
   position (the gather transform) changes between the two states. */
.hdr .brand {
  color: var(--ink);
  transform-origin: left center;
  transition: transform var(--nav-out) var(--ease-ui);
}
.hdr.is-stuck .brand {
  transform: translateX(var(--pill-inset)) scale(.94);
  transition: transform var(--nav-in) var(--ease-pill);
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(.85rem, 1.3vw, 1.15rem);
  transition: transform var(--nav-out) var(--ease-ui);
}
.hdr.is-stuck .nav {
  transform: translateX(calc(var(--pill-inset) * -1));
  transition: transform var(--nav-in) var(--ease-pill);
}

.nav__link {
  position: relative;
  font-size: var(--t-small);
  font-weight: 450;
  color: var(--ink-62);
  padding-block: .35rem;
  white-space: nowrap;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--fast) var(--ease-ui);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { transform: scaleX(1); }
.nav__link[aria-current="page"] { color: var(--ink); }
/* Inherits currentColor from the rule above, which is white on the header. */
.nav__link[aria-current="page"]::after { transform: scaleX(1); }

/* The CTA stays white in both bar states. On the flat bar it separates
   from the hero's blue glow; on the dark glass pill a blue-on-blue button
   would disappear, so white is what actually reads as the button here. */
.nav__cta {
  padding: .72em 1.4em;
  font-size: var(--t-small);
  transition:
    background var(--nav-out) var(--ease-ui),
    color      var(--nav-out) var(--ease-ui);
}
.hdr .nav__cta { background: var(--white); color: var(--black); }
.hdr .nav__cta:hover { background: rgba(255, 255, 255, .84); }

/* The CTA stays white in both bar states: the pill only ever appears while
   scrolling up, so a colour flip tied to it read as the button briefly
   turning blue mid-gesture rather than as a deliberate state. */

/* Mobile menu: native <details>, works with JS disabled */
.menu {
  display: none;
  position: relative;
  transition: transform var(--nav-out) var(--ease-ui);
}
.hdr.is-stuck .menu {
  transform: translateX(calc(var(--pill-inset) * -1));
  transition: transform var(--nav-in) var(--ease-pill);
}
.menu > summary {
  list-style: none;
  cursor: pointer;
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--ink);
  /* Icon only: the accessible name comes from the summary's aria-label, so
     the padding is what keeps it a comfortable tap target. The negative end
     margin cancels that padding at the outer edge, so the bars sit the same
     distance from the pill's right edge as the wordmark does from its left. */
  padding: .6rem .5rem;
  margin-inline-end: -.5rem;
  display: inline-flex;
  align-items: center;
}
.menu > summary::-webkit-details-marker { display: none; }

.menu__bars { display: grid; gap: 4px; width: 20px; }
.menu__bars i {
  display: block; height: 1.5px; background: currentColor;
  transition: transform var(--fast) var(--ease-ui), opacity var(--fast) linear;
}
.menu[open] .menu__bars i:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.menu[open] .menu__bars i:nth-child(2) { opacity: 0; }
.menu[open] .menu__bars i:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* The panel matches the pill rather than the page, so it reads as part of
   the same object. Colours are literal, not tokens, for that reason. */
.menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + .9rem);
  width: min(17rem, calc(100vw - 2.5rem));
  background: #F3F3F5;
  border-radius: 20px;
  padding: .6rem;
  box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .75);
  display: grid;
  gap: 2px;
}
.menu__panel a {
  padding: .8rem .9rem;
  border-radius: 13px;
  font-size: var(--t-small);
  font-weight: 450;
  color: rgba(0, 3, 11, .68);
  transition: background var(--fast) var(--ease-ui), color var(--fast) var(--ease-ui);
}
.menu__panel a:hover { background: rgba(0, 3, 11, .06); color: var(--pill-ink); }
.menu__panel a[aria-current="page"] { color: var(--pill-ink); }
.menu__panel a.is-cta { background: var(--blue); color: #fff; margin-top: .4rem; text-align: center; }
.menu__panel a.is-cta:hover { background: #0B31C4; color: #fff; }

@media (max-width: 599px) {
  .nav { display: none; }
  /* Flex, not block: as a block the inline-flex summary sits on a line box
     whose strut is taller than it is, which drops the bars off the
     wordmark's centre line. */
  .menu { display: flex; align-items: center; }
  .hdr { --hdr-pad-x: clamp(1rem, 3.5vw, 1.6rem); --pill-gap-end: var(--pill-gap); }
  .hdr__in { min-height: 3rem; }
}

/* The header is fixed, so the first section of every page has to make room
   for it. The hero already carries enough top padding of its own. */
main > section:first-child:not(.hero) {
  padding-top: calc(var(--hdr-h) + clamp(1.75rem, 5vw, 3.5rem));
}

/* ---------- 7. Hero ---------- */

.hero {
  /* Symmetric. align-items:center centres inside the padding box, so the
     old heavier top padding was pushing the headline below the optical
     middle of the screen.
     vh-based, not vw: a vw value keeps growing on a wide-but-short window
     (a laptop with a deep bookmarks/tab-preview bar, a large external
     display) with no relationship to how much vertical room is actually
     there, which is exactly what pushed the last line of the hero past
     the fold. Height is the only dimension this padding should answer to. */
  padding-block: clamp(2rem, 8vh, 6rem);
  /* Shared by .hero__eyebrow and .hero__sub below: one vh-scaled value so
     the two gaps around the headline stay equal at any viewport height,
     and both shrink together on a short window instead of one of them
     alone holding the line while the section keeps growing past the fold. */
  --hero-gap: clamp(1.5rem, 9vh, 7rem);
  /* Fills the first screen exactly. svh rather than vh or dvh: vh ignores
     mobile browser chrome and overflows, dvh resizes as that chrome hides
     and drags the shader with it. */
  min-height: 100svh;
  display: flex;
  align-items: center;
  isolation: isolate;
}

/* --- Hero shader -----------------------------------------------------------
   The canvas sits above the CSS gradient and below the text.
   It stays at opacity 0 until the shader has compiled and drawn its first
   frame, so a failed context or a blocked script simply leaves the gradient
   in place with no flash and no gap. */
.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  opacity: 0;
  transition: none;
  pointer-events: none;
}
.hero.has-shader .hero__canvas { opacity: 1; }

/* Scrim: guarantees headline contrast whatever the shader is doing beneath it. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* The rings are born behind the headline, so a hard left-to-right ramp
     would hide the one thing worth seeing. Instead: a local veil sized to
     the headline block, then a gentle falloff so the rest stays open. */
  background:
    radial-gradient(115% 85% at 21% 41%,
      rgba(0, 3, 11, .88) 0%,
      rgba(0, 3, 11, .58) 34%,
      rgba(0, 3, 11, .16) 62%,
      rgba(0, 3, 11, 0) 78%),
    linear-gradient(101deg,
      rgba(0, 3, 11, .50) 0%,
      rgba(0, 3, 11, .26) 46%,
      rgba(0, 3, 11, .02) 86%),
    /* Fully opaque by the very last pixel row, not just mostly: the section
       under this one opens on a flat var(--black), so the hero's bottom
       edge has to actually reach that same solid colour, not merely
       approach it, or the shader shows through right up to a seam that
       then jumps flat at the section boundary.
       Eight stops, not two: a straight two-point linear-gradient ramps
       opacity at a constant rate, which the eye reads as a fade that
       "turns off" abruptly rather than one that eases shut. These stops
       trace a slow-fast-slow (ease-in-out) curve instead — barely moving
       right at the seam and right at the point it disappears, doing most
       of its work in the middle — which is what actually reads as smooth.
       It also now reaches further up the hero (64% of its height) so the
       blend has room to be gradual rather than compressed into a short
       band right at the edge. */
    linear-gradient(to top,
      rgba(0, 3, 11, 1)    0%,
      rgba(0, 3, 11, .96)  8%,
      rgba(0, 3, 11, .86) 18%,
      rgba(0, 3, 11, .70) 28%,
      rgba(0, 3, 11, .50) 38%,
      rgba(0, 3, 11, .30) 48%,
      rgba(0, 3, 11, .14) 56%,
      rgba(0, 3, 11, 0)   64%);
}
@media (max-width: 760px) {
  /* Text occupies most of the frame on a phone, so hold the shader further back. */
  .hero__scrim {
    background:
      linear-gradient(180deg, rgba(0, 3, 11, .72) 0%, rgba(0, 3, 11, .90) 55%, rgba(0, 3, 11, 1) 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero.has-shader .hero__canvas { transition: none; }
}

/* --- Hero lattice -----------------------------------------------------------
   Each stroke is its own SVG path, reconstructed from the supplied artwork.
   That keeps the exact upper-left entry, fold, and lower-right fan while
   allowing the lines to draw independently instead of revealing as one box. */
.hero__lattice {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  display: block;
  overflow: hidden;
  opacity: .86;
  transform: translateY(-4%);
  pointer-events: none;
}

.hero__lattice-lines path {
  --batch-delay: 1300ms;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  animation: hero-lattice-line-draw 1.55s cubic-bezier(.62, .02, .28, 1)
    var(--batch-delay) both;
}

/* Build momentum at 1, 2, 4 and 8 lines, then finish in four-line waves.
   This preserves the accelerating entrance without dropping the final half
   of the lattice in one heavy 16-line paint. Paths are stored in reverse
   visual order, so these ranges run from the last wave back to the first. */
.hero__lattice-lines path:nth-child(n+5):nth-child(-n+8) { --batch-delay: 1225ms; }
.hero__lattice-lines path:nth-child(n+9):nth-child(-n+12) { --batch-delay: 1140ms; }
.hero__lattice-lines path:nth-child(n+13):nth-child(-n+16) { --batch-delay: 1045ms; }
.hero__lattice-lines path:nth-child(n+17):nth-child(-n+20) { --batch-delay: 940ms; }
.hero__lattice-lines path:nth-child(n+21):nth-child(-n+24) { --batch-delay: 820ms; }
.hero__lattice-lines path:nth-child(n+25):nth-child(-n+28) { --batch-delay: 680ms; }
.hero__lattice-lines path:nth-child(n+29):nth-child(-n+30) { --batch-delay: 520ms; }
.hero__lattice-lines path:nth-child(31) { --batch-delay: 340ms; }
.hero__lattice-lines path:nth-child(32) { --batch-delay: 140ms; }

@keyframes hero-lattice-line-draw {
  0% { stroke-dashoffset: 1; opacity: 0; }
  18% { opacity: .72; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__lattice-lines path {
    animation: none;
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

@media (max-width: 760px) {
  .hero__lattice {
    opacity: .92;
    /* Same artwork, repositioned so the fold's end point lands beside the
       headline's last word (about 56% across, 52% down). Widening the box
       pushes the fold right while keeping the strokes anchored to the left
       edge; overflow lets them run past the viewBox to the right edge. */
    left: 0;
    width: 129%;
    transform: translateY(-17.4%);
    overflow: visible;
  }

  .hero__lattice-lines path {
    stroke-width: 1.35;
    animation-duration: 1.3s;
  }
}

@media (max-width: 420px) {
  .hero__lattice-lines path { stroke-width: 1.2; }
}

.hero__grid {
  display: grid;
  gap: clamp(2.75rem, 5vw, 4rem);
  width: 100%;
  position: relative;
  z-index: 3;
}

/* Lighter than the h1 default: the line is long and the shader is busy, so
   the weight carries it without shouting. */
.hero__title {
  /* Pulls the title up out of .hero__grid's own row-gap so it sits right
     under the eyebrow instead of centred in that gap. Not a full cancel:
     the grid gap is vw-driven and the visible whitespace above a line of
     text is never the full margin value (line-box leading eats some of
     it), so an exact algebraic cancel would have overshot. Tuned against
     the live layout instead. */
  margin-top: -2.5rem;
  font-size: clamp(2.35rem, 5.9vw, 5.25rem);
  font-weight: 400;
  letter-spacing: -.035em;
  line-height: 1.02;
}
.hero__title .l { display: block; }
.hero__title .l + .l { margin-top: .16em; }
/* Each word is its own entrance. inline-block because transform does not
   apply to a non-replaced inline box, so plain spans would fade without
   ever moving. Shared with the eyebrow above, which uses the same reveal. */
.hero__title .w, .hero__eyebrow .w, .hero__sub .w { display: inline-block; }

/* Sits directly above the headline, reading as its label rather than a
   separately-centred line. */
.hero__eyebrow {
  margin-bottom: 0;
  /* Overrides .eyebrow's uppercase micro-caps treatment to read as a small
     line of the headline itself rather than a section label: same weight,
     tracking and case the "Look and feel" title uses, just much smaller. */
  font-family: var(--display);
  font-size: var(--t-lead);
  font-weight: 400;
  letter-spacing: -.035em;
  text-transform: none;
}

/* Right-aligned against the left-set headline, so the two lines read as a
   deliberate asymmetry rather than a stray element. margin-top shares
   .hero__eyebrow's --hero-gap exactly: both sit on top of the same
   .hero__grid row-gap, so equal margins give equal visible gaps on either
   side of the headline (eyebrow-to-title and title-to-subhead) at any
   viewport height, with no separate arithmetic needed. Width is tuned to
   wrap at "two and a half" lines — a full block reads heavier than this
   needs to be. */
.hero__sub {
  margin-left: auto;
  margin-top: var(--hero-gap);
  max-width: 44ch;
  text-align: right;
}
@media (max-width: 640px) {
  /* The reference places "Look" at 43% of the hero height. The existing
     content block lands about one viewport step too high on phones, so move
     the complete composition together while preserving its internal rhythm. */
  .hero__grid { transform: translateY(9svh); }

  /* Eyebrow and headline sit a little higher than the rest of the block.
     A transform leaves layout alone, so the subhead stays where it was. */
  .hero__eyebrow, .hero__title { transform: translateY(-2svh); }
  .hero__sub { transform: translateY(6svh); }

  /* Right-aligned ragged lines are hard to read once the block is nearly
     full width; left is what the rest of the page does at this width. */
  .hero__sub { text-align: left; margin-left: 0; margin-top: var(--hero-gap); }

  /* Phone only: at var(--t-lead) both of these read as large as body copy
     gets, which on a narrow column starts to compete with the headline
     for weight instead of sitting clearly beneath it. One step down, on
     both, keeps them secondary. Scoped to this query alone so tablet and
     desktop keep the size already tuned for them. */
  .hero__eyebrow, .hero__sub { font-size: var(--t-small); }
}

/* Rotating word. An inline grid stacks every variant in one cell, so the
   container needs no measured height and the words sit exactly on top of
   each other. JS reserves the widest word once so swaps never reflow text. */
.rot {
  display: inline-grid;
  vertical-align: baseline;
  width: var(--rw, auto);
  transition: none;
}
/* The changing word crossfades vertically, blurring in and out to match the
   hero's text entrance. */
.rot__w {
  grid-area: 1 / 1;
  justify-self: start;
  white-space: nowrap;
  /* One step up from the 500 the line is set in, so the word carries without
     breaking the weight of the sentence. */
  font-weight: 600;
  color: var(--white);
  opacity: 0;
  transform: translate3d(0, .18em, 0);
  filter: blur(8px);
  transition:
    opacity 520ms var(--ease-in-out),
    transform 520ms var(--ease-in-out),
    filter 520ms var(--ease-in-out);
}

.rot__w.is-on {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: none;
}
/* Leaving words move upward rather than dropping the way they came. */
.rot__w.is-out {
  opacity: 0;
  transform: translate3d(0, -.18em, 0);
  filter: blur(8px);
}

@media (prefers-reduced-motion: reduce) {
  .rot { width: auto; transition: none; }
  .rot__w { transition: none; filter: none; animation: none; background-position: 50% 50%; }
}

.dark .index { border-top-color: var(--rule-dark); }

.index__row {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) auto;
  gap: 1rem 1.5rem;
  align-items: start;
  padding-block: clamp(1.6rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--rule);
  position: relative;
  transition: color var(--fast) var(--ease-ui);
}
.dark .index__row { border-bottom-color: var(--rule-dark); }

.index__row::before {
  content: "";
  position: absolute;
  inset: 0 calc(var(--gutter) * -.5);
  background: var(--paper-2);
  opacity: 0;
  z-index: -1;
  border-radius: 6px;
  transition: opacity var(--fast) var(--ease-ui);
}
.dark .index__row::before { background: rgba(255, 255, 255, .045); }
a.index__row:hover::before { opacity: 1; }

.index__num { font-family: var(--display); font-weight: 300; font-size: 1rem; color: var(--ink-45); font-variant-numeric: tabular-nums; padding-top: .35em; transition: color var(--fast) var(--ease-ui); }
.dark .index__num { color: var(--on-dark-48); }
a.index__row:hover .index__num { color: var(--blue); }
.dark a.index__row:hover .index__num { color: var(--accent-dark); }

.index__title { font-family: var(--display); font-weight: 700; font-size: clamp(1.375rem, 2.6vw, 2.125rem); letter-spacing: -.03em; line-height: 1.1; }
.index__desc { color: var(--ink-62); font-size: var(--t-small); margin-top: .7rem; max-width: 54ch; }
.dark .index__desc { color: var(--on-dark-70); }

.index__tags {
  display: flex; flex-wrap: wrap; gap: .4rem .5rem;
  margin-top: 1rem;
}
.index__tags li {
  font-size: var(--t-micro);
  letter-spacing: .04em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-62);
  border: 1px solid var(--rule);
  border-radius: 100px;
  padding: .4em .85em;
}
.dark .index__tags li { color: var(--on-dark-70); border-color: var(--rule-dark); }

.index__go {
  align-self: center;
  color: var(--ink-45);
  transition: transform var(--fast) var(--ease-ui), color var(--fast) var(--ease-ui);
}
a.index__row:hover .index__go { transform: translateX(5px); color: var(--blue); }
.dark a.index__row:hover .index__go { color: var(--accent-dark); }

@media (max-width: 640px) {
  .index__row { grid-template-columns: 2.5rem minmax(0, 1fr); }
  .index__go { display: none; }
}

/* ---------- 9. Statement cards (differentiators) ---------- */

.stack { display: grid; gap: 0; border-top: 1px solid var(--rule); }
.dark .stack { border-top-color: var(--rule-dark); }

.stmt {
  display: grid;
  gap: .9rem 2.5rem;
  padding-block: clamp(2rem, 4vw, 3.25rem);
  border-bottom: 1px solid var(--rule);
}
.dark .stmt { border-bottom-color: var(--rule-dark); }
@media (min-width: 900px) {
  .stmt { grid-template-columns: 7rem minmax(0, 1fr) minmax(0, 1.15fr); align-items: start; }
}
.stmt__num { font-family: var(--display); font-weight: 300; font-size: 1rem; color: var(--blue); font-variant-numeric: tabular-nums; padding-top: .3em; }
.dark .stmt__num { color: var(--accent-dark); }
.stmt__title { font-family: var(--display); font-weight: 700; font-size: clamp(1.25rem, 2vw, 1.625rem); letter-spacing: -.028em; line-height: 1.16; }
.stmt__body { color: var(--ink-62); }
.dark .stmt__body { color: var(--on-dark-70); }

/* ---------- 10. Process ---------- */

.proc {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 4px;
  overflow: hidden;
}
.dark .proc { background: var(--rule-dark); border-color: var(--rule-dark); }
@media (min-width: 860px) { .proc { grid-template-columns: repeat(4, 1fr); } }

.proc__step {
  background: var(--paper);
  padding: clamp(1.6rem, 2.6vw, 2.25rem);
  display: grid;
  gap: .75rem;
  align-content: start;
  position: relative;
  transition: background var(--fast) var(--ease-ui);
}
.dark .proc__step { background: var(--black); }
.proc__step:hover { background: var(--paper-2); }
.dark .proc__step:hover { background: rgba(255, 255, 255, .045); }

.proc__icon {
  width: 4rem;
  height: auto;
  aspect-ratio: 120 / 96;
  overflow: visible;
  margin-bottom: .25rem;
}
.proc__icon path {
  fill: none;
  stroke: url(#proc-lattice-stroke);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.proc__icon path.is-dashed { stroke-dasharray: 3 4; opacity: .6; }
.proc__icon path.is-fill { fill: url(#proc-lattice-stroke); fill-opacity: .16; stroke: none; }

.proc__top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.proc__num { font-family: var(--display); font-weight: 300; font-size: 2.25rem; color: var(--blue); font-variant-numeric: tabular-nums; line-height: 1; }
.dark .proc__num { color: var(--accent-dark); }
.proc__days { font-size: var(--t-micro); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-45); font-weight: 500; }
.dark .proc__days { color: var(--on-dark-48); }
.proc__name { font-family: var(--display); font-weight: 700; font-size: 1.25rem; letter-spacing: -.028em; }
.proc__desc { font-size: var(--t-small); color: var(--ink-62); }
.dark .proc__desc { color: var(--on-dark-70); }

.proc__total {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
  align-items: baseline;
  margin-top: 1.75rem;
  font-size: var(--t-small);
  color: var(--ink-62);
}
.dark .proc__total { color: var(--on-dark-70); }
.proc__total b { font-family: var(--display); font-weight: 700; color: var(--ink); letter-spacing: -.02em; }
.dark .proc__total b { color: var(--on-dark); }

/* ---------- 11. FAQ ---------- */

.faq { border-top: 1px solid var(--rule); }
.dark .faq { border-top-color: var(--rule-dark); }

.qa { border-bottom: 1px solid var(--rule); }
.dark .qa { border-bottom-color: var(--rule-dark); }

.qa > summary {
  list-style: none;
  cursor: pointer;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) 1.5rem;
  gap: 1.25rem;
  align-items: center;
  padding-block: clamp(1.35rem, 2.4vw, 1.85rem);
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.0625rem, 1.55vw, 1.3125rem);
  letter-spacing: -.026em;
  line-height: 1.25;
  transition: color var(--fast) var(--ease-ui);
}
.qa > summary::-webkit-details-marker { display: none; }
.qa > summary:hover { color: var(--blue); }
.dark .qa > summary:hover { color: var(--accent-dark); }

.qa__num { font-weight: 300; font-size: .875rem; color: var(--ink-45); font-variant-numeric: tabular-nums; }
.dark .qa__num { color: var(--on-dark-48); }

.qa__sign { position: relative; width: 14px; height: 14px; justify-self: end; }
.qa__sign::before, .qa__sign::after {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 14px; height: 1.5px;
  background: currentColor;
  transform: translateY(-50%);
  transition: transform var(--mid) var(--ease), opacity var(--fast) linear;
}
.qa__sign::after { transform: translateY(-50%) rotate(90deg); }
.qa[open] .qa__sign::after { transform: translateY(-50%) rotate(0deg); }

/* Animated height without touching layout-triggering properties on the text */
.qa__body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--mid) var(--ease); }
.qa[open] .qa__body { grid-template-rows: 1fr; }
.qa__body > div { overflow: hidden; }
.qa__body p {
  color: var(--ink-62);
  max-width: 64ch;
  padding: 0 1.5rem clamp(1.6rem, 2.6vw, 2.25rem) 4.5rem;
}
.dark .qa__body p { color: var(--on-dark-70); }
.qa__body p + p { padding-top: 1em; padding-bottom: 0; }
.qa__body p + p:last-child { padding-bottom: clamp(1.6rem, 2.6vw, 2.25rem); }

@media (max-width: 640px) {
  .qa > summary { grid-template-columns: 2.25rem minmax(0, 1fr) 1.25rem; gap: .85rem; }
  .qa__body p { padding-left: 3.1rem; padding-right: 0; }
}

/* ---------- 12. Service detail (services page) ---------- */

.svc { border-top: 1px solid var(--rule); padding-block: clamp(2.75rem, 5.5vw, 5rem); }
.svc__grid { display: grid; gap: 2.5rem; }
@media (min-width: 980px) {
  .svc__grid { grid-template-columns: 7rem minmax(0, .95fr) minmax(0, 1.1fr); gap: 3rem; align-items: start; }
  /* The number stays in view while its (often much taller) content scrolls
     past, the same wayfinding pattern the fixed header already uses. */
  .svc__grid > *:first-child {
    position: sticky;
    top: calc(var(--hdr-h) + 1.5rem);
  }
}
.svc__num { font-family: var(--display); font-weight: 300; font-size: clamp(2.5rem, 4vw, 3.5rem); color: var(--blue); line-height: .9; font-variant-numeric: tabular-nums; }
.svc__name { font-size: clamp(1.75rem, 3.1vw, 2.5rem); letter-spacing: -.035em; }
.svc__outcome {
  margin-top: 1.25rem;
  font-size: clamp(1.0625rem, 1.35vw, 1.25rem);
  line-height: 1.45;
  letter-spacing: -.012em;
  color: var(--ink);
  border-left: 2px solid var(--blue);
  padding-left: 1.25rem;
  max-width: 40ch;
}

.deliv { display: grid; gap: 0; }
.deliv__item { padding-block: 1.35rem; border-bottom: 1px solid var(--rule-soft); }
.deliv__item:first-child { padding-top: 0; }
.deliv__item:last-child { border-bottom: 0; padding-bottom: 0; }
.deliv__name {
  font-family: var(--display); font-weight: 700; font-size: 1.0625rem;
  letter-spacing: -.02em; line-height: 1.3;
  display: flex; align-items: baseline; gap: .7rem;
}
.deliv__name::before {
  content: "";
  width: 6px; height: 6px;
  flex: none;
  background: var(--blue);
  transform: rotate(45deg);
  translate: 0 -2px;
}
.deliv__desc { color: var(--ink-62); font-size: var(--t-small); margin-top: .45rem; padding-left: 1.4rem; max-width: 58ch; }

/* ---------- 12b. Package teaser (home) ---------- */

/* Separate rounded cards rather than a single hairline-divided strip.
   Mobile-first as a plain stacked list; the accordion row below is a
   desktop-only enhancement layered on top via the same markup. */
.pkg__grid {
  display: flex;
  flex-direction: column;
  gap: .85rem;
}
@media (min-width: 640px) and (max-width: 859px) {
  .pkg__grid { flex-direction: row; flex-wrap: wrap; }
  .pkg__item { flex: 1 1 calc(50% - .425rem); }
}

.pkg__item {
  /* Same frosted-glass treatment as the nav pill (.hdr__in::before): dark,
     translucent, saturated blur rather than a flat fill. */
  background: var(--pill);
  border: 1px solid var(--pill-border);
  -webkit-backdrop-filter: saturate(160%) blur(28px);
  backdrop-filter: saturate(160%) blur(28px);
  border-radius: 14px;
  padding: clamp(1.75rem, 2.6vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: .85rem;
  transition: background var(--fast) var(--ease-ui), border-color var(--fast) var(--ease-ui);
}
.pkg__item:hover, .pkg__item:focus-within { background: rgba(16, 21, 41, .72); border-color: rgba(255, 255, 255, .16); }

.pkg__num { font-family: var(--display); font-weight: 300; font-size: 2rem; color: var(--blue); font-variant-numeric: tabular-nums; line-height: 1; }
.dark .pkg__num { color: var(--accent-dark); }
.pkg__name { font-family: var(--display); font-weight: 700; font-size: 1.125rem; letter-spacing: -.025em; }
.pkg__body { display: contents; }
.pkg__desc { font-size: var(--t-small); color: var(--ink-62); }
.dark .pkg__desc { color: var(--on-dark-70); }

/* Tighter than .fit-list's own default: three short lines in a narrow card
   read better close together than at the spacing tuned for a full-width
   paragraph list elsewhere on the site. */
.pkg__item .fit-list { margin-top: .1rem; }
.pkg__item .fit-list li { padding-block: .55rem; }

.pkg__cta { margin-top: clamp(2rem, 4vw, 3rem); }

/* Desktop: the four categories become a horizontal accordion instead of a
   static grid, one open panel at a time (its description and checklist
   are what the collapsed rails hide), the rest reading as a row of
   numbered, named tabs. The open panel defaults to the first category and
   follows hover or keyboard focus; :has() support is what drives that
   default, so browsers without it just start with everything collapsed
   until a panel is actually hovered or focused, rather than broken. */
@media (min-width: 860px) {
  .pkg__grid { flex-direction: row; }
  .pkg__item {
    flex: 1 1 0%;
    min-width: 0;
    overflow: hidden;
    cursor: pointer;
    /* backdrop-filter is a per-frame resample of whatever is behind the
       element; animating flex-grow (a layout property, recomputed every
       frame anyway) on four elements that are each also re-sampling a
       28px blur at the same time is what was actually causing the stutter
       here, not the flex-grow transition itself. Dropping the blur only
       where the width is animating (it's kept, cheaply, on the static
       mobile/tablet cards) is what fixes it; the flat fill below is tuned
       to read close to the blurred version without the per-frame cost. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(9, 13, 26, .88);
    /* Both the growth and the shrink-back carry a short delay, not just
       the shrink-back: crossing the row diagonally sweeps the pointer
       over two or three intervening cards before it reaches the one
       you're aiming for, and without a delay on growth too, each of
       those briefly expands and immediately reverses, which is what read
       as "breaking" rather than a clean hand-off. A hover has to hold for
       a beat before anything moves; once something's already open, that
       same beat is what lets the next card pick it up before the old one
       has started closing, so the switch itself still reads as one
       continuous motion rather than two separate snaps. */
    transition: flex-grow 460ms var(--ease-ui) 70ms, background var(--fast) var(--ease-ui);
  }
  .pkg__body { display: block; }

  /* The description reads fine wrapped in a narrow collapsed rail, so it
     stays visible at all times; only the checklist (the part that needs
     real width to read as a list rather than a wrap-mess) waits for the
     panel to open. Same delay pairing as the flex-grow above, for the
     same reason. */
  .pkg__item .fit-list {
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    margin-top: 0;
    transition: opacity 200ms var(--ease-ui) 70ms, max-height 380ms var(--ease-ui) 70ms, margin-top 380ms var(--ease-ui) 70ms;
  }

  .pkg__grid:not(:has(.pkg__item:hover, .pkg__item:focus-within)) .pkg__item:first-child,
  .pkg__item:hover,
  .pkg__item:focus-within {
    flex-grow: 3.4;
  }
  .pkg__grid:not(:has(.pkg__item:hover, .pkg__item:focus-within)) .pkg__item:first-child .fit-list,
  .pkg__item:hover .fit-list,
  .pkg__item:focus-within .fit-list {
    opacity: 1;
    max-height: 14rem;
    margin-top: .1rem;
  }
}

/* ---------- 13. Price block ---------- */

.price {
  display: grid;
  gap: 2.5rem;
  padding: clamp(2rem, 4vw, 3.5rem);
  border: 1px solid var(--rule-dark);
  border-radius: 6px;
  background: rgba(255, 255, 255, .035);
}
@media (min-width: 900px) { .price { grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: 3.5rem; } }

.price__fig {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(3.25rem, 7vw, 5.5rem);
  letter-spacing: -.05em;
  line-height: .9;
  color: var(--on-dark);
  font-variant-numeric: tabular-nums;
}
.price__unit { font-size: .3em; font-weight: 500; letter-spacing: -.01em; margin-left: .35em; color: var(--on-dark-48); vertical-align: baseline; }
.price__cap { margin-top: 1rem; font-size: var(--t-small); color: var(--on-dark-70); max-width: 30ch; }

.price__cols { display: grid; gap: 1.75rem; }
@media (min-width: 620px) { .price__cols { grid-template-columns: 1fr 1fr; } }
.price__col h3 {
  font-family: var(--body); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--on-dark-48); margin-bottom: .85rem;
}
.price__col li {
  font-size: var(--t-small);
  color: var(--on-dark-70);
  padding-block: .4rem;
  display: flex; gap: .65rem;
}
/* Included reads as a filled mark, excluded as a struck line. With the accent
   colour gone from dark surfaces, shape carries the distinction. */
.price__col li::before {
  content: "";
  flex: none;
  width: 7px; height: 1.5px;
  margin-top: 1em;
  background: currentColor;
  opacity: .45;
}
.price__col--yes li::before {
  width: 5px; height: 5px;
  margin-top: .62em;
  background: var(--accent-dark);
  opacity: 1;
  transform: rotate(45deg);
}

/* ---------- 14. Guarantee ---------- */

.guarantee {
  border: 1px solid var(--blue);
  border-radius: 6px;
  padding: clamp(1.9rem, 4vw, 3.25rem);
  display: grid;
  gap: 1.75rem;
  position: relative;
  background:
    linear-gradient(180deg, rgba(16, 63, 234, .05), rgba(16, 63, 234, 0) 65%);
}
@media (min-width: 900px) { .guarantee { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: 3rem; align-items: start; } }
.guarantee__label {
  font-size: var(--t-micro); letter-spacing: .14em; text-transform: uppercase;
  font-weight: 500; color: var(--blue); margin-bottom: 1rem;
}
.guarantee__title { font-size: clamp(1.625rem, 2.9vw, 2.25rem); letter-spacing: -.035em; }

/* ---------- 15. Two-column prose ---------- */

.duo { display: grid; gap: clamp(2rem, 4vw, 3.5rem); }
@media (min-width: 900px) { .duo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(3rem, 6vw, 6rem); } }
@media (min-width: 900px) { .duo--rail { grid-template-columns: 7rem minmax(0, 1fr) minmax(0, 1fr); } }

.callout {
  border-left: 2px solid var(--blue);
  padding-left: clamp(1.25rem, 2.5vw, 2rem);
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.375rem, 2.5vw, 2rem);
  letter-spacing: -.032em;
  line-height: 1.18;
  max-width: 24ch;
}

/* Credential chips */
.creds { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.5rem; }
.creds li {
  font-size: var(--t-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-62);
  border: 1px solid var(--rule);
  border-radius: 100px;
  padding: .55em 1em;
}

/* Fit lists */
.fit { display: grid; gap: 2.5rem; }
@media (min-width: 780px) { .fit { grid-template-columns: 1fr 1fr; gap: 3rem; } }
.fit__h {
  font-family: var(--body); font-size: var(--t-micro); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-45);
  padding-bottom: 1rem; border-bottom: 1px solid var(--rule); margin-bottom: .5rem;
}
.fit li, .fit-list li { padding-block: .95rem; border-bottom: 1px solid var(--rule-soft); display: flex; gap: .85rem; color: var(--ink-80); font-size: var(--t-small); }
.fit li::before, .fit-list li::before { flex: none; font-family: var(--display); font-weight: 700; }
.fit--yes li::before, .fit-list.fit--yes li::before { content: "+"; color: var(--blue); }
.fit--no li::before, .fit-list.fit--no li::before { content: "\2212"; color: var(--grey); }

/* ---------- 16. Contact ---------- */

.chan { display: grid; gap: 1px; background: var(--rule-dark); border: 1px solid var(--rule-dark); border-radius: 6px; overflow: hidden; }
@media (min-width: 760px) { .chan { grid-template-columns: 1fr 1fr; } }
.chan__item {
  background: var(--black);
  padding: clamp(1.75rem, 3.5vw, 2.75rem);
  display: grid; gap: .6rem; align-content: start;
  transition: background var(--fast) var(--ease-ui);
}
.chan__item:hover { background: rgba(255, 255, 255, .05); }
.chan__k { font-size: var(--t-micro); letter-spacing: .14em; text-transform: uppercase; color: var(--on-dark-48); font-weight: 500; }
.chan__v { font-family: var(--display); font-weight: 700; font-size: clamp(1.375rem, 2.4vw, 1.875rem); letter-spacing: -.03em; display: flex; align-items: center; gap: .6rem; }
.chan__v .btn__arrow { color: var(--accent-dark); }
.chan__note { font-size: var(--t-small); color: var(--on-dark-70); }

.steps { counter-reset: s; display: grid; gap: 0; border-top: 1px solid var(--rule); }
.steps li {
  counter-increment: s;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  gap: 0 1.5rem;
  padding-block: 1.6rem;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.steps li::before {
  content: "0" counter(s);
  font-family: var(--display); font-weight: 300; font-size: 1rem;
  color: var(--blue); font-variant-numeric: tabular-nums;
}
/* Keep the title and the description in the content column; the counter
   owns column 1, so both children must be pinned to column 2. */
.steps b,
.steps span { grid-column: 2; }
.steps b { font-family: var(--display); font-weight: 700; letter-spacing: -.022em; font-size: 1.0625rem; margin-bottom: .3rem; }
.steps span { color: var(--ink-62); font-size: var(--t-small); }
.dark .steps span { color: var(--on-dark-70); }
.dark .steps li { border-bottom-color: var(--rule-dark); }
.dark .steps { border-top-color: var(--rule-dark); }

/* ---------- 17. Footer ---------- */

.ftr { background: var(--black); color: var(--on-dark); border-top: 1px solid var(--rule); padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem; }
.ftr__top { display: grid; gap: 2.75rem; padding-bottom: 3rem; border-bottom: 1px solid var(--rule-dark); }
@media (min-width: 900px) { .ftr__top { grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, .65fr)); gap: 3rem; } }
.ftr__mark { font-family: var(--display); font-weight: 800; font-size: clamp(2rem, 4.5vw, 3rem); letter-spacing: -.05em; line-height: .95; }
.ftr__slogan { color: var(--on-dark); font-family: var(--display); font-weight: 500; font-size: 1.0625rem; letter-spacing: -.02em; margin-top: .6rem; }
.ftr__desc { color: var(--on-dark-70); font-size: var(--t-small); max-width: 34ch; margin-top: 1.5rem; }
.ftr h3 { font-family: var(--body); font-size: var(--t-micro); font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--on-dark-48); margin-bottom: 1.1rem; }
.ftr li { padding-block: .4rem; }
.ftr li a, .ftr__desc a { font-size: var(--t-small); color: var(--on-dark-70); transition: color var(--fast) var(--ease-ui); }
.ftr li a:hover, .ftr__desc a:hover { color: #fff; }
.ftr__bot { display: flex; flex-wrap: wrap; gap: .75rem 2rem; justify-content: space-between; padding-top: 2rem; font-size: var(--t-micro); color: var(--on-dark-48); letter-spacing: .02em; }

/* The parent group, set in the same face the ACG mark uses. Capitalised in
   CSS rather than in the markup, and tracked out because caps this small
   close up otherwise. */
.ftr__group {
  font-family: var(--acg);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
}

/* ---------- 17b. Dividers draw in ----------
   The line is painted as a background gradient rather than by the border, so
   its width can animate and stay crisp. The border itself stays in the box
   model at full width and only hands over its colour, so nothing reflows and
   a no-JS visitor keeps every rule exactly as it was. */

.js [data-line] {
  --line-c: var(--rule);
  background-image: linear-gradient(var(--line-c), var(--line-c));
  background-repeat: no-repeat;
  background-origin: border-box;
  background-size: 0 1px;
  transition: background-size 1100ms var(--ease-in-out);
}
.js [data-line="top"] { background-position: left top; border-top-color: transparent; }
.js [data-line="bottom"] { background-position: left bottom; border-bottom-color: transparent; }
.js [data-line].is-drawn { background-size: 100% 1px; }

/* A standalone .rule is its own element, so it just scales. */
.js .rule[data-line] {
  background-image: none;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1100ms var(--ease-in-out);
}
.js .rule[data-line].is-drawn { transform: scaleX(1); }

/* Contexts whose hairline is not the default colour. */
.js .dark [data-line],
.js [data-line].ftr__top { --line-c: var(--rule-dark); }
.js [data-line].deliv__item,
.js .fit [data-line],
.js .fit-list [data-line] { --line-c: var(--rule-soft); }

/* ---------- 18. Motion (progressive enhancement) ---------- */

/* Resting states apply only when JS is active, so the page is fully
   legible and complete with JavaScript disabled. */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity var(--mid) var(--ease),
    transform var(--mid) var(--ease);
  transition-delay: var(--d, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: translate3d(0, 0, 0); }

/* One deliberate moment on load, for whatever opens a page. The blur is the
   part that carries it: fade and slide alone read as boilerplate, while text
   resolving out of focus reads as arriving. Ends on `none` rather than
   blur(0) so nothing stays needlessly layerised once it has landed. */
.js [data-enter] {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  filter: blur(8px);
  animation: enter 1500ms var(--ease-in-out) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes enter {
  to { opacity: 1; transform: translate3d(0, 0, 0); filter: none; }
}

.js .hero [data-enter] {
  animation: hero-enter 900ms cubic-bezier(.22, 1, .36, 1) both;
  animation-delay: var(--d, 0ms);
}
@keyframes hero-enter {
  from { opacity: 0; transform: translate3d(0, 10px, 0); filter: blur(8px); }
  to { opacity: 1; transform: translate3d(0, 0, 0); filter: none; }
}

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

/* ---------- 19. Misc ---------- */

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--blue); color: #fff; padding: .85rem 1.25rem;
  border-radius: 0 0 8px 0; font-size: var(--t-small); font-weight: 500;
}
.skip:focus { left: 0; }

.mt-1 { margin-top: 1rem; }
.mt-2 { margin-top: 2rem; }
.mt-3 { margin-top: clamp(2rem, 4vw, 3.25rem); }
.mt-4 { margin-top: clamp(3rem, 6vw, 5rem); }

/* ---------- 20. Soar scene ----------
   A scroll-scrubbed closer: the headline starts oversized and settles to its
   true size as concentric rings ripple outward past the viewport. The section
   is tall and the stage sticks, so the scroll distance is the timeline.
   JS writes --te, --adv, --ring, --ringfade and --out onto .soar; the values
   below are the resting defaults, so the end state is what shows with no JS. */

.soar {
  --soar-run: 300vh;
  --tsmax: 2.6;
  height: var(--soar-run);
  padding: 0;
  background: var(--black);
  color: var(--on-dark);
}

.soar__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  place-items: center;
  overflow: hidden;
  isolation: isolate;
}

.soar__stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 95% at 50% 0%, rgba(16, 63, 234, .5) 0%, rgba(16, 63, 234, .14) 34%, transparent 66%),
    linear-gradient(180deg, var(--navy) 0%, var(--black) 62%);
  z-index: -1;
}

/* Text only, over a plain surface: no rings, no gradient glow. */
#soar-brand .soar__stage::before { background: var(--black); }

/* Shorter run than the original (300vh): the headline finishes revealing
   at 62% of this height minus one viewport, so cutting it from 300vh to
   200vh roughly halves how far you have to scroll before the text is
   fully resolved, without changing the choreography itself. */
#soar-brand { --soar-run: 200vh; }

/* Rings */
.soar__rings {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--ringfade, .55);
}
.soar__rings svg { width: 100%; height: 100%; }

.soar__set {
  transform-box: view-box;
  transform-origin: center;
  filter: drop-shadow(0 0 12px rgba(16, 63, 234, .55));
  animation: soar-breathe 11s ease-in-out infinite;
}

.soar__rings circle {
  --lp: calc(var(--ring, .55) * 1.6 - var(--k) * .19);
  fill: none;
  stroke: rgba(150, 178, 255, .5);
  stroke-width: 1;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(calc(.24 + clamp(0, var(--lp), 1.35) * 2.35));
  opacity: clamp(0, min(calc(var(--lp) * 6), calc((1.25 - var(--lp)) * 1.6)), 1);
}

@keyframes soar-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.03); }
}

/* Content */
.soar__content {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-inline: var(--gutter);
  text-align: center;
}

.soar__title {
  width: max-content;
  max-width: 100%;
  margin-inline: auto;
  font-size: clamp(2.1rem, 5.6vw, 6rem);
  white-space: nowrap;
  transform-origin: left center;
  transform:
    translate3d(0, calc((1 - var(--te, 1)) * 3vh), 0)
    scale(calc(1 + (var(--tsmax) - 1) * (1 - var(--te, 1))));
  will-change: transform;
}

/* "Make your brand impossible to ignore" is longer than "Make your business
   soar" and, at nowrap, runs past the viewport edge on ordinary desktop
   widths (measured: 1246px of text at 1280px wide) rather than just on
   phones. Scoped to this section alone, on the same terms .soar__title
   already uses below 720px elsewhere, so the original section's single-line
   look at desktop widths is untouched. */
#soar-brand .soar__title {
  width: auto;
  white-space: normal;
  transform-origin: center center;
  /* Matches .hero__title's weight (400) rather than the h2 default (800)
     this class otherwise inherits, so the two headlines read as the same
     type rather than this one landing bolder. */
  font-weight: 400;
}

.soar__w { display: inline-block; white-space: nowrap; }

/* The feather: each letter lights over roughly two and a half letter widths
   behind the advancing head, so the line arrives as a wipe, not a switch. */
.soar__l {
  display: inline-block;
  opacity: clamp(0, calc((var(--adv, 99) - var(--i)) / 2.5), 1);
}

.soar__sub,
.soar__cta {
  opacity: var(--out, 1);
  transform: translate3d(0, calc((1 - var(--out, 1)) * 20px), 0);
}

.soar__sub {
  margin: clamp(1.5rem, 3vw, 2.25rem) auto 0;
  max-width: 46ch;
  color: var(--on-dark-70);
  font-size: var(--t-lead);
}

.soar__cta {
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
  pointer-events: none;
}
.soar.is-open .soar__cta { pointer-events: auto; }

@media (max-width: 720px) {
  .soar {
    --soar-run: 240vh;
    --tsmax: 1.55;
  }
  .soar__title {
    width: auto;
    white-space: normal;
    transform-origin: center center;
  }
}

/* Reduced motion, and any browser without JS running the scrub, get the
   finished composition in a single screen with no pinning. */
.soar.is-flat { height: auto; }
.soar.is-flat .soar__stage {
  position: static;
  height: auto;
  min-height: 0;
  padding-block: var(--section);
}
.soar.is-flat .soar__set { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .soar { height: auto; }
  .soar__stage {
    position: static;
    height: auto;
    padding-block: var(--section);
  }
  .soar__title { transform: none; }
  .soar__sub, .soar__cta { opacity: 1; transform: none; }
  .soar__cta { pointer-events: auto; }
}

/* ---------- 21. Page transitions ----------
   Cross-document view transitions. Browsers without support navigate the
   ordinary way, so there is nothing to fall back to and no JS to fail. */

@view-transition { navigation: auto; }

::view-transition-old(root) {
  animation: page-out 200ms cubic-bezier(.32, .72, 0, 1) both;
}
::view-transition-new(root) {
  animation: page-in 460ms cubic-bezier(.16, 1, .3, 1) both;
}

@keyframes page-out {
  to { opacity: 0; transform: translateY(-10px); }
}
@keyframes page-in {
  from { opacity: 0; transform: translateY(20px); }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root) { animation: page-fade-out 140ms linear both; }
  ::view-transition-new(root) { animation: page-fade-in 140ms linear both; }
  @keyframes page-fade-out { to { opacity: 0; } }
  @keyframes page-fade-in { from { opacity: 0; } }
}

/* The header's contents hold their position across a navigation instead of
   sliding with the page.

   .hdr itself is deliberately NOT named. Naming an element makes it a
   backdrop root, and the frosted pill (.hdr__in::before) lives inside it, so
   naming the header leaves that backdrop-filter with nothing to sample and
   the glass goes flat. Naming the three content elements instead keeps them
   still while .hdr__in stays an ordinary element, so the frost survives. The
   pill itself is unnamed and travels with the page, which is invisible: it
   only exists once scrolled, and an arriving page always starts at the top
   with the bar flat. */
.hdr .brand { view-transition-name: hdr-brand; }
.hdr .nav   { view-transition-name: hdr-nav; }
.hdr .menu  { view-transition-name: hdr-menu; }
