/* JDXPro marketing site
   Colour, type steps, spacing and radii come from tokens.css (generated from
   Development/tokens/tokens.json). Reference semantic roles here, not ramp
   values — see tokens/README.md [SYS-09]. Site-only additions are namespaced
   --s-* so they never collide with the generated token set. */

:root{
  --s-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;

  /* Fluid type for marketing scale — the token steps are sized for app UI. */
  --s-d1: clamp(34px, 5.4vw, 62px);
  --s-d2: clamp(30px, 4.2vw, 46px);
  --s-d3: clamp(23px, 2.4vw, 30px);
  --s-lead: clamp(16px, 1.35vw, 19px);

  --s-maxw: 1180px;
  --s-measure: 64ch;
  --s-pad: clamp(20px, 5vw, 40px);
  --s-section: clamp(72px, 10vw, 128px);

  --s-ease: cubic-bezier(.22, .61, .36, 1);
}

/* Body copy on dark is *secondary* text, not muted text, and tokens.css has a
   step for each. Pointing the role at --n-400 ("Muted text on dark") put this
   page's running copy at 4.00:1 on the base surface and 3.70:1 on raised —
   under the 4.5:1 WCAG AA floor. --n-200 ("Secondary text on dark") is the
   correct step and clears it at 10.58:1 / 9.81:1.

   NOTE for the apps: anything else using --on-surface-muted for running copy
   rather than for genuinely de-emphasised labels fails the same check, and a
   showroom tablet in daylight is the worst case for it. */
:root{ --on-surface-muted: var(--n-200); }

*, *::before, *::after{ box-sizing: border-box; }

html{
  scroll-behavior: smooth;
  /* Anchors must clear the sticky header. */
  scroll-padding-top: 88px;
  -webkit-text-size-adjust: 100%;
}

body{
  margin: 0;
  background: var(--surface);
  color: var(--on-surface);
  font-family: var(--font-ui);
  font-size: var(--s-lead);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

img, video{ display: block; max-width: 100%; height: auto; }

a{ color: inherit; }

h1, h2, h3{
  font-family: var(--s-display);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -.015em;
  margin: 0;
  text-wrap: balance;
}

/* Cormorant defaults to oldstyle figures, which turns "2,000" and "₹100" into
   something closer to "2,ooo" and "₹IOO". Prices must not be guessable. */
h1, h2, h3, .tier-price, .step-num{
  font-variant-numeric: lining-nums;
  font-feature-settings: 'lnum' 1;
}

p{ margin: 0; }

:focus-visible{
  outline: 2px solid var(--guidance);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* ---------- layout primitives ---------- */

.wrap{
  width: 100%;
  max-width: var(--s-maxw);
  margin-inline: auto;
  padding-inline: var(--s-pad);
}

.section{ padding-block: var(--s-section); }

/* The one light block. Re-points semantic roles exactly as .surface-light
   does in tokens.css, plus the web-specific paper/ink pair. */
.section--paper{
  background: var(--paper);
  --surface: var(--paper);
  --surface-raised: #FFFFFF;
  --outline: var(--line);
  --on-surface: var(--ink);
  --on-surface-muted: var(--muted);
  --primary: var(--assay-lo);
  --on-primary: var(--n-050);
  --guidance: var(--assay-lo);
  color: var(--on-surface);
}

.section--raised{ background: var(--surface-raised); }

/* The counter follows the hero directly — it should not read as a fresh start. */
.section--tight{ padding-top: clamp(36px, 5vw, 64px); }

.eyebrow{
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--guidance);
  margin: 0 0 18px;
}

.lede{
  font-size: var(--s-lead);
  color: var(--on-surface-muted);
  max-width: var(--s-measure);
}

.section-head{ max-width: 760px; margin-bottom: clamp(40px, 5vw, 64px); }
.section-head h2{ font-size: var(--s-d2); margin-bottom: 18px; }

/* ---------- buttons ---------- */

.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--touch-min);
  padding: 0 26px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .2s var(--s-ease), border-color .2s var(--s-ease),
              color .2s var(--s-ease), transform .2s var(--s-ease);
}
.btn:hover{ transform: translateY(-1px); }

.btn--primary{ background: var(--primary); color: var(--on-primary); }
.btn--primary:hover{ background: var(--assay-hi); }
.section--paper .btn--primary:hover{ background: var(--assay); }

.btn--ghost{ border-color: var(--n-600); color: var(--on-surface); }
.btn--ghost:hover{ border-color: var(--primary); color: var(--guidance); }
.section--paper .btn--ghost{ border-color: var(--outline); }
.section--paper .btn--ghost:hover{ border-color: var(--primary); color: var(--primary); }

/* ---------- header ---------- */

.site-header{
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--n-900) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--n-700);
}

.site-header .wrap{
  display: flex;
  align-items: center;
  gap: 24px;
  min-height: 72px;
}

.brand{
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  margin-right: auto;
}
/* Optical alignment: the mark's counter line sits below its visual mass, so
   centring it on the cap-height of the wordmark reads better than baseline. */
.brand-mark{ width: 34px; height: 34px; flex: none; }
.brand strong, .brand span{ align-self: baseline; }
.brand strong{
  font-family: var(--s-display);
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--n-100);
}
.brand strong em{ font-style: normal; color: var(--assay-hi); }
.brand span{
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 1.7px;
  text-transform: uppercase;
  /* Semantic role, not the ramp value [SYS-09]. --n-400 put this 9.5px label at
     4.00:1 — small text gets no large-text exemption, so it needs the full 4.5. */
  color: var(--on-surface-muted);
}

.site-nav{ display: flex; align-items: center; gap: 30px; }
.site-nav a{
  font-size: 14px;
  font-weight: 500;
  color: var(--n-200);
  text-decoration: none;
  transition: color .18s var(--s-ease);
}
.site-nav a:hover{ color: var(--assay-hi); }
.site-nav .btn{ min-height: 42px; padding: 0 20px; font-size: 14px; }

@media (max-width: 860px){
  .site-nav a:not(.btn){ display: none; }
}

/* ---------- hero ---------- */

.hero{
  padding-block: clamp(64px, 9vw, 104px) clamp(48px, 6vw, 72px);
  position: relative;
  overflow: hidden;
}
/* Warm pool of light behind the headline — gold at 9%, not a gradient band. */
.hero::before{
  content: '';
  position: absolute;
  top: -28%;
  left: 50%;
  width: min(1100px, 130%);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle, color-mix(in srgb, var(--assay) 9%, transparent) 0%, transparent 62%);
  pointer-events: none;
}
.hero .wrap{ position: relative; }

.hero h1{
  font-size: var(--s-d1);
  /* Wide enough that the explicit <br> is the only break that happens. */
  max-width: 30ch;
  margin-bottom: 26px;
}
.hero h1 em{ font-style: italic; color: var(--guidance); }

.hero .lede{ font-size: clamp(17px, 1.5vw, 21px); max-width: 56ch; }

.hero-actions{
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 36px;
}

.hero-tagline{
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 44px;
  padding-top: 26px;
  border-top: 1px solid var(--outline);
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  /* Semantic role, not the ramp value [SYS-09] — same 4.00:1 problem at 11px. */
  color: var(--on-surface-muted);
}
.hero-tagline span{ display: flex; align-items: center; gap: 22px; }
.hero-tagline span::after{ content: '\00B7'; color: var(--primary); }
.hero-tagline span:last-child::after{ content: none; }

/* ---------- capture: what went in, beside what came back ---------- */

.capture{
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
  gap: clamp(26px, 4vw, 60px);
  align-items: start;
  margin-bottom: clamp(48px, 6vw, 78px);
}

.capture-label{
  margin: 0 0 16px;
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--primary);
}

.capture-grid{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(8px, 1.2vw, 14px);
}
.capture-grid figure{ margin: 0; }
.capture-grid img{
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border: 1px solid var(--outline);
  border-radius: var(--radius-sm);
}
.capture-grid figcaption{
  margin-top: 7px;
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 1.7px;
  text-transform: uppercase;
  color: var(--on-surface-muted);
}

.capture-note{
  margin: 18px 0 0;
  font-size: 14px;
  color: var(--on-surface-muted);
}
.capture-note b{ color: var(--on-surface); font-weight: 600; }

/* -- the rotating output -- */

.capture-stage{
  position: relative;
  border: 1px solid var(--outline);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  overflow: hidden;
}
.capture-stage img{
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
}

.capture-controls{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-top: 12px;
}
.capture-controls button{
  position: relative;
  overflow: hidden;
  border: 1px solid var(--outline);
  border-radius: var(--radius-sm);
  background: transparent;
  padding: 10px 9px;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .2s var(--s-ease), background-color .2s var(--s-ease);
}
.capture-controls button:hover{ border-color: var(--primary); }
.capture-controls button.is-on{ border-color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }
.capture-controls b{
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--on-surface);
}
.capture-controls span{
  display: block;
  margin-top: 2px;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--on-surface-muted);
}
.capture-controls button.is-on span{ color: var(--primary); }

/* Progress hairline — only drawn while actually auto-advancing, so it never
   implies motion that is paused or switched off. */
.capture-controls button.is-on::after{
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left;
}
.capture.is-playing .capture-controls button.is-on::after{
  animation: capture-progress 4s linear forwards;
}
@keyframes capture-progress{ to { transform: scaleX(1); } }

@media (max-width: 820px){
  .capture{ grid-template-columns: 1fr; }
  .capture-grid{ grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 520px){
  .capture-controls{ grid-template-columns: 1fr 1fr; }
}
@media (prefers-reduced-motion: reduce){
  .capture.is-playing .capture-controls button.is-on::after{ animation: none; }
}

/* ---------- proof strip ---------- */

.proof{ padding-bottom: var(--s-section); }

/* The strip now introduces the capture story, so it sits between a section
   head and the three app cards rather than under the hero. */
.section--paper .proof-grid{ margin-bottom: clamp(20px, 3vw, 34px); }
.section--paper .proof-note{ margin-bottom: clamp(48px, 6vw, 78px); }

.proof-grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(10px, 1.4vw, 18px);
}

.shot{
  margin: 0;
  border: 1px solid var(--outline);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-raised);
}
/* Lift each card a little more than the last — reads as a progression. */
.proof-grid .shot:nth-child(2){ transform: translateY(-14px); }
.proof-grid .shot:nth-child(3){ transform: translateY(-28px); }
.proof-grid .shot:nth-child(4){ transform: translateY(-42px); }

.shot img{ width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }

.shot figcaption{
  padding: 13px 15px 15px;
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  /* Semantic, not a ramp value — the strip now sits on the light section. */
  color: var(--on-surface-muted);
  border-top: 1px solid var(--outline);
}
.shot figcaption b{ display: block; font-weight: 600; color: var(--primary); }

.proof-note{
  margin-top: clamp(20px, 3vw, 34px);
  font-size: 15px;
  color: var(--on-surface-muted);
  max-width: var(--s-measure);
}
.proof-note b{ color: var(--on-surface); font-weight: 600; }

@media (max-width: 720px){
  .proof-grid{ grid-template-columns: repeat(2, 1fr); }
  .proof-grid .shot:nth-child(n){ transform: none; }
}

/* ---------- problem ---------- */

.problem-grid{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(28px, 4vw, 52px);
}
.problem-grid h3{
  font-size: var(--s-d3);
  margin-bottom: 12px;
  color: var(--on-surface);
}
.problem-grid p{ color: var(--on-surface-muted); font-size: 16px; }
.problem-grid > div{ border-top: 2px solid var(--primary); padding-top: 22px; }

/* ---------- steps ---------- */

.steps{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: clamp(20px, 2.4vw, 30px);
}

.step{
  background: var(--surface-raised);
  border: 1px solid var(--outline);
  border-radius: var(--radius-lg);
  padding: clamp(26px, 3vw, 36px);
  display: flex;
  flex-direction: column;
}

.step-num{
  font-family: var(--s-display);
  font-size: 56px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--primary);
  margin-bottom: 14px;
}

.step h3{ font-size: var(--s-d3); margin-bottom: 4px; }

.step-role{
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--on-surface-muted);
  margin-bottom: 16px;
}

.step p{ color: var(--on-surface-muted); font-size: 16px; }

.step ul{
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  border-top: 1px solid var(--outline);
}
.step li{
  position: relative;
  padding: 11px 0 11px 22px;
  font-size: 15px;
  color: var(--on-surface-muted);
  border-bottom: 1px solid var(--outline);
}
.step li:last-child{ border-bottom: 0; padding-bottom: 0; }
.step li::before{
  content: '';
  position: absolute;
  left: 2px;
  top: 20px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
}

/* ---------- content matrix ---------- */

.matrix-scroll{ overflow-x: auto; }

.matrix{
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  font-size: 15px;
  background: var(--surface-raised);
  border: 1px solid var(--outline);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.matrix th, .matrix td{
  padding: 14px 18px;
  text-align: left;
  border-bottom: 1px solid var(--outline);
}
.matrix thead th{
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--on-surface-muted);
  background: color-mix(in srgb, var(--primary) 7%, transparent);
}
.matrix tbody th{ font-weight: 500; color: var(--on-surface); }
.matrix td{ text-align: center; color: var(--on-surface-muted); width: 15%; }
.matrix tbody tr:last-child th, .matrix tbody tr:last-child td{ border-bottom: 0; }
.matrix .yes{ color: var(--primary); font-weight: 600; font-size: 17px; }
/* 55% alpha dropped this under the floor; the em dash is the only thing marking
   "not included" in that cell, so it has to stay readable. */
.matrix .no{ color: color-mix(in srgb, var(--on-surface-muted) 78%, transparent); }

.footnote{
  margin-top: 18px;
  font-size: 14px;
  color: var(--on-surface-muted);
  max-width: var(--s-measure);
}

/* ---------- pricing ---------- */

.tiers{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: clamp(18px, 2.2vw, 26px);
  align-items: start;
}

.tier{
  background: var(--surface-raised);
  border: 1px solid var(--outline);
  border-radius: var(--radius-lg);
  padding: clamp(26px, 3vw, 34px);
}
.tier--featured{
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary);
}

.tier-name{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}
.tier-name{ flex-wrap: wrap; }
.tier-name h3{ font-size: var(--s-d3); }
.tier-tag{
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: 1.7px;
  text-transform: uppercase;
  color: var(--on-primary);
  background: var(--primary);
  border-radius: var(--radius-pill);
  padding: 5px 11px;
}

/* The outcome line carries the tier now that no price does. */
.tier-gloss{
  font-family: var(--s-display);
  font-size: 21px;
  line-height: 1.2;
  color: var(--guidance);
  margin: 0 0 20px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--outline);
}

/* Side by side, the featured card's badge would otherwise push its list a row
   lower than the other two. Reserve the space in all three. */
@media (min-width: 880px){
  .tier-name{ min-height: 72px; align-items: flex-start; }
  .tier-gloss{ min-height: 2.4em; }
}

.tier ul{ list-style: none; margin: 0; padding: 0; }
.tier li{
  position: relative;
  padding: 7px 0 7px 24px;
  font-size: 15px;
  color: var(--on-surface-muted);
}
.tier li::before{
  content: '';
  position: absolute;
  left: 3px;
  top: 15px;
  width: 9px;
  height: 2px;
  background: var(--primary);
}

.callout{
  margin-top: clamp(30px, 4vw, 46px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(22px, 3vw, 40px);
  padding: clamp(26px, 3.4vw, 40px);
  border: 1px solid var(--outline);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}
.callout h3{ font-size: var(--s-d3); margin-bottom: 12px; }
.callout p{ font-size: 15px; color: var(--on-surface-muted); }
.callout p + p{ margin-top: 10px; }
.callout b{ color: var(--on-surface); font-weight: 600; }
.callout a{ color: var(--guidance); text-underline-offset: 3px; }

/* ---------- the loop ---------- */

.loop{
  list-style: none;
  counter-reset: loop;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: clamp(20px, 2.6vw, 34px);
  margin: 0;
  padding: 0;
}
.loop li{ counter-increment: loop; position: relative; padding-top: 56px; }
.loop li::before{
  content: counter(loop);
  position: absolute;
  top: 0;
  left: 0;
  width: 38px;
  height: 38px;
  border: 1px solid var(--primary);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--primary);
  font-variant-numeric: lining-nums;
}
/* Connector between steps. It is a cycle, so the line fades out rather than
   arrowheading into a dead end. Dropped once the grid wraps to one column. */
.loop li::after{
  content: '';
  position: absolute;
  top: 19px;
  left: 50px;
  right: calc(clamp(20px, 2.6vw, 34px) * -1);
  height: 1px;
  background: linear-gradient(to right, var(--primary), transparent);
  opacity: .5;
}
.loop li:last-child::after{ display: none; }
.loop b{
  display: block;
  margin-bottom: 6px;
  font-size: 17px;
  font-weight: 600;
  color: var(--on-surface);
}
.loop p{ font-size: 15px; color: var(--on-surface-muted); }

@media (max-width: 640px){
  .loop li::after{ display: none; }
}

.loop-back{
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: clamp(26px, 3.4vw, 38px) 0 0;
  font-size: 15px;
  font-style: italic;
  color: var(--guidance);
}
.loop-back span{ font-style: normal; font-size: 20px; line-height: 1; }

/* Keep the three counter notes on a shared baseline when side by side. */
@media (min-width: 880px){
  .js-notes h3{ min-height: 2.1em; }
}

/* ---------- the balance (ratios, not prices) ---------- */

.balance{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(24px, 3.4vw, 52px);
  margin-top: clamp(22px, 3vw, 34px);
  padding: clamp(26px, 3.4vw, 40px);
  border: 1px solid var(--outline);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}
.balance h3{ font-size: var(--s-d3); margin-bottom: 20px; }

.balance dl{ margin: 0; }
.balance dl > div{
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--outline);
  font-size: 15px;
}
.balance dl > div:last-child{ border-bottom: 0; padding-bottom: 0; }
/* The upgrade row is a different kind of fact from the three levels above it. */
.balance dl > div.is-rule{
  margin-top: 6px;
  border-top: 1px dashed var(--primary);
  border-bottom: 0;
  padding-top: 14px;
}
.balance dt{ color: var(--on-surface-muted); }
.balance dd{
  margin: 0;
  font-weight: 600;
  text-align: right;
  color: var(--on-surface);
  font-variant-numeric: lining-nums;
}
.balance dl > div.is-rule dd{ color: var(--guidance); }

.balance-eq > p{ font-size: 15px; color: var(--on-surface-muted); }
.balance-eq ul{
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.balance-eq li{
  border-left: 2px solid var(--primary);
  padding: 12px 0 12px 16px;
}
.balance-eq li b{
  display: block;
  font-family: var(--s-display);
  font-size: 30px;
  font-weight: 600;
  line-height: 1;
  color: var(--on-surface);
  font-variant-numeric: lining-nums;
}
.balance-eq li span{
  display: block;
  margin-top: 5px;
  font-size: 14px;
  color: var(--on-surface-muted);
}
.balance-note{
  margin-top: 18px !important;
  font-size: 13.5px !important;
}

@media (max-width: 760px){
  .balance{ grid-template-columns: 1fr; }
}

/* ---------- channels: export shapes ----------
   One piece at four aspect ratios, set to a common height so the differing
   widths ARE the point. Wide on purpose — the row scrolls inside itself rather
   than shrinking, so the shapes stay comparable at every width. */

.exports{
  display: flex;
  /* Images share a CSS height, so aligning tops keeps the image band flush
     while captions of differing length hang below it. */
  align-items: flex-start;
  gap: clamp(10px, 1.4vw, 16px);
  overflow-x: auto;
  padding-bottom: 6px;
  scrollbar-width: thin;
}
.exports figure{ margin: 0; flex: none; }
.exports img{
  height: clamp(168px, 21vw, 250px);
  width: auto;
  border: 1px solid var(--outline);
  border-radius: var(--radius-sm);
}
.exports figcaption{
  margin-top: 11px;
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--on-surface-muted);
  max-width: 22ch;
}
.exports figcaption b{
  display: block;
  font-weight: 600;
  color: var(--guidance);
  font-variant-numeric: lining-nums;
}

.section--raised .footnote{ margin-top: clamp(22px, 3vw, 34px); }

/* ---------- what's next (roadmap) ----------
   Visually distinct from everything shipped: dashed rules instead of the solid
   gold used elsewhere, so "not yet" is legible before the status line is read. */

.next{
  margin-top: clamp(48px, 6vw, 80px);
  padding-top: clamp(34px, 4.4vw, 52px);
  border-top: 1px dashed var(--outline);
}

.next-head{ max-width: 640px; margin-bottom: clamp(30px, 4vw, 44px); }
.next-head h3{ font-size: var(--s-d3); margin-bottom: 14px; }
.next-head p{ font-size: 16px; color: var(--on-surface-muted); }

.next-grid{
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(22px, 2.8vw, 36px);
}
.next-grid li{
  border-top: 1px dashed var(--primary);
  padding-top: 18px;
  /* Body copy varies in length; the closing note is pinned to the bottom so the
     four sit on one baseline. */
  display: flex;
  flex-direction: column;
}
.next-grid b{
  display: block;
  margin-bottom: 9px;
  font-size: 17px;
  font-weight: 600;
  color: var(--on-surface);
}
.next-grid p{ font-size: 15px; color: var(--on-surface-muted); }
/* The note's top rule is a visible line, so align those rather than the text
   baselines below them. Tally is the longest body at six lines (6 × 1.62em). */
@media (min-width: 900px){
  .next-grid > li > p:first-of-type{ min-height: 9.8em; }
}
.next-grid em{ font-style: normal; color: var(--guidance); white-space: nowrap; }

.next-note{
  /* Not `auto` — bottom-pinning would fight the body's min-height and push a
     one-line note's rule lower than the rest. */
  margin-top: 14px !important;
  padding-top: 14px;
  border-top: 1px solid var(--outline);
  font-size: 13.5px !important;
  color: color-mix(in srgb, var(--on-surface-muted) 80%, transparent) !important;
}

/* Sits ABOVE the four items on purpose. Read last, a skimmer takes four
   capabilities as available and leaves; read first, it frames them. */
.next-status{
  display: inline-block;
  margin: 0 0 clamp(26px, 3.2vw, 36px);
  padding: 10px 16px;
  border: 1px dashed var(--primary);
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--on-surface-muted);
  max-width: var(--s-measure);
}
.next-status b{ color: var(--guidance); font-weight: 600; }

/* ---------- cta ---------- */

.cta{
  border-top: 1px solid var(--outline);
  background:
    radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--assay) 11%, transparent) 0%, transparent 58%),
    var(--surface);
  text-align: center;
}
.cta h2{ font-size: var(--s-d2); margin-bottom: 18px; }
.cta .lede{ margin-inline: auto; }
.cta .hero-actions{ justify-content: center; }

/* ---------- demo request form ---------- */

.demo-form{
  max-width: 640px;
  margin: clamp(34px, 4.4vw, 48px) auto 0;
  text-align: left;   /* the CTA section is centred; the form must not be */
}

/* Hidden from people, visible to bots. Not display:none — some bots skip those. */
.demo-trap{
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.demo-grid{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 1.8vw, 20px);
}
.demo-field{ margin: 0; }
.demo-field--wide{ grid-column: 1 / -1; }

.demo-field label{
  display: block;
  margin-bottom: 7px;
  font-size: var(--text-section);
  font-weight: 600;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--on-surface-muted);
}
.demo-field label span{ color: var(--primary); }

.demo-field input,
.demo-field textarea{
  width: 100%;
  min-height: var(--touch-min);
  padding: 12px 14px;
  border: 1px solid var(--outline);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--on-surface);
  font: inherit;
  font-size: 15px;
  transition: border-color .18s var(--s-ease), background-color .18s var(--s-ease);
}
.demo-field textarea{ resize: vertical; line-height: 1.5; }
.demo-field input:hover,
.demo-field textarea:hover{ border-color: var(--n-600); }
.demo-field input:focus,
.demo-field textarea:focus{
  outline: none;
  border-color: var(--primary);
  background: var(--surface);
}
/* Only scold a field once it has actually been filled in wrong. */
.demo-field input:user-invalid,
.demo-field textarea:user-invalid{ border-color: var(--error); }

.demo-actions{
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: clamp(20px, 2.6vw, 28px);
}
.demo-actions .btn{ border: 1px solid transparent; }
.demo-actions .btn--ghost{ border-color: var(--n-600); }

.demo-privacy{
  margin: 16px 0 0;
  font-size: 13.5px;
  color: var(--on-surface-muted);
}
.demo-privacy b{ color: var(--on-surface); font-weight: 600; }

.demo-status{
  margin: 18px 0 0;
  padding: 13px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--outline);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--on-surface-muted);
}
.demo-status b{ color: var(--on-surface); font-weight: 600; }
.demo-status a{ color: var(--guidance); text-underline-offset: 3px; }
.demo-status.is-ok{ border-color: var(--success); }
.demo-status.is-warn{ border-color: var(--error); }

@media (max-width: 560px){
  .demo-grid{ grid-template-columns: 1fr; }
}

/* ---------- footer ---------- */

.site-footer{
  border-top: 1px solid var(--outline);
  padding-block: 44px;
  font-size: 14px;
  color: var(--on-surface-muted);
}
.site-footer .wrap{
  display: flex;
  flex-wrap: wrap;
  gap: 18px 32px;
  align-items: center;
}
.site-footer nav{ display: flex; flex-wrap: wrap; gap: 22px; margin-right: auto; }
.site-footer a{ text-decoration: none; }
.site-footer a:hover{ color: var(--assay-hi); }

/* ---------- reveal on scroll ---------- */

.reveal{
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--s-ease), transform .7s var(--s-ease);
}
.reveal.is-in{ opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  .reveal{ opacity: 1; transform: none; }
}
