/* ==========================================================================
   brynko devOps Agent, marketing design system
   Dark-first developer-tool aesthetic. One stylesheet, no build step (matches
   the Laravel/Blade setup). Sections opt into .surface-* for light/dark bands.
   ========================================================================== */

/* ---------- tokens ---------- */
:root{
  /* brand */
  --brand-1:#4f9bff; --brand-2:#7c8cff; --brand-3:#9b7cff;
  --grad:linear-gradient(100deg,var(--brand-1),var(--brand-2),var(--brand-3));
  --grad-soft:linear-gradient(100deg,rgba(79,155,255,.16),rgba(155,124,255,.16));

  /* dark surface scale (default) */
  --bg:#070b18;
  --bg-2:#0b1226;
  --panel:#0e1730;
  --panel-2:#131e3d;
  --line:rgba(255,255,255,.09);
  --line-strong:rgba(255,255,255,.16);
  --ink:#eef2fb;
  --ink-2:#aab4cc;
  --ink-3:#7f8aa6;

  /* semantic */
  --ok:#3ddc97; --warn:#ffb454; --err:#ff6b6b;

  /* type */
  --sans:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Consolas,monospace;

  /* layout */
  --max:1180px; --gut:24px;
  /* Sticky header: 66px nav + 1px border. The pinned hero subtracts this so it
     centres inside the VISIBLE area rather than inside the whole viewport. */
  --header-h:67px;
  --r-sm:10px; --r:14px; --r-lg:20px; --r-xl:28px;
  --shadow:0 18px 50px -12px rgba(0,0,0,.55);
  --shadow-glow:0 0 0 1px var(--line),0 24px 70px -20px rgba(79,155,255,.35);
}

/* light band tokens (applied per-section) */
.surface-light{
  --bg:#ffffff; --bg-2:#f5f8ff; --panel:#ffffff; --panel-2:#f5f8ff;
  --line:#e6ebf5; --line-strong:#d3dbeb;
  --ink:#0d1424; --ink-2:#4d586f; --ink-3:#7c8699;
  --shadow:0 14px 40px -16px rgba(13,20,36,.16);
  --shadow-glow:0 0 0 1px var(--line),0 20px 50px -22px rgba(79,155,255,.28);
  background:var(--bg); color:var(--ink);
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:var(--sans);font-size:16.5px;line-height:1.65;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  /* `clip` contains horizontal overflow WITHOUT creating a scroll container.
     `hidden` here would silently break every position:sticky on the page. */
  overflow-x:clip;
}
@supports not (overflow:clip){body{overflow-x:hidden;}}
img,svg,canvas{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
::selection{background:rgba(124,140,255,.32);}

/* respect user motion + data preferences everywhere */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;}
}

/* ---------- layout ---------- */
.wrap{max-width:var(--max);margin-inline:auto;padding-inline:var(--gut);}
.wrap-narrow{max-width:820px;margin-inline:auto;padding-inline:var(--gut);}
section{padding:clamp(64px,9vw,116px) 0;position:relative;}
.grid{display:grid;gap:clamp(18px,2.4vw,28px);}
.g-2{grid-template-columns:repeat(2,minmax(0,1fr));}
.g-3{grid-template-columns:repeat(3,minmax(0,1fr));}
.g-4{grid-template-columns:repeat(4,minmax(0,1fr));}
@media(max-width:940px){.g-3,.g-4{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media(max-width:660px){.g-2,.g-3,.g-4{grid-template-columns:1fr;}}

/* ---------- type ---------- */
h1,h2,h3,h4{margin:0;font-weight:760;letter-spacing:-.028em;line-height:1.12;}
h1{font-size:clamp(38px,6.2vw,68px);letter-spacing:-.038em;}
h2{font-size:clamp(28px,4vw,45px);}
h3{font-size:clamp(19px,2vw,23px);letter-spacing:-.02em;line-height:1.3;}
p{margin:0;}
.lede{font-size:clamp(17px,1.6vw,20px);color:var(--ink-2);line-height:1.62;}
.muted{color:var(--ink-2);}
.small{font-size:14.5px;}
.grad-text{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;}
.mono{font-family:var(--mono);font-size:.92em;}

.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--brand-1);
}
.eyebrow::before{content:"";width:18px;height:1.5px;background:var(--grad);border-radius:2px;}

.sec-head{max-width:730px;margin:0 auto clamp(38px,5vw,60px);text-align:center;}
.sec-head h2{margin:14px 0 16px;}
.sec-head .lede{margin-inline:auto;}
.sec-head-left{max-width:640px;margin:0 0 clamp(32px,4vw,48px);text-align:left;}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:13px 24px;border-radius:var(--r-sm);border:1px solid transparent;
  font:inherit;font-size:15px;font-weight:640;letter-spacing:-.01em;
  cursor:pointer;transition:transform .18s cubic-bezier(.2,.8,.2,1),box-shadow .18s,background .18s,border-color .18s;
  white-space:nowrap;
}
.btn:hover{transform:translateY(-2px);}
.btn:active{transform:translateY(0);}
.btn-primary{background:var(--grad);color:#080f22;font-weight:700;box-shadow:0 10px 30px -10px rgba(124,140,255,.7);}
.btn-primary:hover{box-shadow:0 16px 40px -12px rgba(124,140,255,.85);}
.btn-ghost{border-color:var(--line-strong);color:var(--ink);background:rgba(255,255,255,.02);}
.btn-ghost:hover{border-color:var(--brand-2);background:rgba(124,140,255,.08);}
.btn-lg{padding:16px 30px;font-size:16px;}
.btn-sm{padding:9px 16px;font-size:14px;}
.btn[disabled]{opacity:.55;cursor:default;transform:none;}

/* ---------- interactive dot field ----------
   Two stacked layers: a faint constant grid so the section never looks empty,
   and a brighter one revealed only inside a spotlight that follows the cursor.
   It's CSS masking driven by two custom properties, so there's no canvas and no
   per-frame layout work, just a cheap paint. Falls back to the faint grid if
   JS never sets the position, and the spotlight is dropped for reduced motion. */
.dotfield{
  position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  color:var(--brand-2);
}
.surface-light .dotfield{color:#33436b;}
.dotfield::before,.dotfield::after{
  content:"";position:absolute;inset:0;
  background-image:radial-gradient(circle,currentColor 1.15px,transparent 1.15px);
  background-size:26px 26px;
}
.dotfield::before{opacity:.14;}
.dotfield::after{
  opacity:.75;
  --spot:radial-gradient(240px circle at var(--mx,50%) var(--my,-200px),
          #000 0%,rgba(0,0,0,.45) 42%,transparent 72%);
  -webkit-mask-image:var(--spot);mask-image:var(--spot);
}
/* slow drifting wash so the section still breathes when nobody is hovering */
.dotfield-glow{
  position:absolute;z-index:0;pointer-events:none;
  width:min(760px,80vw);aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(79,155,255,.16),transparent 68%);
  filter:blur(40px);top:-30%;left:50%;translate:-50% 0;
  animation:drift 22s ease-in-out infinite alternate;
}
.surface-light .dotfield-glow{background:radial-gradient(circle,rgba(79,155,255,.2),transparent 68%);}
@keyframes drift{
  from{transform:translate3d(-14%,0,0) scale(1);}
  to  {transform:translate3d(14%,5%,0) scale(1.12);}
}
@media (prefers-reduced-motion:reduce){
  .dotfield::after{display:none;}
  .dotfield-glow{animation:none;}
}
/* content must sit above the field */
.has-dotfield > .wrap{position:relative;z-index:1;}

/* ---------- cards ---------- */
.card{
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(22px,2.6vw,30px);position:relative;overflow:hidden;
  transition:border-color .22s,transform .22s cubic-bezier(.2,.8,.2,1),box-shadow .22s;
}
.card:hover{border-color:var(--line-strong);transform:translateY(-3px);box-shadow:var(--shadow);}
.card h3{margin-bottom:9px;}
.card p{color:var(--ink-2);font-size:15.5px;}
/* gradient hairline that lights up on hover */
.card-lit::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;background:var(--grad);
  opacity:0;transition:opacity .25s;
}
.card-lit:hover::before{opacity:1;}

/* ---------- problem ledger ----------
   Not another row of icon-in-a-rounded-square cards, that's the fastest way
   for a section to read as machine-templated. This is a short incident log
   instead: a real number pulled out of each story, the problem, then the fix,
   using the same log/resolve language as the hero conversation above. Sits
   directly on the dot-field background rather than a panel on top of it. */
.case-list{
  display:flex;flex-direction:column;
  max-width:860px;margin-inline:auto;
}
.case-row{
  display:grid;grid-template-columns:140px 1fr;gap:clamp(20px,3vw,44px);
  padding:clamp(26px,3.2vw,38px) 0;
  border-top:1px solid var(--line);
}
.case-list .case-row:last-child{border-bottom:1px solid var(--line);}
.case-num{
  display:block;font-family:var(--mono);font-weight:700;
  font-size:clamp(25px,2.5vw,32px);letter-spacing:-.02em;color:var(--ink);
  line-height:1.1;
}
.case-tag{
  display:block;margin-top:7px;font-size:11px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--brand-1);
}
.case-body h3{margin-bottom:10px;}
.case-body > p{color:var(--ink-2);font-size:15.5px;max-width:58ch;}
/* Resolution line: a quiet left-border callout, not a pill badge, badges read
   as UI chrome borrowed from a component library. This reads as a margin note. */
.case-fix{
  margin-top:16px;padding-left:16px;border-left:2px solid rgba(61,220,151,.55);
  font-size:14.5px;line-height:1.6;color:var(--ink-2);
}
.case-fix-tag{
  color:var(--ok);font-weight:700;
}
.case-fix-tag::after{content:". ";}
@media(max-width:660px){
  .case-row{grid-template-columns:1fr;gap:10px;}
  .case-num{font-size:23px;}
}

/* ---------- plain lists ----------
   Used where a bullet needs an icon or a rule instead of a disc. The leading
   element is whatever the markup puts first (an svg, or a .dash rule). */
.plain-list{list-style:none;margin:0;padding:0;display:grid;gap:12px;}
.plain-list li{
  display:flex;gap:11px;align-items:flex-start;
  font-size:15.2px;line-height:1.55;color:var(--ink-2);
}
.plain-list li svg{flex:none;margin-top:4px;}
.plain-list .dash{
  flex:none;width:13px;height:1.5px;margin-top:11px;border-radius:2px;
  background:var(--line-strong);
}

/* ---------- ask list ----------
   Real phrasings a visitor might type, laid out as a loose cloud rather than a
   grid: they are examples, not a feature matrix, and a rigid grid makes them
   read as specification. Monospace because they are things you type. */
.ask-grid{
  display:flex;flex-wrap:wrap;gap:10px;justify-content:center;
  max-width:900px;margin-inline:auto;
}
.ask{
  display:inline-flex;align-items:center;gap:9px;
  padding:10px 16px;border-radius:999px;
  border:1px solid var(--line);background:var(--panel);
  font-family:var(--mono);font-size:13.2px;color:var(--ink-2);
  transition:border-color .18s,color .18s,transform .18s;
}
.ask em{font-style:normal;color:var(--brand-1);font-weight:700;}
.ask:hover{border-color:var(--brand-2);color:var(--ink);transform:translateY(-2px);}
@media(max-width:600px){
  .ask-grid{justify-content:flex-start;}
  .ask{font-size:12.4px;padding:9px 13px;}
}

/* ---------- split list ----------
   Stacked sub-points under a section heading, separated by a rule instead of
   boxed into cards. Cards inside a two-column section start to look like a grid
   inside a grid; a rule keeps the reading order obvious. */
.split-list{display:grid;gap:0;}
.split-list > div{padding:13px 0;border-top:1px solid var(--line);}
.split-list > div:first-child{padding-top:0;border-top:0;}
.split-list h4{
  font-size:15.5px;font-weight:680;letter-spacing:-.02em;margin-bottom:5px;
  display:flex;align-items:baseline;gap:9px;
}
.split-list h4::before{
  content:"";width:5px;height:5px;border-radius:50%;flex:none;
  background:var(--grad);translate:0 -2px;
}
.split-list p{font-size:14.2px;line-height:1.55;color:var(--ink-2);}

/* ---------- numbered step list ----------
   A vertical alternative to the .flow grid, for sequences where each step needs
   a sentence rather than a phrase. The connecting rule makes the order obvious
   without an arrow graphic. */
.step-list{
  list-style:none;margin:0 auto;padding:0;max-width:760px;
  display:grid;gap:0;counter-reset:s;
}
.step-list li{
  display:grid;grid-template-columns:auto 1fr;gap:18px;
  padding:20px 0;position:relative;
}
.step-list li:not(:last-child)::before{
  content:"";position:absolute;left:17px;top:52px;bottom:-8px;width:1px;
  background:linear-gradient(180deg,var(--line-strong),transparent);
}
.step-n{
  width:35px;height:35px;border-radius:11px;display:grid;place-items:center;
  background:var(--grad-soft);border:1px solid var(--line);color:var(--brand-1);
  font-family:var(--mono);font-size:14px;font-weight:700;flex:none;
}
.step-list b{display:block;font-size:17px;letter-spacing:-.015em;margin:6px 0 6px;}
.step-list p{font-size:15px;color:var(--ink-2);line-height:1.6;}

/* ---------- note block ----------
   A quiet aside for caveats and limits. Deliberately not a card: it should read
   as a footnote in the argument, not another feature panel. */
.note-block{
  border-left:2px solid var(--line-strong);padding:2px 0 2px 16px;
}
.note-block b{
  display:block;font-size:12px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:6px;
}
.note-block p{font-size:14.5px;line-height:1.6;color:var(--ink-2);}

/* ---------- mini chat ----------
   A single exchange dropped into a normal page section. Reuses the .msg / .bub
   chat primitives from the hero, just without the scroll sequencing. */
.mini-chat{max-width:660px;}
.mini-chat .bub{box-shadow:0 12px 34px -20px rgba(0,0,0,.6);}
.surface-light .mini-chat .bub-ai{
  background:rgba(255,255,255,.9);color:var(--ink-2);border-color:var(--line);
}
.surface-light .mini-chat .bub-you{color:var(--ink);}

.ico{
  width:44px;height:44px;border-radius:12px;display:grid;place-items:center;
  background:var(--grad-soft);border:1px solid var(--line);margin-bottom:16px;
  color:var(--brand-1);flex:none;
}
.ico svg{width:21px;height:21px;}

/* ---------- chips / badges ---------- */
.chip{
  display:inline-flex;align-items:center;gap:7px;padding:6px 13px;border-radius:999px;
  border:1px solid var(--line);background:rgba(255,255,255,.03);
  font-size:13px;font-weight:560;color:var(--ink-2);
}
.surface-light .chip{background:#fff;}
/* ...but not inside a dark island on a light section. `.surface-light .chip` paints #fff, and it is
   a class-based rule, so pinning custom properties on .cta-band cannot reach it: the chips came out
   white carrying light-grey --ink-2 text. A class override is answered in kind. */
.surface-dark .chip,
.cta-band .chip{background:rgba(255,255,255,.03);}
.chip-dot{width:6px;height:6px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 3px rgba(61,220,151,.18);}

/* ---------- header ---------- */
.site-header{
  position:sticky;top:0;z-index:60;
  background:rgba(7,11,24,.72);backdrop-filter:saturate(160%) blur(14px);
  border-bottom:1px solid var(--line);
}
.nav{display:flex;align-items:center;gap:14px;height:66px;}
.brand{display:flex;align-items:center;gap:10px;font-weight:750;font-size:16.5px;letter-spacing:-.02em;color:#fff;flex:none;}
.brand img{height:26px;width:auto;}
.nav-links{display:flex;align-items:center;gap:4px;margin-left:18px;flex:1;}
.nav-links a{
  padding:8px 13px;border-radius:8px;font-size:14.5px;font-weight:520;color:var(--ink-2);
  transition:color .16s,background .16s;
}
.nav-links a:hover,.nav-links a[aria-current="page"]{color:#fff;background:rgba(255,255,255,.06);}
/* flex:none stops this shrinking, which is right on a wide bar and was wrong on a narrow one:
   at 375px the "Create an account" button ran 12px past the viewport and the whole PAGE scrolled
   sideways, on every page of the site. min-width:0 lets the button's own text truncate instead of
   forcing the nav wider than the screen. */
.nav-cta{display:flex;align-items:center;gap:10px;flex:none;min-width:0;}
.nav-toggle{display:none;background:none;border:1px solid var(--line-strong);border-radius:9px;padding:8px 10px;color:#fff;cursor:pointer;}
@media(max-width:1000px){
  .nav-links{display:none;position:absolute;top:66px;left:0;right:0;flex-direction:column;align-items:stretch;gap:2px;
    padding:14px var(--gut) 20px;background:var(--bg-2);border-bottom:1px solid var(--line);}
  .nav-links.open{display:flex;}
  .nav-links a{padding:12px 14px;font-size:16px;}
  .nav-toggle{display:block;margin-left:auto;}
  .nav-cta .btn-ghost{display:none;}
}

/* Below ~420px even the single remaining button is wider than the space left beside the logo and
   the hamburger. Shortening the label is better than letting it overflow: the destination is
   unchanged and the page stops scrolling sideways. */
@media(max-width:420px){
  .nav-cta .btn-primary{padding-left:12px;padding-right:12px;font-size:13.5px;white-space:nowrap;}
  .nav-cta .btn-primary .nav-cta-long{display:none;}
}

/* ---------- hero ---------- */
.hero{position:relative;padding:clamp(72px,11vw,130px) 0 clamp(60px,8vw,96px);overflow:hidden;}
.hero-grid{
  display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(28px,4vw,56px);align-items:center;position:relative;z-index:2;
}
@media(max-width:960px){.hero-grid{grid-template-columns:1fr;}}
.hero h1{margin:20px 0 22px;}
.hero .lede{max-width:560px;}
.hero-actions{display:flex;flex-wrap:wrap;gap:13px;margin-top:32px;}
.hero-note{margin-top:20px;display:flex;flex-wrap:wrap;gap:16px;color:var(--ink-3);font-size:13.5px;}
.hero-note span{display:inline-flex;align-items:center;gap:7px;}

/* ambient background: grid + aurora glow (pure CSS, no JS) */
.bg-grid{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(var(--line) 1px,transparent 1px),linear-gradient(90deg,var(--line) 1px,transparent 1px);
  background-size:56px 56px;
  mask-image:radial-gradient(ellipse 80% 60% at 50% 0%,#000 30%,transparent 75%);
  -webkit-mask-image:radial-gradient(ellipse 80% 60% at 50% 0%,#000 30%,transparent 75%);
  opacity:.55;
}
.bg-glow{
  position:absolute;z-index:0;pointer-events:none;border-radius:50%;filter:blur(90px);opacity:.5;
}
.bg-glow.a{width:min(620px,70vw);height:min(620px,70vw);top:-18%;right:-8%;background:radial-gradient(circle,rgba(79,155,255,.5),transparent 66%);}
.bg-glow.b{width:min(520px,60vw);height:min(520px,60vw);bottom:-24%;left:-10%;background:radial-gradient(circle,rgba(155,124,255,.42),transparent 66%);}

/* ==========================================================================
   SCROLL-DRIVEN HERO, "problem → solution" chat scrollytelling
   --------------------------------------------------------------------------
   .hero-scroll is a tall scroll track. .hero-pin sticks to the viewport, so
   scrolling that distance advances a set of chat "beats" on the right while
   the headline + CTA stay put on the left.

   Deliberate: the chat cards are real DOM, transformed in CSS 3D. Text stays
   crisp, selectable and indexable, WebGL is only the calm backdrop behind it.
   ========================================================================== */
.hero-scroll{position:relative;height:340vh;}
.hero-pin{
  /* Sticks BELOW the header, not under it, and is exactly as tall as the space
     the header leaves. Previously this was a full 100svh starting 67px down the
     page, so the centred content sat 67px below the optical centre and the gap
     under the header read as dead space on first load. */
  position:sticky;top:var(--header-h);overflow:hidden;
  /* svh = the *small* viewport height, so mobile browser chrome can't clip us.
     ONE grid row only, every other child is absolutely positioned. Adding a
     second in-flow child here silently creates a second row and wrecks the
     vertical centring (that was the blank-screen bug). */
  height:calc(100vh - var(--header-h));
  height:calc(100svh - var(--header-h));
  display:grid;grid-template-rows:1fr;align-items:center;
}

/* calm WebGL particle field, sits behind everything */
#hero-bg{position:absolute;inset:0;z-index:0;}
#hero-bg canvas{width:100%!important;height:100%!important;display:block;}

.hero-scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(70% 60% at 18% 45%,rgba(7,11,24,.94),transparent 70%),
    linear-gradient(0deg,var(--bg) 1%,transparent 22%);
}

.hero-stage{
  position:relative;z-index:2;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.02fr);
  gap:clamp(24px,4vw,64px);align-items:center;
}
@media(max-width:980px){.hero-stage{grid-template-columns:1fr;gap:28px;}}
.hero-copy{max-width:600px;}

/* The headline is short, so it gets to be big. A small headline in a big column
   is what made this feel empty. */
.hero-copy h1{
  font-size:clamp(46px,5.6vw,78px);line-height:1.02;letter-spacing:-.042em;
  margin:18px 0 20px;
}
.hero-copy .lede{font-size:clamp(16.5px,1.35vw,19px);max-width:44ch;}

/* trust points: a real list, stacked, with room to breathe */
.hero-note{
  list-style:none;margin:26px 0 0;padding:0;
  display:grid;gap:11px;
}
.hero-note li{
  display:flex;align-items:center;gap:10px;
  color:var(--ink-2);font-size:14.5px;
}
.hero-note .chip-dot{flex:none;}

/* ---------- the 3D chat deck ---------- */
.deck{
  position:relative;height:min(70svh,560px);min-height:320px;
  perspective:1400px;perspective-origin:55% 50%;
}

/* Short laptop viewports (roughly 1366×768 and similar) still get the full
   pinned experience, we scale the hero down to fit rather than bailing out to
   the static layout, which is what made it look like nothing was happening.
   Four-turn exchanges are tall, so the type and spacing tighten together. */
@media (min-width:981px) and (max-height:840px){
  .hero-copy h1{font-size:clamp(38px,4.8vw,58px);margin:14px 0 16px;}
  .hero-copy .lede{font-size:16px;}
  .hero-copy .hero-actions{margin-top:22px;}
  .hero-copy .hero-note{margin-top:18px;gap:9px;}
  .hero-note li{font-size:13.5px;}
  .deck{height:min(74svh,480px);min-height:300px;}
  .bub{padding:11px 15px;font-size:14px;line-height:1.55;}
  .beat{gap:8px;}
  .resolve{padding:9px 13px;font-size:12.5px;}
  .ava{width:26px;height:26px;font-size:13px;}
}
@media (min-width:981px) and (max-height:700px){
  .hero-copy h1{font-size:clamp(32px,3.9vw,46px);}
  .hero-copy .lede{font-size:15px;}
  .hero-copy .hero-note li:nth-child(3){display:none;}
  .deck{height:min(78svh,430px);min-height:280px;}
  .bub{font-size:13.2px;padding:10px 14px;}
  .beat{gap:7px;}
  .bub-act{font-size:10.8px;}
  .beat-tag{font-size:10px;}
}

.beat{
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:center;gap:11px;
  transform-style:preserve-3d;
  will-change:transform,opacity,filter;
  opacity:0;pointer-events:none;
}
.beat.is-active{pointer-events:auto;}

/* ---------- progressive reveal inside the active beat ----------
   The exchange plays in order, question asked, agent starts working, steps
   tick through, answer lands, outcome confirmed. It should read like watching
   it happen, not like a screenshot appearing. Pure CSS off .is-active. */
.beat .beat-tag,
.beat .msg-you,
.beat .ava,
.beat .msg-body > *{
  opacity:0;transform:translateY(14px);
  transition:opacity .45s ease,transform .45s cubic-bezier(.2,.8,.2,1);
}
.beat.is-active .beat-tag,
.beat.is-active .msg-you,
.beat.is-active .ava,
.beat.is-active .msg-body > *{opacity:1;transform:none;}

/* Turn-by-turn timing: question → agent works → agent asks → you approve →
   agent confirms. Delays are per message row so it plays like a conversation. */
.beat.is-active .beat-tag              {transition-delay:.03s;}
.beat.is-active > .msg:nth-of-type(1)  {transition-delay:.14s;}   /* you ask      */
.beat.is-active > .msg:nth-of-type(2)  {transition-delay:.32s;}   /* agent starts */
.beat.is-active > .msg:nth-of-type(3)  {transition-delay:1.05s;}  /* you approve  */
.beat.is-active > .msg:nth-of-type(4)  {transition-delay:1.28s;}  /* agent done   */
/* inside the agent's first turn: activity strip, then the reply */
.beat.is-active > .msg:nth-of-type(2) .msg-body > :nth-child(1){transition-delay:.36s;}
.beat.is-active > .msg:nth-of-type(2) .msg-body > :nth-child(2){transition-delay:.82s;}
/* inside the agent's closing turn: confirmation, then the verified outcome */
.beat.is-active > .msg:nth-of-type(4) .msg-body > :nth-child(1){transition-delay:1.32s;}
.beat.is-active > .msg:nth-of-type(4) .msg-body > :nth-child(2){transition-delay:1.60s;}

@media (prefers-reduced-motion:reduce){
  .beat .beat-tag,.beat .msg-you,.beat .ava,.beat .msg-body > *{
    opacity:1;transform:none;transition:none;
  }
}

/* Scenario label. Deliberately NOT bubble-shaped, it kept reading as another
   chat message. It's a quiet section heading with a rule, clearly outside the
   conversation. */
.beat-tag{
  display:flex;align-items:center;gap:12px;align-self:stretch;
  color:var(--ink-3);font-size:11px;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  margin-bottom:2px;
}
.beat-tag::after{
  content:"";flex:1;height:1px;
  background:linear-gradient(90deg,var(--line-strong),transparent);
}

/* ---------- chat structure ----------
   Message rows with an avatar on the agent side, so it reads as a conversation
   rather than two floating panels. */
.msg{display:flex;gap:10px;align-items:flex-end;}
.msg-you{justify-content:flex-end;}
.msg-ai{justify-content:flex-start;}
.msg-body{display:flex;flex-direction:column;gap:8px;min-width:0;max-width:min(100%,540px);}

/* Avatars on BOTH sides, without them it doesn't read as a conversation. */
.ava{
  width:29px;height:29px;border-radius:9px;flex:none;
  display:grid;place-items:center;line-height:1;
  font-weight:800;font-size:14px;
}
.ava-ai{
  background:var(--grad);color:#080f22;
  box-shadow:0 6px 18px -7px rgba(124,140,255,.8);
}
.ava-you{
  background:rgba(255,255,255,.07);border:1px solid var(--line-strong);color:var(--ink-3);
}
.ava-you svg{width:15px;height:15px;}

/* chat bubbles */
.bub{
  border-radius:16px;padding:14px 18px;font-size:15px;line-height:1.6;
  border:1px solid var(--line);
  box-shadow:0 16px 44px -22px rgba(0,0,0,.7);
  backdrop-filter:blur(10px);
}
.bub-you{
  max-width:min(88%,430px);
  background:linear-gradient(135deg,rgba(79,155,255,.26),rgba(124,140,255,.2));
  border-color:rgba(124,140,255,.42);color:#eef4ff;border-bottom-right-radius:5px;
}
.bub-ai{
  background:rgba(14,23,48,.9);color:var(--ink-2);border-bottom-left-radius:5px;
}
.bub-ai b{color:var(--ink);font-weight:640;}
.bub-ai .hl{color:var(--brand-1);font-family:var(--mono);font-size:.9em;}

/* ---------- the resolution line ----------
   Every exchange has to END somewhere. This is the "and then it was fixed"
   beat, what was done, and the verified outcome. Without it the demo just
   trails off on a question and the visitor never sees a result. */
.resolve{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;
  padding:11px 15px;border-radius:12px;
  background:linear-gradient(90deg,rgba(61,220,151,.1),rgba(61,220,151,.03));
  border:1px solid rgba(61,220,151,.26);
  font-size:13.2px;
}
.resolve code{
  font-family:var(--mono);font-size:.92em;color:var(--ink);
  background:rgba(255,255,255,.06);padding:1px 6px;border-radius:5px;
}
.resolve-do{color:var(--ink-3);}
.resolve-do::before{
  content:"↳";margin-right:7px;color:var(--brand-2);font-weight:700;
}
.resolve-ok{color:var(--ok);font-weight:640;margin-left:auto;}
@media(max-width:1180px){.resolve-ok{margin-left:0;}}

/* Shown only on mobile, where we render a single exchange. */
.deck-more{display:none;margin-top:4px;font-size:14px;}
.deck-more a{color:var(--brand-1);font-weight:600;}

/* the "what it did" strip, reads as tool activity, not chat.
   Steps tick in one at a time and the last one lands as a green "done", so the
   visitor sees the agent working rather than a finished list appearing at once. */
.bub-act{
  align-self:flex-start;display:flex;flex-wrap:wrap;gap:8px;
  font-family:var(--mono);font-size:11.5px;color:var(--ink-3);
}
.bub-act span{
  padding:5px 11px;border-radius:8px;background:rgba(255,255,255,.04);
  border:1px solid var(--line);
  display:inline-flex;align-items:center;gap:7px;
  opacity:0;transform:translateY(6px);
  transition:opacity .4s ease,transform .4s ease,color .4s ease,border-color .4s ease,background .4s ease;
}
.bub-act span::before{
  content:"";width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.6;flex:none;
}
.beat.is-active .bub-act span{opacity:1;transform:none;}
.beat.is-active .bub-act span:nth-child(1){transition-delay:.42s;}
.beat.is-active .bub-act span:nth-child(2){transition-delay:.58s;}
.beat.is-active .bub-act span:nth-child(3){transition-delay:.74s;}
.bub-act span.done{
  color:var(--ok);border-color:rgba(61,220,151,.32);background:rgba(61,220,151,.09);font-weight:600;
}
.bub-act span.done::before{
  content:"✓";width:auto;height:auto;border-radius:0;background:none;opacity:1;font-size:11px;line-height:1;
}
@media (prefers-reduced-motion:reduce){
  .bub-act span{opacity:1;transform:none;transition:none;}
}

/* ---------- progress rail ---------- */
.beat-rail-wrap{
  position:absolute;left:0;right:0;bottom:clamp(18px,4vh,40px);z-index:3;pointer-events:none;
}
.beat-rail{display:flex;gap:9px;align-items:center;pointer-events:auto;}
.beat-rail button{
  width:34px;height:4px;border-radius:3px;border:0;padding:0;cursor:pointer;
  background:var(--line-strong);transition:background .3s,width .3s;
}
.beat-rail button.on{width:52px;background:var(--grad);}

.scroll-hint{
  position:absolute;left:50%;bottom:22px;transform:translateX(-50%);z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:7px;
  color:var(--ink-3);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  transition:opacity .4s ease;
}
.hero-pin[data-scrolled="1"] .scroll-hint{opacity:0;}
.scroll-hint i{width:21px;height:32px;border:1.5px solid var(--line-strong);border-radius:11px;position:relative;}
.scroll-hint i::after{
  content:"";position:absolute;left:50%;top:6px;width:3px;height:6px;border-radius:2px;
  background:var(--brand-1);transform:translateX(-50%);animation:wheel 1.9s ease-in-out infinite;
}
@keyframes wheel{0%{opacity:0;transform:translate(-50%,0)}30%{opacity:1}100%{opacity:0;transform:translate(-50%,12px)}}

/* --------------------------------------------------------------------------
   Mobile / short viewports: a 100vh pin can't hold the headline AND the deck
   without clipping, and scroll-hijacking is worse on touch. Below 980px (or on
   short screens) we drop the pin and let the beats stack as normal content,
   same story, no clipping, no fighting the user's scroll.
   -------------------------------------------------------------------------- */
@media (max-width:980px),(max-height:480px){
  .hero-scroll{height:auto!important;}
  .hero-pin{
    position:relative!important;height:auto!important;min-height:0!important;overflow:visible;
    padding:clamp(56px,9vw,96px) 0 clamp(48px,7vw,76px);
    display:block;
  }
  .hero-stage{display:block;}
  .hero-copy{max-width:none;margin-bottom:36px;}
  .deck{height:auto!important;min-height:0!important;perspective:none;display:grid;gap:20px;}
  .beat{
    position:relative!important;inset:auto!important;display:flex;
    opacity:1!important;transform:none!important;filter:none!important;
    visibility:visible!important;pointer-events:auto;
    padding:18px;border:1px solid var(--line);border-radius:var(--r-lg);background:rgba(14,23,48,.5);
  }
  /* every reveal step resolved: on mobile this is plain readable content */
  .beat .beat-tag,.beat .msg-you,.beat .ava,.beat .msg-body > *,.bub-act span{
    opacity:1!important;transform:none!important;transition:none!important;
  }
  .bub{backdrop-filter:none;box-shadow:none;}
  .bub-you{max-width:100%;}
  .msg-body{max-width:100%;}
  .resolve-ok{margin-left:0;}
  .beat-rail-wrap,.scroll-hint{display:none;}
  /* Four stacked conversations is a very long scroll before any real content on
     a phone. Show ONE complete exchange, it makes the same point, and send
     people to the product page for the rest. */
  .beat:not(:first-child){display:none;}
  .deck-more{display:block;}
  .hero-scrim{background:linear-gradient(0deg,var(--bg) 2%,transparent 34%);}
  .hero-actions .btn{flex:1 1 auto;justify-content:center;}
}

/* --------------------------------------------------------------------------
   Static mode: no JS, reduced motion, or a device we shouldn't animate on.
   The track collapses and every beat stacks as plain, readable content, the
   page still tells the whole story, which is what crawlers and AI readers get.
   -------------------------------------------------------------------------- */
.no3d .hero-scroll,html:not(.js) .hero-scroll{height:auto;}
.no3d .hero-pin,html:not(.js) .hero-pin{
  position:relative;height:auto;min-height:0;padding:clamp(72px,11vw,116px) 0 clamp(56px,8vw,88px);
}
.no3d .deck,html:not(.js) .deck{height:auto;min-height:0;perspective:none;display:grid;gap:26px;}
.no3d .beat,html:not(.js) .beat{
  position:relative;inset:auto;opacity:1!important;transform:none!important;filter:none!important;
  visibility:visible!important;pointer-events:auto;
}
.no3d .beat .beat-tag,.no3d .beat .msg-you,.no3d .beat .ava,.no3d .beat .msg-body > *,.no3d .bub-act span,
html:not(.js) .beat .beat-tag,html:not(.js) .beat .msg-you,html:not(.js) .beat .ava,
html:not(.js) .beat .msg-body > *,html:not(.js) .bub-act span{
  opacity:1!important;transform:none!important;transition:none!important;
}
.no3d .scroll-hint,.no3d .beat-rail-wrap,.no3d #hero-bg,
html:not(.js) .scroll-hint,html:not(.js) .beat-rail-wrap{display:none;}

/* ---------- terminal / product mock ---------- */
.term{
  background:#080d1c;border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:var(--shadow);font-family:var(--mono);font-size:13.4px;line-height:1.75;
}
.term-bar{display:flex;align-items:center;gap:7px;padding:11px 14px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.02);}
.term-dot{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.16);}
.term-title{margin-left:8px;font-size:12px;color:var(--ink-3);font-family:var(--sans);}
.term-body{padding:16px 18px;color:#c7d2e8;white-space:pre-wrap;word-break:break-word;}
.term-body .u{color:#8fb7ff;}      /* user line */
.term-body .k{color:var(--brand-3);} /* keyword */
.term-body .ok{color:var(--ok);}
.term-body .dim{color:var(--ink-3);}

/* ---------- conversation carousel ----------
   The terminal frame stayed, because the window chrome is what signals "this is
   a real tool". What changed is the inside: turn-taking rows with avatars and
   bubbles instead of a wall of monospace, so it reads as a product rather than
   a log dump. Type stays in the mono family, which is the part that gives it
   its credibility. */
.convo{
  background:#080d1c;border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:var(--shadow);
  font-family:var(--mono);
}
.convo-bar{
  display:flex;align-items:center;gap:7px;padding:11px 14px;
  border-bottom:1px solid var(--line);background:rgba(255,255,255,.02);
}
.convo-nav{margin-left:auto;display:flex;gap:6px;}
.convo-arrow{
  width:26px;height:26px;border-radius:8px;padding:0;cursor:pointer;
  display:grid;place-items:center;
  background:rgba(255,255,255,.04);border:1px solid var(--line);
  color:var(--ink-3);transition:color .18s,border-color .18s,background .18s;
}
.convo-arrow svg{width:14px;height:14px;}
.convo-arrow:hover{color:var(--ink);border-color:var(--line-strong);background:rgba(255,255,255,.08);}

/* Slides are stacked in a single grid cell rather than absolutely positioned.
   That way the stage sizes itself to the TALLEST slide automatically, so a
   longer exchange can never be clipped, and switching slides never shifts the
   page. Absolute positioning needed a hardcoded height, which is exactly the
   kind of number that goes stale the moment the copy changes. */
.convo-stage{display:grid;}
.convo-slide{
  grid-area:1/1;padding:18px 18px 14px;
  display:flex;flex-direction:column;gap:12px;align-content:start;
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .45s ease,transform .45s ease,visibility .45s;
}
.convo-slide.is-on{opacity:1;visibility:visible;transform:none;}
.convo-tag{
  font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);display:flex;align-items:center;gap:10px;margin-bottom:2px;
}
.convo-tag::after{
  content:"";flex:1;height:1px;
  background:linear-gradient(90deg,var(--line-strong),transparent);
}

/* chat rows */
.cx{display:flex;gap:9px;align-items:flex-end;}
/* Agent avatar pins to the TOP of its turn: the turn now starts with activity
   chips, and an avatar floating beside the closing outcome chip read as if it
   belonged to the outcome rather than the message. */
.cx-ai{align-items:flex-start;}
.cx-you{justify-content:flex-end;}
.cx-col{display:flex;flex-direction:column;gap:8px;min-width:0;}
.cx-ava{
  width:24px;height:24px;border-radius:7px;flex:none;
  display:grid;place-items:center;font-size:12px;font-weight:800;line-height:1;
}
.cx-ava-ai{background:var(--grad);color:#080f22;box-shadow:0 5px 14px -6px rgba(124,140,255,.8);}
.cx-ava-you{background:rgba(255,255,255,.06);border:1px solid var(--line-strong);color:var(--ink-3);}
.cx-ava-you svg{width:13px;height:13px;}
.cx-bub{
  font-size:13.2px;line-height:1.65;padding:11px 14px;border-radius:13px;
  border:1px solid var(--line);max-width:min(100%,420px);
}
.cx-you .cx-bub{
  background:linear-gradient(135deg,rgba(79,155,255,.24),rgba(124,140,255,.18));
  border-color:rgba(124,140,255,.4);color:#eef4ff;border-bottom-right-radius:4px;
}
.cx-ai .cx-bub{
  background:rgba(255,255,255,.035);color:#c7d2e8;border-bottom-left-radius:4px;
}
.cx-ai .cx-bub b{color:var(--brand-3);font-weight:600;}

/* The "what it checked" strip: tool activity, not conversation.
   Chips rather than a sentence, because the reads are the evidence. Seeing the
   agent look before it answers is what separates this from a chatbot guessing,
   so it gets its own visual language. The last chip lands as a green done. */
.cx-act{
  display:flex;flex-wrap:wrap;gap:6px;align-self:flex-start;
  font-size:10.6px;color:var(--ink-3);letter-spacing:.01em;
}
.cx-act span{
  padding:4px 9px;border-radius:7px;
  background:rgba(255,255,255,.04);border:1px solid var(--line);
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
}
.cx-act span::before{
  content:"";width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.6;flex:none;
}
.cx-act span.done{
  color:var(--ok);border-color:rgba(61,220,151,.3);background:rgba(61,220,151,.08);font-weight:600;
}
.cx-act span.done::before{
  content:"✓";width:auto;height:auto;border-radius:0;background:none;opacity:1;font-size:10px;line-height:1;
}
/* the outcome line: every exchange has to land somewhere */
.cx-done{
  align-self:flex-start;font-size:11.8px;font-weight:600;color:var(--ok);
  padding:6px 11px;border-radius:8px;
  background:rgba(61,220,151,.09);border:1px solid rgba(61,220,151,.28);
  display:inline-flex;align-items:center;gap:7px;
}
.cx-done::before{content:"✓";font-size:11px;line-height:1;}

.convo-dots{
  display:flex;gap:7px;justify-content:center;padding:0 0 16px;
}
.convo-dots button{
  width:26px;height:4px;border-radius:3px;border:0;padding:0;cursor:pointer;
  background:var(--line-strong);transition:background .25s,width .25s;
}
.convo-dots button.is-on{background:var(--grad);width:38px;}

@media(max-width:520px){
  .convo-slide{padding:16px 14px 12px;}
  .cx-bub{font-size:12.6px;}
  .cx-act{font-size:10px;}
}
@media (prefers-reduced-motion:reduce){
  .convo-slide{transition:none;}
}

/* ---------- cost list ----------
   Task on the left, cost on the right, so the eye can run down the numbers.
   Stacks on narrow screens rather than squeezing two columns. */
.cost-list{margin:0;display:grid;gap:0;}
.cost-list > div{
  display:flex;flex-wrap:wrap;gap:8px 20px;align-items:baseline;
  justify-content:space-between;
  padding:13px 0;border-top:1px solid var(--line);
}
.cost-list > div:first-child{border-top:0;padding-top:0;}
.cost-list dt{font-size:15px;color:var(--ink);flex:1 1 300px;font-weight:560;}
/* What the job replaces. Quieter than the job itself, but present: it is the
   only thing on this table arguing FOR the purchase. */
.cost-instead{
  display:block;margin-top:4px;font-size:13.2px;font-weight:400;
  color:var(--ink-3);line-height:1.45;
}
.cost-list dd{
  margin:0;font-family:var(--mono);font-size:13.6px;font-weight:600;
  color:var(--ink);white-space:nowrap;
}
/* The money equivalent, which is what actually lands: a deploy in credits sounds
   large, the same deploy in dollars sounds like nothing next to an afternoon. */
.cost-money{color:var(--ok);font-weight:700;margin-left:8px;}

/* The closing comparison. This is the line that does the selling, so it is set
   as a statement rather than as another caption. */
.cost-anchor{
  margin-top:20px;padding-top:18px;border-top:1px solid var(--line);
  font-size:15.5px;line-height:1.6;color:var(--ink-2);
}
.cost-anchor b{color:var(--ok);font-weight:750;}

/* ---------- who grid (quick answer) ---------- */
.who-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 32px;}
.who-grid b{display:block;font-size:15.5px;margin-bottom:5px;letter-spacing:-.015em;}
.who-grid b a{color:var(--brand-1);}
.who-grid b a:hover{text-decoration:underline;}
.who-grid p{font-size:14.5px;line-height:1.6;color:var(--ink-2);}
@media(max-width:700px){.who-grid{grid-template-columns:1fr;gap:16px;}}

/* ---------- two paths ----------
   A structural comparison, not a timing claim: it counts context switches. Both
   markers start together, the short path finishes early and waits, and the
   difference is the message. Step names live in HTML beside it rather than in
   the SVG, so they are selectable, translatable and indexable. */
.paths{max-width:1000px;margin-inline:auto;}
.paths-svg{width:100%;height:auto;overflow:visible;}
.pt-label{font-size:13px;font-weight:750;fill:var(--ink-2);letter-spacing:.06em;text-transform:uppercase;}
.pt-label-b{fill:var(--brand-1);}
.pt-count{font-size:12.5px;font-weight:700;fill:var(--ink-3);font-family:var(--mono);}
.pt-count-b{fill:var(--ok);}
.pt-track{stroke:var(--line-strong);stroke-width:2;stroke-linecap:round;}
.pt-node{fill:var(--panel);stroke:var(--line-strong);stroke-width:2;}
.surface-light .pt-node{fill:#fff;}

/* the fill lines advance with each marker */
.pt-fill{stroke-width:2.6;stroke-linecap:round;fill:none;stroke-dasharray:928;stroke-dashoffset:928;}
.pt-fill-a{stroke:var(--ink-3);animation:pt-fill-a 11s linear infinite;}
.pt-fill-b{stroke:var(--ok);animation:pt-fill-b 11s linear infinite;}
@keyframes pt-fill-a{0%{stroke-dashoffset:928;} 72%,100%{stroke-dashoffset:0;}}
@keyframes pt-fill-b{0%{stroke-dashoffset:928;} 24%,100%{stroke-dashoffset:0;}}

.pt-run{fill:var(--ink-2);}
.pt-run-a{animation:pt-run-a 11s linear infinite;}
.pt-run-b{fill:var(--ok);animation:pt-run-b 11s linear infinite;}
@keyframes pt-run-a{0%{transform:translateX(0);} 72%,100%{transform:translateX(928px);}}
@keyframes pt-run-b{0%{transform:translateX(0);} 24%,100%{transform:translateX(928px);}}

/* nodes light up as they are passed */
.pt-node-a{animation:pt-pop 11s linear infinite;}
.pt-node-b{animation:pt-pop-b 11s linear infinite;}
@keyframes pt-pop  {0%,4%{stroke:var(--line-strong);} 9%,100%{stroke:var(--ink-2);}}
@keyframes pt-pop-b{0%,4%{stroke:var(--line-strong);} 9%,100%{stroke:var(--ok);}}

html.js .paths:not(.in) .pt-fill,
html.js .paths:not(.in) .pt-run,
html.js .paths:not(.in) .pt-node{animation-play-state:paused;}

.paths-legend{
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,52px);
  margin-top:clamp(24px,3vw,36px);
}
/* Direct child only. Unscoped, this also caught the <b> inside the "your part"
   sentence and broke it into an uppercase block mid-line. */
.paths-legend > div > b{
  display:block;font-size:12px;font-weight:750;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:12px;
}
.paths-legend ol{margin:0;padding-left:20px;display:grid;gap:7px;}
.paths-legend li{font-size:14.5px;line-height:1.5;color:var(--ink-2);}
.paths-legend > div:last-child > b{color:var(--ok);}
.paths-legend > div:last-child li{color:var(--ink);font-weight:560;}

/* The machine work that each of the three steps absorbs. Set smaller and quieter
   so the step you take still reads as the step, and the rest reads as what it
   does for you. */
.paths-legend .pt-sub{
  display:block;margin:6px 0 14px;padding-left:12px;
  border-left:2px solid var(--line-strong);
  font-size:13.4px;line-height:1.55;color:var(--ink-3);font-weight:400;
}
.paths-legend li:last-child .pt-sub{margin-bottom:0;}

/* the closing "your part" line under each column */
.pt-part{
  margin-top:18px;padding-top:14px;border-top:1px dashed var(--line-strong);
  font-size:13.8px;line-height:1.6;color:var(--ink-3);
}
/* Explicitly inline: this <b> sits mid-sentence and must stay part of the line. */
.pt-part b{
  display:inline;font-size:inherit;font-weight:700;
  text-transform:none;letter-spacing:normal;margin:0;color:var(--ink);
}
.pt-part-b{color:var(--ink-2);}
.pt-part-b b{color:var(--ok);}
@media(max-width:700px){
  .paths-legend{grid-template-columns:1fr;gap:22px;}
  .paths-svg{display:none;}
}
@media (prefers-reduced-motion:reduce){
  .pt-fill,.pt-run,.pt-node{animation:none;}
  .pt-fill{stroke-dashoffset:0;}
  .pt-run-a,.pt-run-b{transform:translateX(928px);}
  .pt-node-a{stroke:var(--ink-2);} .pt-node-b{stroke:var(--ok);}
}

/* ---------- scenario blocks + index ---------- */
.scn-block{padding:18px 0;border-top:1px solid var(--line);}
.scn-block:first-child{padding-top:0;border-top:0;}
.scn-block h3{font-size:17.5px;margin-bottom:7px;letter-spacing:-.02em;}
.scn-block p{font-size:14.8px;line-height:1.6;color:var(--ink-2);}

.wins{margin-top:22px;padding:18px 20px;border-radius:var(--r);
  border:1px solid var(--line);background:var(--panel);}
.wins > b{
  display:block;font-size:11.5px;font-weight:750;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:12px;
}
.wins .plain-list li{font-size:14.5px;}

.scn-index{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(24px,3vw,40px);}
@media(max-width:820px){.scn-index{grid-template-columns:1fr;}}
.scn-area h3{
  font-size:12px;font-weight:750;letter-spacing:.14em;text-transform:uppercase;
  color:var(--brand-1);margin-bottom:14px;
  display:flex;align-items:center;gap:12px;
}
.scn-area h3::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--line-strong),transparent);}
.scn-area dl{margin:0 0 clamp(26px,3vw,36px);display:grid;gap:0;}
.scn-row{padding:13px 0;border-bottom:1px solid var(--line);}
.scn-row dt{font-size:15.5px;font-weight:640;color:var(--ink);letter-spacing:-.015em;margin-bottom:4px;}
.scn-row dd{margin:0;font-size:14.2px;line-height:1.55;color:var(--ink-2);}

/* ---------- CSS-only tabs ----------
   Radio inputs drive the panels, so every panel is server-rendered and stays in
   the DOM: crawlers and AI fetchers read all of it, and the page still works
   with JS disabled. A radio group also gives keyboard users arrow-key movement
   between tabs for free, which a div-based tab strip would have to reimplement.

   The inputs live in a visually hidden fieldset ABOVE the list and panels so the
   sibling combinator can reach both. */
.tabs{position:relative;}
/* Hidden but still focusable: opacity rather than display:none, so the radio
   group keeps its keyboard behaviour. */
.tab-in{position:absolute;top:0;left:0;width:1px;height:1px;opacity:0;pointer-events:none;margin:0;}

.tab-list{
  display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
  margin-bottom:clamp(24px,3vw,36px);
}
.tab-btn{
  display:inline-flex;align-items:center;gap:9px;cursor:pointer;
  padding:11px 18px;border-radius:999px;
  border:1px solid var(--line);background:var(--panel);
  font-size:14.5px;font-weight:620;color:var(--ink-2);letter-spacing:-.01em;
  transition:border-color .18s,color .18s,background .18s,transform .18s;
  user-select:none;
}
.tab-btn:hover{border-color:var(--line-strong);color:var(--ink);transform:translateY(-1px);}
.tab-n{
  font-family:var(--mono);font-size:11.5px;font-weight:700;
  width:20px;height:20px;border-radius:6px;display:grid;place-items:center;
  background:rgba(255,255,255,.05);border:1px solid var(--line);color:var(--ink-3);
  transition:background .18s,color .18s,border-color .18s;
}
.surface-light .tab-n{background:rgba(13,20,36,.05);}

.tab-panel{display:none;}
.tab-panel .convo{margin-top:2px;}

/* Selected state: one rule per index, which is the cost of doing this without
   JS. Five stages, five pairs. */
.tab-in-0:checked ~ .tab-list .tab-btn-0,
.tab-in-1:checked ~ .tab-list .tab-btn-1,
.tab-in-2:checked ~ .tab-list .tab-btn-2,
.tab-in-3:checked ~ .tab-list .tab-btn-3,
.tab-in-4:checked ~ .tab-list .tab-btn-4{
  border-color:transparent;color:#080f22;background:var(--grad);font-weight:700;
  box-shadow:0 10px 26px -12px rgba(124,140,255,.75);
}
.tab-in-0:checked ~ .tab-list .tab-btn-0 .tab-n,
.tab-in-1:checked ~ .tab-list .tab-btn-1 .tab-n,
.tab-in-2:checked ~ .tab-list .tab-btn-2 .tab-n,
.tab-in-3:checked ~ .tab-list .tab-btn-3 .tab-n,
.tab-in-4:checked ~ .tab-list .tab-btn-4 .tab-n{
  background:rgba(8,15,34,.16);border-color:transparent;color:#080f22;
}
.tab-in-0:checked ~ .tab-panels .tab-panel-0,
.tab-in-1:checked ~ .tab-panels .tab-panel-1,
.tab-in-2:checked ~ .tab-panels .tab-panel-2,
.tab-in-3:checked ~ .tab-panels .tab-panel-3,
.tab-in-4:checked ~ .tab-panels .tab-panel-4{
  display:block;animation:tab-in .32s cubic-bezier(.2,.8,.2,1);
}
@keyframes tab-in{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}

/* Keyboard focus has to be visible on the LABEL, since the input is hidden. */
.tab-in-0:focus-visible ~ .tab-list .tab-btn-0,
.tab-in-1:focus-visible ~ .tab-list .tab-btn-1,
.tab-in-2:focus-visible ~ .tab-list .tab-btn-2,
.tab-in-3:focus-visible ~ .tab-list .tab-btn-3,
.tab-in-4:focus-visible ~ .tab-list .tab-btn-4{
  outline:2px solid var(--brand-1);outline-offset:3px;
}

/* No JS at all: show every panel stacked rather than hiding four fifths of the
   page behind interactions that cannot happen. */
html:not(.js) .tab-panel{display:block;margin-bottom:clamp(28px,4vw,48px);}

@media(max-width:600px){
  .tab-list{gap:6px;}
  .tab-btn{padding:9px 13px;font-size:13.5px;}
}
@media (prefers-reduced-motion:reduce){
  .tab-in-0:checked ~ .tab-panels .tab-panel-0,
  .tab-in-1:checked ~ .tab-panels .tab-panel-1,
  .tab-in-2:checked ~ .tab-panels .tab-panel-2,
  .tab-in-3:checked ~ .tab-panels .tab-panel-3,
  .tab-in-4:checked ~ .tab-panels .tab-panel-4{animation:none;}
}

/* ---------- system map ----------
   Inline SVG, themed with the same tokens as everything else, so it follows the
   light band it sits in without a second asset. Motion is decorative: the
   diagram is fully readable frozen, which is what reduced-motion users and the
   no-JS path both get. Animations stay paused until the section is on screen so
   nothing burns frames off-viewport. */
.sysmap{max-width:1000px;margin-inline:auto;}
.sysmap-svg{width:100%;height:auto;overflow:visible;}

/* boxes and connectors */
.sm-box{fill:var(--panel);stroke:var(--line-strong);stroke-width:1.5;}
.surface-light .sm-box{fill:#fff;}
.sm-lane{stroke:var(--line-strong);stroke-width:1.6;fill:none;}

/* type inside the drawing */
.sm-title{font-size:17px;font-weight:700;fill:var(--ink);letter-spacing:-.02em;}
.sm-sub,.sm-node-sub{font-size:11.5px;fill:var(--ink-3);}
.sm-node{font-size:14.5px;font-weight:640;fill:var(--ink);}
.sm-side{font-size:11px;font-weight:700;fill:var(--ink-3);letter-spacing:.14em;text-transform:uppercase;}
.sm-lane-label{font-size:12px;font-weight:750;fill:var(--brand-1);letter-spacing:.04em;text-transform:uppercase;}
.sm-lane-note{font-size:12px;fill:var(--ink-3);}
.sm-gate-label{font-size:11.5px;font-weight:700;fill:var(--ink-2);letter-spacing:.06em;text-transform:uppercase;}

/* the read lane: dashes running out, results running back */
.sm-flow{
  stroke:var(--brand-1);stroke-width:2.2;fill:none;
  stroke-dasharray:5 13;stroke-linecap:round;
  animation:sm-run 1.5s linear infinite;
}
.sm-flow-back{stroke:var(--ok);opacity:.85;animation:sm-run-back 2.1s linear infinite;}
@keyframes sm-run      {to{stroke-dashoffset:-36;}}
@keyframes sm-run-back {to{stroke-dashoffset:36;}}

/* the change lane: one packet, which is stopped at the gate until approved */
.sm-pkt{fill:var(--warn);animation:sm-pkt 7s cubic-bezier(.45,0,.2,1) infinite;}
@keyframes sm-pkt{
  0%       {transform:translateX(0);opacity:0;}
  6%       {opacity:1;}
  26%      {transform:translateX(212px);fill:var(--warn);}   /* arrives at the gate */
  50%      {transform:translateX(212px);fill:var(--warn);}   /* and waits there */
  56%      {fill:var(--ok);}                                  /* approved */
  80%,100% {transform:translateX(426px);fill:var(--ok);opacity:1;}
}

/* the gate reacts: neutral, then waiting, then green */
.sm-gate{
  fill:rgba(255,255,255,.04);stroke:var(--line-strong);stroke-width:1.8;
  animation:sm-gate 7s infinite;
}
.surface-light .sm-gate{fill:#fff;}
@keyframes sm-gate{
  0%,24%   {stroke:var(--line-strong);}
  30%,50%  {stroke:var(--warn);}
  56%,74%  {stroke:var(--ok);}
  82%,100% {stroke:var(--line-strong);}
}
.sm-gate-icon{fill:none;stroke:var(--ink-3);stroke-width:1.8;animation:sm-gate-icon 7s infinite;}
@keyframes sm-gate-icon{
  0%,24%   {stroke:var(--ink-3);}
  30%,50%  {stroke:var(--warn);}
  56%,74%  {stroke:var(--ok);}
  82%,100% {stroke:var(--ink-3);}
}
/* the two state captions above the gate, each visible only in its own window */
.sm-gate-state{font-size:11.5px;font-weight:700;opacity:0;}
.sm-state-wait{fill:var(--warn);animation:sm-wait 7s infinite;}
.sm-state-ok{fill:var(--ok);animation:sm-ok 7s infinite;}
@keyframes sm-wait{0%,26%{opacity:0;} 32%,48%{opacity:1;} 54%,100%{opacity:0;}}
@keyframes sm-ok  {0%,52%{opacity:0;} 58%,78%{opacity:1;} 84%,100%{opacity:0;}}

/* Paused until the section scrolls into view; the .js guard means a browser
   with JS disabled simply plays them rather than freezing on a blank state. */
html.js .sysmap:not(.is-live) .sm-flow,
html.js .sysmap:not(.is-live) .sm-pkt,
html.js .sysmap:not(.is-live) .sm-gate,
html.js .sysmap:not(.is-live) .sm-gate-icon,
html.js .sysmap:not(.is-live) .sm-gate-state{animation-play-state:paused;}

/* captions: the same content as the drawing, in text */
.sysmap-steps{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(18px,2.6vw,30px);margin-top:clamp(28px,4vw,44px);
}
.sysmap-steps b{
  display:block;font-size:16px;letter-spacing:-.015em;margin-bottom:7px;
  padding-left:13px;border-left:2px solid var(--brand-1);
}
.sysmap-steps p{font-size:14.5px;line-height:1.6;color:var(--ink-2);padding-left:13px;}

@media(max-width:860px){
  .sysmap-steps{grid-template-columns:1fr;gap:16px;}
}
@media(max-width:640px){
  /* Below this the drawing is too small to read. The captions carry it. */
  .sysmap-svg{display:none;}
}
@media (prefers-reduced-motion:reduce){
  .sm-flow,.sm-flow-back,.sm-pkt,.sm-gate,.sm-gate-icon,.sm-gate-state{animation:none;}
  .sm-pkt{transform:translateX(212px);}   /* frozen at the gate: the point of the diagram */
  .sm-state-wait{opacity:1;}
}

/* ---------- steps / flow ---------- */
.flow{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;counter-reset:step;}
@media(max-width:900px){.flow{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media(max-width:520px){.flow{grid-template-columns:1fr;}}
.flow-step{
  padding:22px 20px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--panel);position:relative;
}
.flow-step b{display:block;font-size:15.5px;margin-bottom:6px;letter-spacing:-.015em;}
.flow-step p{font-size:14px;color:var(--ink-2);}
.flow-step::after{
  counter-increment:step;content:counter(step);
  position:absolute;top:14px;right:16px;font-family:var(--mono);font-size:12px;color:var(--ink-3);
}

/* ---------- stats ---------- */
.stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;}
@media(max-width:760px){.stats{grid-template-columns:repeat(2,minmax(0,1fr));}}
.stat{background:var(--panel);padding:26px 22px;text-align:center;}
.stat b{display:block;font-size:clamp(26px,3.4vw,36px);font-weight:780;letter-spacing:-.03em;}
.stat span{font-size:13.5px;color:var(--ink-2);}

/* ---------- pricing ---------- */
.price-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;align-items:start;}
@media(max-width:960px){.price-grid{grid-template-columns:1fr;max-width:520px;margin-inline:auto;}}
.plan{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);padding:30px 26px;position:relative;}
.plan.featured{border-color:transparent;box-shadow:var(--shadow-glow);background:linear-gradient(var(--panel),var(--panel)) padding-box,var(--grad) border-box;border:1px solid transparent;}
.plan-tag{position:absolute;top:-11px;left:26px;padding:4px 12px;border-radius:999px;background:var(--grad);color:#080f22;font-size:11.5px;font-weight:750;letter-spacing:.04em;text-transform:uppercase;}
.plan h3{margin-bottom:6px;}
.plan .price{display:flex;align-items:baseline;gap:6px;margin:18px 0 6px;}
.plan .price b{font-size:40px;font-weight:780;letter-spacing:-.035em;}
.plan .price span{color:var(--ink-3);font-size:14.5px;}
.plan ul{list-style:none;margin:22px 0 26px;padding:0;display:grid;gap:11px;}
.plan li{display:flex;gap:10px;align-items:flex-start;font-size:15px;color:var(--ink-2);}
.plan li svg{width:17px;height:17px;flex:none;margin-top:4px;color:var(--brand-1);}
.plan .btn{width:100%;}

/* ---------- FAQ ---------- */
.faq{display:grid;gap:12px;max-width:820px;margin-inline:auto;}
.faq details{border:1px solid var(--line);border-radius:var(--r);background:var(--panel);overflow:hidden;transition:border-color .2s;}
.faq details[open]{border-color:var(--line-strong);}
.faq summary{
  cursor:pointer;list-style:none;padding:20px 24px;font-weight:620;font-size:16.5px;
  display:flex;align-items:center;justify-content:space-between;gap:16px;letter-spacing:-.015em;
}
.faq summary::-webkit-details-marker{display:none;}
.faq summary::after{content:"+";font-family:var(--mono);font-size:20px;color:var(--brand-1);flex:none;transition:transform .22s;}
.faq details[open] summary::after{transform:rotate(45deg);}
.faq .faq-a{padding:0 24px 22px;color:var(--ink-2);font-size:15.5px;}

/* ---------- forms ----------
   Only the contact form uses these today, but they are written as a general
   set so any future form (trial signup, security questionnaire) inherits the
   same look without new CSS. */
.form{display:grid;gap:16px;}
.field{display:grid;gap:7px;}
.field label{
  font-size:13.5px;font-weight:620;color:var(--ink-2);letter-spacing:-.01em;
  display:flex;align-items:baseline;gap:8px;
}
.field .opt{font-size:11.5px;font-weight:500;color:var(--ink-3);text-transform:uppercase;letter-spacing:.08em;}
.field input,.field textarea{
  width:100%;font:inherit;font-size:15px;color:var(--ink);
  background:var(--bg-2);border:1px solid var(--line-strong);border-radius:var(--r-sm);
  padding:12px 14px;transition:border-color .18s,box-shadow .18s,background .18s;
}
.surface-light .field input,.surface-light .field textarea{background:#fff;}
.field textarea{resize:vertical;min-height:110px;line-height:1.6;}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-3);opacity:.7;}
.field input:focus,.field textarea:focus{
  outline:none;border-color:var(--brand-2);
  box-shadow:0 0 0 3px rgba(124,140,255,.18);
}
/* Honeypot: off-screen rather than display:none, because some bots skip
   hidden inputs but not positioned ones. Never focusable by a person. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

/* ---------- alerts ---------- */
.alert{
  border-radius:var(--r-sm);padding:14px 16px;margin-bottom:20px;
  border:1px solid var(--line-strong);background:var(--panel-2);font-size:14.5px;
}
.alert b{display:block;margin-bottom:4px;font-size:15px;}
.alert p{color:var(--ink-2);line-height:1.55;}
.alert a{color:var(--brand-1);text-decoration:underline;}
.alert-ok{border-color:rgba(61,220,151,.36);background:rgba(61,220,151,.08);}
.alert-ok b{color:var(--ok);}
.alert-err{border-color:rgba(255,107,107,.36);background:rgba(255,107,107,.08);}
.alert-err b{color:#ff8b8b;}

/* ---------- CTA band ---------- */
/* DARK ISLAND: the exact mirror of .surface-light, for a block that must stay dark inside a light
   section. The band used to read its colours from whichever section contained it, so it was always
   dark-on-dark and the contrast people saw came entirely from the white FAQ above it. Once that
   moved, the band dissolved into the page.

   THE TOKEN LIST HERE MUST STAY COMPLETE. A first attempt pinned only --panel and --ink and left
   --bg-2 to inherit, so .cta-brief (background:var(--bg-2)) came out near-white while its text
   stayed light grey: an unreadable card, and a failure that only appears on a light section, which
   is the one place this block is not usually tested. Mirror every custom property .surface-light
   overrides, or none. */
.surface-dark,
.cta-band{
  --bg:#070b18; --bg-2:#0b1226; --panel:#0e1730; --panel-2:#131e3d;
  --line:rgba(255,255,255,.09); --line-strong:rgba(255,255,255,.16);
  --ink:#eef2fb; --ink-2:#aab4cc; --ink-3:#7f8aa6;
  --shadow:0 18px 50px -12px rgba(0,0,0,.55);
  --shadow-glow:0 0 0 1px var(--line),0 24px 70px -20px rgba(79,155,255,.35);
}
.surface-dark{background:var(--bg);color:var(--ink);}

.cta-band{
  border:1px solid var(--line);border-radius:var(--r-xl);padding:clamp(36px,5vw,60px);
  background:radial-gradient(110% 130% at 50% 0%,rgba(79,155,255,.16),transparent 62%),var(--panel);
  color:var(--ink);
  text-align:center;position:relative;overflow:hidden;
}
.cta-band h2{margin-bottom:14px;}
.cta-band .hero-actions{justify-content:center;}

/* ---------- footer ---------- */
.site-footer{border-top:1px solid var(--line);background:var(--bg-2);padding:60px 0 34px;color:var(--ink-2);font-size:14.5px;}
/* Five columns since the Legal column was added (brand + Product, Capabilities,
   Company, Legal). Gap tightened from 36px so the longer legal labels do not wrap
   at the 1180px max width. */
.foot-grid{display:grid;grid-template-columns:1.4fr repeat(4,1fr);gap:30px;}
@media(max-width:1040px){.foot-grid{grid-template-columns:1fr 1fr 1fr;gap:30px;}}
@media(max-width:860px){.foot-grid{grid-template-columns:1fr 1fr;gap:28px;}}
.foot-grid h4{font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-bottom:14px;font-weight:700;}
.foot-links{display:grid;gap:9px;}
.foot-links a{color:var(--ink-2);transition:color .16s;}
.foot-links a:hover{color:var(--ink);}
.foot-bot{margin-top:44px;padding-top:22px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;font-size:13.5px;color:var(--ink-3);}
.foot-co{color:var(--ink-2);border-bottom:1px solid var(--line-strong);transition:color .16s,border-color .16s;}
.foot-co:hover{color:var(--ink);border-color:var(--brand-2);}

/* ---------- reveal-on-scroll (progressive enhancement) ---------- */
.reveal{opacity:0;transform:translateY(18px);}
.reveal.in{opacity:1;transform:none;transition:opacity .6s cubic-bezier(.2,.8,.2,1),transform .6s cubic-bezier(.2,.8,.2,1);}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;}}

/* ---------- utilities ---------- */
.center{text-align:center;}
.mt-s{margin-top:14px;} .mt-m{margin-top:26px;} .mt-l{margin-top:44px;}
.flex{display:flex;} .items-center{align-items:center;} .gap-s{gap:10px;} .gap-m{gap:18px;}
.wrap-chips{display:flex;flex-wrap:wrap;gap:10px;}
.sr-only{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;left:-9999px;top:0;background:var(--brand-1);color:#04070f;padding:10px 16px;border-radius:0 0 8px 0;z-index:100;font-weight:700;}
.skip-link:focus{left:0;}
:focus-visible{outline:2px solid var(--brand-1);outline-offset:3px;border-radius:4px;}

/* ==========================================================================
   Legal / policy pages (/terms, /privacy, /refund-policy, /delivery)
   Long-form reading, not marketing. Deliberately plainer than the rest of the
   site: narrower measure, larger line-height, no reveal animations, and a light
   band throughout so it reads like a document rather than a landing page.
   ========================================================================== */
.legal{padding:clamp(40px,5vw,64px) 0 clamp(56px,7vw,88px);}
.legal-doc{max-width:760px;margin-inline:auto;}
.legal-doc h2{
  font-size:clamp(21px,2.4vw,27px);margin:clamp(34px,4vw,48px) 0 14px;
  scroll-margin-top:90px;   /* clears the sticky header when jumped to from the TOC */
}
.legal-doc h2:first-of-type{margin-top:0;}
.legal-doc h3{font-size:17.5px;margin:26px 0 10px;}
.legal-doc p,.legal-doc li{color:var(--ink-2);font-size:16px;line-height:1.72;}
.legal-doc p{margin:0 0 14px;}
.legal-doc ul,.legal-doc ol{margin:0 0 16px;padding-left:22px;}
.legal-doc li{margin-bottom:8px;}
.legal-doc li::marker{color:var(--ink-3);}
.legal-doc b,.legal-doc strong{color:var(--ink);font-weight:650;}
.legal-doc a{color:var(--brand-1);text-decoration:underline;text-underline-offset:2px;}

/* ─────────────────────────────────────────────────────────────────────────
   Blog article body

   LAYERED ON .legal-doc, NOT A REPLACEMENT. That class already carries the
   long-form rhythm every prose page shares - 760px measure, heading scale,
   list and link treatment - so the wrapper is class="legal-doc article" and
   only the things a policy page never has are defined here. Duplicating the
   rhythm would mean two prose stylesheets drifting apart.

   Everything below exists because a TECHNICAL post has it and a legal page
   does not: code, tables, quotes, images, rules. Before this, a generated post
   rendered its command blocks as unstyled body text on the dark background -
   indistinguishable from prose, which is the one thing a command must never be.
   ───────────────────────────────────────────────────────────────────────── */

/* Inline code. Tinted rather than boxed, so a sentence carrying three of them
   stays readable instead of turning into a row of buttons. */
.article :not(pre) > code{
  font-family:var(--mono);
  font-size:.88em;
  color:var(--brand-1);
  background:rgba(79,155,255,.10);
  border:1px solid rgba(79,155,255,.16);
  border-radius:6px;
  padding:.12em .38em;
  /* A long path or flag must wrap rather than push the column sideways. */
  overflow-wrap:anywhere;
}

/* Code blocks. A distinct panel, because the reader is scanning for "what do I
   type" and it should be findable without reading the prose around it. */
.article pre{
  margin:0 0 20px;
  padding:16px 18px;
  background:var(--bg);
  border:1px solid var(--line-strong);
  border-radius:var(--r-sm);
  /* Wide output scrolls INSIDE the block. Without this a long command widens
     the whole page and every paragraph inherits a horizontal scrollbar. */
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.03);
}
.article pre code{
  font-family:var(--mono);
  font-size:14px;
  line-height:1.65;
  color:#d7e2f7;
  background:none;
  border:0;
  padding:0;
  /* Commands are not prose: preserve the author's line breaks exactly. */
  white-space:pre;
  overflow-wrap:normal;
}

/* Tables. Scroll horizontally inside their own wrapper on a phone. */
.article table{
  width:100%;
  margin:0 0 20px;
  border-collapse:collapse;
  font-size:15px;
  display:block;
  overflow-x:auto;
}
.article th,.article td{
  padding:9px 14px;
  border:1px solid var(--line);
  text-align:left;
  color:var(--ink-2);
  vertical-align:top;
}
.article th{
  background:var(--bg-2);
  color:var(--ink);
  font-weight:640;
  white-space:nowrap;
}

.article blockquote{
  margin:0 0 20px;
  padding:2px 0 2px 18px;
  border-left:3px solid var(--brand-1);
  color:var(--ink-2);
}
.article blockquote p:last-child{margin-bottom:0;}

.article img{
  max-width:100%;
  height:auto;
  border-radius:var(--r-sm);
  border:1px solid var(--line);
  margin:0 0 20px;
}

.article hr{
  border:0;
  border-top:1px solid var(--line);
  margin:clamp(30px,4vw,44px) 0;
}

/* ─────────────────────────────────────────────────────────────────────────
   In-article product callout

   Placed by PHP (ProductCalloutService), never written by the model, for the
   same reason internal links are: a prompt asking for a product mention is a
   request, and the first generated post complied by not mentioning the product
   ONCE in 8,000 characters. Code does not forget.

   Visually set apart from the prose on purpose. It is not pretending to be part
   of the article - a reader who wants the manual fix can skip it in one glance,
   which is what keeps the post worth reading for somebody who never clicks.
   ───────────────────────────────────────────────────────────────────────── */
.article .cta-inline{
  margin:clamp(26px,3.4vw,36px) 0;
  padding:18px 20px;
  border:1px solid var(--line-strong);
  border-left:3px solid var(--brand-1);
  border-radius:var(--r-sm);
  background:var(--bg-2);
}
.article .cta-inline__label{
  display:block;
  font-size:12px;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--ink-3);
  margin-bottom:8px;
}
.article .cta-inline p{margin:0 0 12px;color:var(--ink-2);}
.article .cta-inline p:last-child{margin-bottom:0;}
.article .cta-inline pre{
  margin:0 0 12px;
  background:var(--bg);
}

/* The reader's own words, quoted. This is what they would type at the agent, and
   seeing their problem phrased back at them is what makes the block feel like it
   is about their situation rather than about us. */
.article .cta-inline__ask{
  font-size:15.5px;
  color:var(--ink);
  font-style:italic;
  margin:0 0 10px;
}

.article .cta-inline__note{
  font-size:14.5px;
  color:var(--ink-3);
}

.article .cta-inline__actions{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:14px;
  margin:16px 0 0;
}

/* A button, not a link in a sentence.
   The download is the only thing on this site that turns a cold reader into a
   measurable lead, so it gets the weight. The capability link stays beside it as
   the quieter second option for somebody not ready to install anything. */
.article .cta-inline__btn{
  display:inline-block;
  padding:10px 18px;
  border-radius:var(--r-sm);
  background:var(--grad);
  color:#06101f;
  font-weight:680;
  font-size:15px;
  text-decoration:none;
  transition:transform .12s ease, box-shadow .12s ease;
}
.article .cta-inline__btn:hover{
  transform:translateY(-1px);
  box-shadow:0 10px 24px -10px rgba(79,155,255,.6);
  text-decoration:none;
}

.article .cta-inline__link{
  font-size:14.5px;
  color:var(--ink-2);
}

/* ─────────────────────────────────────────────────────────────────────────
   Blog CTA: the product brief

   The heading and body above it are per-post and speak only about the reader's
   problem. This is the part that says what the thing IS - constrained to a
   narrow measure so it reads as a short brief rather than a second article,
   and visually quieter than the button it sits above.
   ───────────────────────────────────────────────────────────────────────── */
/* Brief and transcript side by side.
   Stacked, the reader had to scroll past the whole product description before
   reaching the thing that actually demonstrates it, and the band grew long
   enough to feel like a second article. Beside each other they read as one
   statement: here is what it is, here is it working.
   Single column below 900px, where two would be two unreadable columns. */
.cta-split{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(18px,2.4vw,28px);
  align-items:start;
  text-align:left;
  margin-top:26px;
}
@media (max-width:900px){
  .cta-split{grid-template-columns:1fr;}
}

.cta-brief{
  margin:0;
  padding:20px 22px;
  border:1px solid var(--line);
  border-radius:var(--r);
  background:var(--bg-2);
  text-align:left;
}

/* The wordmark. Height-constrained rather than width-constrained: logo.png is a
   1370x300 lockup, so setting a width would leave the real height to chance and
   shift the block as the image loads. */
/* The icon mark. Square, so height and width are both fixed and the block does
   not shift as the image loads. */
.cta-brief__logo{
  display:block;
  width:44px;
  height:44px;
  margin:0 0 14px;
  border-radius:10px;
}

.cta-brief__pitch{
  margin:0;
  font-size:15.5px;
  line-height:1.65;
  color:var(--ink-2);
}

.cta-brief__stack{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:6px;
  margin-top:18px;
}
/* Its own line, via flex-basis rather than a separate element.
   Inline, it occupied the start of row one, so row one began indented while rows two to five ran
   flush left: a ragged edge down the side of a list whose whole job is to be scanned for one word.
   As an eyebrow it also stops competing with the chips for the same reading weight. */
.cta-brief__stack-label{
  flex-basis:100%;
  margin:0 0 9px;
  font-size:11.5px;
  font-weight:700;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--ink-3);
}
/* Quieter than the default chip. Nineteen full pills with borders read as a row of buttons and
   pulled attention off the three assurances below, which are what actually persuades. A smaller
   radius and no border make the same words read as tags. */
.cta-brief__stack .chip{
  padding:4px 10px;
  border-color:transparent;
  border-radius:8px;
  background:rgba(255,255,255,.055);
  font-size:12.5px;
  font-weight:500;
  color:var(--ink-2);
}

/* Three short guarantees, ticked. Deliberately not bullets: a tick reads as a
   property the product has, a bullet reads as a feature list. */
.cta-brief__points{
  margin:16px 0 0;
  padding:0;
  list-style:none;
}
.cta-brief__points li{
  position:relative;
  padding-left:24px;
  margin-bottom:8px;
  font-size:14.5px;
  line-height:1.6;
  color:var(--ink-2);
}
.cta-brief__points li:last-child{margin-bottom:0;}
.cta-brief__points li::before{
  content:"";
  position:absolute;
  left:2px;
  top:.55em;
  width:9px;
  height:5px;
  border-left:2px solid var(--ok);
  border-bottom:2px solid var(--ok);
  transform:rotate(-45deg);
}

/* The demo conversation inside the CTA band.
   Constrained to the same measure as the brief above it so the two read as one
   block, and left-aligned because a transcript centred with the rest of the band
   would be unreadable. */
.cta-convo{
  margin:0;
  text-align:left;
  /* The grid track can be narrower than the transcript's natural width; without
     this the slide pushes the column wider than its share. */
  min-width:0;
}

/* Price and platform, under the button where the hesitation actually happens. */
.cta-brief__foot{
  margin:14px 0 0;
  font-size:13.5px;
  color:var(--ink-3);
}

@media (max-width:560px){
  .cta-brief{padding:16px;}
}

/* "Last updated" bar under the title. */
.legal-meta{
  display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;
  padding:12px 16px;margin:0 0 clamp(28px,3.5vw,40px);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--bg-2);
  font-size:14px;color:var(--ink-3);
}
.legal-meta b{color:var(--ink-2);font-weight:600;}

/* Jump list. Plain anchors, so it works with JS disabled and is crawlable. */
.legal-toc{
  border:1px solid var(--line);border-radius:var(--r);background:var(--bg-2);
  padding:18px 20px;margin:0 0 clamp(30px,4vw,44px);
}
.legal-toc h2{font-size:13px!important;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 12px!important;}
.legal-toc ol{margin:0;padding-left:20px;columns:2;column-gap:28px;}
.legal-toc li{margin-bottom:6px;font-size:14.5px;break-inside:avoid;}
.legal-toc a{color:var(--ink-2);text-decoration:none;}
.legal-toc a:hover{color:var(--brand-1);text-decoration:underline;}
@media (max-width:640px){.legal-toc ol{columns:1;}}

/* Entity / contact block repeated at the foot of every policy page, because a
   reviewer looks for reachable contact details on the policy page itself. */
.legal-entity{
  border:1px solid var(--line);border-radius:var(--r);background:var(--bg-2);
  padding:22px 24px;margin-top:clamp(34px,4vw,48px);
}
.legal-entity h2{margin-top:0!important;font-size:18px!important;}
.legal-entity dl{display:grid;grid-template-columns:auto 1fr;gap:9px 20px;margin:0;font-size:15px;}
.legal-entity dt{color:var(--ink-3);}
.legal-entity dd{margin:0;color:var(--ink-2);}
@media (max-width:520px){
  .legal-entity dl{grid-template-columns:1fr;gap:2px;}
  .legal-entity dd{margin-bottom:10px;}
}

/* Unfilled config value. Loud on purpose: an unset registered address must be
   impossible to miss in review, and must never render as plausible blank space
   that reads as finished. */
.legal-gap{
  display:inline-block;padding:1px 8px;border-radius:5px;
  border:1px dashed var(--err);color:var(--err);
  background:rgba(255,107,107,.08);
  font-family:var(--mono);font-size:13px;font-weight:600;letter-spacing:.02em;
}
