/* ============================================================
   MERIDIAN — payment routing infrastructure
   Visual system: a network operations surface at 3am. Deep slate
   substrate, mint for healthy routed traffic, amber for cost
   pressure, hazard orange for the degraded path.
   Mono carries all data; Inter Tight carries voice.

   The generative field lives at z-index 0 behind everything.
   Every rule here that touches contrast assumes the WORST case:
   text sitting directly over the densest part of the mesh.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* Slate substrate */
  --ink-900: #080a0e;
  --ink-850: #0b0e13;
  --ink-800: #11151b;
  --ink-750: #161b23;
  --ink-700: #1d232c;
  --ink-600: #2a323e;

  /* Text ramp. 500 and up clear WCAG AA on ink-850 even with the
     field at full density behind it, because the scrim guarantees
     a floor. Below 500 is borders and fills only — never text. */
  --ink-500: #7f8b9c;
  --ink-400: #9aa5b4;
  --ink-300: #b6c0cc;
  --ink-200: #d2d9e2;
  --ink-100: #eceff4;
  --ink-000: #f8fafc;

  /* Mint — healthy routed traffic, the "on" state */
  --mint: #4de0c0;
  /* Small mint text (12px labels) needs more headroom than the brand
     mint provides once the field is lit behind it. */
  --mint-bright: #7cead2;
  --mint-dim: #1f8d78;
  --mint-glow: rgba(77, 224, 192, 0.16);

  /* Amber — cost pressure, an edge getting expensive */
  --amber: #ffc46b;
  --amber-dim: #9c7128;

  /* Hazard — the degraded acquirer */
  --hazard: #ff5a3c;
  --hazard-dim: #99301c;

  --rule: rgba(255, 255, 255, 0.08);
  --rule-strong: rgba(255, 255, 255, 0.15);

  --bg: var(--ink-850);
  --fg: var(--ink-100);

  --font-ui: "Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --wrap: 1180px;
  --gut: clamp(20px, 5vw, 64px);

  /* Vertical rhythm scales with viewport so sections breathe on
     large screens without stranding content on small ones. */
  --sec-y: clamp(96px, 13vh, 176px);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, p, dl, dd, ol, ul, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }

a { color: inherit; }

img, svg, canvas { display: block; max-width: 100%; }

code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--mint);
  background: rgba(77, 224, 192, 0.08);
  border: 1px solid rgba(77, 224, 192, 0.18);
  border-radius: 4px;
  padding: 0.1em 0.4em;
  white-space: nowrap;
}

code sub { font-size: 0.75em; }

::selection {
  background: var(--mint);
  color: var(--ink-900);
}

/* ---------- 3. A11Y UTILITIES ---------- */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--gut);
  z-index: 100;
  padding: 12px 20px;
  background: var(--mint);
  color: var(--ink-900);
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 8px 8px;
  transition: top 0.18s var(--ease);
}
.skip-link:focus { top: 0; }

:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 3px;
  border-radius: 3px;
}

/* ---------- 4. THE FIELD ----------
   Fixed full-viewport layer behind all content. The scrim is a
   vertical gradient that guarantees a contrast floor under the
   text columns while leaving the top and bottom of the viewport
   open, so the mesh stays visible where content is not. */
.field {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.field canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.field__scrim {
  position: absolute;
  inset: 0;
  background:
    /* Centre-column darkening — the text lane. Deliberately lighter
       than a "safe" value: the panels above now carry their own
       translucent backing, so the scrim only has to take the edge
       off the field rather than bury it. Crushing this to 0.78 made
       the mesh read as wallpaper, which is the failure this whole
       page is trying to avoid. */
    linear-gradient(
      90deg,
      rgba(11, 14, 19, 0.10) 0%,
      rgba(11, 14, 19, 0.46) 24%,
      rgba(11, 14, 19, 0.52) 50%,
      rgba(11, 14, 19, 0.46) 76%,
      rgba(11, 14, 19, 0.10) 100%
    ),
    /* Vignette so the mesh never touches the viewport edge harshly */
    radial-gradient(
      120% 80% at 50% 50%,
      rgba(11, 14, 19, 0) 40%,
      rgba(11, 14, 19, 0.55) 100%
    );
}

/* On narrow screens the text lane is the whole viewport, so the
   scrim goes flat and heavier — legibility beats spectacle. */
@media (max-width: 860px) {
  .field__scrim {
    background:
      linear-gradient(180deg,
        rgba(11, 14, 19, 0.40) 0%,
        rgba(11, 14, 19, 0.60) 45%,
        rgba(11, 14, 19, 0.60) 55%,
        rgba(11, 14, 19, 0.40) 100%);
  }
}

/* Everything above the field. */
.nav, main, .foot { position: relative; z-index: 1; }

/* ---------- 5. LAYOUT ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gut);
}

.wrap--narrow { max-width: 760px; }

.sec { padding: var(--sec-y) 0; }

/* ---------- 6. NAV ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(11, 14, 19, 0.72);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--rule);
}

.nav__in {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gut);
  height: 64px;
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--mint);
  flex-shrink: 0;
}

.brand__mark { width: 28px; height: 28px; }

.brand__word {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.14em;
  color: var(--ink-000);
}

.nav__links {
  display: flex;
  gap: clamp(14px, 2.2vw, 30px);
  margin-right: auto;
}

.nav__link {
  font-size: 14px;
  color: var(--ink-400);
  text-decoration: none;
  transition: color 0.16s var(--ease);
}
.nav__link:hover { color: var(--ink-000); }

.nav__meter {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-400);
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.nav__meter strong {
  color: var(--mint);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Live pip — the one piece of ambient motion in the chrome. */
.pip {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mint);
  box-shadow: 0 0 0 0 var(--mint-glow);
  animation: pulse 2.4s var(--ease) infinite;
  flex-shrink: 0;
}

.pip--live { width: 7px; height: 7px; }

@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(77, 224, 192, 0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(77, 224, 192, 0); }
  100% { box-shadow: 0 0 0 0 rgba(77, 224, 192, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .pip { animation: none; }
}

/* Narrow viewports: the live meter and then the header CTA give way,
   but the section links never do — hiding them left the wordmark as
   the only reachable link on a phone, which is a dead nav. Instead
   they drop onto their own row that scrolls horizontally if it must.
   The primary CTA still exists in the page body and the footer. */
@media (max-width: 720px)  { .nav__meter { display: none; } }
@media (max-width: 460px)  { .nav__btn   { display: none; } }

@media (max-width: 1080px) {
  .brand { margin-right: auto; }

  .nav__in {
    flex-wrap: wrap;
    height: auto;
    padding-top: 10px;
    padding-bottom: 0;
    row-gap: 0;
  }

  .nav__links {
    order: 3;
    width: 100%;
    margin: 0 calc(var(--gut) * -1);
    padding: 0 var(--gut) 10px;
    gap: 22px;
    /* Scrolls rather than wraps or clips if the labels outgrow the
       viewport; the scrollbar itself is hidden because the row is
       short and the overflow is obvious from the cut-off item. */
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .nav__links::-webkit-scrollbar { display: none; }

  .nav__link {
    white-space: nowrap;
    padding: 4px 0;
  }
}

/* ---------- 7. BUTTONS ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: var(--mint);
  color: var(--ink-900);
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 0.16s var(--ease), background 0.16s var(--ease),
              box-shadow 0.16s var(--ease);
}

.btn:hover {
  background: #62eecd;
  transform: translateY(-1px);
  box-shadow: 0 8px 24px -8px rgba(77, 224, 192, 0.5);
}

.btn:active { transform: translateY(0); }

.btn--sm { padding: 8px 14px; font-size: 13px; }
.btn--lg { padding: 14px 26px; font-size: 15px; }

.btn--ghost {
  background: transparent;
  border-color: var(--rule-strong);
  color: var(--ink-100);
}
.btn--ghost:hover {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--ink-500);
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
}

/* ---------- 8. HERO ---------- */
.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 120px 0 40px;
  position: relative;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-400);
  text-transform: uppercase;
  padding: 7px 14px 7px 12px;
  border: 1px solid var(--rule);
  border-radius: 100px;
  background: rgba(17, 21, 27, 0.6);
  margin-bottom: 30px;
}

.hero__h {
  font-size: clamp(38px, 7.4vw, 88px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  font-weight: 600;
  max-width: 15ch;
  margin-bottom: 26px;
  text-wrap: balance;
}

.hero__h em {
  display: block;
  font-style: normal;
  color: var(--mint);
}

.hero__sub {
  font-size: clamp(16px, 1.9vw, 20px);
  line-height: 1.62;
  color: var(--ink-200);
  max-width: 56ch;
  margin-bottom: 36px;
}

.hero__sub strong {
  color: var(--ink-000);
  font-weight: 600;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 64px;
}

.hero__stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 10px;
  overflow: hidden;
  max-width: 880px;
}

.stat {
  background: rgba(11, 14, 19, 0.62);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  padding: 18px 20px;
}

.stat dt {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--ink-500);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.stat dd {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.stat__n {
  font-family: var(--font-mono);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 500;
  color: var(--ink-000);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.stat__u {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--mint);
}

.hero__hint {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-500);
  text-align: center;
  padding: 0 var(--gut);
}

@media (max-width: 860px) {
  .hero__stats { grid-template-columns: repeat(2, 1fr); }
  .hero__hint { position: static; transform: none; margin-top: 40px; }
}

@media (max-width: 400px) {
  .hero__stats { grid-template-columns: 1fr; }
}

/* ---------- 9. SECTION FURNITURE ---------- */
.sec__tag {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  /* Brighter than --mint: at 12px this is small text needing 4.5:1,
     and plain --mint measured 4.47:1 over the live field. */
  color: var(--mint-bright);
  text-transform: uppercase;
  margin-bottom: 18px;
}

.sec__h {
  font-size: clamp(28px, 4.4vw, 48px);
  line-height: 1.1;
  letter-spacing: -0.028em;
  font-weight: 600;
  max-width: 20ch;
  margin-bottom: 20px;
  text-wrap: balance;
}

.sec__lede {
  font-size: clamp(15px, 1.7vw, 18px);
  line-height: 1.65;
  /* ink-200, not ink-300: measured against the rendered frame at
     peak mesh density this text sat at 4.21:1, under AA. Body copy
     that can overlap the field gets the brighter ramp value. */
  color: var(--ink-200);
  max-width: 62ch;
  margin-bottom: 56px;
}

.sec__lede em {
  font-style: normal;
  color: var(--ink-000);
}

/* ---------- 10. STEPS ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 12px;
  overflow: hidden;
}

.step {
  /* Translucent + blurred rather than opaque: the mesh stays
     legible through the panel, so content and system read as one
     layer instead of the copy sitting on a lid over the field. */
  background: rgba(11, 14, 19, 0.66);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  padding: 28px 26px 32px;
  position: relative;
}

.step__n {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mint);
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}

.step__h {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.32;
  letter-spacing: -0.012em;
  margin-bottom: 10px;
  color: var(--ink-000);
}

.step__p {
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--ink-400);
}

.step__p em {
  font-style: normal;
  color: var(--amber);
}

/* ---------- 11. INCIDENT ----------
   This section deliberately runs tall and light on content: the
   field is the subject here, so the copy gets out of its way. */
.sec--incident {
  padding-top: calc(var(--sec-y) * 1.1);
  padding-bottom: calc(var(--sec-y) * 1.1);
}

/* The sticky nav overlaps anything scrolled to the top of the
   viewport, so anchored sections reserve headroom for it. */
.sec[id], .hero { scroll-margin-top: 72px; }

/* The stage — the moment the field is the subject.
   A tall, deliberately empty band. Nothing is painted here so the
   fixed canvas behind it is seen directly, uncovered, at the exact
   scroll range where ACQ-3 is evacuating. This is the section the
   copy promises when it says the paths are solved as you scroll. */
.stage {
  height: clamp(300px, 46vh, 460px);
  margin: 8px 0 56px;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

/* Fallback diagram: shown only when the live field is not running.
   field.js sets .field-live on <html> as soon as it starts, so the
   default state (no JS, no canvas) is the one that still explains
   the topology rather than an empty band. */
.stage__fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.85;
}

.field-live .stage__fallback { display: none; }


/* The canvas itself is equally conditional: without JS there is
   nothing to draw into it, and an empty fixed canvas would only
   darken the page. */
.field-live .field__scrim { opacity: 1; }

.stage__cap {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-400);
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px;
  border: 1px solid var(--rule);
  border-radius: 100px;
  background: rgba(8, 10, 14, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Caption swaps with the layer it describes. Declared after the
   base .stage__cap rule above, whose own `display` would otherwise
   win on source order and show both captions at once. */
.stage__cap--live { display: none; }
.field-live .stage__cap--live { display: inline-flex; }
.field-live .stage__cap--static { display: none; }

.stage__pip {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--hazard);
  animation: pulse-hz 1.8s var(--ease) infinite;
}

@keyframes pulse-hz {
  0%   { box-shadow: 0 0 0 0 rgba(255, 90, 60, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(255, 90, 60, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 90, 60, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .stage__pip { animation: none; }
}

/* Legend — the canvas is aria-hidden, so this is how the colour
   language reaches anyone not looking at it (or not seeing it). */
.legend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px 26px;
  margin-bottom: 40px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--rule);
}

.legend__i {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  color: var(--ink-400);
  line-height: 1.4;
}

.legend__sw {
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.legend__sw--mint   { background: var(--mint);   box-shadow: 0 0 10px var(--mint-glow); }
.legend__sw--amber  { background: var(--amber); }
.legend__sw--hazard { background: var(--hazard); }
.legend__sw--dot    { width: 5px; height: 5px; background: var(--ink-200); margin: 0 2.5px; }

.readout {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule-strong);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 56px;
  font-family: var(--font-mono);
}

.readout__row {
  background: rgba(8, 10, 14, 0.78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: 16px 18px;
}

.readout__k {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-500);
  margin-bottom: 7px;
}

.readout__v {
  font-size: 17px;
  color: var(--ink-000);
  font-variant-numeric: tabular-nums;
}

.readout__v span { color: var(--mint); }

/* Phase colour is swapped by JS via a data attribute on <body>,
   so the readout reads as instrumentation, not decoration. */
.readout__v--phase { color: var(--mint); }
body[data-phase="degrading"] .readout__v--phase { color: var(--amber); }
body[data-phase="rerouting"] .readout__v--phase { color: var(--hazard); }
body[data-phase="healed"] .readout__v--phase { color: var(--mint); }

.timeline {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 10px;
  overflow: hidden;
}

.tl {
  background: rgba(11, 14, 19, 0.70);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  padding: 20px 24px;
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 24px;
  align-items: baseline;
}

.tl__t {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
}

.tl__d {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-400);
}

.tl__d strong {
  color: var(--ink-000);
  font-weight: 600;
}

@media (max-width: 720px) {
  .readout { grid-template-columns: repeat(2, 1fr); }
  .tl { grid-template-columns: 1fr; gap: 6px; }
}

/* ---------- 12. NUMBERS GRID ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 12px;
  overflow: hidden;
}

.card {
  background: rgba(11, 14, 19, 0.66);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  padding: 30px 26px 34px;
}

.card__n {
  font-family: var(--font-mono);
  font-size: clamp(30px, 3.6vw, 40px);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--mint);
  line-height: 1;
  margin-bottom: 16px;
  font-variant-numeric: tabular-nums;
}

.card__h {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink-000);
  margin-bottom: 9px;
}

.card__p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-400);
}

/* ---------- 13. CTA ---------- */
.sec--cta {
  text-align: center;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: rgba(8, 10, 14, 0.55);
}

.cta__h {
  font-size: clamp(28px, 4.6vw, 50px);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 600;
  margin-bottom: 18px;
  text-wrap: balance;
}

.cta__p {
  font-size: clamp(15px, 1.7vw, 18px);
  line-height: 1.62;
  color: var(--ink-200);
  max-width: 52ch;
  margin: 0 auto 34px;
}

.cta__form {
  display: flex;
  gap: 10px;
  max-width: 480px;
  margin: 0 auto 18px;
}

.cta__input {
  flex: 1;
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--rule-strong);
  border-radius: 7px;
  background: rgba(8, 10, 14, 0.9);
  color: var(--ink-000);
  font-family: var(--font-ui);
  font-size: 15px;
}

.cta__input::placeholder { color: var(--ink-500); }

.cta__input:focus {
  outline: none;
  border-color: var(--mint);
  box-shadow: 0 0 0 3px rgba(77, 224, 192, 0.16);
}

.cta__fine {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-500);
}

@media (max-width: 520px) {
  .cta__form { flex-direction: column; }
}

/* ---------- 14. FAQ ---------- */
.faq {
  border-top: 1px solid var(--rule);
}

.qa {
  border-bottom: 1px solid var(--rule);
}

.qa__q {
  list-style: none;
  cursor: pointer;
  padding: 22px 40px 22px 0;
  font-size: 16.5px;
  font-weight: 500;
  color: var(--ink-100);
  position: relative;
  transition: color 0.16s var(--ease);
}

.qa__q::-webkit-details-marker { display: none; }

.qa__q:hover { color: var(--mint); }

/* Plus/minus built from two rules so it needs no icon font. */
.qa__q::after,
.qa__q::before {
  content: "";
  position: absolute;
  right: 4px;
  top: 50%;
  width: 13px;
  height: 1.5px;
  background: var(--ink-400);
  transition: transform 0.22s var(--ease), background 0.16s var(--ease);
}

.qa__q::before { transform: translateY(-50%) rotate(90deg); }
.qa__q::after  { transform: translateY(-50%); }

.qa[open] .qa__q::before { transform: translateY(-50%) rotate(0deg); }
.qa[open] .qa__q { color: var(--mint); }
.qa[open] .qa__q::before,
.qa[open] .qa__q::after { background: var(--mint); }

.qa__a {
  padding: 0 40px 24px 0;
  font-size: 15px;
  line-height: 1.68;
  color: var(--ink-400);
  max-width: 68ch;
}

@media (prefers-reduced-motion: reduce) {
  .qa__q::before, .qa__q::after { transition: none; }
}

/* ---------- 15. FOOTER ---------- */
.foot {
  padding: 48px 0;
  border-top: 1px solid var(--rule);
  background: var(--ink-900);
}

.foot__in {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px 28px;
}

.foot__brand {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.14em;
  color: var(--ink-000);
}

.foot__note {
  font-size: 13.5px;
  color: var(--ink-500);
  margin-right: auto;
}

.foot__links {
  display: flex;
  gap: 22px;
}

.foot__links a {
  font-size: 13.5px;
  color: var(--ink-400);
  text-decoration: none;
  transition: color 0.16s var(--ease);
}
.foot__links a:hover { color: var(--mint); }

/* ---------- 16. REVEAL ----------
   Opt-in: elements only hide once JS confirms it will animate
   them, so a JS failure never leaves content invisible. */
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.js-reveal [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
