/* Roven Systems — site.css
   Marketing-only components: nav, hero, product grid, steps, budget,
   metrics, CTA, footer, legal pages. Loads last. */

/* ═════════════════════════════════════════════════════════════════════
   0. BAND TOKEN OVERRIDES
   tokens.css is byte-identical with web/assets/ and must not diverge, so
   the marketing-only band remaps live here instead. site.css loads after
   tokens.css at equal specificity, so these win.
   ════════════════════════════════════════════════════════════════════ */

/* .section--dark only remapped --section-*, leaving --accent pinned to the
   light-surface #4B3CFF by data-theme="light". That put .step .num at
   3.19:1 on #0A0A0C and made every on-dark status dot use light fills.
   These are the dark-surface values from tokens.css:101-122. */
.section--dark {
  --accent: #8577FF;          /* 5.73:1 on #0A0A0C */
  --accent-strong: #A29AFF;
  --accent-soft: #201C40;
  --status-active-text:   #4ADE80;
  --status-active-fill:   #34D399;
  --status-paused-text:   #FBBF24;
  --status-paused-fill:   #FBBF24;
  --status-inactive-text: #F87171;
  --status-inactive-fill: #F87171;
  --status-unsynced-text: #60A5FA;
  --status-unsynced-fill: #60A5FA;
}

/* #F1EFFF sat ~2% off the #FFFFFF band that follows it, so the
   dark/light/dark alternation lost a beat and read as one long pale
   stretch. Deepened until the boundary is visible at full-page zoom. */
.section--tint { --section-bg: #EAE5FF; --section-border: #CFC6FF; }

/* ═════════════════════════════════════════════════════════════════════
   1. NAV
   ════════════════════════════════════════════════════════════════════ */

.nav {
  /* The bar carries the dark band tokens so it is legible over the hero
     and over every section it later floats above. */
  --section-bg: #0A0A0C;
  --section-ink: #F5F5F3;
  --section-ink-soft: #A8A8A3;
  --section-border: #29292E;

  position: sticky;
  top: 0;
  z-index: 100;
  color: var(--section-ink);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background var(--dur-moderate) var(--ease-standard),
    border-color var(--dur-moderate) var(--ease-standard),
    backdrop-filter var(--dur-moderate) var(--ease-standard);
}
/* Pages with no hero behind the bar (legal, 404) get it solid from the
   start — translucency over the page background reads as muddy grey. */
.nav--opaque, .nav--opaque.is-scrolled {
  background: var(--section-bg);
  border-bottom-color: var(--section-border);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.nav.is-scrolled {
  background: rgba(10, 10, 12, 0.82);
  border-bottom-color: var(--section-border);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
}

.nav-inner {
  max-width: var(--wide-max);
  margin-inline: auto;
  padding-inline: var(--space-6);
  height: 72px;
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  font-size: 1.25rem;
  line-height: 1;
  letter-spacing: -0.02em;
  flex: 0 0 auto;
}
.brand b { font-weight: 800; color: currentColor; }
.brand span {
  font-weight: 500;
  letter-spacing: 0;
  color: var(--section-ink-soft);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin-left: auto;
}
.nav-links a {
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--section-ink-soft);
  transition: color var(--dur-base) var(--ease-standard);
}
.nav-links a:hover { color: var(--section-ink); }

.nav-cta { flex: 0 0 auto; }
.nav .btn-primary { padding: 0.65rem 1.25rem; font-size: var(--text-small); }

.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  margin-left: auto;
  border-radius: var(--radius-sm);
  align-items: center;
  justify-content: center;
  color: var(--section-ink);
}
.nav-toggle .bars, .nav-toggle .bars::before, .nav-toggle .bars::after {
  display: block;
  width: 20px; height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--dur-base) var(--ease-standard), opacity var(--dur-fast);
}
.nav-toggle .bars { position: relative; }
.nav-toggle .bars::before, .nav-toggle .bars::after { content: ""; position: absolute; left: 0; }
.nav-toggle .bars::before { top: -6px; }
.nav-toggle .bars::after  { top: 6px; }
.nav-toggle[aria-expanded="true"] .bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .bars::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .bars::after  { transform: translateY(-6px) rotate(-45deg); }

.nav-panel {
  position: fixed;
  inset: 72px 0 0 0;
  z-index: 99;
  background: #0A0A0C;
  padding: var(--space-7) var(--space-5) var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow-y: auto;
}
.nav-panel[hidden] { display: none; }
.nav-panel a {
  display: block;
  padding: var(--space-4) 0;
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #F5F5F3;
  border-bottom: 1px solid #1F1F24;
}
.nav-panel .panel-foot {
  margin-top: var(--space-7);
  color: #A8A8A3;
}

@media (max-width: 47.99em) {
  .nav-inner { height: 56px; padding-inline: var(--space-5); gap: var(--space-4); }
  /* Scoped to .nav: the footer brand has the whole width and reads as a
     truncation without "Systems". */
  .nav .brand span { display: none; }
  .nav-links { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-cta { order: 3; }
  /* 0.6rem/12px gave the page's most important control a ~31px box.
     0.9375rem x2 + a 14px line box = exactly 44, and the width budget at
     375 is brand 60 + 16 + toggle 44 + 16 + CTA 101 + 48 = 285. */
  .nav .btn-primary { padding: 0.9375rem 1.1rem; font-size: var(--text-small); font-family: var(--font-sans); letter-spacing: 0; }
  .nav-panel { inset: 56px 0 0 0; }
}
@media (max-width: 22.5em) {
  .nav-cta { display: none; }
}

body.is-locked { overflow: hidden; }

/* The IntersectionObserver target that flips .nav.is-scrolled.
   Sits ~100px down the hero so the bar solidifies after a deliberate
   scroll, not on the first pixel. */
.nav-sentinel {
  position: absolute;
  top: 100px; left: 0;
  width: 100%; height: 1px;
  pointer-events: none;
}

/* ═════════════════════════════════════════════════════════════════════
   2. AGENT FIELD (hero background treatment)
   ════════════════════════════════════════════════════════════════════ */

.agent-field {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    radial-gradient(38% 45% at 18% 22%, rgba(133, 119, 255, 0.55), transparent 70%),
    radial-gradient(45% 50% at 82% 15%, rgba(75, 60, 255, 0.35), transparent 70%),
    radial-gradient(60% 60% at 55% 85%, rgba(34, 197, 94, 0.12), transparent 70%),
    #0A0A0C;
}
.agent-field::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-radial-gradient(circle at 50% 40%, transparent 0 78px, rgba(255, 255, 255, 0.06) 79px 80px);
  -webkit-mask-image: radial-gradient(60% 60% at 50% 40%, black, transparent 75%);
  mask-image: radial-gradient(60% 60% at 50% 40%, black, transparent 75%);
}
/* Two concentric-ring systems with different centres read as noise: the
   ::before rings centre on the section (50% 40%), the hero SVG's orbits
   on the visual column. The hero keeps the mesh and the grain; the rings
   stay where they are the only ring system (.cta-section, .error-page). */
.hero.agent-field::before { background-image: none; }

.agent-field::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ═════════════════════════════════════════════════════════════════════
   3. HERO
   ════════════════════════════════════════════════════════════════════ */

.hero {
  /* The nav sits on top of this section, so pull its height back in. */
  margin-top: -72px;
  padding-top: calc(72px + var(--space-10));
  padding-bottom: var(--space-11);
  /* Full-height on a normal screen, capped so an unusually tall viewport
     doesn't stretch the hero into an empty field. */
  min-height: min(100svh, 900px);
  /* grid, not flex: a flex child would refuse to shrink below its
     min-content width and blow the layout out on a 375px screen. */
  display: grid;
  align-content: center;
}
.hero > .wrap { width: 100%; }

.hero-grid {
  display: grid;
  /* 1.4/0.6, not 1.35/0.65: at the spec'd 88px hero cap (base.css §2)
     "You set the budget." measures 786px, so the copy column needs ~800.
     1.4fr gives 863 at 1440 — real slack — while leaving the visual 370px
     rather than the 308 a 1.5fr split starved it down to. */
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.6fr);
  gap: var(--space-8);
  align-items: center;
}

.hero .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  margin-bottom: var(--space-6);
}
.hero .eyebrow .status-dot { transform: translateY(-1px); }

.hero h1 { color: #FFFFFF; }
.hero h1 .em { color: #C9C2FF; }

.hero .t-lead {
  margin-top: var(--space-6);
  color: #C4C4C0;
  max-width: 34rem;
}
.hero .btn-row { margin-top: var(--space-7); }
/* The hero ghost link points down the page, not off-site: its glyph is a
   down arrow, so the travel is vertical. */
.hero .btn-ghost:hover .arrow { transform: translateY(3px); }

.hero-stats {
  display: grid;
  /* The rule and the tiles must end together. A max-width capped the
     block short of the tiles; spanning the whole copy column ran the
     rule 154px past the last tile. width:max-content sizes the block to
     exactly the three tiles plus their gaps, so the border-top ends
     where the content does — and max-width keeps it from forcing an
     overflow if the tiles ever outgrow the column. */
  grid-template-columns: repeat(3, minmax(0, 13rem));
  width: max-content;
  max-width: 100%;
  gap: var(--space-6);
  margin-top: var(--space-9);
  padding-top: var(--space-7);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.hero-stats .value { color: #FFFFFF; font-size: clamp(1.75rem, 1.2rem + 1.9vw, 2.75rem); }
.hero-stats .label { color: #9B9BA6; letter-spacing: 0.08em; }

/* The field visual sitting beside the copy. */
.hero-visual {
  position: relative;
  aspect-ratio: 1 / 1;
  max-width: 34rem;
  margin-inline: auto;
  width: 100%;
}
.hero-visual svg { width: 100%; height: 100%; overflow: visible; }
.hero-visual .halo {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 45%, rgba(133, 119, 255, 0.45), transparent 62%);
  filter: blur(28px);
  pointer-events: none;
}

/* Four agents on their orbits, breathing out of phase. Motion here is
   ambient, not a status signal — the pulse ring stays exclusive to the
   active status dot. */
.orbiter {
  transform-origin: 200px 200px;
  animation: agent-breathe 6s var(--ease-standard) infinite;
  animation-delay: calc(var(--i) * -1.4s);
}
@keyframes agent-breathe {
  0%, 100% { opacity: 0.7; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.06); }
}

/* Hand-off into the products band. A white gradient over the black field
   reads as fog, so the bleed runs the other way: the hero's violet is
   carried a few hundred pixels down into the white section (#products
   ::before), and the hero itself only softens its own last 90px. */
.hero-fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 90px;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(10, 10, 12, 0) 0%, #0A0A0C 100%);
}

#products { position: relative; isolation: isolate; }
#products::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 320px;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60% 100% at 22% 0%, rgba(133, 119, 255, 0.16), transparent 70%),
    radial-gradient(50% 100% at 78% 0%, rgba(75, 60, 255, 0.10), transparent 70%);
}

/* 1.35/0.65 squeezes the visual column to ~270px at 1024, which drops the
   SVG's scale factor to 0.68 and takes the labels back under 10px. */
@media (min-width: 64em) and (max-width: 79.99em) {
  .hero-grid { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); }
}
@media (max-width: 63.99em) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .hero-visual { max-width: 26rem; order: 2; }
  .hero { padding-bottom: var(--space-10); }
}
@media (max-width: 47.99em) {
  .hero {
    margin-top: -56px;
    padding-top: calc(56px + var(--space-8));
    padding-bottom: var(--space-9);
    min-height: 0;
  }
  .hero-stats {
    /* 3-up at 375 gave each label ~100px, so two of the three wrapped to
       a second line and the row's bottom edge went ragged. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* Undo the desktop max-content sizing: 1fr columns need a real width
       to divide, and max-content would collapse the block to the text. */
    width: auto;
    gap: var(--space-5) var(--space-4);
    margin-top: var(--space-8);
    padding-top: var(--space-6);
  }
  .hero-stats .value { font-size: 1.5rem; }
  .hero-stats .label { font-size: 0.625rem; letter-spacing: 0.05em; }
  .hero .btn-row { gap: var(--space-5); }
  .hero .btn-primary { width: 100%; }
  .hero-fade { height: 90px; }
}

/* ═════════════════════════════════════════════════════════════════════
   4. PRODUCTS
   ════════════════════════════════════════════════════════════════════ */

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-5);
  margin-top: var(--space-8);
}
@media (min-width: 80em) {
  .product-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-6); }
  .product-card { padding: var(--space-7); }
}
@media (min-width: 48em) and (max-width: 79.99em) {
  .product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 47.99em) {
  .product-grid { grid-template-columns: minmax(0, 1fr); }
}

.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
  /* --section-border #E2E2DD is 1.30:1 on the white band — the four cards
     carrying the whole product story barely separated from the page.
     --border-strong #CBCBC4 takes that to 2.02:1: still a quiet edge, but
     the cards read as objects. */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  /* --surface-0 is #FFFFFF on a #FFFFFF band: the cards read as outlines,
     not objects, and .promise on the same page already uses --surface-1.
     design-language.md:334 specifies --surface-1. */
  background: var(--surface-1);
  overflow: hidden;
  transition:
    transform var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard),
    box-shadow var(--dur-base) var(--ease-standard);
}
.product-card::before {
  content: "";
  position: absolute;
  inset: -40% -30% auto -30%;
  height: 70%;
  background: radial-gradient(50% 60% at 50% 100%, var(--card-accent) 0%, transparent 70%);
  /* 0.09 left every card reading grey; 0.14 lets each one carry its own
     product hue without turning the row into four coloured panels. */
  opacity: 0.14;
  pointer-events: none;
  transition: opacity var(--dur-moderate) var(--ease-standard);
}
.product-card:hover {
  transform: translateY(-4px);
  /* The resting border is already --border-strong, so hover borrows the
     card's own hue rather than repeating a value that would not change. */
  border-color: var(--card-accent, var(--accent));
  /* A tinted card needs less lift than a white one. */
  box-shadow: var(--shadow-sm);
}
.product-card:hover::before { opacity: 0.22; }

.icon-tile {
  position: relative;
  width: 56px; height: 56px;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  color: #FFFFFF;
  background:
    radial-gradient(120% 120% at 22% 12%, rgba(255, 255, 255, 0.5), transparent 58%),
    var(--card-accent, var(--accent));
  box-shadow: 0 6px 18px -6px var(--card-accent, var(--accent));
}
.icon-tile svg { width: 26px; height: 26px; }

.product-card h3 { margin-top: var(--space-1); }
.product-card .one-liner {
  font-size: var(--text-body);
  color: var(--section-ink-soft);
  margin-top: calc(var(--space-2) * -1);
}
/* margin-top:auto here dumped every card's equal-height slack into this
   one gap: measured 62/36/36/16px across the four cards, a 4:1 spread
   that put a visible hole in RankRight. The list now sits at a fixed
   distance from the one-liner and the slack collects above the `Included`
   rule instead, where a rule already explains the break. */
.product-card ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--text-small);
  color: var(--section-ink-soft);
  margin-top: 0;
  padding-top: var(--space-2);
}
.product-card li {
  position: relative;
  padding-left: 1.15em;
  line-height: 1.45;
}
.product-card li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.55em;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--card-accent, var(--accent));
}
.product-card .cta {
  margin-top: auto;
  padding-top: var(--space-5);
  border-top: 1px solid var(--section-border);
  font-size: var(--text-small);
  font-weight: 600;
  /* --card-ink is the contrast-checked -text form of the card's hue;
     --card-accent is a -fill and fails 4.5:1 as text on white. */
  color: var(--card-ink, var(--accent));
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}
.product-card .cta .arrow { transition: transform var(--dur-base) var(--ease-standard); }
.product-card:hover .cta .arrow { transform: translateX(4px); }

/* Network weave */
.weave {
  position: relative;
  margin-top: var(--space-9);
  padding: var(--space-8) var(--space-6) var(--space-6);
  border-top: 1px solid var(--section-border);
}
.weave::before {
  content: "";
  position: absolute;
  inset: 1px 0 0 0;
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
  background: radial-gradient(70% 120% at 50% 0%, #F1EEFF 0%, rgba(241, 238, 255, 0) 72%);
  pointer-events: none;
}
.weave > * { position: relative; }
.network-weave { width: 100%; height: auto; }
.network-weave .link { transition: stroke-dashoffset var(--dur-slow) var(--ease-out); }
.weave-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-7);
  margin-top: var(--space-5);
}
.weave-legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--section-ink-soft);
}
.weave-legend .swatch { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }

@media (max-width: 63.99em) {
  /* Below 1024 the weave scales to 0.59x or less. The strokes now scale
     with the drawing (6 units, ~6px at desktop), so they thin to ~3.5px
     here — still visible, but the four nodes and five links are squeezed
     into a band too short to read as a constellation. Drop it, keep the
     legend it explains. Was 47.99em, which left a washed-out version on
     screen through the whole tablet range. */
  .weave { margin-top: var(--space-7); padding: var(--space-6) 0 0; }
  .weave::before { display: none; }
  .network-weave { display: none; }
  .weave-legend { gap: var(--space-3) var(--space-5); margin-top: 0; }
  .weave-legend li:last-child { margin-left: 0 !important; width: 100%; color: var(--section-ink); }
}

/* ═════════════════════════════════════════════════════════════════════
   5. HOW IT WORKS
   ════════════════════════════════════════════════════════════════════ */

.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin-top: var(--space-9);
  border-top: 1px solid var(--section-border);
}
.step {
  padding: var(--space-7) var(--space-6) var(--space-8) 0;
  border-right: 1px solid var(--section-border);
  position: relative;
}
.step:last-child { border-right: 0; }
.step:not(:first-child) { padding-left: var(--space-6); }
.step::before {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width var(--dur-slow) var(--ease-out);
}
.step.is-revealed::before { width: 100%; }
/* Every other reveal is gated on html.js so that visibility is never
   JS-dependent (base.css §6). This one was not: with JS off the four
   accent bars stayed at width:0 forever. */
html:not(.js) .step::before { width: 100%; }
.step .num {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--accent);
  margin-bottom: var(--space-5);
}
.step h3 { margin-bottom: var(--space-3); }
.step p { font-size: var(--text-body); color: var(--section-ink-soft); }

@media (max-width: 63.99em) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .step:nth-child(2n) { border-right: 0; }
  .step:nth-child(n + 3) { border-top: 1px solid var(--section-border); }
}
@media (max-width: 47.99em) {
  .steps { grid-template-columns: minmax(0, 1fr); margin-top: var(--space-8); }
  .step { padding: var(--space-6) 0; border-right: 0; border-top: 1px solid var(--section-border); }
  .step:first-child { border-top: 0; }
  .step:not(:first-child) { padding-left: 0; }
}

.dot-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-6);
  margin-top: var(--space-8);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--section-border);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.02);
  align-items: center;
}
/* The title is a <p> outside the <ul> (it was never a list entry); the
   <ul> carries its own flex row. */
.dot-legend ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-6);
}
.dot-legend .legend-title {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--section-ink-soft);
  margin-right: var(--space-2);
}
.dot-legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.65em;
  font-size: var(--text-small);
  color: var(--section-ink);
}
.dot-legend li .meaning { color: var(--section-ink-soft); }

/* ═════════════════════════════════════════════════════════════════════
   6. BUDGET (the single tint band)
   ════════════════════════════════════════════════════════════════════ */

.budget-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-9);
  align-items: center;
}
.budget-copy p + p { margin-top: var(--space-5); }
.budget-copy p {
  color: var(--section-ink-soft);
  font-size: var(--fs-lead);
  line-height: 1.55;
  max-width: 34rem;
}
.budget-copy .t-h2 { margin-bottom: var(--space-6); }
.budget-notes {
  margin-top: var(--space-7);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.budget-notes li {
  display: flex;
  gap: 0.7em;
  font-size: var(--text-small);
  color: var(--section-ink);
}
/* 0.25em on a 16px icon in a ~21px line box drops it into the gap between
   lines on the two-line notes. */
.budget-notes li svg { flex: 0 0 auto; margin-top: 0.15em; color: var(--accent); }

.budget-beam-bg {
  position: relative;
  border-radius: var(--radius-xl);
  padding: var(--space-7);
  background: linear-gradient(120deg, #4B3CFF 0%, #8577FF 35%, #22C55E 100%);
  overflow: hidden;
}
.budget-beam-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(70% 90% at 20% 10%, rgba(255, 255, 255, 0.35), transparent 60%);
  pointer-events: none;
}

.glass-panel {
  position: relative;
  z-index: 1;
  /* Dark-tinted glass, not white: the beam runs from indigo to green and
     white-on-green fails contrast at the right-hand end. */
  background: rgba(12, 10, 30, 0.42);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-xl);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.25);
  padding: var(--space-6);
  color: #FFFFFF;
}
.glass-panel .panel-label {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
}

.budget-control { display: flex; flex-direction: column; gap: var(--space-4); }
.budget-control .readout {
  font-size: clamp(2.5rem, 1.8rem + 3vw, 3.75rem);
  line-height: 1;
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  margin-top: var(--space-3);
}
.budget-control .readout .per {
  font-size: var(--text-body);
  font-weight: 500;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.75);
  margin-left: 0.35em;
}

.budget-control input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  margin: var(--space-2) 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(
    to right,
    #FFFFFF var(--pct, 22%),
    rgba(255, 255, 255, 0.25) var(--pct, 22%)
  );
  cursor: pointer;
}
.budget-control input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #FFFFFF;
  border: 3px solid rgba(75, 60, 255, 0.9);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
  transition: transform var(--dur-fast) var(--ease-spring);
}
.budget-control input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #FFFFFF;
  border: 3px solid rgba(75, 60, 255, 0.9);
}
.budget-control input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.15); }
.budget-control .range-ends {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  /* 0.7 alpha put "$10,000" at 3.64:1 over the green end of the beam —
     12px text needs 4.5:1. The dark glass already carries the contrast;
     white on the green end measures 5.65:1. */
  color: rgba(255, 255, 255, 0.92);
}

.alloc { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-5); }
.alloc-row .alloc-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  font-size: var(--text-small);
  margin-bottom: var(--space-2);
}
.alloc-row .alloc-head .amount {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.alloc-track {
  height: 8px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.2);
  overflow: hidden;
}
/* No width transition: the split is a constant 55/25/20, so these bars
   never change width no matter where the slider goes. */
.alloc-fill {
  height: 100%;
  border-radius: var(--radius-pill);
  background: #FFFFFF;
}
.alloc-row:nth-child(2) .alloc-fill { background: rgba(255, 255, 255, 0.78); }
.alloc-row:nth-child(3) .alloc-fill { background: rgba(255, 255, 255, 0.55); }

/* Sentence case, sans — a mono uppercase run this long is unreadable at
   12px over a gradient. */
.budget-caption {
  margin-top: var(--space-5);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  line-height: 1.5;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  /* 0.82 alpha measured 4.37:1 over the green end — just under the 4.5:1
     that 12px text requires. Full white. */
  color: #FFFFFF;
}

/* The page's only oversized-imagery moment. Above 80em the 50/50 split
   reduced the beam to a 48px frame around a panel; here it stacks under
   the copy and bleeds to the viewport edges, giving the middle of the
   page one full-width image band between the hero and the footer.
   Sizing note: 100vw INCLUDES the scrollbar, so a 100vw full-bleed is
   genuinely ~15px wider than the content box (measured: beam 1440 inside
   a 1425 clientWidth). html's overflow-x: clip (base.css:18) hides that,
   but the element really is wider than the viewport. 100cqw against the
   section container is the scrollbar-free equivalent, so the bleed is
   exact; the 100vw pair stays first as the fallback for engines without
   container queries, where the clip still covers it. */
@media (min-width: 80em) {
  /* Container for the full-bleed maths below. .section is width:100% and
     so never sizes from its contents — inline-size containment costs
     nothing here. */
  #budget { container-type: inline-size; }
  .budget-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-9); }
  /* Same headline-left / prose-right shape as .section-head--split, so a
     full-width copy block doesn't become one narrow left column. */
  .budget-copy {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: var(--space-9);
    align-items: start;
  }
  .budget-copy > .t-caption { grid-column: 1 / -1; }
  .budget-copy .t-h2 { grid-column: 1; grid-row: 2; margin-bottom: 0; }
  .budget-copy p { grid-column: 2; max-width: 36rem; }
  .budget-copy p:nth-of-type(1) { grid-row: 2; }
  .budget-copy p:nth-of-type(2) { grid-row: 3; margin-top: var(--space-5); }
  /* The notes used to span both columns on a row of their own, which left
     row 3 / column 1 as a 350x669px void directly under the headline —
     the largest unintentional hole on the page. Moving them into that
     cell fills it and stops the notes reading as a thin full-width strip
     squeezed against the beam. */
  .budget-copy .budget-notes {
    grid-column: 1;
    grid-row: 3;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    margin-top: var(--space-6);
  }
  .budget-beam-bg {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    width: 100cqw;
    margin-inline: calc(50% - 50cqw);
    border-radius: 0;
    padding: var(--space-9) var(--space-8);
    display: grid;
    place-items: center;
  }
  /* 42rem left 53% of a 1440 band as bare gradient — the right third was
     a flat green field with nothing in it. 58rem composes the band. */
  .budget-beam-bg .glass-panel { width: 100%; max-width: 58rem; }
  /* The beam is a hard-edged full-bleed band and ends the section
     visually; ANY tint after it reads as leftover, so the padding goes to
     zero rather than being merely reduced. (--space-9 here still left a
     96px orphan strip of #EAE5FF under the beam.) */
  #budget { padding-bottom: 0; }
}

@media (max-width: 63.99em) {
  .budget-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
}
@media (max-width: 47.99em) {
  .budget-beam-bg { padding: var(--space-4); border-radius: var(--radius-lg); }
  .glass-panel { padding: var(--space-5); }
}

/* ═════════════════════════════════════════════════════════════════════
   7. PROOF / METRICS
   ════════════════════════════════════════════════════════════════════ */

.metric-band {
  display: grid;
  /* Equal 1fr cells gave a one-glyph value a 328px box beside a value
     that filled its own, so the row read tiny/tiny/huge/huge. Size each
     cell to its content and let the gaps do the distributing.
     minmax(0, max-content), not max-content: the cells must still be able
     to shrink when the four labels outrun the column at ~1024. */
  /* Four equal quarters, not max-content tracks distributed by
     space-between. With space-between the free space landed entirely in
     the track gaps, so each rule sat 32px before the next stat and 164px
     after the previous one and read as belonging to the stat on its
     right. (Adding margin-left to the divider cannot fix that: margin is
     inside the track, so space-between simply redistributes the same
     total.) Equal tracks put the rules at exactly 25/50/75% and the
     content is centred in its own quarter, so every rule is equidistant
     from the two stats it divides. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin-top: var(--space-8);
  padding-top: var(--space-7);
  border-top: 1px solid var(--section-border);
}
.metric-band .value { color: var(--section-ink); }
.metric-band .stat { text-align: center; padding-inline: var(--space-5); }
/* Rules between the cells so the row reads as one band rather than four
   numbers floating in whitespace. */
.metric-band .stat + .stat {
  border-left: 1px solid var(--section-border);
}

.proof-caption {
  margin-top: var(--space-7);
  max-width: 52rem;
  color: var(--section-ink-soft);
  font-size: var(--text-small);
}

.promises {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  margin-top: var(--space-8);
}
.promise {
  padding: var(--space-6);
  /* Same 1.30:1 ghost-edge problem as .product-card — see §4. */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-1);
}
.promise h3 { font-size: var(--fs-h4); margin-bottom: var(--space-3); }
.promise p { font-size: var(--text-small); color: var(--section-ink-soft); }

@media (max-width: 63.99em) {
  .metric-band {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    justify-content: stretch;
    gap: var(--space-7) var(--space-6);
  }
  /* Back to left-aligned below the divider breakpoint: centring only
     earns its place when the vertical rules give it a reason to. */
  .metric-band .stat { text-align: left; padding-inline: 0; }
  /* In a 2-up wrap the divider would land on the left edge of row 2. */
  .metric-band .stat + .stat { border-left: 0; }
  .promises { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 30em) {
  .metric-band { gap: var(--space-6) var(--space-4); }
}

/* ═════════════════════════════════════════════════════════════════════
   8. FINAL CTA
   ════════════════════════════════════════════════════════════════════ */

.cta-section {
  text-align: center;
  overflow: hidden;
  /* Re-aim the agent field: the hero's off-centre mesh reads as a smudge
     behind centred copy in a short band. */
  background:
    radial-gradient(52% 90% at 50% -10%, rgba(133, 119, 255, 0.42), transparent 70%),
    radial-gradient(60% 90% at 50% 115%, rgba(34, 197, 94, 0.16), transparent 70%),
    #0A0A0C;
}
.cta-section .wrap { max-width: 60rem; }
.cta-section h2 { color: #FFFFFF; }
.cta-section h2 .em { color: #C9C2FF; }
.cta-section .t-lead {
  margin-top: var(--space-6);
  margin-inline: auto;
  color: #B6B6B2;
}
.cta-section .btn-row { justify-content: center; margin-top: var(--space-8); }
.cta-section .btn-ghost { color: #F5F5F3; }
.cta-section .foot-note { margin-top: var(--space-7); color: #86868A; }

@media (max-width: 47.99em) {
  /* The forced break keeps the accent word off the end of line 1 on a wide
     canvas; at 375 the headline needs all three lines to rebalance. */
  .cta-section .br-wide { display: none; }
  .cta-section .btn-row { flex-direction: column; align-items: stretch; }
  .cta-section .btn-primary { width: 100%; }
  .cta-section .btn-ghost { align-self: center; }
}

/* ═════════════════════════════════════════════════════════════════════
   9. FOOTER
   ════════════════════════════════════════════════════════════════════ */

.site-footer {
  padding-block: var(--space-9) var(--space-7);
  border-top: 1px solid var(--section-border);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr));
  gap: var(--space-7) var(--space-6);
}
.footer-brand .brand { font-size: 1.375rem; }
.footer-brand p {
  margin-top: var(--space-4);
  font-size: var(--text-small);
  color: var(--section-ink-soft);
  max-width: 24rem;
}
/* The visible label is a <p aria-hidden>; the real <h2> is
   visually-hidden so four 12px column headers don't sit at the same
   outline level as the page's five section headings. */
.footer-col .col-title {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--section-ink-soft);
  margin-bottom: var(--space-4);
}
.footer-col ul { display: flex; flex-direction: column; gap: var(--space-3); }
.footer-col a {
  font-size: var(--text-small);
  color: var(--section-ink);
  transition: color var(--dur-base) var(--ease-standard);
}
/* Light lilac, not --accent-strong: this bar is always dark. */
.footer-col a:hover { color: #C9C2FF; }

.footer-bottom {
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid var(--section-border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4) var(--space-6);
}
.footer-bottom .legal { font-size: var(--text-caption); color: var(--section-ink-soft); }
.footer-dots {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}
.footer-dots li {
  display: inline-flex;
  align-items: center;
  /* The active dot's pulse ring reaches 14.4px from its centre; 0.5em
     (6px at 12px type) let it overrun the first letter of the label. */
  gap: 0.9em;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--section-ink-soft);
}
/* NOT dead code, despite containing no <a> on the homepage: 404.html,
   privacy.html and terms.html reuse .footer-dots as a compact link row
   (Home / Terms / email), where these rules lift the anchors out of the
   list's --section-ink-soft and supply the on-dark hover. */
.footer-dots a { color: var(--section-ink); transition: color var(--dur-base) var(--ease-standard); }
.footer-dots a:hover { color: #C9C2FF; }

@media (max-width: 63.99em) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 30em) {
  .footer-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
}

/* ═════════════════════════════════════════════════════════════════════
   10. LEGAL + 404 PAGES
   ════════════════════════════════════════════════════════════════════ */

.page-head { padding-top: calc(72px + var(--space-9)); }
.doc {
  max-width: var(--prose-max);
  margin-top: var(--space-8);
}
.doc h2 {
  font-size: var(--fs-h3);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-top: var(--space-8);
  margin-bottom: var(--space-4);
}
.doc h2:first-child { margin-top: 0; }
.doc p, .doc li { color: var(--section-ink-soft); }
.doc p + p { margin-top: var(--space-4); }
.doc ul {
  list-style: disc;
  padding-left: 1.2em;
  margin-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.doc a { color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em; }
.doc .updated {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--section-ink-soft);
}

.error-page {
  min-height: min(78svh, 620px);
  display: flex;
  align-items: center;
  padding-top: calc(72px + var(--space-8));
}
.error-page .code {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.14em;
  color: #C9C2FF;
  margin-bottom: var(--space-5);
  display: block;
}
@media (max-width: 47.99em) {
  .page-head { padding-top: calc(56px + var(--space-7)); }
  .error-page { padding-top: calc(56px + var(--space-7)); }
}
