/* Trvaly base stylesheet */

/* Fonts are linked from the document head, not imported here: an @import in an
   external sheet cannot start downloading until this file has itself arrived.
   Fallbacks are close in metrics so a blocked font request does not reflow the page. */

:root{
  --bg:#12141B;
  --bg-darker:#0D0F14;
  --card:#1B1E28;
  --card-hover:#222634;
  --card-subtle:#161922;
  --card-elevated:#1F232F;
  --border:#282C38;
  --border-strong:#363B4A;
  --head:#FFFFFF;
  --lead:#CBD1DC;
  --body:#A0A6B4;
  --label:#7C8496;
  --meta:#646B7B;
  --blue:#2B4BE0;
  --blue-text:#6C8CFF;
  /* the two blues carried at low alpha, so a surface can read as "the fixed thing"
     without introducing another colour */
  --blue-subtle:rgba(43,75,224,.10);
  --red:#DC4A2E;
  --red-subtle:rgba(220,74,46,.12);
  --absent:#4A505E;

  /* Montserrat sets the headings, Open Sans the running text, IBM Plex Mono the
     labels and numbers. Every rule in this sheet reads one of these three rather
     than naming a family, so the type system changes in one place. */
  --font-head:'Montserrat',system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --font-body:'Open Sans',system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;

  --hdr:72px;
  --max:1280px;
  --r-sm:5px;
  --r-md:8px;
  --r-lg:16px;
  --r-xl:24px;
  --pad:clamp(20px,3vw,48px);
  --s4:4px; --s8:8px; --s12:12px; --s16:16px; --s20:20px; --s24:24px;
  --s32:32px; --s48:48px; --s64:64px; --s80:80px; --s96:96px; --s128:128px;

  --shadow-card:0 12px 32px rgba(0,0,0,.35);
  --shadow-deep:0 20px 48px rgba(0,0,0,.3);
}

*{box-sizing:border-box;margin:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}
svg{font-family:inherit}
html{scroll-behavior:smooth}
body{
  background:var(--bg);
  color:var(--body);
  font-family:var(--font-body);
  font-size:17px;
  line-height:28px;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
}

.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--pad)}

h1,h2,h3,h4{color:var(--head);font-family:var(--font-head);font-weight:500;letter-spacing:-0.02em}
h1{font-size:clamp(30px,4vw,44px);line-height:1.14}
h2{font-size:clamp(24px,3.2vw,32px);line-height:1.25;letter-spacing:-0.01em}
h3{font-size:clamp(20px,2.2vw,24px);line-height:1.35;letter-spacing:0}
p{margin:0 0 var(--s16);max-width:68ch}
p:last-child{margin-bottom:0}

/* Eyebrows read as a technical tag. The brackets are drawn by CSS rather than
   typed into the markup, so this is decoration on existing copy, not new copy. */
.label{
  font-family:var(--font-mono);
  font-size:11px;line-height:16px;font-weight:500;
  text-transform:uppercase;letter-spacing:0.12em;color:var(--blue-text);
  display:inline-flex;align-items:center;gap:6px;
}
.label::before{content:'[';color:var(--border-strong)}
.label::after{content:']';color:var(--border-strong)}
.label--on{color:var(--blue-text)}

a{color:var(--blue-text);text-decoration:none;
  border-bottom:1px solid rgba(108,140,255,.4);transition:border-color .2s}
a:hover{border-bottom-color:var(--blue-text)}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s8);
  background:#fff;color:var(--bg);
  font-weight:500;font-size:15px;line-height:1;
  padding:13px 24px;border-radius:var(--r-md);border:1px solid #fff;
  transition:background .2s,border-color .2s,transform .2s cubic-bezier(.16,1,.3,1),box-shadow .2s;
  cursor:pointer;white-space:nowrap;
}
.btn:hover{background:#E8EAEF;border-color:#E8EAEF;transform:translateY(-1px);
  box-shadow:0 4px 16px rgba(0,0,0,.25)}
.btn:active{transform:scale(.98)}
.btn:focus-visible{outline:2px solid var(--blue-text);outline-offset:2px}
/* the quieter second action, for pages that pair two */
.btn--ghost{background:rgba(255,255,255,.04);color:var(--head);border-color:var(--border)}
.btn--ghost:hover{background:rgba(255,255,255,.08);border-color:var(--border-strong);
  color:var(--head);box-shadow:none}

/* header */
header{position:sticky;top:0;z-index:50;transition:background .25s,border-color .25s;
  border-bottom:1px solid transparent}
header.scrolled{background:rgba(18,20,27,.88);backdrop-filter:blur(10px);border-bottom-color:var(--border)}
.nav{display:flex;align-items:center;justify-content:space-between;height:var(--hdr)}
.nav img,.nav svg.logo{height:26px;display:block}
.nav ul{display:flex;gap:var(--s32);list-style:none}
.nav ul a{color:var(--body);border:0;font-size:16px;position:relative;padding-bottom:4px;
  transition:color .2s}
.nav ul a::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--blue);transform:scaleX(0);transform-origin:left;
  transition:transform .3s cubic-bezier(.16,1,.3,1)}
.nav ul a:hover{color:var(--head)}
.nav ul a:hover::after{transform:scaleX(1)}
.nav ul a.on{color:var(--head)}
.nav ul a.on::after{transform:scaleX(1);background:var(--border-strong)}
.nav .btn{font-size:15px;padding:8px 16px}
.burger{display:none;background:none;border:0;color:var(--head);cursor:pointer;padding:8px}

/* sections */
section{padding:clamp(56px,7vw,96px) 0}
section.tight{padding:clamp(48px,6vw,80px) 0}

/* reveal on entry. Hidden only when JS is running, so no-JS shows everything. */
.js .rv{opacity:0;transform:translateY(14px);
  transition:opacity .5s cubic-bezier(.16,1,.3,1),transform .5s cubic-bezier(.16,1,.3,1)}
.js .rv.in{opacity:1;transform:none}

/* scroll progress line */
#prog{position:fixed;top:0;left:0;height:2px;width:0;background:var(--blue);z-index:200;
  transition:width .1s linear}

/* ---- hero ----
   The statement on the left, the diagram on the right. Both hold still: the whole
   stage pins for the length of the runway and only the diagram changes under it.
   When the fourth state has had its turn the stage lets go and the page carries on.
   Each state carries its own labels, so the same markup reads as a plain annotated
   stack when the sequence cannot run (no JS, reduced motion). Only .is-live pins it. */
/* --run is 0 at every width: the four states advance on their own rather than
   costing the reader two screens of scrolling before the page moves on. The
   timed path is the same one the phone layout has always used. */
.hero{--steps:4;--run:0vh;padding:0}
.hero__grid{display:grid;grid-template-columns:minmax(0,1.08fr) minmax(0,1fr);
  gap:clamp(28px,3.5vw,56px);align-items:center;width:100%}
.hero__copy{display:flex;flex-direction:column;justify-content:center;
  padding:clamp(40px,6vw,72px) 0}
.hero__copy h1{font-size:clamp(33px,3.9vw,56px);line-height:1.08;letter-spacing:-0.035em;
  margin-bottom:var(--s32);text-wrap:balance}
.hero__copy p{font-size:clamp(17px,1.35vw,20px);line-height:1.6;margin-bottom:var(--s48);
  color:var(--lead);max-width:52ch}
.hero__copy .btn{align-self:flex-start}
.hero__visual{min-width:0}

/* the four states */
.hero__states{list-style:none;display:grid;gap:clamp(40px,6vw,64px)}
.hero__state{position:relative;aspect-ratio:2402/1473;margin:0}
.hero__layer{position:absolute;inset:0;width:100%;height:100%;display:block}

/* a dot on the thing, a hairline, the name of it. Nothing else. */
.hero__note{position:absolute;left:var(--x);top:var(--y);transform:translateY(-50%);
  pointer-events:none;z-index:2}
.hero__note[data-side="left"]{transform:translate(-100%,-50%)}
.hero__note-in{display:flex;align-items:center;white-space:nowrap}
.hero__note[data-side="left"] .hero__note-in{flex-direction:row-reverse}
.hero__note-dot{width:5px;height:5px;border-radius:50%;background:var(--label);flex:0 0 auto}
.hero__note-line{width:var(--len,44px);height:1px;background:var(--border-strong);flex:0 0 auto}
.hero__note-text{font-family:var(--font-mono);
  font-size:11px;line-height:1;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  color:var(--label);padding-left:var(--s8);
  /* the label can cross a hairline of the drawing, so it carries its own ground */
  text-shadow:0 0 7px var(--bg),0 0 4px var(--bg),0 0 2px var(--bg)}
.hero__note[data-side="left"] .hero__note-text{padding-left:0;padding-right:var(--s8)}
.hero__note--issue .hero__note-dot{background:var(--red)}
.hero__note--issue .hero__note-text{color:var(--body)}
.hero__note--fix .hero__note-dot{background:var(--blue-text)}
.hero__note--fix .hero__note-text{color:var(--head)}

/* ---- hero, driven ----
   The track runs long and the whole stage pins inside it for that length, so the
   statement and the diagram both stay put while the states change under them.
   Only opacity, transform and brightness animate, so it stays on the compositor.
   Brightness is the activation: a state arrives dim and comes up to full. */
.hero.is-live .hero__track{
  height:calc((100vh - var(--hdr)) + (var(--steps) * var(--run)));
  height:calc((100svh - var(--hdr)) + (var(--steps) * var(--run)))}
.hero.is-live .hero__stage{position:sticky;top:var(--hdr);
  height:calc(100vh - var(--hdr));
  height:calc(100svh - var(--hdr));
  display:flex;align-items:center}
.hero.is-live .hero__copy{padding:0}
.hero.is-live .hero__states{display:block;position:relative;width:100%;
  aspect-ratio:2402/1473;gap:0}
.hero.is-live .hero__state{position:absolute;inset:0;aspect-ratio:auto}
.hero.is-live .hero__layer{opacity:0;visibility:hidden;filter:brightness(.55);
  transform:translate3d(0,2%,0) scale(.985);backface-visibility:hidden}
.hero.is-live .hero__note-in{opacity:0;transform:translateX(-8px);
  transition:opacity .5s cubic-bezier(.16,1,.3,1),transform .5s cubic-bezier(.16,1,.3,1)}
.hero.is-live .hero__note[data-side="left"] .hero__note-in{transform:translateX(8px)}
.hero.is-live .hero__state.is-on .hero__note-in{opacity:1;transform:none;transition-delay:.16s}
.hero.is-live .hero__state.is-on .hero__note+.hero__note .hero__note-in{transition-delay:.3s}

/* numbered blocks */
.blocks{display:grid;gap:clamp(32px,4vw,48px);margin-top:clamp(48px,6vw,64px)}
.blocks.three{grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr))}
.blk .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;
  color:var(--label);display:block;margin-bottom:var(--s16)}
.blk h3{margin-bottom:var(--s12);font-size:22px;line-height:30px}
.blk p{font-size:17px}

/* capability list */
.caps{border-top:1px solid var(--border);margin-top:var(--s64)}
.cap{display:grid;grid-template-columns:clamp(40px,4vw,56px) minmax(180px,300px) minmax(0,1fr);gap:clamp(16px,2vw,24px);align-items:baseline;
  padding:var(--s32) 0;border-bottom:1px solid var(--border);
  transition:background .2s;color:inherit;border-left:0;border-right:0}
.cap:hover{background:var(--card)}
.cap .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;color:var(--label)}
.cap h3{font-size:21px;line-height:28px}
.cap>span:last-child{color:var(--body);font-size:17px}
a.cap{border-bottom:1px solid var(--border)}

/* two column sector strip */
.sectors{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));
  gap:var(--s48);margin-top:var(--s48)}
.sector .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;color:var(--label);display:block;margin-bottom:var(--s12)}
.sector h3{font-size:21px;margin-bottom:var(--s8)}

/* approach row */
.stages{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:var(--s32);margin-top:var(--s64);
  position:relative;padding-top:var(--s32)}
.stages::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;background:var(--border)}
.stage .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;color:var(--label)}
.stage .dot{width:7px;height:7px;background:var(--blue);position:absolute;top:-3px}
.stage h3{font-size:21px;margin:var(--s12) 0 var(--s8)}
.stage p{font-size:16px;line-height:26px}

/* why / pause */
.pause{padding:clamp(64px,8vw,96px) 0}
.pause h2{font-size:clamp(28px,3.4vw,44px);line-height:1.16;max-width:20ch;margin-bottom:var(--s32)}
.pause p{font-size:clamp(17px,2vw,19px);line-height:1.7;max-width:62ch;color:var(--lead)}

/* ---- close ----
   The last block on every page is the same object: a lit card rather than a band.
   Built entirely off the existing markup, so no page needed a new wrapper. */
.close{background:transparent;border:0;padding:clamp(48px,6vw,80px) 0}
.close-box{
  position:relative;overflow:hidden;text-align:center;
  display:flex;flex-direction:column;align-items:center;
  background:linear-gradient(180deg,var(--card) 0%,#151821 100%);
  border:1px solid var(--border);border-radius:var(--r-xl);
  padding:clamp(44px,5.5vw,80px) clamp(24px,4vw,64px);
  box-shadow:var(--shadow-deep);
}
.close-box::before{content:'';position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:60%;height:1px;
  background:linear-gradient(90deg,rgba(108,140,255,0),var(--blue-text),rgba(108,140,255,0))}
/* The glow fills the whole box and is sized so it reaches zero alpha inside its own
   edges. The previous one was a fixed 260px ellipse still at ~45% opacity where the
   element ended, so overflow:hidden cut it into a visible arc. Stops end on a
   transparent *blue* rather than `transparent`, which would fade through grey. */
.close-box::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(55% 58% at 50% -4%,
    rgba(43,75,224,.20) 0%,
    rgba(43,75,224,.10) 38%,
    rgba(43,75,224,.035) 62%,
    rgba(43,75,224,0) 100%)}
.close h2{margin-bottom:var(--s16);max-width:24ch;position:relative;z-index:1}
.close p{margin-bottom:var(--s32);max-width:54ch;color:var(--lead);position:relative;z-index:1;
  font-size:clamp(17px,1.8vw,20px);line-height:1.6}
.close .btn,.close .label{position:relative;z-index:1}

/* footer */
footer{padding:clamp(48px,6vw,72px) 0 var(--s32);
  background:var(--bg-darker);border-top:1px solid var(--border)}
.fgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
  gap:clamp(32px,4vw,48px);padding-bottom:var(--s48);border-bottom:1px solid var(--border)}
footer img,footer svg{height:26px;margin-bottom:var(--s16);display:block}
footer .flab{color:var(--head);font-size:14px;font-weight:500;margin-bottom:var(--s16);
  font-family:inherit;letter-spacing:0;text-transform:none}
footer ul{list-style:none}
footer li{margin-bottom:var(--s8)}
footer a{color:var(--body);border:0;font-size:16px}
footer a:hover{color:var(--head)}
.fbase{display:flex;justify-content:space-between;align-items:center;gap:var(--s24);
  padding-top:var(--s24);font-size:14px;color:var(--meta);flex-wrap:wrap}


/* mobile */
/* The drawer is always laid out and only hidden, because display:none cannot be
   transitioned. visibility keeps it out of the tab order while closed. */
.mob{position:fixed;inset:0;background:var(--bg);z-index:100;
  display:flex;flex-direction:column;padding:var(--s24) 20px;overflow:hidden;
  opacity:0;visibility:hidden;transform:translateY(-12px);
  transition:opacity .26s ease,transform .34s cubic-bezier(.16,1,.3,1),visibility 0s .34s}
.mob.open{opacity:1;visibility:visible;transform:none;
  transition:opacity .26s ease,transform .38s cubic-bezier(.16,1,.3,1),visibility 0s}
.mob .top{display:flex;align-items:center;justify-content:space-between;height:48px}
.mob-logo{border:0;display:inline-flex;align-items:center}
.mob nav{margin-top:var(--s48);display:flex;flex-direction:column;gap:var(--s24)}
.mob nav a{color:var(--head);font-size:30px;line-height:1.2;border:0;font-weight:500;
  opacity:0;transform:translateY(12px)}
.mob.open nav a{animation:mIn .42s cubic-bezier(.16,1,.3,1) forwards}
@keyframes mIn{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .mob{transition:none}
  .mob nav a{opacity:1;transform:none;animation:none}
}
.mob .foot{margin-top:auto;padding-bottom:var(--s16)}
.mob .btn{width:100%;text-align:center}

/* tablet and below */
@media (max-width:1080px){
  .stage .dot{display:none}
  .stages::before{display:none}
}

/* small tablet and large phone */
@media (max-width:860px){
  .nav ul,.nav .btn{display:none}
  .burger{display:block}
  .cap{grid-template-columns:40px 1fr;row-gap:var(--s4);padding:var(--s24) 0}
  .cap .n{grid-row:1}
  .cap h3{grid-column:2;grid-row:1}
  .cap>span:last-child{grid-column:2;grid-row:2}

  .fbase{flex-direction:column;gap:var(--s8)}
}

/* the hero goes single column: statement above, diagram below, both locked together */
@media (max-width:900px){
  /* --run is already 0 sitewide, restated here so the single column layout still
     reads as complete on its own. */
  .hero{--run:0vh}
  .hero__grid{grid-template-columns:minmax(0,1fr);gap:clamp(20px,5vw,32px)}
  .hero__copy{padding:clamp(24px,7vw,40px) 0 0}
  .hero__copy p{max-width:none}
  .hero.is-live .hero__stage{overflow-x:clip}
  .hero.is-live .hero__copy{padding:0}
  /* the diagram takes what width it can, but never so much height that it pushes
     the statement off a locked screen. --w may exceed the column, so centre it by
     margin rather than relying on auto. */
  .hero.is-live .hero__states{--w:min(100vw,55vh);width:var(--w);
    margin-inline:calc((100% - var(--w)) / 2)}
  /* there is no room to run a label out to the left of the drawing */
  .hero__note{--len:14px}
  .hero__note[data-side="left"]{transform:translateY(-50%)}
  .hero__note[data-side="left"] .hero__note-in{flex-direction:row}
  .hero__note[data-side="left"] .hero__note-text{padding-left:var(--s8);padding-right:0}
  .hero.is-live .hero__note[data-side="left"] .hero__note-in{transform:translateX(-8px)}
  .hero.is-live .hero__state.is-on .hero__note-in{transform:none}
  .hero__note-text{font-size:10px;letter-spacing:.1em}
}

/* on a phone the statement and the diagram share one locked screen, so both give ground */
@media (max-width:620px){
  .hero__copy h1{font-size:clamp(26px,7vw,33px);margin-bottom:var(--s16)}
  .hero__copy p{font-size:16px;line-height:1.55;margin-bottom:var(--s24)}
  .hero.is-live .hero__states{--w:min(100vw,46vh)}
}

/* phone */
@media (max-width:560px){
  :root{--hdr:64px}
  .nav svg,.nav img{height:24px!important}
  .mob nav a{font-size:26px}
  .blk h3{font-size:19px}
  p{max-width:none}
}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .rv{opacity:1;transform:none}
  html{scroll-behavior:auto}
}

/* ---- inner page patterns ---- */
.phead{padding:clamp(72px,7vw,96px) 0 clamp(40px,4vw,56px);border-bottom:1px solid var(--border)}
.phead h1{font-size:clamp(28px,3.6vw,44px);line-height:1.1;letter-spacing:-0.03em;
  margin:0 0 var(--s24)}
.phead .plead{font-size:clamp(21px,2.6vw,30px);line-height:1.25;letter-spacing:-0.025em;
  color:var(--head);font-weight:500;max-width:40ch;margin-bottom:var(--s24);text-wrap:balance}
.phead p{font-size:clamp(17px,2vw,19px);line-height:1.6;max-width:60ch;color:var(--lead)}

.blk-lg{border-bottom:1px solid var(--border);padding:clamp(48px,5.5vw,72px) 0}
.blk-lg:last-child{border-bottom:0}
.punch{font-size:clamp(21px,2.6vw,30px);line-height:1.32;color:var(--head);font-weight:500;
  letter-spacing:-0.02em;max-width:26ch;margin:var(--s16) 0 var(--s48)}
.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr));
  gap:clamp(32px,5vw,64px)}
.flab{color:var(--label);font-family:var(--font-mono);font-size:12px;
  font-weight:500;letter-spacing:.12em;text-transform:uppercase;margin-bottom:var(--s16)}
.one{margin-top:var(--s48)}
.tick{list-style:none}
.tick li{position:relative;padding-left:24px;margin-bottom:var(--s12)}
.tick li::before{content:'';position:absolute;left:0;top:11px;width:9px;height:1px;background:var(--blue)}
.outcome{border-left:3px solid var(--blue);padding-left:var(--s24);margin-top:var(--s48);
  color:var(--head);font-size:clamp(17px,2.1vw,19px);line-height:1.55;max-width:52ch}

/* numbered failure list, single column */
.fails{list-style:none;border-top:1px solid var(--border);margin-top:var(--s32)}
.fails li{display:grid;grid-template-columns:clamp(40px,4vw,56px) minmax(0,1fr);gap:clamp(16px,2vw,24px);
  padding:var(--s32) 0;border-bottom:1px solid var(--border)}
.fails .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;color:var(--label);padding-top:4px}
.fails h3{font-size:clamp(19px,2.1vw,21px);line-height:1.35;margin-bottom:var(--s8)}
.fails p{font-size:17px;max-width:72ch}

/* case flow */
.flow{display:flex;gap:var(--s16);align-items:flex-start;margin:var(--s32) 0 0;
  overflow-x:auto;padding-bottom:var(--s8)}
.flow .step{flex:1 0 auto;min-width:132px;padding-top:var(--s16);border-top:1px solid var(--border);position:relative}
.flow .step::before{content:'';position:absolute;top:-3px;left:0;width:6px;height:6px;background:var(--absent)}
.flow .step.break::before{background:var(--red)}
.flow .step span{display:block;font-size:15px;line-height:22px;color:var(--head)}
.flow .step em{font-style:normal;font-size:14px;line-height:20px;
  color:var(--red);display:block;margin-top:var(--s4)}
.flow .step:not(.break) em{display:none}

/* ---- stage stack for the approach page ----
   The same run as the landing page, stood on its end: one rail down the stages
   with a node on each, so the page reads as a sequence rather than a list. */
.stack{position:relative;border-top:1px solid var(--border)}
.stack::before{content:'';position:absolute;left:5px;z-index:0;width:2px;
  top:clamp(48px,5vw,64px);bottom:clamp(48px,5vw,64px);
  background:var(--border);border-radius:2px}
.stg{position:relative;z-index:1;display:grid;grid-template-columns:96px minmax(0,1fr);
  gap:var(--s24);padding:clamp(48px,5vw,64px) 0;border-bottom:1px solid var(--border)}
.stg .n{position:relative;padding-top:8px;padding-left:28px;
  font-family:var(--font-mono);
  font-size:12px;letter-spacing:.12em;color:var(--label);transition:color .3s ease}
.stg .n::before{content:'';position:absolute;left:0;top:8px;width:12px;height:12px;
  border-radius:50%;background:var(--bg);border:2px solid var(--border-strong);
  transition:border-color .35s ease,background .35s ease,box-shadow .35s ease}
/* .on is the touch equivalent of :hover. A phone has no pointer to hover with,
   so the script sets it on whichever stage is crossing the middle of the screen. */
.stg:hover .n,.stg.on .n{color:var(--blue-text)}
.stg:hover .n::before,.stg.on .n::before{border-color:var(--blue-text);background:var(--blue);
  box-shadow:0 0 0 4px rgba(43,75,224,.18)}
.stg h2{margin-bottom:var(--s16)}
.stg .aside{margin-top:var(--s32);padding-left:var(--s24);border-left:1px solid var(--border)}
.stg .aside h4{color:var(--label);font-family:var(--font-mono);font-size:12px;
  font-weight:500;letter-spacing:.12em;text-transform:uppercase;margin-bottom:var(--s12)}

/* principles grid */
.prin{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));
  gap:clamp(24px,3vw,32px);margin-top:var(--s48)}
.prin .p{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:clamp(24px,3vw,32px);transition:background .2s,border-color .2s}
.prin .p:hover{background:var(--card-hover);border-color:var(--border-strong)}
.prin .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;color:var(--label);display:block;margin-bottom:var(--s12)}
.prin h3{font-size:21px;margin-bottom:var(--s8)}
.prin p{font-size:16px;line-height:26px}

/* form */
form{max-width:760px;margin-top:var(--s48)}
.fld{margin-bottom:var(--s24)}
label{display:block;color:var(--head);font-size:15px;font-weight:500;margin-bottom:var(--s8)}
label .opt{color:var(--label);font-weight:400}
input,select,textarea{width:100%;background:var(--card);border:1px solid var(--border);
  border-radius:var(--r-md);color:var(--head);font-family:inherit;font-size:17px;padding:12px 16px;
  transition:border-color .2s}
textarea{min-height:132px;resize:vertical;line-height:26px}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--blue-text)}
input::placeholder,textarea::placeholder{color:var(--label)}
.hint{font-size:15px;color:var(--label);margin-top:var(--s8);line-height:22px}
.err{color:var(--red);font-size:15px;margin-top:var(--s8);display:none}
.err.on{display:block}
.ok{display:none;border-left:3px solid var(--blue);padding-left:var(--s24)}
.ok.on{display:block}

/* ---- legal reading pages ----
   The reading measure belongs on the text, not on the section. Putting it on the
   section made the whole band 70ch wide starting at the page edge, so the .wrap
   inside could never line up with the column the header sits in. */
.legal{padding:clamp(48px,5.5vw,72px) 0}
.legal .wrap > *{max-width:72ch}
/* matches .phead h1. Without this the h1 inherits a zero margin and the
   standfirst sits hard against the title. */
.legal h1{margin:0 0 var(--s24)}
.legal h2{font-size:clamp(19px,2.3vw,21px);margin:var(--s48) 0 var(--s16)}
.legal h2:first-of-type{margin-top:var(--s32)}
.legal p{font-size:17px;line-height:30px;margin-bottom:var(--s16)}
.legal .stand{font-size:clamp(17px,2.1vw,19px);line-height:1.6;color:var(--head);margin-bottom:var(--s16)}
.legal .upd{font-size:15px;color:var(--label)}

/* 404 */
.nf{min-height:70vh;display:flex;flex-direction:column;justify-content:center}

@media (max-width:860px){
  /* the number moves above the text, so the rail needs its own gutter or it runs
     straight through the paragraphs */
  .stack{padding-left:30px}
  .stg{grid-template-columns:1fr;gap:var(--s12)}
  .stg .n{padding-top:0;padding-left:0}
  .stg .n::before{left:-30px;top:4px}
  .fails li{grid-template-columns:40px 1fr;gap:var(--s16)}
}

/* ---- scannability ---- */
/* label + explanation lists */
.builds{list-style:none}
.builds li{position:relative;padding-left:24px;margin-bottom:var(--s16);max-width:72ch}
.builds li::before{content:'';position:absolute;left:0;top:12px;width:9px;height:1px;background:var(--blue)}
.builds b{color:var(--head);font-weight:500}

/* chips: short facts as separate objects rather than one long sentence */
.chips{list-style:none;display:flex;flex-wrap:wrap;gap:var(--s8)}
.chips li{border:1px solid var(--border);border-radius:var(--r-sm);padding:8px 12px;
  font-size:15px;line-height:22px;color:var(--head);background:var(--card)}

/* short orienting line above a long list */
.lead{color:var(--head);font-size:17px;margin-top:var(--s8);max-width:60ch}

/* home bottleneck blocks get a number like everything else */
.blk .n{display:block}

/* sticky section label so a reader always knows where they are in a long page */
.blk-lg{position:relative}



/* ---- section rhythm: the dark canvas is the whitespace ---- */
/* A lifted section sits on a panel with a hairline border. Alternating these
   gives the page rhythm without needing motion to create it. */
.lift{background:var(--card-subtle);border-top:1px solid var(--border);border-bottom:1px solid var(--border)}

/* a panel inside a section, for content that should read as an object */
.panel{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:clamp(24px,3.4vw,48px);margin-top:var(--s32)}
.lift .panel{background:var(--bg)}

/* flow and failure lists sit inside panels, not on bare canvas */
.panel .flow{margin-top:0}
.panel .fails{border-top:0;margin-top:var(--s16)}
.panel .fails li:last-child{border-bottom:0;padding-bottom:0}
.panel>.flab:first-child{margin-bottom:var(--s16)}

/* meta level */
.meta{color:var(--meta);font-size:15px;line-height:24px}


/* flow stacks on small screens rather than scrolling out of the panel */
@media (max-width:860px){
  .flow{display:block;overflow:visible;padding-bottom:0}
  .flow .step{min-width:0;border-top:0;border-left:1px solid var(--border);
    padding:0 0 16px 16px;margin-left:3px}
  .flow .step:last-child{padding-bottom:0}
  .flow .step::before{top:7px;left:-3.5px}
  .flow .step span{font-size:16px}
}


/* ---- cards ----
   One card treatment for the whole site: a hairline surface that lifts under the
   cursor and lights a rule along its top edge. */
.card{position:relative;background:var(--card);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:clamp(24px,2.6vw,32px);overflow:hidden;
  transition:background .25s ease,border-color .25s ease,transform .25s cubic-bezier(.16,1,.3,1),
    box-shadow .25s ease}
.lift .card{background:var(--bg)}
.card::after{content:'';position:absolute;left:0;right:0;top:0;height:2px;
  background:var(--blue);transform:scaleX(0);transform-origin:left;
  transition:transform .35s cubic-bezier(.16,1,.3,1)}
.card:hover{border-color:var(--border-strong);transform:translateY(-3px);
  box-shadow:var(--shadow-card)}
.card:hover::after{transform:scaleX(1)}
.card .n{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;
  color:var(--label);display:block;margin-bottom:var(--s16);transition:color .25s}
.card:hover .n{color:var(--blue-text)}
.card h3{font-size:clamp(19px,2.1vw,21px);line-height:1.35;margin-bottom:var(--s8)}
.card p{font-size:16px;line-height:26px;color:var(--body)}

.grid3{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));
  gap:clamp(16px,1.8vw,24px);margin-top:clamp(48px,5vw,64px)}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));
  gap:clamp(16px,1.8vw,24px);margin-top:clamp(32px,4vw,48px)}

/* ---- cards that carry a mark ----
   The card states the problem; the mark under it states the same thing drawn.
   One grammar, the same as the capability marks: dashed grey is the broken thing,
   solid blue is the thing that replaces it. The grey moves, the blue holds. */
.bento{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));
  gap:clamp(16px,1.8vw,24px);margin-top:clamp(40px,5vw,56px)}
.bento-card{position:relative;display:flex;flex-direction:column;justify-content:space-between;
  overflow:hidden;padding:clamp(24px,2.6vw,32px);
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  transition:background .25s ease,border-color .25s ease,
    transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s ease}
.lift .bento-card{background:var(--card)}
.bento-card::after{content:'';position:absolute;left:0;right:0;top:0;height:2px;
  background:var(--blue);transform:scaleX(0);transform-origin:left;
  transition:transform .35s cubic-bezier(.16,1,.3,1)}
.bento-card:hover{border-color:var(--border-strong);transform:translateY(-3px);
  box-shadow:var(--shadow-card)}
.bento-card:hover::after{transform:scaleX(1)}
.bento-card__n{display:block;margin-bottom:var(--s16);transition:color .25s;
  font-family:var(--font-mono);
  font-size:11px;letter-spacing:.12em;color:var(--label)}
.bento-card:hover .bento-card__n{color:var(--blue-text)}
.bento-card h3{font-size:clamp(19px,2.1vw,22px);line-height:1.32;margin-bottom:var(--s12)}
.bento-card p{font-size:16px;line-height:26px;color:var(--body)}
/* the mark sits in its own recessed frame inside the card, like a read-out */
.bento-card__mark{margin-top:var(--s24);padding:var(--s20);
  background:var(--bg);border:1px solid var(--border);border-radius:var(--r-md);
  display:flex;align-items:center;justify-content:center}
.bento-card__mark svg{display:block;width:100%;height:auto}
.mk-grid{stroke-opacity:.5}

/* the broken pieces loosen and brighten under the cursor; the blue never moves */
.mk-g{transition:stroke-opacity .35s ease,transform .55s cubic-bezier(.16,1,.3,1)}
.bento-card:hover .mk-g{stroke-opacity:.9}
.bento-card:hover .mk-g--a{transform:translateY(-2.5px)}
.bento-card:hover .mk-g--b{transform:translateY(2.5px)}
.mk-dot{transition:r .35s ease}
.bento-card:hover .mk-dot{r:5}


/* the line the three cards resolve into */
.bento-res{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s24);flex-wrap:wrap;margin-top:clamp(20px,2.4vw,28px);
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:clamp(20px,2.4vw,28px) clamp(20px,2.6vw,32px)}
.lift .bento-res{background:var(--bg)}
.bento-res p{margin:0;font-size:clamp(17px,1.6vw,19px);line-height:1.5;color:var(--head)}
.bento-res__tag{display:inline-flex;align-items:center;gap:var(--s8);flex:0 0 auto;
  font-family:var(--font-mono);
  font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  color:var(--blue-text)}

@media (prefers-reduced-motion:reduce){
}

/* capability rows get an arrow that moves */
a.cap{position:relative}
a.cap::after{content:'';position:absolute;right:0;top:50%;width:14px;height:1px;
  background:var(--label);transform:translateX(-8px);opacity:0;
  transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s}
a.cap:hover::after{transform:translateX(0);opacity:1;background:var(--blue-text)}
a.cap:hover h3{color:var(--blue-text)}
.cap h3{transition:color .25s}

/* builds list: the rule grows on hover of the block */
.panel:hover .builds li::before,.one:hover .builds li::before{background:var(--blue-text)}
.builds li::before{transition:background .3s}

/* chips lift */
.chips li{transition:border-color .2s,background .2s,transform .2s}
.chips li:hover{border-color:var(--border-strong);transform:translateY(-1px)}

/* fails rows respond */
.fails li{transition:background .2s}
.fails li:hover{background:rgba(255,255,255,.015)}


/* ---- sticky sub navigation for long pages ---- */
.subnav{border-bottom:1px solid var(--border);background:var(--card)}
.subnav .wrap{padding-top:var(--s16);padding-bottom:var(--s16)}
.subnav-links{display:flex;gap:var(--s24)}
.subnav-links a{color:var(--label);border:0;white-space:nowrap;
  font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;transition:color .2s;padding-bottom:3px;
  border-bottom:1px solid transparent}
.subnav-links a:hover{color:var(--head)}
.subnav-links a.on{color:var(--head);border-bottom-color:var(--blue)}

/* tabs, not a form control. They scroll if they must, and the active one is filled. */
.subnav .wrap{display:flex}
.subnav-links{display:flex;gap:var(--s8);overflow-x:auto;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;padding:2px 0}
.subnav-links::-webkit-scrollbar{display:none}
.subnav-links a{color:var(--head);border:1px solid var(--border);border-radius:var(--r-sm);
  white-space:nowrap;font-size:15px;line-height:22px;padding:8px 12px;background:var(--card);
  font-family:inherit;letter-spacing:0;text-transform:none;
  transition:background .2s,border-color .2s,color .2s}
.subnav-links a:hover{border-color:var(--border-strong);background:var(--card-hover)}
.subnav-links a.on{border-color:var(--blue);background:rgba(43,75,224,.12)}

@media (max-width:560px){
  .subnav-links a{font-size:14px;padding:8px 10px}
}

/* only the header is sticky now, so the anchor offset is smaller */
section[id]{scroll-margin-top:96px}
@media (max-width:860px){ section[id]{scroll-margin-top:88px} }

/* ---- capability marks ---- */
.caphead{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));
  gap:var(--s48);align-items:start}
@media (max-width:860px){
  .capmark{max-width:280px;margin-top:var(--s16)}
}


/* ---- accessibility ---- */
.skip{position:absolute;left:-9999px;top:0;background:#fff;color:var(--bg);
  padding:var(--s12) var(--s16);border-radius:var(--r-sm);z-index:300;font-weight:500}
.skip:focus{left:var(--s16);top:var(--s16)}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,
textarea:focus-visible,.card:focus-visible{outline:2px solid var(--blue-text);
  outline-offset:3px;border-radius:var(--r-sm)}

/* legal pages are for reading: no grid texture */
body.plain{background-image:none}

/* honeypot */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* two column footer */


/* ---- marks: one grammar, one motion rule ----
   grey dashed is the broken thing, solid blue is the fixed thing.
   The block responds to the cursor, not the SVG, because nobody points at an SVG.
   The grey pieces drift. The blue piece never moves. That is the whole idea. */
.capmark{width:100%;max-width:320px;height:auto;display:block;margin-top:var(--s8)}
.capmark .g,.capmark .b{transition:transform .5s cubic-bezier(.16,1,.3,1),
  stroke-opacity .35s ease,fill-opacity .35s ease}

/* arrival */
.js .capmark > *{opacity:0;transform:translateY(6px)}
.js .rv.in .capmark > *{animation:markin .5s cubic-bezier(.16,1,.3,1) forwards}
.js .rv.in .capmark > *:nth-child(1){animation-delay:.06s}
.js .rv.in .capmark > *:nth-child(2){animation-delay:.12s}
.js .rv.in .capmark > *:nth-child(3){animation-delay:.18s}
.js .rv.in .capmark > *:nth-child(4){animation-delay:.24s}
.js .rv.in .capmark > *:nth-child(5){animation-delay:.30s}
.js .rv.in .capmark > *:nth-child(6){animation-delay:.36s}
.js .rv.in .capmark > *:nth-child(7){animation-delay:.42s}
.js .rv.in .capmark > *:nth-child(8){animation-delay:.48s}
.js .rv.in .capmark > *:nth-child(9){animation-delay:.54s}
.js .rv.in .capmark > *:nth-child(10){animation-delay:.60s}
.js .rv.in .capmark > *:nth-child(n+11){animation-delay:.66s}
@keyframes markin{to{opacity:1;transform:none}}

/* response: the grey loosens and brightens, the blue holds */
.blk-lg:hover .capmark .g{stroke-opacity:.72}
.blk-lg:hover .capmark .b{fill-opacity:.2}
.secmark{max-width:320px}

@media (prefers-reduced-motion:reduce){
  .js .capmark > *{opacity:1;transform:none;animation:none}
  .capmark .g,.capmark .b{transition:none}
}


/* sub-nav labels shorten themselves rather than scrolling out of view */
.subnav .long{display:inline}
.subnav .short{display:none}
@media (max-width:700px){
  .subnav .long{display:none}
  .subnav .short{display:inline}
  .subnav .wrap{gap:var(--s8);justify-content:space-between}
  .subnav a{font-size:11px;letter-spacing:.04em}
}
@media (max-width:340px){
  .subnav a{font-size:10px;letter-spacing:0}
}


/* ---- capabilities showcase ----
   The four capabilities as a tab rail against a live preview deck. Each tab is
   still a real link to its own section on the capabilities page, so pointing at it
   previews and clicking it navigates; nothing depends on script to stay usable. */
.caps-showcase{display:grid;grid-template-columns:minmax(0,380px) minmax(0,1fr);
  gap:clamp(16px,2vw,28px);margin-top:clamp(32px,4vw,48px);align-items:start}
.caps-tabs{display:flex;flex-direction:column;gap:var(--s12)}
.caps-tab{position:relative;display:block;overflow:hidden;text-decoration:none;
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);
  padding:var(--s20);
  transition:background .25s ease,border-color .25s ease,box-shadow .25s ease}
.caps-tab::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--blue);opacity:0;transform:scaleY(.4);
  transition:opacity .25s ease,transform .25s ease}
.caps-tab:hover{background:var(--card-hover);border-color:var(--border-strong)}
.caps-tab.active{background:var(--card-elevated);border-color:rgba(108,140,255,.4);
  box-shadow:0 4px 24px rgba(0,0,0,.3)}
.caps-tab.active::before{opacity:1;transform:scaleY(1)}
.caps-tab-top{margin-bottom:var(--s8)}
.caps-tab .n{font-family:var(--font-mono);
  font-size:11px;font-weight:500;letter-spacing:.12em;color:var(--label);
  transition:color .25s ease}
.caps-tab.active .n{color:var(--blue-text)}
.caps-tab h3{font-size:20px;line-height:28px;margin-bottom:var(--s8);color:var(--head)}
.caps-tab p{margin:0;max-width:none;font-size:15px;line-height:24px;color:var(--body);
  transition:color .25s ease}
.caps-tab.active p{color:var(--lead)}

.caps-preview-deck{position:relative;overflow:hidden;display:grid;align-items:center;
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:clamp(24px,3vw,40px);min-height:clamp(280px,24vw,360px)}
/* same treatment as the close card: the glow fills the panel rather than being a
   circle clipped by it, so there is no arc where overflow:hidden cuts it */
.caps-preview-deck::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(58% 64% at 74% 14%,
    rgba(43,75,224,.15) 0%,
    rgba(43,75,224,.06) 42%,
    rgba(43,75,224,0) 100%)}
.caps-preview-panel{grid-area:1/1;position:relative;z-index:1;
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .35s ease,transform .35s ease,visibility 0s .35s}
.caps-preview-panel.active{opacity:1;visibility:visible;transform:none;
  transition-delay:0s,0s,0s}
.caps-preview-panel svg{display:block;width:100%;height:auto}

/* a diagram in its own recessed frame, for the pages that carry one beside the text */
.figmark{position:relative;overflow:hidden;background:var(--bg-darker);
  border:1px solid var(--border);border-radius:var(--r-md);padding:clamp(16px,2vw,24px)}
.figmark svg{display:block;width:100%;height:auto}
.figmark .capmark{max-width:none;margin-top:0}

/* the drawing-office corner ticks, borrowed for anything that reads as a frame */
.corner{position:absolute;width:9px;height:9px;pointer-events:none;z-index:2}
.corner::before,.corner::after{content:'';position:absolute;background:var(--label);opacity:.8}
.corner::before{width:9px;height:1px;top:4px;left:0}
.corner::after{width:1px;height:9px;top:0;left:4px}
.corner--tl{top:10px;left:10px}
.corner--tr{top:10px;right:10px}
.corner--bl{bottom:10px;left:10px}
.corner--br{bottom:10px;right:10px}

@media (max-width:900px){
  .caps-showcase{grid-template-columns:minmax(0,1fr)}
  /* The preview only reads as a preview when it sits beside the tab it belongs to.
     Stacked, it lands under all four with nothing to tie it to any of them, so it
     comes out entirely. The four cards carry the section on their own. */
  .caps-preview-deck{display:none}
}

/* ---- why Trvaly: the brief against the diagnosis ----
   Two surfaces rather than a run of paragraphs; the second is the one that
   carries the argument, so it is the one that is lit. */
/* exactly two, so the columns are stated rather than left to auto-fit, which was
   laying out a third empty track on wide screens */
.why-workbench{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(16px,2vw,28px);margin-top:clamp(32px,4vw,48px)}
@media (max-width:760px){
  .why-workbench{grid-template-columns:minmax(0,1fr)}
}
.why-card{position:relative;background:var(--card);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:clamp(24px,3vw,40px);
  transition:border-color .25s ease,transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s ease}
.lift .why-card{background:var(--bg)}
.why-card p{max-width:none;font-size:clamp(16px,1.4vw,18px);line-height:1.65;color:var(--lead)}
.why-card p + p{margin-top:var(--s16)}
.why-card:hover{border-color:var(--border-strong);transform:translateY(-3px);
  box-shadow:var(--shadow-card)}
.why-card--highlight{border-color:var(--blue);
  box-shadow:0 8px 32px rgba(43,75,224,.12)}
.lift .why-card--highlight{
  background:linear-gradient(180deg,var(--card) 0%,var(--card-subtle) 100%)}
.why-card--highlight p:first-child{color:var(--head);font-weight:500;
  font-size:clamp(18px,1.7vw,21px);line-height:1.45}

/* ---- how the work runs ----
   One path through all four steps. The dot travels it as the section comes up the
   screen and each step lights as the dot reaches it. The rail is measured from the
   node centres rather than guessed from column percentages, because the grid gap
   moves them. Without script every step simply reads as complete. */
.runs{--p:1;position:relative;list-style:none;display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(16px,1.8vw,24px);
  margin-top:clamp(40px,5vw,56px)}
.runs__rail{position:absolute;background:var(--border);border-radius:2px;z-index:0}
.runs__live{position:absolute;background:var(--blue);border-radius:2px}
.runs__dot{position:absolute;width:11px;height:11px;border-radius:50%;
  background:var(--blue-text);box-shadow:0 0 0 4px rgba(43,75,224,.22);
  opacity:0;transition:opacity .3s ease}
.runs.is-live .runs__dot{opacity:1}
.runs[data-axis="x"] .runs__live{left:0;top:0;bottom:0;width:calc(var(--p) * 100%)}
.runs[data-axis="x"] .runs__dot{left:calc(var(--p) * 100%);top:50%;margin:-5.5px 0 0 -5.5px}
.runs[data-axis="y"] .runs__live{left:0;right:0;top:0;height:calc(var(--p) * 100%)}
.runs[data-axis="y"] .runs__dot{top:calc(var(--p) * 100%);left:50%;margin:-5.5px 0 0 -5.5px}

.runs__step{position:relative;z-index:1;padding-top:var(--s32)}
.runs__node{position:absolute;top:-5px;left:0;width:12px;height:12px;border-radius:50%;
  background:var(--bg);border:2px solid var(--border-strong);
  transition:border-color .35s ease,background .35s ease,box-shadow .35s ease}
.runs__step.is-on .runs__node{border-color:var(--blue-text);background:var(--blue);
  box-shadow:0 0 0 4px rgba(43,75,224,.18)}
.runs__step.is-done .runs__node{border-color:var(--blue);background:var(--blue)}
.runs__n{display:block;margin-bottom:var(--s12);transition:color .35s ease;
  font-family:var(--font-mono);
  font-size:11px;font-weight:500;letter-spacing:.12em;color:var(--label)}
.runs__step.is-on .runs__n{color:var(--blue-text)}
/* the heading lights with the number: dim until the dot arrives, brightest while it
   is there, and left a shade up once the dot has passed */
.runs__step h3{font-size:clamp(19px,2vw,21px);line-height:1.3;margin-bottom:var(--s8);
  color:var(--body);transition:color .35s ease}
.runs__step.is-done h3{color:var(--lead)}
.runs__step.is-on h3{color:var(--head)}
.runs__step p{font-size:15px;line-height:24px;color:var(--body)}

@media (max-width:860px){
  .runs{grid-template-columns:minmax(0,1fr);gap:clamp(24px,5vw,32px);padding-left:30px}
  .runs__step{padding-top:0;padding-left:0}
  .runs__node{top:4px;left:-30px}
  .runs__n{margin-bottom:var(--s8)}
}

/* ---- markets globe ----
   The same hairline grammar as the hero diagram, wrapped onto a sphere. Every
   market stays a real <path>, so pointing at the region and pointing at the block
   beside it are the same gesture, and the keyboard gets the same thing.
   Geometry: Natural Earth 110m, public domain, reduced to one local file. */
.globe{position:relative;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.15fr) minmax(0,1fr);
  gap:clamp(20px,3vw,48px);align-items:center;margin-top:clamp(40px,5vw,56px)}

/* leader lines from each region on the sphere out to the card that names it.
   Drawn over the row in page pixels, so a line can cross from one column to
   another. Wide screens only: stacked on a phone there is nothing to point at. */
.globe__leads{position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:2;overflow:visible}
.globe__lead{fill:none;stroke:var(--border-strong);stroke-width:1;
  transition:stroke .3s ease,stroke-width .3s ease}
.globe__lead-dot{fill:var(--label);stroke:var(--bg);stroke-width:1.5;transition:fill .3s ease,r .3s ease}
.globe__lead.is-on{stroke:var(--blue-text);stroke-width:1.25}
.globe__lead-dot.is-on{fill:var(--blue-text);r:3.5}
.globe__mkt h3{padding-left:0}
/* On wide screens the leader line now ends in its own dot at the card, so the
   heading's own bullet would sit under it. Hide it there and let the leader
   do the job; below 901px the leaders are off and the bullet comes back. */
@media (min-width:901px){
  .globe__mkt h3::before{display:none}
  .globe__mkt h3{gap:0}
  .globe__side--r .globe__mkt h3{padding-left:var(--s12)}
}
.globe__side{display:grid;gap:clamp(24px,3vw,40px);align-content:center}
.globe__stage{min-width:0}
.globe__svg{display:block;width:100%;height:auto;max-width:460px;margin:0 auto}
.globe__sphere{fill:var(--bg);stroke:var(--border-strong);stroke-width:1}
.globe__grat{fill:none;stroke:var(--border);stroke-width:.6}
.globe__land{fill:var(--card);stroke:var(--label);stroke-width:.7;
  stroke-linejoin:round;stroke-linecap:round;
  transition:fill .3s ease,stroke .3s ease,stroke-width .3s ease}
.globe__land--mkt{cursor:pointer}
.globe__land--mkt.is-on{fill:var(--blue);stroke:var(--blue-text);stroke-width:1.1}

/* the block beside the globe and the region on it light together */
.globe__mkt{position:relative;padding-top:var(--s24);border-top:1px solid var(--border);
  transition:border-color .3s ease}
.globe__mkt::before{content:'';position:absolute;top:-2px;left:0;height:3px;
  width:var(--w,20%);background:var(--blue);
  transition:width .8s cubic-bezier(.16,1,.3,1),background .3s ease}
.js .rv .globe__mkt::before{width:0}
.js .rv.in .globe__mkt::before{width:var(--w,20%)}
.globe__mkt h3{display:flex;align-items:center;gap:var(--s8);
  font-size:clamp(19px,2.1vw,21px);margin-bottom:var(--s8);transition:color .3s ease}
.globe__mkt h3::before{content:'';width:6px;height:6px;border-radius:50%;
  background:var(--absent);flex:0 0 auto;transition:background .3s ease}
.globe__mkt p{font-size:16px;line-height:26px}
.globe__mkt.is-on{border-top-color:var(--blue-text)}
.globe__mkt.is-on::before{background:var(--blue-text)}
.globe__mkt.is-on h3{color:var(--blue-text)}
.globe__mkt.is-on h3::before{background:var(--blue-text)}
.globe__mkt:focus-visible{outline:2px solid var(--blue-text);outline-offset:6px;
  border-radius:var(--r-sm)}

/* the globe stacks above the markets before the columns get too narrow to read */
@media (max-width:900px){
  .globe{grid-template-columns:minmax(0,1fr);gap:clamp(28px,5vw,40px)}
  .globe__stage{order:-1}
  .globe__svg{max-width:min(100%,340px)}
  .globe__leads{display:none}
  .globe__side--l,.globe__side--r{display:grid;gap:clamp(24px,5vw,32px)}
}

/* form: fields pair up instead of one long column */
.frow{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));
  gap:var(--s24)}
.fgroup{border-top:1px solid var(--border);padding-top:var(--s32);margin-top:var(--s48)}
.fgroup:first-of-type{border-top:0;padding-top:0;margin-top:var(--s32)}
.fgroup > .flab{color:var(--label);font-family:var(--font-mono);font-size:12px;
  font-weight:500;letter-spacing:.12em;text-transform:uppercase;margin-bottom:var(--s24)}
/* ---- choice cards ----
   One option per row and the whole card is the control: the chosen one fills with
   the primary and carries a tick, the rest keep a hollow marker on the right.
   The native input stays in the tab order and in the accessibility tree; only the
   browser's own dot is replaced, and the tick is driven by a plain sibling
   selector so selection is never invisible even where :has() is unsupported. */
.radios{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s12);max-width:660px}
.radio{position:relative;display:grid;
  grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto;
  column-gap:var(--s20);align-items:center;
  padding:var(--s16) var(--s20);cursor:pointer;
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);
  transition:background .22s ease,border-color .22s ease,box-shadow .22s ease,
    transform .2s cubic-bezier(.16,1,.3,1)}
.radio:hover{background:var(--card-hover);border-color:var(--border-strong)}
.radio:active{transform:scale(.995)}
.radio input{position:absolute;width:1px;height:1px;margin:0;padding:0;
  opacity:0;pointer-events:none}
.radio strong{grid-column:1;grid-row:1;display:block;color:var(--head);
  font-size:17px;font-weight:500;line-height:1.35;transition:color .22s ease}
.radio em{grid-column:1;grid-row:2;display:block;margin-top:3px;font-style:normal;
  color:var(--body);font-size:15px;line-height:21px;transition:color .22s ease}

.radio__mark{grid-column:2;grid-row:1/3;align-self:center;
  width:22px;height:22px;border-radius:6px;
  border:1.5px solid var(--border-strong);background-color:transparent;
  background-repeat:no-repeat;background-position:center;background-size:13px 10px;
  transition:border-color .22s ease,background-color .22s ease,box-shadow .22s ease}
.radio:hover .radio__mark{border-color:var(--label)}

/* chosen */
.radio input:checked ~ .radio__mark{border-color:transparent;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='10' viewBox='0 0 13 10' fill='none'%3E%3Cpath d='M1.6 5.3 4.7 8.4 11.4 1.6' stroke='%23ffffff' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.radio:has(input:checked){background:var(--blue);border-color:var(--blue);
  box-shadow:0 8px 24px rgba(43,75,224,.25)}
.radio:has(input:checked) strong{color:#fff}
.radio:has(input:checked) em{color:rgba(255,255,255,.76)}

/* keyboard focus lands on the marker wherever :has() is not available */
.radio input:focus-visible ~ .radio__mark{box-shadow:0 0 0 3px rgba(108,140,255,.45)}
.radio:has(input:focus-visible){outline:2px solid var(--blue-text);outline-offset:3px}


/* tap targets on touch screens meet the 44px minimum */
@media (max-width:560px){
  .btn{padding:14px 24px}
  .burger{padding:10px}
}


/* four principles sit as two by two, never three with an orphan */
.principles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));
  gap:clamp(16px,1.8vw,24px);margin-top:clamp(48px,5vw,64px);max-width:820px}


/* ---- page ground ----
   No pattern. Dots and rules both read as wallpaper, and the page has enough
   structure in the panels already. Depth comes from the surfaces lifting,
   from the grain, and from one soft glow behind the hero. Nothing else. */
body::before{
  content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(120% 70% at 72% -10%, rgba(43,75,224,.10), transparent 60%),
    radial-gradient(90% 60% at 8% -20%, rgba(255,255,255,.03), transparent 55%);
}
body > main,body > footer,body > .subnav{position:relative;z-index:1}
header{z-index:50}
.mob{z-index:100}

/* a fine grain over the top so the dark reads as paper rather than screen */
body::after{
  content:'';position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.028;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}


/* move between sectors without scrolling back to the top */
.nextsec{display:flex;justify-content:flex-end;margin-top:clamp(48px,5vw,64px)}
.nextsec a{color:var(--body);border:1px solid var(--border);border-radius:var(--r-sm);
  padding:10px 14px;font-size:15px;background:var(--card);display:inline-flex;gap:var(--s8);
  align-items:center;transition:border-color .2s,color .2s,background .2s}
.nextsec a:hover{color:var(--head);border-color:var(--border-strong);background:var(--card-hover)}
.nextsec span{color:var(--label);font-family:var(--font-mono);
  font-size:11px;letter-spacing:.1em;text-transform:uppercase}
