/* ============================================================
   VYG.AI — site redesign
   Type: Geist (sans) + Kode Mono (mono) — nothing else
   Palette: space black #15151A · cream #FAF9F5 · primary blue #1A8CFF
   ============================================================ */
:root{
  --bg:#15151A;            /* space black (design token) */
  --panel:#1C1C22;         /* raised panel */
  --panel-2:#101014;       /* recessed */
  --ink:#FAF9F5;           /* warm cream */
  --dim:rgba(255,255,255,0.65);    /* was #B0ACA3 — solid grey went beige over blue */
  --faint:rgba(255,255,255,0.44);  /* was #7C7B77 */
  --line:rgba(250,249,245,0.14);
  --line-2:rgba(255,255,255,0.2);   /* panel borders — matches --strong */
  --strong:rgba(255,255,255,0.2);
  --border-light:rgba(255,255,255,0.1);  /* Figma "Border Light" — frame rails, hero viz divider */
  --btn-line:rgba(250,249,245,0.32);     /* secondary button hairline */
  --live:#1A8CFF;          /* primary blue */
  --mono:'Kode Mono',ui-monospace,monospace;
  --sans:'Geist',system-ui,-apple-system,sans-serif;
  /* page frame: hatched outer strip + bordered rail, each side */
  --hatch:24px;
  --rail:24px;
  --frame:calc(var(--hatch) + var(--rail));   /* 48px */
  --gut:clamp(16px,2.2vw,32px);               /* content inset inside the frame */
  --pad:calc(var(--frame) + var(--gut));      /* 80px at 1512px — matches Figma */
}
*{box-sizing:border-box;}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overflow-x:clip;scroll-behavior:smooth;}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.55;overflow-x:clip;}
a{color:inherit;text-decoration:none;}
::selection{background:var(--ink);color:var(--bg);}
img,svg,canvas{display:block;max-width:100%;}

/* mono utility — Kode Mono is always uppercase */
.m{font-family:var(--mono);text-transform:uppercase;}
.dim{color:var(--dim);}
.live{color:var(--live);}

/* faint starfield — space theme, kept subtle & technical */
.stars{position:fixed;inset:0;pointer-events:none;z-index:0;opacity:.5;}
main,header.site,footer.site{position:relative;z-index:1;}

/* ---------- page frame (serro: content in a hairline shell) ---------- */
.shell{width:100%;padding:0 var(--pad);}

/* ---------- side strips — hatched outer edge + hairline rail, full page height ---------- */
/* transparent overlays — section rules and the hero glow run underneath them,
   exactly as the strips sit above the page in Figma */
.frame{position:fixed;inset:0;z-index:70;pointer-events:none;}
.frame .fr{position:absolute;top:0;bottom:0;}
.frame .fr-hatch{
  width:var(--hatch);
  background:repeating-linear-gradient(135deg,
    rgba(255,255,255,0.09) 0 1px,
    transparent 1px 6px);
}
.frame .fr-rail{width:var(--rail);border-left:1px solid var(--border-light);border-right:1px solid var(--border-light);}
/* tablet/phone: one stripe per side, the hatched one, closed off by an inner
   hairline. --frame collapses to the hatch width so every rule that runs to
   the frame now touches the stripe — while --pad keeps the full three-part
   sum, so text stays exactly where it was and the old rail zone reads as air. */
@media(max-width:1060px){
  .frame .fr-rail{display:none;}
  .frame .l-hatch{border-right:1px solid var(--border-light);}
  .frame .r-hatch{border-left:1px solid var(--border-light);}
  :root{
    --frame:var(--hatch);
    --pad:calc(var(--hatch) + var(--rail) + var(--gut));
  }
}
.frame .l-hatch{left:0;}
.frame .l-rail{left:var(--hatch);}
.frame .r-rail{right:var(--hatch);}
.frame .r-hatch{right:0;}

/* ---------- nav ---------- */
header.site{
  position:sticky;top:0;z-index:60;
  background:transparent;
  border-bottom:1px solid var(--line);
}
/* The blur lives on a pseudo-element covering just the bar, not on the header
   itself. backdrop-filter establishes a Backdrop Root: anything inside it —
   the Products dropdown — would have nothing left to sample and render
   unblurred. Keeping the filter off the ancestor lets the menu blur the page. */
header.site::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);
}
.nav{display:flex;align-items:center;justify-content:space-between;gap:24px;height:64px;}
.nav .logo img{height:30px;width:auto;}
.nav .links{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;}
.nav .links>a,.nav .drop>button{
  color:var(--dim);padding:8px 12px;background:none;border:0;cursor:pointer;
  font:inherit;letter-spacing:inherit;text-transform:inherit;transition:color .15s;
  display:inline-flex;align-items:center;gap:7px;
}
.nav .links>a:hover,.nav .drop>button:hover{color:var(--ink);}
/* the reset above strips borders from nav links — the demo button keeps its
   own hairline (Figma 102-3855), so re-assert it at higher specificity */
.nav .links>a.btn.sec{border:1px solid var(--btn-line);}
.nav .links>a.btn.sec:hover{border:1px solid rgba(250,249,245,0.6);background:rgba(255,255,255,0.07);}
.nav .links .sep{color:var(--faint);}
.nav .drop{position:relative;}
.nav .drop .menu{
  position:absolute;top:calc(100% + 10px);left:0;min-width:230px;
  background:transparent;border:1px solid var(--strong);
  backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);
  opacity:0;visibility:hidden;transform:translateY(-4px);transition:.18s;
}
.nav .drop:hover .menu,.nav .drop:focus-within .menu{opacity:1;visibility:visible;transform:none;}
.nav .menu a{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:13px 14px;color:var(--ink);border-bottom:1px solid var(--border-light);}
.nav .menu a:last-child{border-bottom:0;}
.nav .menu a:hover{background:rgba(250,249,245,0.05);}

/* buttons — b/w primary, hairline secondary */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--mono);font-size:12px;letter-spacing:.05em;text-transform:uppercase;
  padding:14px 22px;border:1px solid var(--ink);cursor:pointer;position:relative;
  transition:background .16s,color .16s,border-color .16s,box-shadow .2s,transform .15s;white-space:nowrap;
}
.btn.pri{background:var(--live);border-color:var(--live);color:#fff;font-weight:400;}
.btn.pri:hover{background:#3FA0FF;border-color:#3FA0FF;}
.btn.pri:active{background:#1478E0;border-color:#1478E0;}
.btn.sec{border:1px solid var(--btn-line);color:var(--ink);background:transparent;}
.btn.sec:hover{border:1px solid rgba(250,249,245,0.6);background:rgba(255,255,255,0.07);}
.btn.sm{padding:10px 16px;font-size:11px;}
/* hero pair runs larger than the rest (Figma 76-1661 / 76-1663) — fluid so the
   nowrap label ("See Earth in 90 seconds") still fits a 320px screen */
.btn.lg{padding:clamp(15px,2vw,20px) clamp(18px,3vw,32px);font-size:clamp(13px,1.5vw,16px);font-weight:500;letter-spacing:.06em;}
.btn.sec.lg{border-width:1.5px;}
.btn.sec.lg:hover{border-width:1.5px;}
.btn .ar{font-size:1.1em;line-height:1;display:inline-flex;}
[class^="ph-"],[class*=" ph-"]{line-height:1;vertical-align:middle;}
.tl .src i{font-size:14px;margin-right:7px;vertical-align:-2px;color:var(--dim);}
.nav .drop>button i{font-size:1.05em;}

/* ---------- section scaffold: numbered mono headers ---------- */
section{position:relative;}
section.sec{border-top:1px solid var(--line-2);padding:26px 0 clamp(64px,8vw,120px);}
.sec-bar{display:flex;align-items:baseline;gap:18px;margin-bottom:clamp(36px,5vw,72px);}
.sec-bar .no{font-family:var(--mono);font-size:12px;color:var(--ink);}
.sec-bar .no::after{content:"/";color:var(--faint);margin-left:2px;}
.sec-bar .lb{font-family:var(--mono);font-size:12px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);}
.sec-bar .fill{flex:1;}
.sec-bar .tag{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);}

/* type scale */
h1,h2,h3{margin:0;font-family:var(--sans);font-weight:500;letter-spacing:-0.04em;line-height:1.06;}
/* 6.5vw rather than 4.8: at 4.8 the headline sat on its 34px floor all the way
   from 390 to ~760, so a tablet got phone-sized type in a container twice the
   width. 6.5 leaves the floor at ~520 and still tops out at the Figma 72. */
.h-hero{font-size:clamp(34px,6.5vw,72px);letter-spacing:-0.06em;line-height:1.0;color:#fff;}
.h-sec{font-size:clamp(26px,3.3vw,46px);max-width:22ch;color:#fff;}
.h-sub{font-family:var(--sans);font-size:clamp(16px,1.5vw,20px);font-weight:400;color:rgba(255,255,255,0.7);}
.body{font-family:var(--sans);font-size:clamp(15px,1.1vw,16px);line-height:1.58;color:rgba(255,255,255,0.7);max-width:56ch;}
.body b,.body strong{color:var(--ink);font-weight:500;}

/* barcode strip — serro motif */
.barcode{
  height:56px;position:relative;overflow:hidden;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,0.22) 0 1px,transparent 1px 12px);
}

/* corner ticks */
.tick{position:absolute;width:8px;height:8px;pointer-events:none;opacity:.6;}
.tick.tl{top:-1px;left:-1px;border-top:1px solid var(--ink);border-left:1px solid var(--ink);}
.tick.tr{top:-1px;right:-1px;border-top:1px solid var(--ink);border-right:1px solid var(--ink);}
.tick.bl{bottom:-1px;left:-1px;border-bottom:1px solid var(--ink);border-left:1px solid var(--ink);}
.tick.br{bottom:-1px;right:-1px;border-bottom:1px solid var(--ink);border-right:1px solid var(--ink);}

/* reveal on scroll */
.rv{opacity:0;transform:translateY(16px);transition:opacity .7s ease,transform .7s cubic-bezier(.16,.84,.44,1);}
.rv.in{opacity:1;transform:none;}
@media(prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none;}}

/* ============================================================
   INTRO — vibor.it: giant brand letters stagger-reveal, curtain up
   ============================================================ */
#intro{
  position:fixed;inset:0;z-index:200;background:#1C1C1C;
  display:flex;align-items:center;justify-content:center;
  transition:transform .75s cubic-bezier(.76,0,.24,1);
}
#intro.lift{transform:translateY(-100%);}
#intro .wordmark{width:min(86vw,1240px);height:auto;overflow:visible;}
#intro .wordmark g{clip-path:inset(0 0 100% 0);}
#intro.play .wordmark g{animation:letter-in .62s cubic-bezier(.22,.9,.24,1) forwards;}
#intro.play .wordmark g:nth-child(1){animation-delay:.10s;}
#intro.play .wordmark g:nth-child(2){animation-delay:.20s;}
#intro.play .wordmark g:nth-child(3){animation-delay:.30s;}
#intro.play .wordmark g:nth-child(4){animation-delay:.40s;}
#intro.play .wordmark g:nth-child(5){animation-delay:.48s;}
#intro.play .wordmark g:nth-child(6){animation-delay:.56s;}
@keyframes letter-in{from{clip-path:inset(100% 0 0 0);}to{clip-path:inset(0 0 0 0);}}
#intro .boot{
  position:absolute;left:var(--pad);bottom:26px;
  font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);
}
#intro .pct{position:absolute;right:var(--pad);bottom:26px;font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--dim);}
@media(prefers-reduced-motion:reduce){#intro{display:none;}}
body.locked{overflow:hidden;}
/* html sets overflow-x:clip, so its overflow is no longer `visible` and the
   body value never propagates to the viewport — the opening was scrollable.
   Lock the actual scroller instead. */
html:has(body.locked){overflow:hidden;}

/* ============================================================
   HOME
   ============================================================ */
/* hero */
/* The hero sizes to its content. It used to stretch to the viewport, which on
   tall screens left slack the flex column had to put somewhere — below the
   barcode, then above the stats. Neither reads right: the block should hug. */
#hero{display:flex;flex-direction:column;}
.earth-stage{position:relative;width:min(30vw,480px);height:min(30vw,480px);}
.earth-stage::before{content:"";position:absolute;inset:2%;border-radius:50%;background:#000;}
#earth-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:1;}
.earth-stage.no-webgl::before{background:radial-gradient(circle at 35% 32%,#dbe7f5 0%,#5d7f9e 30%,#17202b 72%,#000 100%);}
.hv-anno{position:absolute;font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);}
.hv-anno.a1{top:18px;left:24px;}
.hv-anno.a2{bottom:18px;right:0;text-align:right;}





/* close / demo */
.close-wrap{text-align:left;max-width:900px;}
.close-wrap h2{max-width:20ch;margin-bottom:22px;}
.close-wrap .body{margin-bottom:36px;}
.close-note{margin-top:18px;font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);}


/* ============================================================
   PRODUCT PAGES (earth / jupiter)
   ============================================================ */
.p-hero{padding:clamp(48px,7vw,100px) var(--pad) clamp(40px,6vw,80px);display:grid;grid-template-columns:1.1fr .9fr;gap:48px;align-items:center;}
.p-hero .crumb{font-family:var(--mono);font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);margin-bottom:24px;display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.p-hero .crumb a{color:var(--dim);}.p-hero .crumb a:hover{color:var(--ink);}
.p-hero .crumb .sep{color:var(--faint);}
.p-hero .crumb .badge{border:1px solid var(--line-2);padding:3px 8px;font-size:9.5px;letter-spacing:.14em;color:var(--ink);}
.p-hero h1{margin-bottom:16px;}
.p-hero .h-sub{margin-bottom:30px;max-width:44ch;line-height:1.45;}
.p-visual{position:relative;display:flex;align-items:center;justify-content:center;min-height:320px;border-left:1px solid var(--line);}
.jupiter-orb{width:min(24vw,360px);height:min(24vw,360px);border-radius:50%;position:relative;overflow:hidden;background:repeating-linear-gradient(179deg,#D6DAE0 0 6px,#7E868F 6px 10px,#AEB5BD 10px 18px,#575E66 18px 21px,#C2C8CF 21px 30px);box-shadow:inset -26px -20px 70px rgba(0,0,0,.75),0 0 40px rgba(200,210,225,.14);}
.jupiter-orb::after{content:"";position:absolute;left:14%;top:58%;width:26%;height:14%;border-radius:50%;border:1px solid rgba(10,11,13,.55);background:rgba(240,243,246,.5);transform:rotate(-14deg);}

/* problem / fix statements */
.state-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4vw,64px);align-items:start;}
.state-grid .h-sec{max-width:16ch;}

/* console / product mockups (shared) */
.win{border:1px solid var(--line-2);background:var(--panel);position:relative;}
.win .bar{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 16px;border-bottom:1px solid var(--line-2);font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);}
.win .bar .l{display:inline-flex;align-items:center;gap:10px;}
.win .bar .dots{display:inline-flex;gap:5px;}
.win .bar .dots i{width:8px;height:8px;border-radius:50%;border:1px solid var(--line-2);}
.win .bar .rec{color:var(--live);}
.win .pad{padding:20px;}
.prof-head{display:flex;align-items:center;gap:14px;padding-bottom:16px;border-bottom:1px solid var(--line);margin-bottom:6px;flex-wrap:wrap;}
.prof-head .av{width:42px;height:42px;border:1px solid var(--line-2);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:13px;font-weight:400;}
.prof-head .nm{font-family:var(--mono);font-size:15.5px;font-weight:400;text-transform:uppercase;}
.prof-head .mt{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin-top:4px;}
.prof-head .tags{margin-left:auto;display:flex;gap:6px;}
.prof-head .tags span{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;border:1px solid var(--line-2);padding:4px 8px;}
.tl{list-style:none;margin:0;padding:0;}
.tl li{display:grid;grid-template-columns:96px 1fr auto;gap:14px;align-items:baseline;padding:13px 0;border-bottom:1px solid var(--line);}
.tl li:last-child{border-bottom:0;}
.tl .src{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink);}
.tl .ev{font-family:var(--sans);font-size:14px;color:var(--dim);}
.tl .ev b{color:var(--ink);font-weight:500;}
.tl .ts{font-family:var(--mono);font-size:10px;color:var(--faint);white-space:nowrap;}
.win-cap{margin-top:14px;font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);line-height:1.7;}

/* ask-anything Q&A table */
.qa{border:1px solid var(--border-light);}
.qa-row{display:grid;grid-template-columns:1fr 1fr;border-bottom:1px solid var(--border-light);}
.qa-row:last-child{border-bottom:0;}
.qa .q,.qa .a{padding:clamp(18px,2.2vw,30px);}
.qa .q{border-right:1px solid var(--border-light);font-family:var(--mono);font-size:clamp(14.5px,1.45vw,19px);font-weight:400;text-transform:uppercase;letter-spacing:.01em;}
.qa .q::before{content:"› ";color:var(--live);}
.qa .a{font-family:var(--sans);font-size:14.5px;color:var(--dim);}
.qa .a b{color:var(--ink);font-weight:500;}
.qa .a .k{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint);margin-bottom:8px;}

/* mcp chat mockup */
.chat .msg{padding:16px 18px;border-bottom:1px solid var(--line);}
.chat .msg:last-child{border-bottom:0;}
.chat .who{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint);margin-bottom:8px;}
.chat .say{font-family:var(--sans);font-size:14px;color:var(--ink);}
.chat .say.dim{color:var(--dim);}
.chat .card{border:1px solid var(--line-2);margin-top:12px;padding:14px;display:flex;gap:12px;align-items:center;}
.chat .card .av{width:34px;height:34px;border:1px solid var(--line-2);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:11px;font-weight:400;}
.chat .card .cnm{font-family:var(--mono);font-size:13px;text-transform:uppercase;font-weight:400;}
.chat .card .cmt{font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin-top:3px;}

/* flow builder mockup (jupiter) */
.flow{padding:26px 18px;overflow-x:auto;}
.flow svg{min-width:560px;width:100%;height:auto;}
.flow text{font-family:var(--mono);text-transform:uppercase;fill:var(--ink);}
/* same surface as the section 01 cards: opaque base under a light white wash,
   with the page's hairline rather than the old brighter stroke */
.flow .nd{fill:rgba(255,255,255,0.06);stroke:var(--line-2);stroke-width:1;}
.flow .nd-bg{fill:var(--bg);stroke:none;}
/* the highlighted node reads as active: blue tint rather than the flat base */
.flow .nd.tr{stroke:var(--live);fill:rgba(26,140,255,0.14);}
.flow .nd-bg.tr-bg{fill:var(--bg);}
.flow .ln{stroke:var(--border-light);fill:none;}
.flow .lb{fill:rgba(255,255,255,0.42);}

/* trio (AI-era features) */
.trio{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border:1px solid var(--line-2);}
.trio .t{padding:clamp(18px,2.2vw,30px);border-right:1px solid var(--line-2);}
.trio .t:last-child{border-right:0;}
.trio h4{margin:0 0 10px;font-family:var(--mono);font-size:14.5px;font-weight:400;text-transform:uppercase;}
.trio p{margin:0;font-size:13.5px;color:var(--dim);line-height:1.55;}

/* ---------- responsive ---------- */
@media(max-width:1060px){
  .earth-stage{width:min(58vw,380px);height:min(58vw,380px);}
  .p-hero{grid-template-columns:1fr;gap:24px;}
  .p-visual{border-left:0;min-height:240px;order:-1;}
  .state-grid{grid-template-columns:1fr;}
  .feat-grid{grid-template-columns:repeat(2,1fr);}
}
@media(max-width:760px){
  .qa-row{grid-template-columns:1fr;}
  .qa .q{border-right:0;border-bottom:1px solid var(--line);}
  .feat-grid{grid-template-columns:1fr;}
  .trio{grid-template-columns:1fr;}
  .trio .t{border-right:0;border-bottom:1px solid var(--line-2);}
  .trio .t:last-child{border-bottom:0;}
  .frag:nth-child(n){transform:none;}
  .orbit-map{height:120px;}
  .om-p b,.om-p em{display:none;}
}

/* ============================================================
   LOADER SEQUENCE (Figma Opening 1 → 2 → Hero, nodes 76-1282/1774/1773)
   p1 letters → p2 tagline words → p3 planets zoom up → p4 zoom to Earth
   ============================================================ */
#loader{position:fixed;inset:0;z-index:300;background:var(--bg);overflow:hidden;}
#loader.out{opacity:0;transition:opacity .55s ease .1s;pointer-events:none;}
body.locked{overflow:hidden;}

#loader .ld-logo{
  position:absolute;top:46px;left:50%;transform:translateX(-50%);
  width:min(1420px,94vw);height:auto;fill:#FAF9F5;overflow:visible;
}
#loader .ld-logo g{clip-path:inset(-5% 105% -5% -2%);}
#loader.p1 .ld-logo g{transition:clip-path .55s cubic-bezier(.3,.6,.2,1);clip-path:inset(-5% -3% -5% -2%);}
#loader.p1 .ld-logo g:nth-child(1){transition-delay:.05s;}
#loader.p1 .ld-logo g:nth-child(2){transition-delay:.17s;}
#loader.p1 .ld-logo g:nth-child(3){transition-delay:.29s;}
#loader.p1 .ld-logo g:nth-child(4){transition-delay:.41s;}
#loader.p1 .ld-logo g:nth-child(5){transition-delay:.50s;}
#loader.p1 .ld-logo g:nth-child(6){transition-delay:.60s;}

#loader .ld-tag{
  position:absolute;right:40px;bottom:56px;text-align:right;
  font-family:var(--mono);font-size:clamp(14px,1.35vw,20px);line-height:1.4;text-transform:uppercase;
}
#loader .ld-tag .tl1{color:rgba(250,249,245,0.5);}
#loader .ld-tag .tl2{color:#FAF9F5;}
#loader .ld-tag .w{display:inline-block;opacity:0;transform:translateY(6px);}
#loader.p2 .ld-tag .w{opacity:1;transform:none;transition:opacity .5s ease,transform .5s ease;}

/* p4 — camera dolly toward Earth: whole row scales about Earth's center (JS),
   neighbours sweep past the frame with a slow fade + slight motion blur */
#loader.p4 .ld-logo{opacity:0;transform:translateX(-50%) scale(1.06);transition:opacity .95s ease,transform 1.5s ease;}
#loader.p4 .ld-tag{opacity:0;transition:opacity .8s ease;}

/* ============================================================
   HERO (Figma 136-19324) — planets row, rule, copy + CTAs, stats.
   No longer 100vh: the section is exactly as tall as its content.
   ============================================================ */
#hero{display:flex;flex-direction:column;padding-top:48px;}

/* the row lives here permanently; during the loader it is transformed out to
   the opening position, so nothing is swapped or re-mounted mid-flight */
.hero-planets{
  display:flex;justify-content:space-between;align-items:center;
  width:calc(100% - var(--pad) * 2);margin:0 auto;
  transition:width 1.05s cubic-bezier(.62,.02,.2,1),
             transform 1.05s cubic-bezier(.62,.02,.2,1);
}
.hero-planets .lp{
  width:17.16%;   /* 5 bodies + 4 gaps of 3.55% = 100% */height:auto;aspect-ratio:1;flex:none;position:relative;
  opacity:0;transform:translateY(56px) scale(.9);
}
.hero-planets .lp svg,.hero-planets .lp img{display:block;width:100%;height:100%;}
/* the body's ink is carried by colour alpha, so hover is one colour transition.
   Mercury is an image, so it rides the same range on opacity instead. */
.hero-planets .lp{color:rgba(255,255,255,0.5);transition:color .45s ease,
             opacity .6s ease, transform .8s cubic-bezier(.18,.9,.24,1.03),
             width 1.05s cubic-bezier(.62,.02,.2,1);}
.hero-planets .lp:hover,.hero-planets .lp:focus-visible{color:#fff;}
body.planets-in .hero-planets .lp{opacity:1;transform:none;}
.hero-planets .lp:nth-child(1){transition-delay:0s;}
.hero-planets .lp:nth-child(2){transition-delay:.09s;}
.hero-planets .lp:nth-child(3){transition-delay:.18s;}
.hero-planets .lp:nth-child(4){transition-delay:.27s;}
.hero-planets .lp:nth-child(5){transition-delay:.36s;}

/* opening position: wider row (Figma 128-9608 is 1420 with 30px gaps) sitting
   at the loader's centre line. space-between means the gap follows the width,
   so only two properties animate. */
body.pre main{z-index:400;}
body.pre .hero-planets .lp{width:18.31%;}
body.planets-up .hero-planets .lp{width:17.16%;transition-delay:0s;}
body.pre .hero-planets{
  width:min(1420px,94vw);
  transform:translateY(calc(60.7vh - 242px));
  position:relative;
}
body.planets-up .hero-planets{width:calc(100% - var(--pad) * 2);transform:none;}


.hero-main{
  display:flex;align-items:flex-end;justify-content:space-between;gap:48px;
  padding:64px var(--pad) 44px;
}
.hcopy{max-width:700px;display:flex;flex-direction:column;gap:24px;padding:0;}
.hcrumb{
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  text-transform:uppercase;color:var(--live);
}
.hbody{margin:0;font-family:var(--sans);font-size:16px;line-height:1.58;color:rgba(255,255,255,0.7);max-width:700px;}
/* CTAs stack and right-align against the page gutter */
.hctas{display:flex;flex-direction:column;align-items:flex-end;gap:12px;flex:none;}
.hctas .btn{width:auto;justify-content:center;}

.stats{display:flex;padding:0 var(--frame);border-top:1px solid var(--strong);border-bottom:1px solid var(--strong);}
.stats .stat{flex:1 0 0;min-width:1px;padding:24px var(--gut) 28px;display:flex;flex-direction:column;gap:8px;border-right:1px solid var(--strong);overflow:hidden;}
.stats .stat:last-child{border-right:0;}
.stats .n{
  font-family:var(--mono);font-weight:700;font-size:clamp(38px,4.76vw,72px);letter-spacing:-0.04em;line-height:1;
  color:var(--live);
  -webkit-mask-image:repeating-linear-gradient(180deg,#000 0 1.5px,transparent 1.5px 3px);
  mask-image:repeating-linear-gradient(180deg,#000 0 1.5px,transparent 1.5px 3px);
}
.stats .k{font-family:var(--mono);font-size:10px;letter-spacing:1.2px;text-transform:uppercase;color:#fff;}
#hero .barcode{flex:none;height:56px;opacity:.5;margin:0 var(--frame);}

/* ---------- reveal choreography ---------- */
header.site{transition:transform .7s cubic-bezier(.22,.9,.26,1),opacity .6s ease;}
body.pre header.site{transform:translateY(-101%);opacity:0;}
.hr{transition:opacity .7s ease,transform .8s cubic-bezier(.22,.9,.26,1);}
body.pre .hr{opacity:0;transform:translateY(22px);}
/* #hero .barcode carries its own opacity, which outranks the .hr pre-state —
   without this it paints over the loader (main rides above it during pre) */
body.pre #hero .barcode{opacity:0;}
/* The hero sizes to its content now, so on tall screens the sections below it
   sit inside the viewport during the opening — and body.pre main{z-index:400}
   puts them above the loader. Hold everything after the hero back until the
   hand-off. */
body.pre main > :not(#hero){opacity:0;}
main > section{transition:opacity .6s ease;}
.hr-3{transition-delay:.05s;}
.hr-4{transition-delay:.12s;}
.hr-5{transition-delay:.20s;}
.hr-6{transition-delay:.28s;}
.hr-7{transition-delay:.36s;}
.hr-8{transition-delay:.46s;}
.hr-9{transition-delay:.54s;}

@media(prefers-reduced-motion:reduce){
  #loader{display:none;}
  body.pre .hr,body.pre header.site{opacity:1;transform:none;}
  body.pre .hero-planets{transform:none;width:calc(100% - var(--pad) * 2);}
  .hero-planets .lp{opacity:1;transform:none;}
}
@media(max-width:1060px){
  .hero-main{flex-direction:column;align-items:flex-start;gap:32px;}
  .hctas{align-items:stretch;width:100%;}
  .stats .stat{padding:20px var(--gut) 22px;}
  .stats .n{font-size:clamp(30px,5vw,48px);}
  /* once the hero stacks the paragraph runs the full page width, and 16/1.58
     reads oversized against the headline — step it down and close the leading */
  .hbody{font-size:15px;line-height:1.45;}
}
/* the CTA pair has the full page width to itself once the hero stacks — two
   half-width buttons read better than two full-width slabs until phone size */
@media(min-width:601px) and (max-width:1060px){
  .hctas{flex-direction:row;}
  .hctas .btn{flex:1 1 0;}
}
/* stats stack only at phone size. `flex:1 0 0` is a *main-axis* basis: the
   moment the container turns column that becomes height:0, and .stat clips its
   own content with overflow:hidden — which is why the numbers and their labels
   vanished on every screen under 1060. Height has to come from content here. */
@media(max-width:600px){
  .stats{flex-direction:column;}
  .stats .stat{flex:0 0 auto;overflow:visible;border-right:0;border-bottom:1px solid var(--strong);}
  .stats .stat:last-child{border-bottom:0;}
}

/* ============================================================
   01 · THE STACK — pinned scroll-scrub
   Figma 79-2628 (scattered) -> 79-2294 (aligned) -> 79-2717 (stitched)
   Reference stage: 1352 x 522 at a 1512 viewport.
   ============================================================ */
section.stitch-sec{padding:0;border-top:1px solid var(--strong);}
.stitch-wrap{height:360vh;position:relative;}
.stitch-pin{
  position:sticky;top:64px;height:calc(100vh - 64px);min-height:640px;
  display:flex;flex-direction:column;overflow:hidden;
  padding-top:clamp(28px,5.3vh,47px);
}
/* .shell carries margin:0 auto — inside a flex column that shrink-to-fits and
   centres the block instead of honouring the page gutter, so pin the width */
.stitch-head,.stitch-body{width:100%;}
.stitch-head{display:flex;align-items:flex-end;justify-content:space-between;gap:32px;}
.st-copy{min-width:0;}

/* eyebrow — 01 / THE STACK TODAY -> WHAT WE SOLVE */
.st-label{
  display:flex;align-items:baseline;gap:8px;margin-bottom:24px;
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;text-transform:uppercase;
}
.st-label .n{color:#fff;}
.st-label .d{color:rgba(255,255,255,0.4);}
.st-label .t{position:relative;white-space:nowrap;color:rgba(255,255,255,0.6);}
.st-label .tb{position:absolute;left:0;top:0;opacity:0;}

/* headline — two stacked sets, revealed word by word during the swap */
.st-title{
  position:relative;margin:0;max-width:825px;
  font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,4.2vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
.st-title .tset{display:block;}
.st-title .tset.tb{position:absolute;left:0;top:0;width:100%;}
.st-title .ln{display:block;}
.st-title .w{display:inline-block;white-space:pre;will-change:opacity,transform,filter;}

/* kicker pill — orange (nobody knows) crossfades to green (one profile knows) */
.st-kicker{position:relative;flex:none;margin-bottom:9px;}
.st-kicker .kp{
  display:inline-flex;align-items:center;justify-content:center;padding:8px 14px;
  font-family:var(--mono);font-weight:700;font-size:12px;letter-spacing:1.44px;
  text-transform:uppercase;white-space:nowrap;
}
.st-kicker .ka{background:rgba(255,102,26,0.2);color:#FF661A;}
.st-kicker .kb{position:absolute;right:0;top:0;background:rgba(23,229,126,0.2);color:#17E57E;opacity:0;}

/* stage */
.stitch-body{flex:1;display:flex;align-items:center;min-height:0;}
.stitch-stage{
  position:relative;width:100%;height:min(522px,64vh);overflow:hidden;
  background-image:
    linear-gradient(to right, rgba(255,255,255,0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.045) 1px, transparent 1px);
  background-size:32px 32px;
}

.slinks{position:absolute;inset:0;width:100%;height:100%;overflow:visible;}
.slinks polyline{
  fill:none;stroke:rgba(255,255,255,0.28);stroke-width:1;
  stroke-dasharray:4 4;vector-effect:non-scaling-stroke;
}
.slinks rect{fill:var(--live);}

.shub{
  position:absolute;left:50%;top:50%;
  height:30.65%;aspect-ratio:1;border-radius:50%;
  background:var(--live);display:flex;align-items:center;justify-content:center;
  transform:translate(-50%,-50%) scale(var(--hub,.62));
  opacity:var(--hubo,0);will-change:transform,opacity;
}
.shub img{width:60%;height:auto;}
.shub-tag{
  position:absolute;left:50%;top:69.16%;
  transform:translateX(-50%) translateY(var(--tagy,10px));
  padding:10px 14px;border:1px solid var(--strong);
  font-family:var(--mono);font-weight:500;font-size:12px;line-height:1;
  text-transform:uppercase;color:#fff;white-space:nowrap;
  opacity:var(--tago,0);will-change:transform,opacity;
}

.schip{
  position:absolute;left:0;top:0;
  display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  padding:10px 14px;
  border:1px solid var(--strong);background:rgba(255,255,255,0.05);
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  font-family:var(--mono);font-size:11px;text-transform:uppercase;color:var(--ink);
  will-change:transform;
}
.schip i{font-size:14px;line-height:1;color:var(--ink);}
.schip em{font-style:normal;color:rgba(255,255,255,0.4);}

/* mobile / reduced motion — no pin, stacked list under the hub */
@media (max-width:1060px),(prefers-reduced-motion:reduce){
  .stitch-wrap{height:auto;}
  .stitch-pin{position:static;height:auto;min-height:0;overflow:visible;padding:26px 0 clamp(56px,8vw,96px);}
  .stitch-head{flex-direction:column;align-items:flex-start;gap:20px;}
  .st-title .tset.ta,.st-label .ta{display:none;}
  .st-title .tset.tb{position:static;opacity:1;}
  .st-label .tb{position:static;opacity:1;}
  /* The kicker only earns its place on desktop, where it crossfades orange to
     green as the scrub runs. Stacked there is no crossfade, so it lands as a
     green slab restating the headline directly under the headline. */
  .st-kicker{display:none;}
  .stitch-body{margin-top:36px;}
  .stitch-stage{
    height:auto;overflow:visible;background-image:none;
    display:flex;flex-direction:column;align-items:center;gap:16px;
  }
  .slinks{display:none;}
  /* the chips were nowrap inside an overflow:hidden box, so "Subscriptions app /
     knows subscriptions" lost its tail on anything narrow. Uniform full-width
     rows read as a list, which is what the stacked layout is anyway. */
  .schip{
    position:relative;left:0;top:0;transform:none !important;opacity:1 !important;
    width:100%;max-width:440px;overflow:visible;white-space:normal;
    justify-content:flex-start;
  }
  .schip b{flex:1 1 auto;}
  .schip em{flex:none;text-align:right;}
  /* the tag reads as the circle's caption, so it hangs right off it —
     negative margin eats the stage's 16px flex gap down to 4px */
  .shub{position:static;transform:none;height:auto;width:132px;opacity:1;}
  /* opaque background so the connector node can tuck behind the tag's bottom
     edge — the frame is a hairline box, and without a fill the node would show
     through inside it */
  /* will-change:transform (a desktop-scrub hint) makes the tag a stacking
     context, which would trap the z-index:-1 node ABOVE the tag's own
     background — clear it so the node can genuinely tuck behind */
  .shub-tag{position:relative;left:0;top:0;transform:none;opacity:1;margin:-4px 0 16px;background:var(--bg);will-change:auto;}

  /* Stacking the diagram dropped the connectors with it (.slinks is desktop
     geometry), which left ten tools sitting under a hub with nothing joining
     them to it. A dashed spine threads the slices instead — same
     dashed-hairline-and-blue-node vocabulary as the desktop connectors, and it
     holds at any width because each segment is just the flex gap. */
  .stitch-stage .schip::before{
    content:"";position:absolute;left:50%;bottom:100%;
    width:1px;height:16px;transform:translateX(-50%);
    background-image:linear-gradient(to bottom,
      rgba(255,255,255,0.34) 0 4px, transparent 4px 8px);
    background-size:1px 8px;
  }
  /* The junction node straddles the tag's bottom edge, half tucked behind it —
     same treatment as the desktop connector rects. z-index:-1 works because the
     tag is position:relative with z-index auto (no stacking context of its
     own), so the pseudo drops into the negative layer of the ancestor context
     and the tag's opaque background paints over its top half. */
  .stitch-stage .shub-tag::after{
    content:"";position:absolute;left:50%;top:calc(100% - 4px);z-index:-1;
    width:8px;height:8px;margin-left:-4px;background:var(--live);
  }
}


/* ============================================================
   SHARED — planet sprites, section headings, word reveal
   ============================================================ */
/* generated wireframe planets fill their box exactly — no asset offsets */
.plt,.plt svg,.plt img{display:block;width:100%;height:100%;}


/* section headline — same scale as section 01 */
.sec-title{
  margin:0;max-width:825px;
  font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,4.2vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}

/* word-by-word reveal on entry (JS splits .rvw into .w spans and staggers) */
.rvw .w{
  display:inline-block;white-space:pre;
  opacity:0;transform:translateY(14px);
  transition:opacity .62s cubic-bezier(.22,1,.36,1),
             transform .72s cubic-bezier(.22,1,.36,1);
}
.rvw.in .w{opacity:1;transform:none;}
@media(prefers-reduced-motion:reduce){
  .rvw .w{opacity:1;transform:none;transition:none;}
}

/* status pill — live / beta / in orbit */
.pill{
  display:inline-flex;align-items:center;gap:8px;padding:4px 10px;white-space:nowrap;
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  font-family:var(--mono);font-weight:700;font-size:10px;letter-spacing:1px;text-transform:uppercase;
}
.pill i{width:4px;height:4px;flex:none;}
.pill.live{background:rgba(23,229,126,0.2);color:#17E57E;}
.pill.live i{background:#17E57E;animation:pip 2.4s ease-in-out infinite;}
.pill.beta{background:rgba(255,179,26,0.2);color:#FFB31A;}
.pill.beta i{background:#FFB31A;animation:pip 2.4s ease-in-out infinite .4s;}
.pill.orbit{background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.4);font-size:9px;letter-spacing:0.9px;}
.pill.orbit i{background:rgba(255,255,255,0.4);}
@keyframes pip{0%,100%{opacity:1;}50%{opacity:.35;}}

/* small status badge — nav dropdown (Figma 102-4161 / 102-4165) */
.tagpill{
  display:inline-flex;align-items:center;gap:5px;padding:3px 7px;
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  background:rgba(255,255,255,0.1);
  font-family:var(--mono);font-weight:600;font-size:9px;line-height:1.3;
  letter-spacing:.8px;text-transform:uppercase;color:rgba(255,255,255,0.6);
}
.tagpill i{width:3px;height:3px;flex:none;background:rgba(255,255,255,0.6);}
.tagpill.live{background:rgba(23,229,126,0.2);color:#17E57E;}
.tagpill.live i{background:#17E57E;}
@media(prefers-reduced-motion:reduce){.pill i{animation:none !important;}}

/* ============================================================
   02 · THE VYG UNIVERSE (Figma 79-2964 / graphic 102-3983)
   ============================================================ */
section.uni-sec{padding:clamp(28px,5.3vh,48px) 0 clamp(32px,5.3vh,48px);border-top:1px solid var(--strong);}
.uni-head{display:flex;align-items:flex-start;justify-content:space-between;gap:48px;width:100%;}
.uni-copy{min-width:0;}
.uni-note{
  flex:none;width:360px;margin:63px 0 0;
  font-family:var(--sans);font-size:13px;line-height:1.6;color:rgba(255,255,255,0.6);text-align:justify;
}

.uni-stage{
  position:relative;width:100%;height:min(522px,62vh);margin-top:49px;overflow:hidden;
  background-image:radial-gradient(circle, rgba(255,255,255,0.05) 1.5px, transparent 1.5px);
  background-size:32px 32px;
}
.corners{position:absolute;inset:0;pointer-events:none;}
.corners i{position:absolute;width:16px;height:16px;}
.corners i:nth-child(1){left:0;top:0;border-left:1px solid rgba(255,255,255,0.8);border-top:1px solid rgba(255,255,255,0.8);}
.corners i:nth-child(2){right:0;top:0;border-right:1px solid rgba(255,255,255,0.8);border-top:1px solid rgba(255,255,255,0.8);}
.corners i:nth-child(3){left:0;bottom:0;border-left:1px solid rgba(255,255,255,0.8);border-bottom:1px solid rgba(255,255,255,0.8);}
.corners i:nth-child(4){right:0;bottom:0;border-right:1px solid rgba(255,255,255,0.8);border-bottom:1px solid rgba(255,255,255,0.8);}

/* annotations are plain text now — the vertical rules were removed from the design */
.uni-anno{position:absolute;display:flex;align-items:center;}
.uni-anno span{font-family:var(--mono);font-size:11px;text-transform:uppercase;color:#fff;white-space:nowrap;}
.uni-anno.tl{left:32px;top:28px;}
.uni-anno.br{right:32px;bottom:28px;}
.uni-anno.br span{font-size:10px;color:rgba(255,255,255,0.5);}

/* --hit gives each orb a real hover/click target centred on --x */
.orb{
  position:absolute;left:var(--x);top:0;bottom:0;
  width:var(--hit,210px);margin-left:calc(var(--hit,210px) / -2);
  --o:1;--po:.8;
  color:rgba(255,255,255,0.5);            /* same rest level as the hero bodies */
}
.orb>*{position:absolute;left:50%;}
.orb .pill,.orb .onm{opacity:var(--o);transition:opacity .4s ease;}
/* Figma 130-12745 puts every pill and every label on one baseline, rather than
   offsetting them per planet size */
.orb .pill{top:24.14%;transform:translateX(-50%);}
/* --pscale lets the stage shrink every body together as the viewport narrows.
   --pd arrives per-orb from the inline style, so the multiplier has to live
   here rather than as an override of --pd itself. */
.orb .plt{
  top:50%;transform:translate(-50%,-50%);
  width:calc(var(--pd,160px) * var(--pscale,1));height:calc(var(--pd,160px) * var(--pscale,1));
  opacity:var(--po);
  transition:opacity .45s ease,color .45s ease;
}
.orb .onm{
  top:71.84%;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;white-space:nowrap;
  font-family:var(--mono);text-transform:uppercase;
}
.orb .onm b{font-weight:700;font-size:12px;color:rgba(255,255,255,0.6);}
.orb .onm.lead b{font-size:16px;color:#fff;}
.orb .onm em{font-style:normal;font-size:12px;color:rgba(255,255,255,0.6);}
.orb.dim{--po:.62;}
.orb.link{cursor:pointer;color:rgba(255,255,255,0.75);--po:1;}
.orb.link:focus-visible{outline:1px solid var(--live);outline-offset:6px;}

/* hovering a product planet brightens and colours it — no scaling — while the
   rest of the row steps back */
.uni-stage:has(.orb.link:hover) .orb,
.uni-stage:has(.orb.link:focus-visible) .orb{--o:.35;--po:.34;}
.uni-stage:has(.orb.link:hover) .orb.link:hover,
.uni-stage:has(.orb.link:focus-visible) .orb.link:focus-visible{--o:1;--po:1;color:var(--live);}



/* ============================================================
   STAGES — unify / act / consolidate (Figma 100-3749)
   ============================================================ */
.stagestrip{
  display:flex;padding:0 var(--frame);
  border-top:1px solid var(--strong);border-bottom:1px solid var(--strong);
}
.stg{
  flex:1 0 0;min-width:1px;position:relative;overflow:hidden;
  display:flex;flex-direction:column;gap:14px;
  padding:40px var(--gut) 48px;border-right:1px solid var(--strong);
}
.stg:last-child{border-right:0;}
.stg h3{margin:0;font-family:var(--sans);font-weight:500;font-size:clamp(22px,2.4vw,26px);letter-spacing:-0.03em;color:#fff;}
.stg p{margin:0;font-family:var(--sans);font-size:15px;line-height:1.5;color:rgba(255,255,255,0.7);max-width:408px;}
.stg .who{
  display:flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:10px;letter-spacing:1px;text-transform:uppercase;color:rgba(255,255,255,0.5);
}
.stg .who i{width:4px;height:4px;flex:none;background:var(--live);}
/* ghost numeral, scanlined like the hero stats */
.stg .ghost{
  position:absolute;right:32px;bottom:32px;pointer-events:none;
  /* line-height .75 shrinks the box onto the glyph so `bottom` measures from
     the digit's ink rather than from the font's descender space */
  font-family:var(--mono);font-weight:700;font-size:180px;line-height:.75;color:rgba(255,255,255,0.11);
  -webkit-mask-image:repeating-linear-gradient(180deg,#000 0 2px,transparent 2px 5px);
  mask-image:repeating-linear-gradient(180deg,#000 0 2px,transparent 2px 5px);
  opacity:0;transform:translateY(28px);
  transition:opacity .8s ease .1s,transform .9s cubic-bezier(.16,1,.3,1) .1s;
}
.stg.in .ghost{opacity:1;transform:none;}

/* ============================================================
   03 · SEE IT ON YOUR CUSTOMERS (Figma 102-4061)
   ============================================================ */
.cta-sec{
  position:relative;background:var(--live);overflow:hidden;
  background-image:repeating-linear-gradient(90deg,rgba(255,255,255,0.06) 0 1px,transparent 1px 20px);
}
/* Figma 102-4076: 160px above and below the content. The corner frame's own
   48px sits INSIDE that, so the two paddings sum to 160 rather than stacking. */
.cta-inner{
  position:relative;width:100%;
  padding:clamp(24px,3.6vw,54px) var(--pad);
  display:flex;flex-direction:column;align-items:center;
}
/* width:max-content — the frame hugs the widest line so it always contains the
   headline, instead of being pinned to a fixed box the copy can outgrow */
.cta-frame{
  position:relative;width:max-content;max-width:100%;
  padding:clamp(32px,5.7vw,86px) clamp(28px,3.2vw,48px);
  display:flex;flex-direction:column;align-items:center;gap:24px;text-align:center;
}
.cta-corners{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .9s ease .25s;}
.cta-sec.in .cta-corners{opacity:.75;}
.cta-corners i{position:absolute;width:20px;height:20px;}
.cta-corners i:nth-child(1){left:0;top:0;border-left:1px solid #fff;border-top:1px solid #fff;}
.cta-corners i:nth-child(2){right:0;top:0;border-right:1px solid #fff;border-top:1px solid #fff;}
.cta-corners i:nth-child(3){left:0;bottom:0;border-left:1px solid #fff;border-bottom:1px solid #fff;}
.cta-corners i:nth-child(4){right:0;bottom:0;border-right:1px solid #fff;border-bottom:1px solid #fff;}
.cta-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(28px,5.4vw,64px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
.cta-body{
  margin:0;max-width:720px;
  font-family:var(--sans);font-size:16px;line-height:1.58;color:rgba(255,255,255,0.7);
}
.cta-btn{background:#fff;border-color:#fff;color:var(--live);letter-spacing:.06em;}
.cta-btn:hover{background:var(--ink);border-color:var(--ink);}
.cta-note{
  margin:0;font-family:var(--mono);font-size:10px;letter-spacing:1px;
  text-transform:uppercase;color:rgba(255,255,255,0.5);
}

/* the closer's secondary path, under the primary button: a real link rather
   than a second button, so the self-serve CTA keeps the visual weight */
.cta-second{
  margin-top:-8px;
  font-family:var(--mono);font-size:11px;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,0.72);
  border-bottom:1px solid rgba(255,255,255,0.3);padding-bottom:3px;
  transition:color .16s ease,border-color .16s ease;
}
.cta-second:hover{color:#fff;border-bottom-color:#fff;}
/* wraps to a ragged two-liner once the closer narrows — desktop only */
@media(max-width:1060px){
  .cta-note{display:none;}
}

/* ============================================================
   FOOTER (Figma 148-23333) — three ruled columns, indexed nav
   ============================================================ */
footer.site{border-top:1px solid var(--strong);}
.foot{display:flex;padding:0 32px;}
.foot-col{flex:1 1 0;min-width:0;padding:48px;display:flex;flex-direction:column;}
.foot-col:not(:last-child){border-right:1px solid var(--border-light);}

.foot-brand{justify-content:space-between;gap:48px;}
.fb-top{display:flex;flex-direction:column;gap:24px;}
.fb-top img{width:142px;height:auto;}
.fb-top p{margin:0;font-family:var(--sans);font-size:16px;line-height:1.5;color:rgba(255,255,255,0.5);max-width:387px;}
.fb-legal{margin:0;font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:.6px;
  text-transform:uppercase;color:rgba(255,255,255,0.4);}

/* oversized indexed nav — the row is the hit target, so the whole band lifts */
.foot-nav{gap:0;}
.foot-nav a{
  display:flex;align-items:baseline;justify-content:space-between;gap:24px;
  padding:14px 0;
}
.foot-nav a + a{border-top:1px solid var(--border-light);}
.foot-nav a:first-child{padding-top:0;}
.foot-nav a:last-child{padding-bottom:0;}
.foot-nav span{
  font-family:var(--sans);font-weight:500;font-size:clamp(26px,4.6vw,40px);letter-spacing:-.04em;line-height:1.3;
  color:var(--ink);transition:color .2s ease;
}
.foot-nav i{
  font-style:normal;font-family:var(--mono);font-weight:600;font-size:16px;letter-spacing:.96px;
  color:rgba(255,255,255,0.4);transition:color .2s ease;
}
.foot-nav a:hover span{color:rgba(255,255,255,0.45);}
.foot-nav a:hover i{color:rgba(255,255,255,0.25);}

.foot-meta{justify-content:space-between;gap:48px;}
.fm-links{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:16px;}
.fm-links li{display:flex;}
.fm-links a{
  font-family:var(--mono);font-weight:600;font-size:11.5px;line-height:1.3;letter-spacing:.69px;
  text-transform:uppercase;color:rgba(255,255,255,0.8);transition:color .15s;
}
.fm-links a:hover{color:rgba(255,255,255,0.4);}
.fm-bottom{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;}
.fm-contact{display:flex;flex-direction:column;gap:10px;}
.fm-contact .k{font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  text-transform:uppercase;color:rgba(255,255,255,0.4);}
.fm-contact a{font-family:var(--sans);font-weight:500;font-size:clamp(18px,3.4vw,24px);letter-spacing:-.02em;
  color:var(--ink);transition:color .15s;}
.fm-contact a:hover{color:rgba(255,255,255,0.45);}
.fm-social{display:flex;gap:8px;flex:none;}
.fm-social a{
  width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,0.1);color:rgba(255,255,255,0.75);
  transition:background .18s ease,color .18s ease;
}
.fm-social svg{width:16px;height:16px;display:block;fill:currentColor;}
.fm-social a:hover{background:rgba(255,255,255,0.2);color:#fff;}

/* the absolute orbit row only holds while there is room between --x stops for a
   planet plus its label — below ~1240 the bodies start colliding, so shrink
   them, then hand over to the flow layout at 1060 */
/* --x stops are 18.7% apart, so the space between two orbit centres is roughly
   0.187 x stage width: 222px at 1340, 190px at 1160, 172px at 1061. --hit (the
   label/hover box) has to stay under that or neighbouring labels run together,
   which is what a flat 210px was doing all the way down. */
@media(max-width:1340px){
  .uni-stage{--pscale:.92;--hit:185px;}
  .orb .onm{white-space:normal;width:var(--hit,210px);}
}
@media(max-width:1160px){
  .uni-stage{--pscale:.82;--hit:165px;}
}
@media(max-width:1060px){
  .uni-head{flex-direction:column;gap:24px;}
  .uni-note{width:100%;margin-top:0;text-align:left;}
  /* Both annotations are desktop margin notes pinned to the corners of the
     stage. Stacked they lose that anchoring and just become a third block of
     copy repeating the headline above them. */
  .uni-anno{display:none;}

  /* orbit row -> a wrapping row. All five stay on one line while there is room
     and then drop to 4, 3, 2 on their own, with any short last row centred —
     so it reads as a row for as long as it can, instead of snapping straight to
     a single column at 760 the way it used to. */
  .uni-stage{
    height:auto;padding:32px 0;overflow:visible;background-size:26px 26px;
    display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;
    gap:clamp(22px,3vw,36px);
    --pscale:.8;
  }
  .uni-anno{position:static;flex:1 0 100%;padding:0;}
  /* Three fixed bands — pill / planet / name — so pills sit on one line and the
     bodies share a centreline across the row even though Mercury is 160 and
     Earth is 180, and only the trailing labels differ in height. */
  .orb{
    position:relative;left:auto;top:auto;bottom:auto;margin-left:0;
    flex:0 1 calc((100% - 4 * clamp(22px,3vw,36px)) / 5);min-width:118px;max-width:190px;
    display:grid;grid-template-rows:24px calc(180px * var(--pscale,1)) auto;
    justify-items:center;gap:12px;
  }
  /* the pill band is fixed too: "Live" sets at 10px and "In orbit" at 9px, and
     letting row 1 size itself pushed each planet to a different centreline */
  .orb .pill{align-self:end;}
  .orb>*{position:static;left:auto;top:auto;bottom:auto;transform:none !important;}
  .orb .onm{width:auto;}
  .orb .plt{
    animation:none;align-self:center;
    width:min(100%,calc(var(--pd,160px) * var(--pscale,1)));height:auto;aspect-ratio:1;
  }

  /* same main-axis trap as .stats: flex:1 0 0 became height:0 the moment the
     strip turned column, and overflow:hidden (there for the ghost numeral) then
     cut every card off mid-sentence */
  .stagestrip{flex-direction:column;}
  .stg{flex:0 0 auto;border-right:0;border-bottom:1px solid var(--strong);}
  .stg:last-child{border-bottom:0;}
  .stg .ghost{font-size:clamp(96px,14vw,120px);right:var(--gut);bottom:8px;}

  .foot{flex-direction:column;gap:0;padding:0 var(--frame);}
  .foot-col{flex:0 0 auto;padding:32px var(--gut);}
  .foot-col:not(:last-child){border-right:0;border-bottom:1px solid var(--border-light);}
  .legal{flex-direction:column;gap:10px;align-items:flex-start;}
}

/* ============================================================
   WORDFIELD — the wordmark reads as gaps in a field of vertical
   rules, with a slow pulse travelling across it
   ============================================================ */
.wordfield{
  position:relative;z-index:80;width:100%;overflow:hidden;
  height:clamp(150px,21vw,330px);
  background:var(--bg);
}
.wordfield canvas{display:block;width:100%;height:100%;}
@media(prefers-reduced-motion:reduce){.wordfield{height:clamp(120px,16vw,240px);}}

/* ============================================================
   REQUEST A DEMO — modal (transparent panel over a blurred page)
   Same construction as the HQ "Talk to us" dialog: the overlay
   owns the blur, the panel is a near-transparent white film with
   a hairline border. Type, fields and buttons are Voyage's own —
   Kode Mono labels, Geist copy, square hairline inputs, blue CTA.
   ============================================================ */
.dm-overlay{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:center;justify-content:center;
  padding:24px;
  background:rgba(21,21,26,0.32);
  backdrop-filter:blur(40px) saturate(120%);-webkit-backdrop-filter:blur(40px) saturate(120%);
  animation:dmFade .2s ease both;
}
.dm-overlay[hidden]{display:none;}
@keyframes dmFade{from{opacity:0;}to{opacity:1;}}

.dm-modal{
  position:relative;z-index:1;
  width:648px;max-width:100%;max-height:calc(100vh - 48px);overflow:hidden;
  display:flex;flex-direction:column;
  padding:clamp(28px,3.2vw,44px);
  background:rgba(255,255,255,0.06);
  border:1px solid var(--strong);
  box-shadow:0 60px 60px rgba(0,0,0,0.22),0 150px 100px rgba(0,0,0,0.10);
  animation:dmIn .22s cubic-bezier(.22,.61,.36,1) both;
}
@keyframes dmIn{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}
/* the panel itself never scrolls, so the corner brackets and close button stay
   pinned to the frame — only the content column moves */
.dm-body{display:flex;flex-direction:column;gap:32px;overflow-y:auto;}
.dm-close{
  position:absolute;top:18px;right:18px;width:32px;height:32px;
  display:inline-flex;align-items:center;justify-content:center;
  background:none;border:0;padding:0;cursor:pointer;
  color:rgba(255,255,255,0.55);font-size:16px;line-height:1;
  transition:color .18s;
}
.dm-close:hover{color:var(--ink);}

.dm-head{display:flex;flex-direction:column;gap:12px;padding-right:36px;}
.dm-eyebrow{
  display:flex;align-items:baseline;gap:8px;
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;text-transform:uppercase;
}
.dm-eyebrow .n{color:#fff;}
.dm-eyebrow .d{color:rgba(255,255,255,0.4);}
.dm-eyebrow .t{color:rgba(255,255,255,0.6);}
.dm-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,2.6vw,36px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
.dm-sub{margin:0;font-family:var(--sans);font-size:15px;line-height:1.55;color:rgba(255,255,255,0.6);}

.dm-form,.f-form{display:flex;flex-direction:column;gap:20px;}
.dm-row,.f-row{display:flex;gap:20px;}
.dm-field,.f-field{display:flex;flex-direction:column;gap:9px;flex:1 1 0;min-width:0;}
.dm-label,.f-label{
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  text-transform:uppercase;color:rgba(255,255,255,0.6);
}
.dm-label .opt,.f-label .opt{letter-spacing:1.2px;color:rgba(255,255,255,0.35);}

.dm-input,.dm-select,.dm-textarea,
.f-input,.f-select,.f-textarea{
  width:100%;padding:0 14px;height:46px;
  background-color:transparent;border:1px solid var(--line-2);
  color:var(--ink);font-family:var(--sans);font-size:14px;line-height:20px;
  outline:none;appearance:none;-webkit-appearance:none;
  transition:border-color .18s,background-color .18s;
}
.dm-textarea,.f-textarea{height:auto;min-height:96px;padding:12px 14px;resize:vertical;}
.dm-input::placeholder,.dm-textarea::placeholder,
.f-input::placeholder,.f-textarea::placeholder{color:rgba(255,255,255,0.34);}
.dm-input:hover,.dm-select:hover,.dm-textarea:hover,
.f-input:hover,.f-select:hover,.f-textarea:hover{border-color:var(--btn-line);}
.dm-input:focus,.dm-select:focus,.dm-textarea:focus,
.f-input:focus,.f-select:focus,.f-textarea:focus{
  border-color:var(--live);background-color:rgba(26,140,255,0.05);
}
/* the field is empty until a real choice is made — grey it like a placeholder */
.dm-select:invalid,.f-select:invalid{color:rgba(255,255,255,0.34);}
.dm-select,.f-select{
  padding-right:36px;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'><path d='M1 1 L5 5 L9 1' stroke='%23FAF9F5' stroke-opacity='0.7' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat;background-position:right 14px center;
}
.dm-select option,.f-select option{background:var(--panel-2);color:var(--ink);}

.dm-error,.f-error{
  margin:0;font-family:var(--mono);font-size:10px;letter-spacing:1px;text-transform:uppercase;
  color:#FF8A8A;
}
.dm-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:4px;}
.f-actions{display:flex;flex-direction:column;gap:12px;padding-top:4px;}
.dm-actions .btn{flex:none;}
.dm-actions .btn[disabled]{opacity:.55;cursor:default;}

/* sent — mirrors the "transmission open" language used on the Earth CTA */
.dm-modal>.corners{inset:14px;}
.dm-modal>.corners i{width:14px;height:14px;}
.dm-modal>.corners i:nth-child(n){border-color:rgba(255,255,255,0.45);}

.dm-sent{display:flex;flex-direction:column;align-items:flex-start;gap:20px;padding:8px 0 4px;}
.dm-sent .dm-title{max-width:24ch;}

@media(max-width:640px){
  .dm-overlay{padding:0;align-items:stretch;}
  /* .dm-body is the scroller. With the side padding on the modal it ended 20px
     short of the screen, so its scrollbar drew over the form fields instead of
     down the edge of the display. Padding moves onto the scroller itself: the
     track sits at the screen edge, the content keeps its inset. */
  .dm-modal{
    width:100%;max-width:100%;height:100dvh;max-height:100dvh;
    padding:max(28px,env(safe-area-inset-top) + 10px) 0 0;
    gap:24px;border:0;
  }
  .dm-body{
    padding:0 20px max(28px,env(safe-area-inset-bottom) + 16px);
    scrollbar-gutter:stable;
  }
  .dm-modal>.corners{display:none;}   /* full-bleed on phones — no frame to bracket */
  .dm-row{flex-direction:column;gap:20px;}
  .dm-actions{flex-direction:column-reverse;}
  .dm-actions .btn{width:100%;}
}
@media(prefers-reduced-motion:reduce){
  .dm-overlay,.dm-modal{animation:none;}
}

/* ============================================================
   PRODUCT HERO (Figma 136-14654) — copy left, wireframe body right,
   split by a full-height hairline. Reference frame 1512 x 627:
   copy col x=80 w=700 · rule x=837 · visual box 627 square ending at
   the page frame (1464), corner chevrons 20px inset 40px.
   ============================================================ */
.ph{
  display:grid;
  grid-template-columns:minmax(0,700fr) minmax(0,627fr);
  gap:clamp(28px,3.77vw,57px);
  align-items:stretch;
  padding:0 var(--frame) 0 var(--pad);
  border-bottom:1px solid var(--line);
}
.ph-copy{
  display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  padding:clamp(48px,8.7vw,132px) 0;
}
/* eyebrow — dot / word / rule / line, the homepage .hcrumb scale */
.ph-crumb{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  text-transform:uppercase;color:rgba(255,255,255,0.6);
}
.ph-crumb i{width:4px;height:4px;flex:none;background:var(--live);}
.ph-crumb .w{color:var(--ink);}
.ph-crumb .d{color:rgba(255,255,255,0.4);}
.ph-title{
  margin:24px 0 0;font-family:var(--sans);font-weight:500;
  font-size:clamp(34px,4.23vw,64px);letter-spacing:-0.06em;line-height:1.125;color:#fff;
}
.ph-body{
  margin:24px 0 0;max-width:700px;
  font-family:var(--sans);font-size:16px;line-height:1.55;color:rgba(255,255,255,0.7);
}
.ph-ctas{display:flex;flex-wrap:wrap;gap:12px;margin-top:48px;}

/* aspect-ratio:1 against a stretched row height means the box asks to be as
   wide as the hero is tall. That holds at the 1512 reference, but as the page
   narrows the copy column stops shrinking and the square pushed straight
   through its own grid track and off the right edge — max-width pins it back
   to the column and lets it read as a tall panel instead. */
.ph-visual{
  position:relative;aspect-ratio:1;max-width:100%;
  display:flex;align-items:center;justify-content:center;
  border-left:1px solid var(--line);
}
/* the body fills 440/627 of the square, exactly as in the frame */
.ph-body-art{width:70.2%;color:var(--ink);}
/* corner chevrons — 20px arms held 40/627 in from the box edge */
.ph-visual .corners{inset:6.38%;}
.ph-visual .corners i{width:20px;height:20px;}
.ph-visual .corners i:nth-child(n){border-color:rgba(255,255,255,0.55);}

@media(max-width:900px){
  .ph{grid-template-columns:1fr;gap:0;padding:0 var(--pad);}
  .ph-copy{padding:clamp(32px,7vw,56px) 0 clamp(28px,5vw,40px);order:2;}
  .ph-title{font-size:clamp(34px,7.6vw,48px);}
  .ph-ctas{margin-top:32px;width:100%;}
  .ph-ctas .btn{flex:1 1 auto;justify-content:center;}
  /* the visual spans the content column so its corner brackets land on the
     same left/right lines as the copy below; the square ratio goes with the
     column width and the globe keeps its own cap instead */
  .ph-visual{
    border-left:0;order:1;aspect-ratio:auto;max-width:none;width:100%;
    margin:clamp(20px,4.5vw,36px) 0 0;
    padding:clamp(28px,7vw,48px) 0;
  }
  .ph-visual .corners{inset:0;}
  .ph-body-art{width:min(70vw,320px);}
}

/* beta product hero — the eyebrow dot carries the status colour */
/* the beta tag sits in the eyebrow, in the nav dropdown's small grey style */
.ph-crumb .tagpill{margin-left:4px;font-size:8px;}

/* the product-hero barcode stops at the rails, same as the homepage hero's —
   running it full-bleed puts it underneath the hatched edge strips */
.ph + .barcode{margin:0 var(--frame);opacity:.5;}

/* ============================================================
   SECTION 01 · THE PROBLEM (Figma 156-381) — copy left, schematic
   right in a bracketed panel. Same split and gutter as the product
   hero, so the two read as one system down the page.
   ============================================================ */
/* Figma 158-3889 at 1512: pad 80 | copy 640 | gap 80 | panel 640 | pad 72,
   with 46px of air above and below the panel. */
section.sp{padding:clamp(28px,3vw,46px) 0;}
/* same column geometry as the product hero (.ph), so the panel's left edge
   lands exactly under the hero graphic's; the 32px gutter to the frame rail
   is taken off the visual rather than the grid, so the caption respects it too */
.sp-grid{
  display:grid;
  grid-template-columns:minmax(0,700fr) minmax(0,627fr);
  gap:clamp(28px,3.77vw,57px);
  align-items:stretch;
  padding:0 var(--frame) 0 var(--pad);
}
/* the eyebrow rides the top of the section; the copy block centres against
   the panel beside it */
.sp-copy{position:relative;display:grid;}
.sp-copy .st-label{position:absolute;top:0;left:0;}
.sp-copy .st-label{margin:0 0 clamp(40px,9.3vw,140px);}
.sp-text{align-self:center;}
.sp-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,3.18vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
  max-width:18ch;
}
.sp-body{
  margin:24px 0 0;max-width:56ch;
  font-family:var(--sans);font-size:16px;line-height:1.58;color:rgba(255,255,255,0.7);
}

.sp-visual{margin:0 32px 0 0;}
/* the schematic breathes inside the bracket frame — the brackets are
   absolutely positioned against the padding box, so they stay on the outer
   edge while the svg is inset */
/* the dot field belongs to the frame, so it runs corner to corner behind the
   drawing rather than stopping at the inset svg */
.sp-frame{
  --sp-pad:clamp(20px,3.2vw,48px);
  position:relative;padding:var(--sp-pad);
  background-image:radial-gradient(rgba(255,255,255,0.07) 1px,transparent 1px);
  background-size:16px 16px;background-position:8px 8px;
}
.sp-frame .corners{inset:0;}
.sp-frame .corners i{width:18px;height:18px;}
.sp-frame .corners i:nth-child(n){border-color:rgba(255,255,255,0.4);}
.frag{width:100%;height:auto;display:block;overflow:visible;}

/* --- tally + verdict --- */
.sp-frame .fg-tally{
  position:absolute;top:0;left:var(--sp-pad);right:var(--sp-pad);height:var(--sp-pad);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:10px;letter-spacing:1.4px;
  text-transform:uppercase;color:rgba(255,255,255,0.4);
}
.frag .fg-verdict{
  font-family:var(--mono);letter-spacing:1.4px;text-transform:uppercase;text-anchor:middle;
}
.frag .fg-verdict{font-size:11px;fill:rgba(255,255,255,0.72);
  animation:fgBlink 3.2s ease-in-out infinite;}

/* --- the profile that should be here, and isn't --- */
.frag .fg-slot .slot{
  fill:none;stroke:rgba(255,255,255,0.34);stroke-width:1;stroke-dasharray:5 5;
  animation:fgCrawl 20s linear infinite;
}
@keyframes fgCrawl{to{stroke-dashoffset:-200;}}
.frag .fg-slot .ghost{fill:rgba(255,255,255,0.13);stroke:none;}
.frag .fg-slot .av{fill:none;stroke:rgba(255,255,255,0.26);stroke-width:1;stroke-dasharray:3 3;}

/* --- feeds that run at the middle and stop short --- */
.frag .fg-feeds .f{
  fill:none;stroke:rgba(26,140,255,0.85);stroke-width:1.25;
  stroke-dasharray:4 5;
  animation:fgRun 1.6s linear infinite;
}
.frag .f2{animation-delay:.4s;}
.frag .f3{animation-delay:.8s;}
.frag .f4{animation-delay:1.2s;}
@keyframes fgRun{to{stroke-dashoffset:-18;}}
.frag .fg-taps rect{fill:var(--live);}

/* the break where each feed fails to land */
.frag .fg-breaks path{
  fill:none;stroke:rgba(255,255,255,0.55);stroke-width:1.25;stroke-linecap:round;
  animation:fgBlink 3.2s ease-in-out infinite;
}
.frag .fg-breaks path:nth-child(2){animation-delay:.4s;}
.frag .fg-breaks path:nth-child(3){animation-delay:.8s;}
.frag .fg-breaks path:nth-child(4){animation-delay:1.2s;}
@keyframes fgBlink{0%,100%{opacity:.3;}50%{opacity:1;}}

/* --- the four owners --- */
/* SVG has no backdrop-filter, and the only thing behind a card is the dot
   field — so an opaque base under a light white wash gives the frosted panel
   look and stops the dots at the card edge. */
.frag .fg-card .bg{fill:var(--bg);stroke:none;}
.frag .fg-card .fc{fill:rgba(255,255,255,0.06);stroke:var(--line-2);stroke-width:1;}
.frag .fg-card .pip{stroke:none;fill:#FFB31A;animation:fgBlink 3.2s ease-in-out infinite;}
.frag .c2 .pip{animation-delay:.4s;}
.frag .c3 .pip{animation-delay:.8s;}
.frag .c4 .pip{animation-delay:1.2s;}
.frag .fg-card .k{
  font-family:var(--mono);font-size:10px;letter-spacing:1.2px;
  text-transform:uppercase;fill:rgba(255,255,255,0.55);
}
.frag .fg-card .v{font-family:var(--sans);font-size:15px;fill:var(--ink);}

@media(max-width:900px){
  .sp-grid{grid-template-columns:1fr;gap:32px;padding:0 var(--pad);}
  .sp-title{max-width:none;}
  /* the 32px right margin held the panel off the frame rail in the two-column
     layout; once stacked it just made the schematic sit off-centre */
  .sp-visual{order:2;margin-right:0;}
}
@media(prefers-reduced-motion:reduce){
  .frag *{animation:none !important;}
}

/* packets: each source keeps sending, each send dies at the break */
.frag .fg-packets .p{
  fill:var(--ink);
  offset-rotate:0deg;
  animation:fgPacket 2.2s cubic-bezier(.5,0,.7,1) infinite;
  opacity:0;
}
.frag .p1{offset-path:path('M 114 112 V 224 H 196');}
.frag .p2{offset-path:path('M 526 112 V 224 H 444');animation-delay:.55s;}
.frag .p3{offset-path:path('M 114 388 V 276 H 196');animation-delay:1.1s;}
.frag .p4{offset-path:path('M 526 388 V 276 H 444');animation-delay:1.65s;}
@keyframes fgPacket{
  0%{offset-distance:0%;opacity:0;}
  10%{opacity:1;}
  78%{offset-distance:100%;opacity:1;}
  92%,100%{offset-distance:100%;opacity:0;}
}

/* ============================================================
   SECTION 02 · THE FIX (Figma 161-3955) — head band, then a ruled
   full-width stage carrying the product window.
   ============================================================ */
/* Figma 161-3955 at 1512: head band 48 top / 90 tall / 48 bottom, rules at
   y=186 and y=812, graphic wrapper 1416 wide (inset var(--frame)) x 626 tall. */
section.sf{padding:0 0 clamp(28px,3.2vw,48px);border-top:1px solid var(--line-2);}
.sf-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:clamp(32px,5vw,80px);
  padding:clamp(28px,3.2vw,48px) var(--pad);
}
.sf-copy{min-width:0;}
.sf-copy .st-label{margin-bottom:24px;}
/* same scale as every other section headline */
.sf-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,3.18vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
.sf-body{
  margin:0;flex:none;width:min(360px,42vw);text-align:justify;
  font-family:var(--sans);font-size:14px;line-height:1.45;color:rgba(255,255,255,0.62);
}

/* the stage is the band between the two rules; the graphic wrapper inside it
   is inset to the page frame and carries the dot field */
/* these two rules sit inside the section, so they take the light hairline —
   the strong one is reserved for the section boundary on section.sf */
.sf-stage{
  border-top:1px solid var(--border-light);border-bottom:1px solid var(--border-light);
  padding:0 var(--frame);
}
.sf-graphic{
  min-height:clamp(360px,41.4vw,626px);
  display:grid;place-items:center;
  padding:clamp(20px,2.6vw,40px) 0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.045) 1px, transparent 1px);
  background-size:32px 32px;
}

/* ---------- the product window ---------- */
.app{
  width:100%;max-width:1134px;margin:0 auto;
  /* same light-white surface as the section 01 cards. This one is HTML, so it
     can take a real backdrop blur — at 30px the 16px dot field behind it
     smears to a flat wash rather than reading through the panel. */
  background:rgba(255,255,255,0.06);
  backdrop-filter:blur(30px) saturate(120%);-webkit-backdrop-filter:blur(30px) saturate(120%);
  border:1px solid var(--line-2);
  display:flex;flex-direction:column;position:relative;
  container-type:inline-size;
}
.app-bar{
  display:flex;align-items:center;gap:16px;flex:none;
  padding:0 16px;height:40px;border-bottom:1px solid var(--line);
  background:rgba(255,255,255,0.02);
}
.app-bar .dots{display:inline-flex;gap:6px;flex:none;}
.app-bar .dots i{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,0.18);}
.app-bar .crumb{
  font-family:var(--mono);font-size:10px;letter-spacing:1.1px;text-transform:uppercase;
  color:rgba(255,255,255,0.5);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.app-bar .crumb b{color:rgba(255,255,255,0.28);font-weight:400;margin:0 4px;}
.app-bar .live-tag{
  display:inline-flex;align-items:center;gap:6px;flex:none;
  font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;color:#17E57E;
}
.app-bar .live-tag i{width:4px;height:4px;background:#17E57E;animation:pip 2.4s ease-in-out infinite;}

.app-body{display:flex;align-items:stretch;min-height:0;}

.app-rail{
  flex:none;width:48px;border-right:1px solid var(--line);
  display:flex;flex-direction:column;align-items:center;gap:4px;padding:14px 0;
}
.app-rail i{
  width:32px;height:32px;display:grid;place-items:center;font-size:16px;
  color:rgba(255,255,255,0.3);
}
.app-rail i.on{color:var(--ink);background:rgba(255,255,255,0.07);}

.app-main{flex:1;min-width:0;padding:20px 20px 84px;display:flex;flex-direction:column;gap:16px;}
.ap-head{display:flex;align-items:center;justify-content:space-between;gap:16px;}
.ap-id{display:flex;align-items:center;gap:12px;min-width:0;}
.ap-id .av{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:var(--live);color:#fff;
  font-family:var(--mono);font-size:12px;letter-spacing:.5px;
}
.ap-id .who{display:flex;flex-direction:column;gap:3px;min-width:0;}
.ap-id .who b{font-family:var(--sans);font-size:17px;font-weight:500;color:#fff;}
.ap-id .who em{
  font-family:var(--mono);font-style:normal;font-size:9.5px;letter-spacing:1px;
  text-transform:uppercase;color:rgba(255,255,255,0.42);
}
.ap-tags{display:flex;gap:6px;flex:none;}
.ap-tags span{
  padding:4px 8px;border:1px solid var(--line-2);
  font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,0.7);
}

.ap-stats{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);}
.ap-stats div{
  padding:12px 14px;display:flex;flex-direction:column;gap:6px;
  border-right:1px solid var(--line);min-width:0;
}
.ap-stats div:last-child{border-right:0;}
.ap-stats .k{
  font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,0.4);
}
.ap-stats .n{font-family:var(--mono);font-size:17px;color:#fff;}

.ap-feed{border:1px solid var(--line);display:flex;flex-direction:column;min-height:0;}
.ap-feed-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:10px 14px;border-bottom:1px solid var(--line);
  font-family:var(--mono);font-size:9.5px;letter-spacing:1.1px;text-transform:uppercase;
}
.ap-feed-head .t{color:rgba(255,255,255,0.6);}
.ap-feed-head .c{display:inline-flex;align-items:center;gap:6px;color:rgba(255,255,255,0.4);}
.ap-feed-head .c i{width:4px;height:4px;background:var(--live);animation:pip 2.4s ease-in-out infinite;}

.ap-list{list-style:none;margin:0;padding:0;}
.ap-list li{
  position:relative;
  display:grid;grid-template-columns:112px 1fr auto;align-items:center;gap:14px;
  padding:11px 14px;border-bottom:1px solid var(--line);
}
.ap-list li:last-child{border-bottom:0;}
.ap-list .src{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,0.45);
}
.ap-list .src i{font-size:14px;color:rgba(255,255,255,0.55);}
.ap-list .ev{font-family:var(--sans);font-size:13.5px;color:rgba(255,255,255,0.72);min-width:0;}
.ap-list .ev b{color:#fff;font-weight:500;}
.ap-list .ts{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.8px;text-transform:uppercase;
  color:rgba(255,255,255,0.32);
}
/* the list slides as a whole when a row lands (see site.js), so the row itself
   only carries the "this one is new" mark: a blue edge and a wash that take
   their time fading rather than snapping */
.ap-feed{overflow:hidden;}
.ap-list{transform:translateZ(0);}
.ap-list.sliding{animation:apSlide .6s cubic-bezier(.22,.9,.26,1);}
@keyframes apSlide{
  from{transform:translateY(calc(var(--slide,44px) * -1));}
  to{transform:translateY(0);}
}
.ap-list li.new{animation:apGlow 2.4s ease-out both;}
@keyframes apGlow{
  0%,15%{background:rgba(26,140,255,0.09);}
  100%{background:transparent;}
}
.ap-list li.new::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--live);
  animation:apEdge 2.4s ease-out both;
}
@keyframes apEdge{0%,15%{opacity:1;}100%{opacity:0;}}

.app-side{
  flex:none;width:196px;border-left:1px solid var(--line);padding:20px 16px 84px;
  display:flex;flex-direction:column;gap:12px;
}
.sd-h{
  font-family:var(--mono);font-size:9.5px;letter-spacing:1.1px;text-transform:uppercase;
  color:rgba(255,255,255,0.42);
}
.sd-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;}
.sd-list li{
  display:flex;align-items:center;gap:9px;padding:7px 0;
  font-family:var(--sans);font-size:13px;color:rgba(255,255,255,0.72);
  border-bottom:1px solid var(--line);
}
.sd-list li:last-child{border-bottom:0;}
.sd-list li i{width:5px;height:5px;flex:none;background:#17E57E;}
.sd-list li:nth-child(2) i{animation-delay:.3s;}
.sd-list li:nth-child(3) i{animation-delay:.6s;}
.sd-list li:nth-child(4) i{animation-delay:.9s;}
.sd-list li:nth-child(5) i{animation-delay:1.2s;}
.sd-list li i{animation:pip 2.4s ease-in-out infinite;}
.sd-list li span{
  margin-left:auto;font-family:var(--mono);font-size:8.5px;letter-spacing:1px;
  text-transform:uppercase;color:rgba(255,255,255,0.32);
}
.sd-note{
  margin-top:auto;font-family:var(--mono);font-size:9px;line-height:1.7;letter-spacing:.8px;
  text-transform:uppercase;color:rgba(255,255,255,0.3);
}

/* the floating ask bar, borrowed from the reference */
.app-ask{
  position:absolute;left:50%;bottom:18px;transform:translateX(-50%);
  width:min(420px,72%);display:flex;align-items:center;gap:12px;
  padding:11px 12px 11px 16px;
  background:rgba(28,28,34,0.82);border:1px solid var(--line-2);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  box-shadow:0 18px 40px rgba(0,0,0,0.45);
}
.app-ask .askph{
  flex:1;min-width:0;display:inline-flex;align-items:center;justify-content:flex-start;
  text-align:left;
  font-family:var(--sans);font-size:13.5px;color:rgba(255,255,255,0.42);
}
/* the cursor sits where a cursor sits in an empty field: at the start */
.app-ask .car{
  flex:none;width:1px;height:15px;margin-right:7px;background:var(--ink);
  animation:apCaret 1.1s steps(1) infinite;
}
@keyframes apCaret{0%,49%{opacity:1;}50%,100%{opacity:0;}}
.app-ask .go{
  flex:none;width:26px;height:26px;display:grid;place-items:center;border-radius:50%;
  background:var(--live);color:#fff;font-size:13px;
}

@container (max-width:820px){
  .app-side{display:none;}
  .ap-stats{grid-template-columns:repeat(2,1fr);}
  .ap-stats div:nth-child(2){border-right:0;}
}
@media(max-width:720px){
  .sf-head{flex-direction:column;gap:24px;}
  .sf-body{width:100%;text-align:left;}
  .app-rail{display:none;}
  .ap-list li{grid-template-columns:1fr auto;gap:8px;}
  .ap-list .src{grid-column:1/-1;}
  .app-ask{width:calc(100% - 32px);}
}
@media(prefers-reduced-motion:reduce){
  .app-ask .car,.ap-list li.new,.ap-list li.new::before{animation:none;}
}

/* ============================================================
   SECTION 03 · WHAT YOU GET (Figma 164-4151)
   Head band 186 tall, then a 3x3 grid inset to var(--frame):
   cells 472 x 226 at 1512, padding 40/32/48, a 48px blue icon
   chip on the right of the index row.
   ============================================================ */
section.sg{padding:0;border-top:1px solid var(--line-2);}
.sg-head{padding:clamp(28px,3.2vw,48px) var(--pad);}
.sg-head .st-label{margin-bottom:24px;}
.sg-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,3.18vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
/* Rows run the full page width so their rules carry across the edge strips,
   exactly as the Figma draws them at x=0 w=1512; only the cells are inset.
   No vertical rule at the grid's outer edges — the page frame's rails already
   draw a hairline at var(--frame) on both sides, and adding one there stacked
   two 1px lines in the same place and read as a thick border. */
.sg-grid{border-top:1px solid var(--border-light);}
.feat-row{
  display:grid;grid-template-columns:repeat(3,1fr);
  padding:0 var(--frame);
  border-bottom:1px solid var(--border-light);
}
.feat + .feat{border-left:1px solid var(--border-light);}
/* the next section draws the boundary — a rule here would stack on it and
   read as one thick line */
.feat-row:last-child{border-bottom:0;}
.feat{
  padding:clamp(24px,2.65vw,40px) clamp(20px,2.12vw,32px);
  display:flex;flex-direction:column;gap:clamp(12px,1.06vw,16px);
  transition:background .18s;
}
.feat:hover{background:rgba(250,249,245,0.04);}
.ft-top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;}
.feat .no{
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  color:rgba(255,255,255,0.4);
}
/* 20% blue plate, icon at full blue */
.feat .ic{
  flex:none;width:40px;height:40px;display:grid;place-items:center;
  background:rgba(26,140,255,0.2);color:var(--live);font-size:20px;
  transition:background .18s;
}
.feat:hover .ic{background:rgba(26,140,255,0.32);}
.ft-txt{display:flex;flex-direction:column;gap:8px;}
/* card type is shared with the section 05 trio — see .tri h4 / .tri p */
.feat h4,.tri h4{
  margin:0;font-family:var(--mono);font-weight:400;
  font-size:clamp(13px,1.06vw,16px);line-height:1.5;letter-spacing:.01em;
  text-transform:uppercase;color:var(--ink);
}
.feat p,.tri p{
  margin:0;font-family:var(--sans);font-size:13px;line-height:1.5;
  color:rgba(255,255,255,0.5);
}

@media(max-width:900px){
  .feat-row{grid-template-columns:1fr;}
  .feat + .feat{border-left:0;border-top:1px solid var(--border-light);}
}
@media(max-width:620px){
  .feat-row{padding:0 var(--pad);}
}

/* ============================================================
   SECTION 04 · STOP GUESSING, START ASKING (Figma 164-4152)
   Mirror of section 01: graphic 630x504 on the left at var(--pad),
   label pinned top-right, copy block centred against the frame.
   ============================================================ */
section.sq{padding:clamp(28px,3.2vw,48px) 0;border-top:1px solid var(--line-2);}
.sq-grid{
  display:grid;
  grid-template-columns:minmax(0,630fr) minmax(0,602fr);
  gap:clamp(32px,7.94vw,120px);
  align-items:stretch;
  padding:0 var(--pad);
}
.sq-copy{position:relative;display:grid;}
.sq-copy .st-label{position:absolute;top:0;right:0;}
.sq-text{align-self:center;}
.sq-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,3.18vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
  max-width:16ch;
}
.sq-body{
  margin:24px 0 0;max-width:560px;
  font-family:var(--sans);font-size:14px;line-height:1.45;color:rgba(255,255,255,0.62);
}

.sq-visual{margin:0;}
.sq-frame{
  position:relative;aspect-ratio:630/504;
  padding:clamp(18px,2.1vw,32px);
  background-image:radial-gradient(rgba(255,255,255,0.07) 1px,transparent 1px);
  background-size:16px 16px;background-position:8px 8px;
}
.sq-frame .corners{inset:0;}
.sq-frame .corners i{width:16px;height:16px;}
.sq-frame .corners i:nth-child(n){border-color:rgba(255,255,255,0.4);}

/* ---------- the thread ---------- */
.ask{
  height:100%;overflow:hidden;
  padding:0 clamp(16px,2.1vw,32px) 12px;
  display:flex;flex-direction:column;justify-content:flex-end;
  /* older turns fade out as they leave the top rather than being cut off */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 88px,#000 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 88px,#000 100%);
}
.ask-thread{display:flex;flex-direction:column;gap:14px;}

.ask-msg{display:flex;flex-direction:column;gap:6px;max-width:78%;}
.ask-msg .who{
  font-family:var(--mono);font-size:9px;letter-spacing:1.2px;text-transform:uppercase;
  color:rgba(255,255,255,0.35);
}
.ask-msg p{
  margin:0;font-family:var(--sans);font-size:14px;line-height:1.5;
  padding:12px 16px;
}
/* you, on the right — the same light-white plate as the rest of the page */
.ask-msg.q{align-self:flex-end;align-items:flex-end;}
.ask-msg.q p{
  background:rgba(255,255,255,0.06);border:1px solid var(--line-2);color:var(--ink);
  /* frosted like every other light plate on the page, so the dot field behind
     it reads as a wash rather than showing through the bubble */
  backdrop-filter:blur(30px) saturate(120%);-webkit-backdrop-filter:blur(30px) saturate(120%);
}
/* Earth, on the left */
.ask-msg.a{align-self:flex-start;}
.ask-msg.a p{background:var(--live);border:1px solid var(--live);color:#fff;}

/* typewriter caret while a question is being written */
.ask-msg.q .car{
  display:inline-block;width:1px;height:1em;margin-left:2px;
  background:var(--ink);vertical-align:-2px;
  animation:apCaret 1.1s steps(1) infinite;
}
/* the answer thinks before it lands */
.ask-msg.a .dots{display:inline-flex;align-items:center;gap:5px;height:21px;}
.ask-msg.a .dots i{width:5px;height:5px;border-radius:50%;background:rgba(255,255,255,0.85);
  animation:sqThink 1.2s ease-in-out infinite;}
.ask-msg.a .dots i:nth-child(2){animation-delay:.15s;}
.ask-msg.a .dots i:nth-child(3){animation-delay:.3s;}
@keyframes sqThink{0%,100%{opacity:.35;transform:translateY(0);}50%{opacity:1;transform:translateY(-2px);}}
/* each bubble rises into the thread */
.ask-msg.in{animation:sqRise .32s cubic-bezier(.22,.9,.26,1) both;}
@keyframes sqRise{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}

@media(max-width:900px){
  .sq-grid{grid-template-columns:1fr;gap:32px;}
  .sq-visual{order:2;}
  .sq-title{max-width:none;}
  .sq-copy .st-label{position:static;margin-bottom:24px;}
  .ask-msg{max-width:88%;}
}
@media(prefers-reduced-motion:reduce){
  .ask-msg.in,.ask-msg.a .dots i,.ask-msg.q .car{animation:none;}
}

/* ============================================================
   SECTION 05 · BUILT FOR THE AI ERA
   Same construction as section 02 — head band, a ruled stage with
   the dot field, then a full-bleed row of supporting points on the
   section 03 card rhythm.
   ============================================================ */
section.sn{padding:0;border-top:1px solid var(--line-2);}
.sn-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:clamp(32px,5vw,80px);
  padding:clamp(28px,3.2vw,48px) var(--pad);
}
.sn-copy{min-width:0;}
.sn-copy .st-label{margin-bottom:24px;}
.sn-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,3.18vw,48px);letter-spacing:-0.06em;line-height:1.1;color:#fff;
}
.sn-body{
  margin:0;flex:none;width:min(360px,42vw);text-align:justify;
  font-family:var(--sans);font-size:14px;line-height:1.45;color:rgba(255,255,255,0.62);
}
.sn-stage{
  border-top:1px solid var(--border-light);border-bottom:1px solid var(--border-light);
  padding:0 var(--frame);
}
.sn-graphic{
  display:grid;place-items:center;
  padding:clamp(28px,3.8vw,58px) 0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.045) 1px, transparent 1px);
  background-size:32px 32px;
}

/* ---------- the MCP session ---------- */
.mcp{
  width:100%;max-width:680px;overflow:hidden;
  background:rgba(255,255,255,0.06);
  backdrop-filter:blur(30px) saturate(120%);-webkit-backdrop-filter:blur(30px) saturate(120%);
  border:1px solid var(--line-2);
}
.mcp-bar{
  display:flex;align-items:center;gap:16px;
  padding:0 16px;height:40px;border-bottom:1px solid var(--line);
  background:rgba(255,255,255,0.02);
}
.mcp-bar .dots{display:inline-flex;gap:6px;flex:none;}
.mcp-bar .dots i{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,0.18);}
.mcp-bar .crumb{
  flex:1;min-width:0;font-family:var(--mono);font-size:10px;letter-spacing:1.1px;
  text-transform:uppercase;color:rgba(255,255,255,0.5);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.mcp-bar .crumb b{color:rgba(255,255,255,0.28);font-weight:400;margin:0 4px;}
.mcp-bar .conn{
  display:inline-flex;align-items:center;gap:6px;flex:none;
  font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;color:#17E57E;
}
.mcp-bar .conn i{width:4px;height:4px;background:#17E57E;animation:pip 2.4s ease-in-out infinite;}

.mcp-body{padding:22px;display:flex;flex-direction:column;gap:20px;overflow:hidden;}
.mcp-turn{display:flex;flex-direction:column;gap:8px;}
.mcp-turn .who{
  font-family:var(--mono);font-size:9px;letter-spacing:1.2px;text-transform:uppercase;
  color:rgba(255,255,255,0.35);
}
.mcp-turn p{
  margin:0;font-family:var(--sans);font-size:14.5px;line-height:1.55;
  color:rgba(255,255,255,0.55);max-width:64ch;
}
.mcp-turn.ai p{color:var(--ink);}
.mcp-turn.ai p b{font-weight:500;color:#fff;}

/* the profile the agent rendered back into the chat */
.mcp-card{
  display:flex;align-items:center;gap:14px;margin-top:4px;
  padding:14px 16px;border:1px solid var(--border-light);
  background:rgba(255,255,255,0.03);
}
.mcp-card .av{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:var(--live);color:#fff;font-family:var(--mono);font-size:12px;
}
.mcp-card .meta{display:flex;flex-direction:column;gap:4px;min-width:0;}
.mcp-card .meta b{font-family:var(--sans);font-size:15px;font-weight:500;color:#fff;}
.mcp-card .meta em{
  font-family:var(--mono);font-style:normal;font-size:9.5px;letter-spacing:1px;
  text-transform:uppercase;color:rgba(255,255,255,0.42);
}
.mcp-card .mcp-tick{
  margin-left:auto;flex:none;width:24px;height:24px;display:grid;place-items:center;
  background:rgba(23,229,126,0.16);color:#17E57E;font-size:14px;
}

/* what the agent actually did, not just what it said */
.mcp-acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px;}
.mcp-acts .act{
  display:inline-flex;align-items:center;gap:7px;padding:6px 10px;
  border:1px solid var(--border-light);background:rgba(255,255,255,0.03);
  font-family:var(--mono);font-size:9.5px;letter-spacing:1px;text-transform:uppercase;
  color:rgba(255,255,255,0.6);
}
.mcp-acts .act i{font-size:13px;color:var(--live);}

/* --- the session replays itself --- */
.mcp-turn.pending{display:none;}
.mcp-turn.in{animation:mcpRise .34s cubic-bezier(.22,.9,.26,1) both;}
@keyframes mcpRise{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}
.mcp-turn .think{display:inline-flex;align-items:center;gap:5px;height:22px;}
.mcp-turn .think i{
  width:5px;height:5px;border-radius:50%;background:rgba(255,255,255,0.6);
  animation:sqThink 1.2s ease-in-out infinite;
}
.mcp-turn .think i:nth-child(2){animation-delay:.15s;}
.mcp-turn .think i:nth-child(3){animation-delay:.3s;}
@media(prefers-reduced-motion:reduce){
  .mcp-turn.pending{display:flex;}
  .mcp-turn.in,.mcp-turn .think i{animation:none;}
}

/* ---------- the three points ---------- */
.sn-trio{
  display:grid;grid-template-columns:repeat(3,1fr);
  padding:0 var(--frame);
}
/* even padding top and bottom — the 48px bottom the frame specified read as
   bottom-heavy once the cards were built */
.tri{padding:clamp(24px,2.65vw,40px) clamp(20px,2.12vw,32px);}
.tri + .tri{border-left:1px solid var(--border-light);}
.tri h4{margin-bottom:10px;}

@media(max-width:900px){
  .sn-head{flex-direction:column;gap:24px;}
  .sn-body{width:100%;text-align:left;}
  .sn-trio{grid-template-columns:1fr;}
  .tri + .tri{border-left:0;border-top:1px solid var(--border-light);}
}
@media(max-width:620px){
  .sn-stage,.sn-trio{padding:0 var(--pad);}
}

/* ---------- Jupiter section 01 schematic: one trigger runs straight to a
   send while five live signals hit a wall the flow never looks past.
   Cards use the same frosted construction as the Earth section 01 cards:
   an opaque base under a light white wash, so the grid stops at the edge. */
.jf .jf-node .bg{fill:var(--bg);stroke:none;}
.jf .jf-node .fc{fill:rgba(255,255,255,0.06);stroke:var(--line-2);stroke-width:1;}
.jf .jf-node .pip{stroke:none;fill:#FFB31A;animation:fgBlink 3.2s ease-in-out infinite;}
.jf .jf-node .pip.live{fill:var(--live);}
.jf .send .pip{animation-delay:.8s;}
.jf .jf-node .k{
  font-family:var(--mono);font-size:10px;letter-spacing:1.2px;
  text-transform:uppercase;fill:rgba(255,255,255,0.55);
}
.jf .jf-node .v{font-family:var(--sans);font-size:15px;fill:var(--ink);}

/* the one path the tool actually reads */
.jf .jf-line .f{
  fill:none;stroke:rgba(26,140,255,0.85);stroke-width:1.25;stroke-dasharray:4 5;
  animation:fgRun 1.6s linear infinite;
}
.jf .jf-taps rect{fill:var(--live);}
.jf .jf-packets .p{
  fill:var(--ink);offset-rotate:0deg;
  offset-path:path('M 212 92 H 428');
  animation:fgPacket 2.4s cubic-bezier(.5,0,.7,1) infinite;
  opacity:0;
}
/* the wall, and the five signals that never get past it */
.jf .jf-sep{
  font-family:var(--mono);font-size:10px;letter-spacing:1.4px;text-transform:uppercase;
  text-anchor:middle;fill:rgba(255,255,255,0.35);
}
.jf .jf-wall{fill:none;stroke:var(--border-light);stroke-width:1;stroke-dasharray:6 5;}
.jf .jf-stubs .s{
  fill:none;stroke:rgba(255,255,255,0.16);stroke-width:1;stroke-dasharray:3 4;
}
.jf .jf-breaks path{
  fill:none;stroke:rgba(255,255,255,0.5);stroke-width:1.25;stroke-linecap:round;
  animation:fgBlink 3.2s ease-in-out infinite;
}
.jf .jf-breaks path:nth-child(2){animation-delay:.35s;}
.jf .jf-breaks path:nth-child(3){animation-delay:.7s;}
.jf .jf-breaks path:nth-child(4){animation-delay:1.05s;}
.jf .jf-breaks path:nth-child(5){animation-delay:1.4s;}

/* real records, just never read — dimmed rather than drawn as empty outlines */
.jf .ghost{opacity:.62;animation:jfIdle 4.8s ease-in-out infinite;}
.jf .ghost .v{fill:rgba(255,255,255,0.72);}
.jf .g2{animation-delay:.5s;} .jf .g3{animation-delay:1s;}
.jf .g4{animation-delay:1.5s;} .jf .g5{animation-delay:2s;}
@keyframes jfIdle{0%,100%{opacity:.55;}50%{opacity:.78;}}

/* ---------- Jupiter: the builder window reuses the .app shell ---------- */
.flowwin .flow{padding:clamp(16px,2vw,28px) clamp(16px,2vw,28px) 0;}
.flowwin .flow svg{display:block;width:100%;height:auto;}
/* The diagram keeps a 560px floor — its node labels are 10px and shrinking it
   to a phone would make them unreadable — so below that it scrolls sideways.
   Left to itself that just looks like a cut-off drawing, so the panel fades at
   the edge and says so. */
.flowwin .flow{overscroll-behavior-x:contain;}

.flow-cap{
  padding:clamp(14px,1.6vw,22px) clamp(16px,2vw,28px) clamp(18px,2vw,26px);
  font-family:var(--mono);font-size:10px;line-height:1.7;letter-spacing:1px;
  text-transform:uppercase;color:rgba(255,255,255,0.38);
}

/* the live planets already navigate — make that legible before the click */
/* The planet SVG is re-rendered every frame while it spins, so a mousedown on
   a path is destroyed before the mouseup and the browser never fires a click —
   only the (static) name text was clickable. Taking the body out of hit-testing
   lets the anchor itself receive both events, so the whole column is clickable. */
.orb.link .plt{pointer-events:none;}

/* the flow renders at ~1.5x its viewBox, so type is sized down to land at the
   same 10px label / 15px value as every other graphic on the site */
.flow .lb{font-size:6.5px;letter-spacing:.08em;}
.flow .nv{font-size:10px;letter-spacing:.02em;}
/* the live path: trigger fires, the profile check unlocks the VIP branch */
.flow .ln{stroke-dasharray:3 4;animation:fgRun 1.9s linear infinite;}
.flow .nd.tr{animation:flPulse 3.2s ease-in-out infinite;}
@keyframes flPulse{0%,100%{stroke:var(--live);}50%{stroke:rgba(26,140,255,0.45);}}
.flow .fl-packets .fp{fill:var(--ink);offset-rotate:0deg;opacity:0;}
.flow .fp1{
  offset-path:path('M 220 50 H 290');
  animation:fgPacket 2.6s cubic-bezier(.5,0,.7,1) infinite;
}
.flow .fp2{
  offset-path:path('M 470 50 H 540');
  animation:fgPacket 2.6s cubic-bezier(.5,0,.7,1) infinite .5s;
}
@media(prefers-reduced-motion:reduce){
  .flow .ln,.flow .nd.tr,.flow .fl-packets .fp{animation:none;}
}

/* ============================================================
   MOBILE NAV + SMALL-SCREEN SCALE
   Kept last so the frame variables win wherever they are used.
   ============================================================ */

/* ---------- hamburger + slide-down panel ---------- */
/* Built by site.js from whatever links the page's own header carries, so the
   panel stays in sync per page instead of being duplicated in four files. */
.nav-toggle{
  display:none;position:relative;z-index:2;
  width:40px;height:40px;margin-right:-10px;padding:0;
  align-items:center;justify-content:center;
  background:none;border:0;color:var(--ink);cursor:pointer;
}
.nav-toggle span{
  position:absolute;left:11px;width:18px;height:1px;background:currentColor;
  transition:transform .28s cubic-bezier(.4,0,.2,1),opacity .18s ease;
}
.nav-toggle span:nth-child(1){transform:translateY(-3px);}
.nav-toggle span:nth-child(2){transform:translateY(3px);}
.nav-toggle[aria-expanded="true"] span:nth-child(1){transform:rotate(45deg);}
.nav-toggle[aria-expanded="true"] span:nth-child(2){transform:rotate(-45deg);}

/* Full-screen sheet under the 64px bar (the bar stays for the ×) — dvh so
   phone browser chrome collapsing doesn't leave a strip at the bottom.
   top:64px, not 65: the header's 1px bottom border sits at 64-65, and leaving
   the sheet below it let the blurred page show through as a seam. The sheet
   starts at 64 and covers that row itself. Solid --bg rather than a translucent
   blur so it matches the bar exactly (see the :has rule below). */
.nav-panel{
  position:fixed;left:0;right:0;top:64px;height:calc(100dvh - 64px);z-index:59;
  overflow-y:auto;
  display:flex;flex-direction:column;
  background:var(--bg);
  padding:8px var(--pad) 0;
  transform-origin:top;
  /* animating clip rather than height keeps the rows from reflowing mid-open */
  clip-path:inset(0 0 100% 0);opacity:0;visibility:hidden;
  transition:clip-path .34s cubic-bezier(.22,.9,.26,1),opacity .2s ease,visibility 0s .34s;
}
.nav-panel.open{clip-path:inset(0 0 0 0);opacity:1;visibility:visible;transition-delay:0s;}
.nav-panel a{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:18px 0;border-bottom:1px solid var(--border-light);
  font-family:var(--mono);font-size:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink);
}
.nav-panel a:last-of-type{border-bottom:0;}
/* The serro barcode closes the sheet under the CTA, matching the page's own
   strip: the element bleeds out of the panel padding to the screen edge so its
   top rule runs the full width, while background-clip pulls the bars in to
   stop at the stripe — the same geometry the hero barcode has on the page. */
.nav-panel::after{
  content:"";flex:none;height:calc(38px + env(safe-area-inset-bottom,0px));
  margin:18px calc(-1 * var(--pad)) 0;
  border-top:1px solid var(--line);
  padding:0 var(--frame);
  background:repeating-linear-gradient(90deg,rgba(255,255,255,0.22) 0 1px,transparent 1px 12px);
  background-clip:content-box;
  opacity:.5;
}

/* the page you are on: a small blue pip ahead of the label, same vocabulary
   as the eyebrow dots and status pills — the label itself stays cream.
   Absolutely positioned so it doesn't join the row's space-between flexing. */
/* :not(.np-cta) — on /signup the Start free button IS the current page, and the
   active treatment (blue label + pip) painted blue-on-blue inside the filled
   button. A filled CTA doesn't need a "you are here" marker anyway. */
.nav-panel a[aria-current="page"]:not(.np-cta){position:relative;padding-left:16px;color:var(--live);}
.nav-panel a[aria-current="page"]:not(.np-cta)::before{
  content:"";position:absolute;left:0;top:50%;margin-top:-2.5px;
  width:5px;height:5px;background:var(--live);
}
.nav-panel a:nth-last-of-type(2){border-bottom:0;margin-bottom:24px;}
/* margin-top:auto pins the CTA to the sheet's bottom edge on tall screens;
   on short ones it just follows the list — the nth-last rule keeps a floor
   under the gap once the auto margin has no space to absorb */
.nav-panel .np-cta{
  margin-top:auto;flex:none;justify-content:center;border:1px solid var(--live);background:var(--live);
  color:#fff;font-size:14px;letter-spacing:.06em;padding:18px 22px;
}
@media(prefers-reduced-motion:reduce){
  .nav-panel{transition:opacity .01s,visibility 0s;}
}

/* ---------- 900: the desktop link row runs out of room ---------- */
/* At 768 the row wrapped onto two lines and pushed the header into the hero.
   Everything moves into the panel here rather than being hidden outright —
   under the old rule a phone had no way to reach Earth or Jupiter at all. */
@media(max-width:900px){
  .nav .links{display:none;}
  .nav-toggle{display:inline-flex;}
  .nav{gap:12px;}
}
@media(min-width:901px){
  .nav-panel{display:none;}
}

/* While the sheet is open the bar stops being a translucent blur of the page
   and becomes the same solid surface, so the two read as one panel with no
   seam and nothing showing through. The blur pseudo goes with it. */
header.site:has(.nav-panel.open){
  /* position:fixed, not sticky. The scroll lock puts overflow:hidden on body,
     which makes body its own scroll container — a sticky header then sticks to
     the TOP OF THE DOCUMENT rather than the viewport, so opening the menu part
     way down the page dropped the bar out of view and showed the page through
     the 64px above the sheet. Fixed is independent of the scroll container.
     Taking it out of flow is invisible here: the bar plus the sheet cover the
     viewport, and the scroll position is untouched. */
  position:fixed;top:0;left:0;right:0;
  background:var(--bg);
  border-bottom-color:transparent;
}
header.site:has(.nav-panel.open)::before{display:none;}

/* ---------- 640: phone. Pull the page frame in ---------- */
/* --hatch + --rail are 48px a side by design. On a 390px screen that plus the
   gutter spent a third of the viewport on decoration, so the frame scales down
   with the screen. --frame and --pad are calc()s over these, so everything that
   aligns to the page edge follows automatically. */
@media(max-width:1060px){
  :root{--hatch:18px;--rail:18px;}
}
@media(max-width:640px){
  :root{--hatch:10px;--rail:12px;--gut:14px;}
  .hero-main{padding:40px var(--pad) 32px;}
  .hcopy{gap:18px;}
  .hbody{font-size:14.5px;line-height:1.42;}
  /* 6.5vw bottoms out at the 34px floor well before phone width, so the
     headline stopped growing while the column kept widening. Track the column
     instead — "One unified profile." is the widest line and this keeps it on
     one line down to 320. 42px at 640 hands back to the 6.5vw curve cleanly. */
  .h-hero{font-size:min(10.4vw,42px);}
  .stitch-head{gap:16px;}
  .fb-top{gap:18px;}
  .fb-top img{width:118px;}
  /* 15px-tall text links are a poor phone target — pad the row, not the type */
  .fm-links{gap:4px;}
  .fm-links a{padding:9px 0;}
  /* the loader tagline is set on one nowrap-ish line; bound it to the screen */
  #loader .ld-tag{left:var(--gut);right:3vw;text-align:right;bottom:40px;}
}

/* ---------- 400: the smallest phones still in circulation ---------- */
@media(max-width:400px){
  :root{--hatch:8px;--rail:10px;--gut:12px;}
  .btn.lg{font-size:12px;padding:15px 14px;}
  .stg .ghost{font-size:88px;}
  /* "One profile knows your customer" is nowrap and ran 6px past a 320 screen */
  .st-kicker .kp{font-size:11px;letter-spacing:1px;padding:8px 11px;}
}

/* ============================================================
   PRODUCT PAGES — phone tuning
   The Earth/Jupiter product window and the MCP session are dense
   chrome mock-ups; at phone width they need their own gutters.
   ============================================================ */
@media(max-width:620px){
  /* .sn-stage already does this — the app window band should match, or the two
     mock-ups sit on different left edges down the same page */
  .sf-stage{padding:0 var(--pad);}
}
@media(max-width:480px){
  /* name + status tags shared one line, which squeezed "Jordan Avery" down to
     about 50px on a 320 screen. Let the tags drop to their own row instead. */
  .ap-head{flex-wrap:wrap;gap:10px;}
  .ap-id{flex:1 1 100%;}
  .app-main{padding:16px 14px 76px;}
  .app-ask{width:calc(100% - 24px);padding:10px 10px 10px 14px;}

  .mcp-body{padding:16px;gap:16px;}
  .mcp-card{padding:12px;gap:10px;}
  .mcp-card .av{width:32px;height:32px;}

  /* the product hero CTA is a single full-width button here */
  .ph-ctas .btn{width:100%;}
}

/* ============================================================
   SECTION RHYTHM — tablet and mobile
   Each section carried its own top/bottom air on desktop (48 on
   the hero, 26/60 on the pinned stack, 48/48 on the universe, a
   3.6vw clamp on the closer), which was tuned per-section against
   the 1512 frame. Stacked, those differences stop reading as
   composition and start reading as an uneven page, so every
   section top and bottom comes off one variable here.
   Horizontal spacing is already one system and is left alone:
   text sits on --pad, panel and rule edges sit on --frame.
   ============================================================ */
@media(max-width:1060px){
  :root{--sec-y:clamp(36px,5vw,52px);}
  /* the wordmark is min(1420px,94vw) centred, so its right edge sits at 3vw —
     the fixed 40px offset left the tagline hanging past it on tablet */
  #loader .ld-tag{right:3vw;}
  #hero{padding-top:var(--sec-y);}
  .stitch-pin{padding:var(--sec-y) 0;}
  section.uni-sec{padding:var(--sec-y) 0;}
  /* the closer's air lives on .cta-frame, since that is what the corner
     brackets are pinned to — the wrapper only carries the side gutter */
  /* air on BOTH sides of the corner brackets: .cta-inner keeps the frame off
     the section edge (the brackets were sitting flush against it), and the
     frame's own padding grows so the whole closer stands taller */
  .cta-inner{padding:clamp(28px,4.5vw,48px) var(--pad);}
  .cta-frame{padding:clamp(52px,9vw,88px) clamp(20px,3vw,40px);}
  .foot-col{padding:var(--sec-y) var(--gut);}
}
@media(max-width:640px){
  :root{--sec-y:32px;}
  .cta-inner{padding:24px var(--gut);}
  .cta-frame{padding:48px 16px;}
  /* brackets ride the content edge on phones — at inset:0 they hugged the
     blue panel's own corners and read as part of the section, not the frame */
  .cta-corners{inset:0 16px;}
}

/* ---------- section subtitles, tablet + mobile ----------
   One treatment for every note paragraph that rides a section title
   (.uni-note, .cta-body, .sp-body, .sf-body, .sq-body, .sn-body), matched
   proportionally to the hero subtitle: same 1.45 leading on tablet with sizes
   untouched, and on mobile the same ~10% step the hero takes (16→14.5, 14→13,
   13-px note joins the 13px floor). Justified desktop margin notes go
   left-ragged once they span the full column. */
@media(max-width:1060px){
  .uni-note,.cta-body,.sp-body,.sf-body,.sq-body,.sn-body{line-height:1.45;}
  /* the 16px-class bodies track the hero subtitle exactly (15px at tablet) —
     leaving them at 16 made the closer's paragraph read a step bigger than
     the hero copy it should echo. The stage-card paragraphs join the same
     tier so cards and sections carry one subtitle voice. */
  .cta-body,.sp-body,.stg p{font-size:15px;line-height:1.45;}
  .uni-note{text-align:left;}
}
@media(max-width:640px){
  .cta-body,.sp-body,.stg p{font-size:14.5px;line-height:1.42;}
  .uni-note,.sf-body,.sq-body,.sn-body{font-size:13px;line-height:1.42;}
}

/* Card families live in containers inset to --frame, with --gut inside the
   cell. Collapsing --frame (single-stripe mode) stretched their rules to the
   stripe but dragged the cell text toward the edge with them — pad the cell
   by what the container gave up, so card text keeps sitting on the --pad line
   with all the other copy. Kept last in the sheet: the per-card base and
   responsive rules use shorthand padding, and this longhand must outrank them.
*/
@media(max-width:1060px){
  .stats .stat,.stg,.feat,.tri,.foot-col{
    padding-left:calc(var(--pad) - var(--frame));
    padding-right:calc(var(--pad) - var(--frame));
  }
}

/* footer utility links (Log in / Privacy / Terms) — tablet and phone run
   smaller and tighter; last in the sheet so it outranks the earlier
   breakpoint blocks that padded these rows */
@media(max-width:1060px){
  .fm-links{gap:0;}
  .fm-links a{font-size:10.5px;padding:6px 0;}
}

/* footer brand block, tablet + phone: more air above the wordmark, and the
   strapline joins the section-subtitle tier in its muted footer colour */
@media(max-width:1060px){
  .foot-brand{padding-top:calc(var(--sec-y) + 16px);}
  .fb-top p{font-size:15px;line-height:1.45;color:rgba(255,255,255,0.5);}
}
@media(max-width:640px){
  .fb-top p{font-size:14.5px;line-height:1.42;}
}

/* The legal line's layout box already bottom-aligns with the social buttons,
   but its INK doesn't: 10px caps have no descenders, so the glyphs stop ~3px
   short of the box edge while the filled circles print right to theirs. Shift
   the baseline down by the descent so the two read as one line. Desktop only —
   stacked footers don't share a bottom edge with the buttons. */
@media(min-width:1061px){
  .fb-legal{transform:translateY(3px);}
}

/* ============================================================
   PRODUCT PAGES — matched to the homepage's small-screen system
   Same --sec-y rhythm, same headline curve, same subtitle tier.
   Appended last so it outranks the per-section responsive blocks.
   ============================================================ */
@media(max-width:1060px){
  /* vertical rhythm — every product section band rides --sec-y like the
     homepage sections do */
  .ph-copy{padding:var(--sec-y) 0;}
  section.sp{padding:var(--sec-y) 0;}
  section.sq{padding:var(--sec-y) 0;}
  .sf-head,.sn-head,.sg-head{padding:var(--sec-y) var(--pad);}

  /* section titles pick up the homepage's steeper tablet curve (4.2vw) —
     at 3.18vw they sat pinned to the 26px floor across the whole range */
  .sp-title,.sf-title,.sg-title,.sq-title,.sn-title{font-size:clamp(26px,4.2vw,48px);}

  /* product hero subtitle joins the hero-subtitle tier */
  .ph-body{font-size:15px;line-height:1.45;}
}
@media(max-width:640px){
  /* product hero headline tracks the column like the homepage h1 */
  .ph-title{font-size:min(10.4vw,42px);margin-top:18px;}
  .ph-body{font-size:14.5px;line-height:1.42;margin-top:18px;}
}

/* section 01's eyebrow is corner-pinned for the two-column desktop layout —
   static once the grid stacks, or it prints straight over the title. Lives at
   the sheet tail because the base absolute rule comes after the .ph block. */
@media(max-width:900px){
  .sp-copy .st-label{position:static;margin:0 0 24px;}
}

/* the "1 person · 4 records · 0 agree" tally rides the schematic's top frame
   band on desktop; in the stacked layout it floats as a stray caption */
@media(max-width:900px){
  .sp-frame .fg-tally{display:none;}
}

/* product windows (Earth app, MCP session, Jupiter flow) align to the content
   column on tablet/mobile — but the stage's grid backdrop keeps running to the
   stripe. The band stays frame-anchored (grid paints across its padding) and
   the inner wrapper carries the difference, so only the WINDOW moves in. */
@media(max-width:1060px){
  .sf-stage,.sn-stage{padding:0 var(--frame);}
  .sf-graphic,.sn-graphic{
    padding-left:calc(var(--pad) - var(--frame));
    padding-right:calc(var(--pad) - var(--frame));
  }
}

/* feature/trio card rows stay frame-anchored at phone width too: their rules
   keep running to the stripe, and the cells' (--pad - --frame) inner padding
   is what puts the text on the content line. The earlier 620 rule that moved
   the ROW to var(--pad) stacked the two and pushed card copy past the line. */
@media(max-width:620px){
  .feat-row,.sn-trio{padding:0 var(--frame);}
}

/* "What you get" cards, tablet: continuous two-up pairing across the whole
   grid. The rows-of-three markup serves the desktop 3-col layout, so here the
   rows dissolve (display:contents) and .sg-grid itself lays all cards out in
   pairs — with only the very last card going full width, and only when the
   count is odd (rows are uniform 3s, so an odd row-count means an odd total:
   Earth's 9 gets 4 pairs + 1 full, Jupiter's 6 gets clean pairs). */
@media(min-width:621px) and (max-width:900px){
  .sg-grid{display:grid;grid-template-columns:repeat(2,1fr);padding:0 var(--frame);}
  .feat-row{display:contents;}
  .feat{border-top:1px solid var(--border-light);border-left:0;}
  .feat-row:first-child .feat:nth-child(-n+2){border-top:0;}
  /* right-column cards: c2 of odd rows, c1/c3 of even rows */
  .feat-row:nth-child(odd) .feat:nth-child(2),
  .feat-row:nth-child(even) .feat:nth-child(1),
  .feat-row:nth-child(even) .feat:nth-child(3){border-left:1px solid var(--border-light);}
  .feat-row:last-child:nth-child(odd) .feat:last-child{grid-column:1/-1;border-left:0;}
}

/* the ask-Earth chat frame: the desktop 630/504 ratio leaves it ~260px tall on
   a phone, room for barely two bubbles — give it a taller portrait stage */
@media(max-width:640px){
  .sq-frame{aspect-ratio:auto;height:clamp(340px,95vw,400px);}
}

/* ---------- Jupiter flow, phone: vertical spine ----------
   The 748-wide SVG swaps for a top-to-bottom HTML read of the same flow —
   trigger, branch, and the two side outcomes hanging off a dashed spine. */
.flow-m{display:none;}
@media(max-width:700px){
  .flowwin .flow{display:none;}
  .flow-m{display:flex;flex-direction:column;padding:20px 16px 6px;}
  .fm-node{
    position:relative;border:1px solid var(--line-2);background:rgba(255,255,255,0.06);
    padding:10px 14px;display:flex;flex-direction:column;gap:3px;
  }
  .fm-node em{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;color:rgba(255,255,255,0.42);}
  .fm-node b{font-family:var(--mono);font-weight:500;font-size:12px;letter-spacing:.02em;text-transform:uppercase;color:var(--ink);}
  .fm-node.tr{border-color:var(--live);background:rgba(26,140,255,0.14);}
  /* dashed spine segment with the edge label beside it */
  .fm-edge{
    position:relative;margin-left:28px;padding:9px 0 9px 14px;min-height:32px;
    display:flex;align-items:center;
    font-family:var(--mono);font-size:9px;letter-spacing:1px;text-transform:uppercase;color:rgba(255,255,255,0.42);
  }
  .fm-edge::before{
    content:"";position:absolute;left:0;top:0;bottom:0;width:1px;
    background-image:linear-gradient(to bottom,rgba(255,255,255,0.34) 0 4px,transparent 4px 8px);
    background-size:1px 8px;
  }
  /* side outcomes indent off the spine with a dashed elbow, and the spine
     keeps running past them to the next step */
  .fm-node.side{margin-left:46px;}
  .fm-node.side::before{
    content:"";position:absolute;left:-18px;top:50%;width:17px;height:1px;
    background-image:linear-gradient(to right,rgba(255,255,255,0.34) 0 4px,transparent 4px 8px);
    background-size:8px 1px;
  }
  .fm-node.side::after{
    content:"";position:absolute;left:-18px;top:-6px;bottom:-6px;width:1px;
    background-image:linear-gradient(to bottom,rgba(255,255,255,0.34) 0 4px,transparent 4px 8px);
    background-size:1px 8px;
  }
}

/* social buttons hidden — the X/LinkedIn hrefs are placeholders with no real
   profiles behind them yet. Markup stays; delete this rule to bring them back. */
.fm-social{display:none;}

/* ============================================================
   SIGN-UP PAGE (/signup) — "Start free"
   Two-column split: the pitch on the left, the form on the right,
   divided by a full-height hairline. Fields are underline-only with
   the label riding the line as a small chip. Shares the .f-* controls
   with the demo modal; every hook the page script reads is untouched.
   ============================================================ */
.su-split{
  display:grid;grid-template-columns:1fr 1fr;
  align-items:stretch;
  /* derive the inset from --pad, not --frame: below 1060 --frame collapses to
     the hatch width alone, so frame + gut stopped equalling --pad and the
     column text drifted 10px inside the rest of the page's text line */
  margin:0 calc(var(--pad) - var(--gut));
}
.su-col{position:relative;padding:clamp(32px,3.2vw,48px) var(--gut);}
.su-col + .su-col{border-left:1px solid var(--border-light);}

/* single corner tick on the form column, per the frame */
.su-tick{
  position:absolute;top:clamp(32px,3.2vw,48px);right:var(--gut);
  width:16px;height:16px;pointer-events:none;
  border-top:1px solid rgba(255,255,255,0.55);
  border-right:1px solid rgba(255,255,255,0.55);
}

/* the two ruled bands that top and tail the split */
.su-band{margin:0 var(--frame);}
/* The bars band bleeds to the screen edge so its bottom rule runs the full
   width like the nav's does — the bars themselves are held back to the frame by
   padding + background-clip. The rule uses --line (the nav's border) rather than
   --strong, and the fade is baked into the gradient instead of an element
   opacity, which would have washed the border out with it. */
.su-band-bars{
  margin:0;padding:0 var(--frame);
  height:56px;
  border-bottom:1px solid var(--line);
  background:repeating-linear-gradient(90deg,rgba(255,255,255,0.11) 0 1px,transparent 1px 12px);
  background-clip:content-box;
}
/* same full-bleed trick as the bars band: rule runs edge to edge, dots stay
   inside the frame. Dots brightened from 0.07 to 0.18 and grown to 1.5px —
   at 1px/0.07 they were effectively invisible against the page black. */
/* Figma 178:5243/5244: the band is inset to the frame, then the dot field sits
   inside a further 32px horizontal / 24px vertical inset — so the dots occupy
   the middle of the band rather than running edge to edge. 48 + 32 is --pad,
   which puts them on the same line as the page's text.
   Top rule is --strong to match the footer rule closing the band below it. */
.su-band-dots{
  margin:0;
  padding:24px var(--pad);
  height:120px;
  border-top:1px solid var(--strong);
  background-image:radial-gradient(rgba(255,255,255,0.18) 1.5px,transparent 1.5px);
  background-size:16px 16px;background-position:8px 8px;
  /* origin as well as clip: background-origin defaults to padding-box, so the
     dot grid was laid out from the padding edge and merely clipped to the
     content box — the first full dot landed wherever the 16px grid happened to
     fall, reading as a wider inset than --pad. */
  background-origin:content-box;
  background-clip:content-box;
}

/* ---------- left: the pitch ---------- */
/* the column gap now spaces the three BLOCKS (title / stats / contact); the
   eyebrow-title-sub run has its own tighter gap inside .su-head */
.su-left{display:flex;flex-direction:column;gap:clamp(36px,3.6vw,52px);}
.su-head{display:flex;flex-direction:column;gap:24px;}
.su-eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:10px;line-height:1.3;letter-spacing:1.2px;
  /* white label, blue pip — same construction as the product pages' .ph-crumb */
  text-transform:uppercase;color:#fff;
}
.su-eyebrow i{width:4px;height:4px;flex:none;background:var(--live);}
.su-title{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(32px,4.2vw,56px);letter-spacing:-0.06em;line-height:1.04;color:#fff;
  max-width:14ch;
}
.su-sub{margin:0;font-family:var(--sans);font-size:15px;line-height:1.5;color:rgba(255,255,255,0.62);}

/* the three-up band, same ruled-cell construction as the homepage stats */
.su-steps{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--border-light);}
.su-step{padding:20px 18px;display:flex;flex-direction:column;gap:10px;min-width:0;}
.su-step + .su-step{border-left:1px solid var(--border-light);}
/* same construction as the homepage hero stats: scanlined blue numeral over a
   small mono caption */
.su-step b{
  font-family:var(--mono);font-weight:700;font-size:clamp(30px,2.6vw,38px);
  letter-spacing:-0.04em;line-height:1;color:var(--live);
  -webkit-mask-image:repeating-linear-gradient(180deg,#000 0 1.5px,transparent 1.5px 3px);
  mask-image:repeating-linear-gradient(180deg,#000 0 1.5px,transparent 1.5px 3px);
}
.su-step em{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:1.08px;
  text-transform:uppercase;line-height:1.45;color:#fff;}

/* no margin-top:auto — pinning the contact block to the bottom of the column
   left a much bigger gap under the stats row than above it. The column's own
   gap now sets both, so the stats sit evenly between the copy and the contact. */
.su-foot{display:flex;flex-direction:column;gap:14px;}
.su-foot p{margin:0;font-family:var(--sans);font-size:13.5px;line-height:1.55;color:rgba(255,255,255,0.5);}
/* same hover as .su-mail below — white, going blue */
.su-foot p a{color:#fff;transition:color .16s ease;}
.su-foot p a:hover{color:var(--live);}
.su-mail{
  align-self:flex-start;font-family:var(--mono);font-size:12px;letter-spacing:1px;text-transform:uppercase;
  color:#fff;transition:color .16s ease;
}
.su-mail:hover{color:var(--live);}

/* ---------- right: the form ---------- */
.su-right{display:flex;flex-direction:column;gap:28px;}
.su-formtitle{
  margin:0;font-family:var(--sans);font-weight:500;
  font-size:clamp(24px,2.4vw,32px);letter-spacing:-0.05em;line-height:1.1;color:#fff;
}
/* underline-only fields; the label rides the line in a small chip */
.su-form .f-form{gap:26px;}
.su-form .f-field{gap:0;}
.su-form .f-label{
  align-self:flex-start;
  padding:4px 8px;margin-bottom:2px;
  background:rgba(255,255,255,0.07);
  color:rgba(255,255,255,0.66);
}
/* the value sits inset from the field edge rather than flush against the focus
   outline, as on the reference form */
.su-form .f-input,.su-form .f-select{
  height:44px;padding:0 14px;
  border:0;border-bottom:1px solid var(--line-2);background-color:transparent;
  font-size:15px;
}
.su-form .f-select{padding-right:36px;background-position:right 14px center;}
.su-form .f-input:hover,.su-form .f-select:hover{border-bottom-color:var(--btn-line);}
.su-form .f-input:focus,.su-form .f-select:focus{
  border-bottom-color:var(--live);background-color:transparent;
}
.su-form .f-input.invalid{border-bottom-color:#FF8A8A;}
.su-form .f-error{margin-top:8px;}
.su-form .f-actions{padding-top:8px;}
.su-form .f-actions .btn{width:100%;}

/* sign-in method — two selectable cards */
.su-choice{display:flex;gap:12px;margin-top:10px;}
.su-opt{
  flex:1 1 0;min-width:0;position:relative;cursor:pointer;
  display:flex;flex-direction:column;gap:4px;
  padding:13px 14px;border:1px solid var(--line-2);
  transition:border-color .18s ease,background .18s ease;
}
.su-opt input{position:absolute;opacity:0;pointer-events:none;}
.su-opt b{font-family:var(--mono);font-weight:500;font-size:11px;letter-spacing:1px;
  text-transform:uppercase;color:var(--ink);}
.su-opt em{font-style:normal;font-family:var(--sans);font-size:12.5px;line-height:1.4;color:rgba(255,255,255,0.5);}
.su-opt:hover{border-color:var(--btn-line);}
.su-opt:has(input:checked){
  border-color:var(--live);
  background-color:rgba(26,140,255,0.08);
  background-image:repeating-linear-gradient(135deg,
    rgba(26,140,255,0.30) 0 1px, transparent 1px 6px);
}
.su-opt:has(input:focus-visible){outline:1px solid var(--live);outline-offset:2px;}

/* display:flex on .f-field outranks the UA's [hidden]{display:none}, which left
   the password row on screen while Magic link was selected. */
.f-field[hidden],.f-row[hidden],[hidden]{display:none !important;}
.f-input.invalid,.f-select.invalid,.f-textarea.invalid{border-color:#FF8A8A;}
.f-error:empty{display:none;}

.su-status{
  margin:0;padding:12px 14px;border:1px solid var(--line-2);
  font-family:var(--mono);font-size:10.5px;line-height:1.5;letter-spacing:.9px;
  text-transform:uppercase;color:rgba(255,255,255,0.72);
}
.su-status[data-state="error"]{border-color:#FF8A8A;color:#FF8A8A;}
.su-status[data-state="ok"]{border-color:#17E57E;color:#17E57E;}

.su-fine{
  margin:0;font-family:var(--mono);font-size:9.5px;line-height:1.6;letter-spacing:.8px;
  text-transform:uppercase;color:rgba(255,255,255,0.32);
}
.su-fine a{color:rgba(255,255,255,0.6);border-bottom:1px solid rgba(255,255,255,0.25);}
.su-fine a:hover{color:#fff;border-bottom-color:#fff;}

/* honeypot — off-screen, never focusable */
.hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

@media(max-width:1060px){
  .su-title{font-size:clamp(30px,5.4vw,44px);}
  .su-sub{font-size:15px;line-height:1.45;}
}
@media(max-width:900px){
  /* One continuous column: title block -> form -> contact block. The pitch and
     the form live in different columns, so display:contents lifts both columns'
     children into .su-split and lets them be ordered across what was the column
     boundary. Padding moves up to .su-split for the same reason. */
  .su-split{
    display:flex;flex-direction:column;gap:clamp(28px,4vw,40px);
    padding:clamp(32px,4vw,44px) var(--gut);
  }
  .su-left,.su-right{display:contents;}
  .su-head{order:1;}
  .su-right .f-form{order:2;}
  .su-foot{order:3;}
  /* desktop-only furniture: the stats band, the form's own heading (the page
     title already says what this is), and the corner tick */
  .su-steps,.su-formtitle,.su-tick{display:none;}
  .su-title{max-width:18ch;}
  /* the dot band is the page's closing beat once the stats are gone — give it
     room on tablet as well as phone */
  .su-band-dots{height:132px;padding:22px var(--pad);}
}
@media(max-width:640px){
  /* track the site's mobile headline scale — the 1060 clamp bottomed out at
     30px, noticeably smaller than every other h1 on a phone */
  .su-title{font-size:min(9.5vw,38px);max-width:none;}
  .su-sub{font-size:14.5px;line-height:1.42;}
  .su-choice{flex-direction:column;}
  /* the two decorative bands are ~180px of a phone screen — halve them */
  .su-band-bars{height:36px;}
  .su-band-dots{height:112px;padding:20px var(--pad);}
}

/* ---------- signup input states ----------
   Modelled on the conductorai.com/contact form, in our palette:
     default → hairline underline, faint label chip
     hover   → underline brightens
     filled  → chip picks up a blue tint, so completed fields read at a glance
     focus   → chip inverts to solid blue, the wrap outlines, and the site's own
               diagonal hatch fades in behind the field
   `:not(:placeholder-shown)` gives us "filled" with no JS — every field here
   carries a placeholder, which is what makes that selector reliable. */
.su-form .f-field:has(.f-input){
  position:relative;
  border:1px solid transparent;
  transition:border-color .2s ease;
}
.su-form .f-field:has(.f-input)::before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:0;
  background-image:repeating-linear-gradient(135deg,
    rgba(255,255,255,0.09) 0 1px, transparent 1px 6px);
  transition:opacity .2s ease;
}
.su-form .f-field > *{position:relative;}
.su-form .f-label{transition:background .2s ease,color .2s ease;}
.su-form .f-input{transition:border-color .2s ease,color .2s ease;}

.su-form .f-field:hover .f-input{border-bottom-color:var(--btn-line);}

/* :has() inherits the specificity of its argument, so the filled rule outranked
   the focus rule below — a filled field kept the tint instead of inverting when
   you clicked into it. Scoping it to :not(:focus-within) is also what it means. */
.su-form .f-field:not(:focus-within):has(.f-input:not(:placeholder-shown)) .f-label{
  background:rgba(26,140,255,0.2);color:var(--live);
}

.su-form .f-field:has(.f-input):focus-within{border-color:var(--live);}
.su-form .f-field:has(.f-input):focus-within::before{opacity:1;}
.su-form .f-field:focus-within .f-label{background:var(--live);color:#fff;}
/* the wrap's own 1px border already outlines the field on focus — leaving the
   input's underline on as well stacked two lines and read as a 2px bottom */
.su-form .f-field:has(.f-input):focus-within .f-input{border-bottom-color:transparent;}

@media(prefers-reduced-motion:reduce){
  .su-form .f-field,.su-form .f-field::before,
  .su-form .f-label,.su-form .f-input{transition:none;}
}
