:root{
  --black:#07080B;
  --panel:#101218;
  --panel-glass:rgba(255,255,255,.055);
  --line:rgba(255,255,255,.11);
  --line-strong:rgba(255,255,255,.22);
  --white:#FAFAFB;
  --muted:#BCC2CC;
  --dim:#8B9299;
  --red:#E11414;
  --red-2:#FF453A;
  --ok:#30D158;
  --amber:#FFD60A;
  --max:1200px;
  --r:26px;
  --ease:cubic-bezier(.22,.8,.24,1);
  --z:1;
  /* the single gap between the stacked home panels — see .home-more */
  --home-gap:clamp(22px,3vw,34px);
  /* Space above a view's first element. The sticky header is already 84px of separation,
     so the old flat 76px on top of it pushed a 12px eyebrow label ~160px down the screen
     — most of a phone's fold, and a visible dead band on desktop. Anything reading this
     token must use it rather than hardcode the number (see .contact-hero). */
  --viewpad-top:clamp(30px,4.4vh,46px);
  --viewpad-bottom:clamp(64px,8vh,96px);
  /* the gap between major blocks inside a view — one value, so About / Why / Contact
     all breathe at the same rate instead of each carrying its own flat 72px */
  --sect-gap:clamp(48px,6.5vw,76px);
}
*{margin:0;padding:0;box-sizing:border-box}
/* Nothing constrained replaced media before this. body has overflow-x:hidden, which MASKS an
   over-wide element by clipping it rather than preventing the overflow — so a too-wide image
   would have been silently cut off instead of visibly breaking. This is the actual guard.
   height is left alone: several images here set an explicit height and would be distorted. */
img,video,canvas,svg,iframe{max-width:100%}
h1,h2,h3,.cmp-lead{font-family:'Space Grotesk','Inter',system-ui,sans-serif;letter-spacing:-.02em;text-wrap:balance}
body{font-family:'Inter',-apple-system,BlinkMacSystemFont,'SF Pro Display',system-ui,sans-serif;background:var(--black);color:var(--white);font-size:17.5px;line-height:1.68;letter-spacing:.005em;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;
  font-optical-sizing:auto;font-synthesis-weight:none;overflow-x:hidden}
/* body copy sits at a comfortable measure (~65–75 characters) wherever it isn't capped already */
p{text-wrap:pretty}
a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer;color:inherit}
a:focus-visible,button:focus-visible{outline:2px solid var(--red);outline-offset:3px}
.wrap{max-width:var(--max);margin:0 auto;padding:0 26px}
.red{color:var(--red-2)}
.muted{color:var(--muted)}
.grad{background:linear-gradient(180deg,#FFFFFF 30%,#A8AEB8 115%);-webkit-background-clip:text;background-clip:text;color:transparent}
.grad-r{background:linear-gradient(135deg,#FF6257,#E11414 75%);-webkit-background-clip:text;background-clip:text;color:transparent}

/* ambient */
.bg-orb{position:fixed;z-index:0;pointer-events:none;width:1200px;height:1200px;border-radius:50%;
  background:radial-gradient(circle,rgba(225,20,20,.14) 0%,rgba(225,20,20,.04) 42%,transparent 66%);
  top:-460px;left:50%;transform:translateX(-50%);filter:blur(8px);animation:breathe 14s ease-in-out infinite alternate}
@keyframes breathe{to{opacity:.7;transform:translateX(-50%) scale(1.05)}}
/* emblem watermark — page furniture like the orb and grid above, so every view
   carries it (it used to be an <img> duplicated inside About and Why only) */
.wmark{position:fixed;z-index:0;pointer-events:none;user-select:none;
  top:calc(var(--nav,84px) + 8px);right:-180px;width:640px;height:640px;
  background:url('../assets/emblem.png') no-repeat center/contain;opacity:.05}
@media(max-width:1080px){.wmark{width:460px;height:460px;right:-140px}}
@media(max-width:760px){.wmark{width:340px;height:340px;right:-110px;opacity:.04}}
.bg-grid{position:fixed;inset:0;pointer-events:none;z-index:0;opacity:.4;
  background-image:linear-gradient(rgba(255,255,255,.055) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.055) 1px,transparent 1px);
  background-size:88px 88px;
  mask-image:radial-gradient(ellipse 85% 62% at 50% 22%,black 0%,transparent 80%);
  -webkit-mask-image:radial-gradient(ellipse 85% 62% at 50% 22%,black 0%,transparent 80%);
}

/* ============ NAV ============ */
header{position:sticky;top:0;z-index:100;background:rgba(7,8,11,.62);-webkit-backdrop-filter:blur(24px) saturate(1.5);backdrop-filter:blur(24px) saturate(1.5);border-bottom:1px solid var(--line)}
/* one row: lockup in the left corner | module links centred | CTA in the right corner.
   1fr auto 1fr keeps the links optically centred whatever the side widths are. */
.nav{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:18px;height:84px}
.brand{display:flex;align-items:center;gap:14px;flex:none;grid-column:1;justify-self:start}
/* The emblem is the mark that carries presence, so it runs slightly taller than the
   text block and takes the eye first — the way to give the lockup weight without
   pushing the wordmark to headline size. 71% of the bar, 12px clear top and bottom. */
.brand img.em{height:60px;width:auto;filter:drop-shadow(0 0 9px rgba(225,20,20,.26))}
/* The supplied text block. Its three lines scale with the image, so height IS the font
   size — height × .389 is the TAURUS wordmark, × .233 the tagline, × .193 the DataSmith
   line. 58px puts the wordmark at ~22.6px: header scale, not headline scale, and it
   leaves 13px of clearance in an 84px bar.
   The artwork is already pure #FFF, so brightness() has nothing to lift. A faint halo
   keeps it from sitting flat on the bar — one soft pass, low alpha, no second tight ring:
   the wordmark is white on near-black and needs no help being legible. The red DataSmith
   line keeps a touch of saturation. */
.brand img.brand-text{height:58px;width:auto;display:block;
  filter:saturate(1.08) drop-shadow(0 0 10px rgba(255,255,255,.13))}
.brand img.wm{height:24px;width:auto;display:none;filter:drop-shadow(0 0 8px rgba(255,255,255,.14))}
.brand img{transition:filter .3s var(--ease)}
.brand:hover img.em{filter:drop-shadow(0 0 12px rgba(225,20,20,.4))}
.brand:hover img.brand-text{filter:saturate(1.12) drop-shadow(0 0 12px rgba(255,255,255,.22))}
/* .brand-txt / .brand-tag / .brand-pw lived here for a typed lockup — a wordmark with the
   tagline and the DataSmith line stacked under it. The header now uses the supplied artwork
   (assets/brand-text.png), so none of those elements exist any more. They were the only
   users of Jost, which is why it is no longer downloaded at all. */
.modules{grid-column:2;display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;padding:4px;align-items:center;justify-self:center}
.modules::-webkit-scrollbar{display:none}
.nav-right{grid-column:3;justify-self:end;display:flex;align-items:center;gap:10px}
.mod-btn{background:transparent;border:1px solid transparent;color:var(--muted);border-radius:999px;padding:10px 18px;font-size:15.5px;font-weight:600;letter-spacing:0;white-space:nowrap;transition:all .3s var(--ease)}
.mod-btn:hover{color:var(--white);background:rgba(255,255,255,.06)}
.mod-btn.active{background:rgba(255,255,255,.11);color:var(--white)}
.mod-btn.cta{background:linear-gradient(135deg,var(--red-2),var(--red) 75%);color:#fff;font-weight:600;box-shadow:0 6px 24px rgba(225,20,20,.38)}
.mod-btn.cta:hover{transform:translateY(-1px);box-shadow:0 10px 30px rgba(225,20,20,.5)}
.nav-item{position:relative}
.drop{position:absolute;top:calc(100% + 12px);left:50%;transform:translate(-50%,8px);min-width:224px;background:rgba(13,14,19,.97);border:1px solid var(--line);border-radius:18px;padding:10px;display:flex;flex-direction:column;gap:2px;opacity:0;visibility:hidden;transition:all .28s var(--ease);box-shadow:0 26px 60px rgba(0,0,0,.6);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);z-index:120}
.nav-item:hover .drop,.nav-item.open .drop{opacity:1;visibility:visible;transform:translate(-50%,0)}
.drop::before{content:'';position:absolute;top:-12px;left:0;right:0;height:12px}
.drop button{background:transparent;border:0;color:var(--muted);text-align:left;font-size:14.5px;font-weight:500;padding:10px 14px;border-radius:11px;transition:all .2s;white-space:nowrap;cursor:pointer}
.drop button:hover{background:rgba(225,20,20,.14);color:#fff}
.drop button i{color:var(--red-2);font-style:normal}
.drop-sep{font-size:10.5px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:#4a4e57;padding:10px 14px 4px}
/* tight desktop widths: let the centre column take the slack rather than overlap the corners.
   The lockup steps down with the width so the module links keep their room. */
@media(max-width:1280px){
  .nav{height:80px}
  .brand img.em{height:56px}
  .brand img.brand-text{height:54px}
}
@media(max-width:1080px){
  .nav{grid-template-columns:auto minmax(0,1fr) auto;gap:12px;height:76px}
  .brand img.wm{height:22px}.brand img.em{height:50px}
  .brand img.brand-text{height:48px}
  .mod-btn{padding:10px 13px;font-size:15px}
}
@media(max-width:880px){.drop{left:auto;right:0;transform:translate(0,8px)}.nav-item:hover .drop,.nav-item.open .drop{transform:translate(0,0)}}
/* 761–900px — tablet portrait, which is where an iPad lands (768) along with the
   iPad Air and Pro 11 (820). The single-row grid cannot hold the lockup, four
   module links and the CTA at these widths: the links run under "Contact us" and
   the active pill collides with the lockup. Wrap to two rows here, the way phones
   already do, but keep the full lockup and the dropdowns — both still have room.
   min-width:761 keeps this clear of the phone block below, which owns everything
   narrower and swaps the lockup for the wordmark. */
@media(max-width:900px) and (min-width:761px){
  .nav{display:flex;flex-wrap:wrap;height:auto;gap:8px 10px;padding-top:12px;padding-bottom:8px}
  .brand{order:0}
  .nav-right{order:1;margin-left:auto}
  .modules{order:2;width:100%;justify-content:flex-start;gap:4px;padding:2px 0 4px}
}
@media(max-width:760px){
  .brand img.em{height:42px}
  /* the full text block needs ~216px of width — more than a phone can spare next to
     the CTA — so it drops back to the wordmark alone */
  .brand img.brand-text{display:none}
  .brand img.wm{display:block;height:19px}
  /* too narrow for one row: lockup + CTA on top, links scroll underneath */
  .nav{display:flex;flex-wrap:wrap;height:auto;gap:6px 10px;padding-top:10px;padding-bottom:6px}
  .brand{order:0}
  .nav-right{order:1;margin-left:auto}
  .modules{order:2;width:100%;justify-content:flex-start;gap:4px;padding:2px 0 4px}
  .mod-btn{padding:9px 14px;font-size:14.5px}
  .mod-btn.cta{padding:9px 16px}
  .nav-item .drop{display:none!important}
}
/* phones: at 375px the full lockup + CTA come to within a pixel of the gutters and
   wrap to a third row — trimming the wordmark keeps them on one line */
@media(max-width:430px){
  .brand img.wm{height:14px}.brand img.em{height:30px}
  .brand{gap:10px}
  .mod-btn.cta{padding:9px 14px;font-size:14px}
}

/* ============ VIEWS ============ */
main{position:relative;z-index:1}
.view{display:none}
.view.active{display:block}
.view.enter{animation:vIn .4s var(--ease) both}
.view.exit{animation:vOut .15s var(--ease) both}
@keyframes vIn{from{opacity:0}to{opacity:1}}
@keyframes vOut{from{opacity:1}to{opacity:0}}
/* content stagger inside entering views */
.sg{opacity:0}
.view.enter .sg{animation:sgIn .45s var(--ease) both}
@keyframes sgIn{from{opacity:0}to{opacity:1}}
.view.settled .sg{opacity:1;animation:none}
@media(prefers-reduced-motion:reduce){
  .view.enter,.view.exit,.view.enter .sg{animation:none}
  .sg{opacity:1}
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}
.label{display:inline-block;font-size:12px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--dim)}
.label.r{color:var(--red-2)}
.label.nocase{text-transform:none;letter-spacing:.14em}

/* ============ HOME / HERO ============ */
/* The headline block sits in the middle of the fold. The bottom pad is the heavier of
   the two so the centre lands optically true — the scroll cue is out of the flow and
   pinned to the foot of the fold (see .scroll-cue), and would otherwise crowd it. */
.hero{min-height:calc(var(--vhz,calc(100vh/var(--z))) - var(--nav,84px));display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:clamp(12px,3vh,40px) 0 68px;position:relative}
/* the lockup used to sit here, but the header already carries it — the headline leads instead */
.hero .emblem{height:min(118px,calc(var(--vhz,100vh)*0.125));width:auto;filter:drop-shadow(0 0 44px rgba(225,20,20,.5));animation:emIn .6s var(--ease) both}
@keyframes emIn{from{opacity:0}to{opacity:1}}
.hero .wordmark{width:clamp(240px,30vw,380px);height:auto;margin:16px 0 10px;animation:emIn .6s .07s var(--ease) both}
.hero .brandline{font-size:clamp(14px,1.5vw,17px);font-weight:500;letter-spacing:.18em;color:var(--muted);animation:emIn .6s .12s var(--ease) both}
.hero .brandline em{font-style:italic;font-weight:700;color:var(--white)}
.hero .powered{margin-top:8px;font-size:12.5px;font-weight:500;letter-spacing:.06em;color:var(--dim);animation:emIn .6s .16s var(--ease) both}
.hero .powered b{color:var(--red-2);font-weight:700}
/* capped against the viewport height as well as its width, so a big headline on a
   short laptop screen still leaves the sub-line and the button inside the fold */
.hero h1{margin-top:0;font-weight:700;font-size:min(6.8vw,calc(var(--vhz,100vh)*0.105),94px);line-height:1.04;letter-spacing:-.04em;animation:emIn .6s .2s var(--ease) both}
.hero .cycler{display:block;text-align:center;min-height:1.08em;white-space:nowrap}
.hero .cycler span{display:inline-block;background:linear-gradient(135deg,#FF6257,#E11414 75%);-webkit-background-clip:text;background-clip:text;color:transparent;animation:wordIn .4s var(--ease)}
@keyframes wordIn{from{opacity:0;transform:translateY(38%)}to{opacity:1;transform:none}}
.hero-sub{margin:18px auto 26px;color:var(--muted);font-size:clamp(16.5px,1.65vw,22px);line-height:1.6;max-width:640px;animation:emIn .6s .25s var(--ease) both}
.hero-actions{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;animation:emIn .6s .3s var(--ease) both}
.hero-actions .btn{font-size:16.5px;padding:18px 40px}
.btn{display:inline-flex;align-items:center;gap:8px;background:linear-gradient(135deg,var(--red-2),var(--red) 75%);color:#fff;font-weight:600;font-size:15.5px;padding:16px 34px;border:0;border-radius:999px;transition:all .3s var(--ease);letter-spacing:-.01em;box-shadow:0 10px 30px rgba(225,20,20,.38)}
.btn:hover{transform:translateY(-2px);box-shadow:0 16px 42px rgba(225,20,20,.52)}
.btn.ghost{background:rgba(255,255,255,.07);border:1px solid var(--line);color:var(--white);box-shadow:none;font-weight:500}
.btn.ghost:hover{background:rgba(255,255,255,.12);border-color:var(--line-strong);box-shadow:none}
/* pinned to the foot of the fold, so it reads as "there is more below" and the click
   drags the page down to the joint */
.scroll-cue{position:absolute;left:50%;transform:translateX(-50%);bottom:14px;
  background:none;border:0;cursor:pointer;color:var(--dim);font-size:11.5px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;transition:color .25s;animation:emIn .6s .38s var(--ease) both}
.scroll-cue:hover{color:var(--white)}
.scroll-cue i{display:block;width:1px;height:24px;background:linear-gradient(180deg,var(--red-2),transparent);margin:8px auto 0;animation:cue 1.8s ease-in-out infinite}
@keyframes cue{0%,100%{transform:scaleY(.4);transform-origin:top}50%{transform:scaleY(1)}}

/* flange band — bottom spacing is left to .home-more's shared gap so the three panels
   below the hero sit on one even rhythm */
.flange-band{padding:24px 0 0}
.flange-card{background:linear-gradient(180deg,rgba(255,255,255,.065),rgba(255,255,255,.02));border:1px solid var(--line);border-radius:32px;display:grid;grid-template-columns:1fr 1fr;align-items:center;overflow:hidden;box-shadow:0 34px 80px rgba(0,0,0,.5)}
@media(max-width:940px){.flange-card{grid-template-columns:1fr}}
.flange-card .txt{padding:54px 52px}
@media(max-width:940px){.flange-card .txt{padding:40px 30px 8px;text-align:center}}
.flange-card .txt .label{margin-bottom:16px}
.flange-card h2{font-weight:700;font-size:clamp(28px,3.4vw,44px);line-height:1.06;letter-spacing:-.035em;margin-bottom:16px}
.flange-card p{color:var(--muted);max-width:420px;line-height:1.65}
@media(max-width:940px){.flange-card p{margin:0 auto}}
.flange-stage{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:34px 20px}
.flange-halo{position:absolute;width:min(500px,90vw);height:min(500px,90vw);border-radius:50%;background:radial-gradient(circle,rgba(225,20,20,.18),transparent 62%);pointer-events:none}
.flange-stage canvas{position:relative;width:min(430px,80vw);height:min(430px,80vw);max-width:100%;cursor:grab;touch-action:pan-y}
.flange-stage canvas:active{cursor:grabbing}
.drag-hint{font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);margin-top:2px}
/* marquee */
.marquee{border-top:1px solid var(--line);border-bottom:1px solid var(--line);overflow:hidden}
.marquee .track{display:flex;white-space:nowrap;animation:mq 30s linear infinite;width:max-content}
.marquee span{font-size:12.5px;font-weight:600;letter-spacing:.2em;color:var(--dim);padding:18px 40px}
.marquee span b{color:var(--white);font-weight:700}
@keyframes mq{to{transform:translateX(-50%)}}
/* The global reduced-motion reset clamps every animation to .01ms, which is right for a
   one-shot entrance but wrong for an infinite loop — it restarts the marquee thousands of
   times a second instead of stopping it. Kill this one outright. */
@media(prefers-reduced-motion:reduce){.marquee .track{animation:none}}

/* ============ shared ============ */
.viewpad{padding:var(--viewpad-top) 0 var(--viewpad-bottom);position:relative}
.vhead{margin-bottom:44px;max-width:820px}
.vhead .label{margin-bottom:16px}
.vhead h2{font-weight:700;font-size:clamp(38px,5vw,66px);line-height:1.02;letter-spacing:-.04em}
.vhead .vsub{margin-top:18px;color:var(--muted);font-size:18px;max-width:560px}
.card{background:linear-gradient(180deg,rgba(255,255,255,.065),rgba(255,255,255,.022));border:1px solid var(--line);border-radius:var(--r);transition:all .35s var(--ease)}
.card:hover{border-color:var(--line-strong);transform:translateY(-4px);box-shadow:0 26px 56px rgba(0,0,0,.5)}
.sect-gap{margin-top:var(--sect-gap)}
.sect-label{display:flex;align-items:center;gap:14px;margin-bottom:26px}
.sect-label .ln{flex:1;height:1px;background:var(--line)}
.sect-label .label{flex:none}

/* ============ ABOUT ============ */
.q3-label{display:inline-block;margin-bottom:20px}
/* The opening fold: the page head and the three questions hold the first screen on
   their own, and Why now follows below it in the normal flow. min-height reserves one
   screen below the sticky header so the next section starts off it; flex-start keeps
   the head at the top rather than re-opening the dead band above it. Gated on width
   AND height: under 820px the q3 grid stacks three deep, and under 560px tall nothing
   sensible fits — both fall back to an ordinary stack. */
@media(min-width:821px) and (min-height:560px){
  .about-fold{min-height:calc(var(--vhz,100vh) - var(--nav,84px) - var(--viewpad-top));
    display:flex;flex-direction:column;justify-content:flex-start}
  /* everything below is sized against the viewport's height, not just its width — the
     constraint that decides whether both blocks fit is vertical */
  #view-about .vhead{margin-bottom:clamp(24px,4vh,44px)}
  #view-about .vhead .label{margin-bottom:clamp(8px,1.6vh,16px)}
  #view-about .vhead h2{font-size:min(5vw,calc(var(--vhz,100vh)*0.062),62px)}
  #view-about .vhead .vsub{margin-top:clamp(10px,1.8vh,18px);max-width:640px}
  #view-about .q3{padding:clamp(26px,3.4vh,46px) clamp(28px,3vw,44px)}
  #view-about .q3-label{margin-bottom:clamp(12px,2vh,20px)}
  #view-about .q3-item p{font-size:min(2.2vw,calc(var(--vhz,100vh)*0.031),27px)}
  #view-about .q3-grid{margin-bottom:clamp(16px,2.4vh,26px)}
  #view-about .q3-sub{font-size:clamp(14.5px,1.05vw,16px);line-height:1.55}
}
.q3{padding:46px 44px}
.q3:hover{transform:none}
.q3-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:26px}
@media(max-width:820px){.q3-grid{grid-template-columns:1fr}}
.q3-item{border-left:2px solid rgba(225,20,20,.55);padding:6px 0 6px 20px}
.q3-item .qn{display:block;font-weight:900;font-size:12px;letter-spacing:.16em;color:var(--red-2);margin-bottom:8px}
.q3-item p{font-weight:800;font-size:clamp(20px,2.2vw,27px);letter-spacing:-.03em;line-height:1.2}
.q3-sub{color:var(--muted);font-size:16px;line-height:1.7;max-width:820px}
.why-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
@media(max-width:900px){.why-grid{grid-template-columns:1fr}}
.why-card{padding:36px 32px}
.why-card .wn{display:block;font-weight:900;font-size:13px;letter-spacing:.12em;color:var(--red-2);margin-bottom:20px}
.why-card h3{font-weight:700;font-size:clamp(19px,1.9vw,23px);letter-spacing:-.025em;margin-bottom:12px;line-height:1.3}
.why-card p{color:var(--muted);font-size:15.5px;line-height:1.65}
.ind-list{border-top:1px solid var(--line)}
.ind-row{display:grid;grid-template-columns:260px 1fr;gap:24px;padding:22px 4px;border-bottom:1px solid var(--line);transition:all .3s var(--ease)}
@media(max-width:720px){.ind-row{grid-template-columns:1fr;gap:6px}}
.ind-row:hover{padding-left:14px;background:linear-gradient(90deg,rgba(225,20,20,.06),transparent 60%)}
.ind-row h4{font-weight:700;font-size:17.5px;letter-spacing:-.02em}
.ind-row p{color:var(--muted);font-size:15.5px;line-height:1.6}
/* One wide panel, not a third grid. About already runs a 3-up card grid (.why-grid) and a
   row list (.ind-list); a third grid pattern would make the page read as repetitive. The
   Tri-Star mark is the same asset the Contact page uses, so the logo appears where the
   claim is actually made. */
.maker{padding:44px 46px}
.maker:hover{transform:none}
.maker-mark{height:36px;width:auto;opacity:.92;margin-bottom:22px;display:block}
.maker h3{font-weight:700;font-size:clamp(24px,2.8vw,34px);line-height:1.1;letter-spacing:-.03em;margin-bottom:16px}
.maker p{color:var(--muted);max-width:68ch;line-height:1.7;margin-bottom:14px}
.maker p:last-of-type{margin-bottom:0}
.maker p strong{color:var(--white);font-weight:600}
.maker-stats{display:flex;gap:16px;flex-wrap:wrap;margin-top:26px;padding-top:24px;border-top:1px solid var(--line)}
.maker-stats>div{flex:1 1 150px;min-width:0}
.maker-stats b{display:block;font-weight:800;font-size:clamp(18px,1.9vw,23px);letter-spacing:-.02em;color:var(--white)}
.maker-stats span{display:block;margin-top:5px;font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
/* the tool itself — same visual weight as the company stats above it, so the two read as a
   pair (who they are / what they build) rather than as a spec sheet bolted onto an essay */
.toolspec{margin-top:26px;padding-top:24px;border-top:1px solid var(--line)}
.toolspec-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;margin-bottom:20px}
.toolspec-sub{font-size:12.5px;color:var(--dim)}
.spec-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:20px 16px;margin:0}
.spec-grid>div{min-width:0}
.spec-grid dt{font-weight:800;font-size:clamp(17px,1.8vw,21px);letter-spacing:-.02em;color:var(--white);font-variant-numeric:tabular-nums}
.spec-grid dd{margin:5px 0 0;font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);line-height:1.5}
@media(max-width:640px){.maker{padding:30px 24px}
  .spec-grid{grid-template-columns:repeat(2,1fr);gap:16px 12px}}
/* the quiet hand-off at the foot of About */
.about-next{margin-top:26px;color:var(--dim);font-size:13.5px}

.quoteband{margin-top:var(--sect-gap);padding:52px 50px;text-align:center}
.quoteband:hover{transform:none}
.quoteband p{font-weight:700;font-size:clamp(21px,2.8vw,32px);letter-spacing:-.03em;line-height:1.35;max-width:880px;margin:0 auto}
/* ============ ECOSYSTEM ============ */
.eco-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
@media(max-width:1000px){.eco-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.eco-grid{grid-template-columns:1fr}}
.eco-card{padding:34px 30px;text-align:left;position:relative;overflow:hidden;color:var(--white)}
.eco-card::after{content:'→';position:absolute;right:24px;bottom:22px;color:var(--dim);font-size:19px;transition:all .3s var(--ease)}
.eco-card:hover{border-color:rgba(225,20,20,.5);box-shadow:0 26px 56px rgba(0,0,0,.5),0 0 0 1px rgba(225,20,20,.18) inset}
.eco-card:hover::after{color:var(--red-2);transform:translateX(4px)}
.eco-card .n{font-size:11.5px;font-weight:700;letter-spacing:.18em;color:var(--dim);margin-bottom:42px;text-transform:uppercase}
/* one-word headings, so they take a display leading rather than the body's 1.68 —
   at 28px that was 47px of line box around a single word */
.eco-card h3{font-weight:700;font-size:clamp(23px,2vw,28px);line-height:1.15;letter-spacing:-.02em;margin-bottom:8px}
.eco-card p{color:var(--muted);font-size:15.5px;line-height:1.6;padding-right:14px}
.eco-admin{margin-top:14px;padding:30px 34px;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;color:var(--white);width:100%;text-align:left}
.eco-admin:hover{border-color:rgba(225,20,20,.5)}
.eco-admin h3{font-weight:700;font-size:22px;line-height:1.2;letter-spacing:-.02em;margin-bottom:6px}
.eco-admin p{color:var(--muted);font-size:15.5px;max-width:560px}
.eco-admin .go{font-size:12px;font-weight:700;letter-spacing:.16em;color:var(--red-2);text-transform:uppercase}

.eco-detail{display:none}
/* a column so the stage below the bar can be told to absorb the leftover height */
.eco-detail.open{display:flex;flex-direction:column;animation:vIn .5s var(--ease) both}
#eco-home{display:flex;flex-direction:column}
#eco-home.gone{display:none}
#eco-home.leaving{animation:vOut .24s var(--ease) both}
#eco-home.entering{animation:vIn .5s var(--ease) both}
/* An open module scrolls to the top of the page, so even the tightened --viewpad-top
   leaves the stage sitting low. In detail mode the pad closes up further and the bar
   below becomes the module's own header row. Overriding the token rather than the
   padding keeps .eco-detail's one-screen calc below in step with it automatically. */
#view-ecosystem.detail-mode{--viewpad-top:20px}
.eco-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:18px}
.eco-crumb{display:flex;align-items:center;gap:9px;font-size:11.5px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);white-space:nowrap}
.eco-crumb i{font-style:normal;color:rgba(255,255,255,.22)}
.eco-crumb b{font-weight:700;color:var(--red-2)}
@media(max-width:560px){.eco-crumb{display:none}}
.back-btn{background:rgba(255,255,255,.06);border:1px solid var(--line);color:var(--muted);border-radius:999px;padding:10px 22px;font-size:15px;font-weight:500;transition:all .3s var(--ease)}
.back-btn:hover{color:var(--white);border-color:var(--line-strong)}
/* The forward control. Given the accent because it is the one thing on this bar that moves the
   visitor onward — "All modules" is an escape hatch, this is the path. Named, not an arrow. */
.eco-next{display:inline-flex;align-items:center;gap:9px;background:rgba(225,20,20,.14);
  border:1px solid rgba(225,20,20,.5);color:var(--white);border-radius:999px;
  padding:10px 20px;font:inherit;font-size:13.5px;font-weight:600;cursor:pointer;white-space:nowrap;
  transition:background .25s var(--ease),border-color .25s var(--ease)}
.eco-next:hover{background:rgba(225,20,20,.24);border-color:rgba(225,20,20,.8)}
/* the UA rule for [hidden] is display:none, but .eco-next sets display:inline-flex at equal
   specificity and wins by order — so hiding the button on the last module needs this */
.eco-next[hidden]{display:none}
.eco-next:focus-visible{outline:2px solid var(--red-2);outline-offset:3px}
.eco-next .k{font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.eco-next b{font-weight:600}
.eco-next i{font-style:normal;font-size:15px;line-height:1;transition:transform .25s var(--ease)}
.eco-next:hover i{transform:translateX(3px)}
@media(prefers-reduced-motion:reduce){.eco-next:hover i{transform:none}}
/* on a narrow bar the crumb is already hidden; keep the two controls on one line */
@media(max-width:560px){.eco-next{padding:9px 15px;font-size:12.5px}.eco-next .k{display:none}}
.stage{background:linear-gradient(180deg,rgba(255,255,255,.065),rgba(255,255,255,.022));border:1px solid var(--line);border-radius:32px;overflow:hidden;display:grid;grid-template-columns:1fr 1.12fr}
@media(max-width:940px){.stage{grid-template-columns:1fr}}
.stage .info{padding:48px 46px}
.stage .info .step-tag{font-size:12px;font-weight:700;letter-spacing:.18em;color:var(--red-2);margin-bottom:14px;text-transform:uppercase}
/* display leading — a one-word module name was sitting in a 77px line box at 46px */
.stage .info h3{font-weight:700;font-size:clamp(32px,3.2vw,46px);line-height:1.06;letter-spacing:-.03em;margin-bottom:14px}
/* .dpanel sits between .info and the copy — the module panels are .info's children, so
   a `.info > p` child combinator here matched nothing and the lede rendered unmuted and
   uncapped. Scoped to .dpanel's own child so it cannot leak into .acc-body p. */
.stage .info .dpanel>p{color:var(--muted);max-width:470px;line-height:1.6;margin-bottom:26px}
.stage .info .dpanel>p strong{color:var(--white);font-weight:600}
/* Content anchored to the TOP, not vertically centred. Both columns share one grid row, so
   opening a clause on the left grows the row — and a centred screenshot re-centres in the
   taller column, which is the demo sliding downwards as you click. Anchored to the top it
   cannot move. The column itself still stretches, so the background and the divider keep
   filling the panel; only the position of the contents inside it is fixed. At full size the
   difference at rest is about 18px, which is a small price for a demo that never jumps. */
.stage .demo{background:rgba(0,0,0,.4);border-left:1px solid var(--line);padding:36px;display:flex;align-items:flex-start;justify-content:center;position:relative;min-height:460px}
@media(max-width:940px){.stage .demo{border-left:0;border-top:1px solid var(--line);min-height:420px}}
.dpanel{display:none;width:100%}
.dpanel.active{display:block}
/* accordions */
.acc{border-top:1px solid var(--line)}
.acc-item{border-bottom:1px solid var(--line)}
.acc-head{width:100%;display:flex;justify-content:space-between;align-items:center;gap:14px;background:transparent;border:0;padding:16px 2px;font-size:15.5px;font-weight:600;letter-spacing:-.015em;text-align:left;transition:color .25s}
.acc-head:hover{color:var(--red-2)}
.acc-head .pm{flex:none;width:24px;height:24px;border-radius:50%;border:1px solid var(--line);display:inline-flex;align-items:center;justify-content:center;font-size:14px;font-weight:500;color:var(--muted);transition:all .3s var(--ease)}
.acc-item.open .acc-head .pm{background:var(--red);border-color:var(--red);color:#fff;transform:rotate(45deg)}
/* Animating grid-template-rows from 0fr to 1fr resolves to the clause's OWN height, which
   is what makes this smooth. The old max-height:0 -> 220px could not: a 90px clause spent
   the first half of its closing animation shrinking from 220 to 90 with nothing visibly
   moving, then dropped — that stall is the glitch. A fixed cap also clips any clause that
   outgrows it, which the longer EXECUTE and INSPECT copy was heading towards. */
/* max-height, not a 0fr grid. The grid technique animates to the clause's own height,
   which is smoother in principle, but it needs the item to shrink AND the container to
   clip, and it kept leaving a strip of text showing. This is blunt and it is certain:
   height 0 with overflow hidden is closed, full stop.

   The cap is 300px, comfortably above the tallest clause (~180px at the narrowest column
   the copy is ever laid out in), so nothing is ever cut off.

   Opening and closing are timed differently on purpose. A fixed cap means the closing
   animation spends its first stretch travelling from 300px down to the clause's real
   height with nothing visibly moving — that stall is what read as a glitch. Closing at
   .24s makes the invisible part short enough not to register; opening at .42s stays
   unhurried, and opening is the half a reader actually watches. */
.acc-body{max-height:0;overflow:hidden;transition:max-height .24s var(--ease)}
.acc-item.open .acc-body{max-height:300px;transition:max-height .42s var(--ease)}
.acc-body p{color:var(--muted);font-size:15.5px;line-height:1.65;padding:0 2px 18px;max-width:460px}
.acc-item{position:relative}
@media(prefers-reduced-motion:reduce){.acc-body{transition:none}}
/* .prog was the countdown bar under an auto-advancing clause. The accordion is click-only
   now, so there is no countdown to draw. */

/* An open module holds one screen: copy column, demo column, nothing to scroll for
   except the footer. The info column is the tall one — the demo is a fixed frame — so
   everything compressible in it is sized against viewport HEIGHT. Must stay after the
   rules it overrides; the selectors match at equal specificity and win on source order.
   Gated at 941px because .stage drops to a single column below that (copy stacked above
   demo, which cannot fit a fold). The height gate is 680px, not 600px: INSPECT is the
   tallest panel — four tabs and the longest accordion body — and at 640px of viewport its
   copy column wants ~446px against ~427px of room. .stage clips rather than scrolls, so
   below 680px the fold is switched off and the page simply scrolls, which is honest.
   The overflow rule below is the belt to that braces: nothing is ever cut off. */
@media(min-width:941px) and (min-height:680px){
  .eco-detail{min-height:calc(var(--vhz,100vh) - var(--nav,84px) - var(--viewpad-top))}
  /* The stage absorbs the whole fold rather than the container holding a screen's worth of
     height and leaving the slack empty underneath — that slack was the dead space.
     min-height:0 is what makes it a FIXED height rather than a minimum: without it a flex
     child refuses to shrink below its content, so opening a clause would push the stage
     taller and drag the demo column with it. With it, the copy column scrolls inside its
     own box (see .stage .info) and the panel never changes size. */
  .eco-detail.open>.stage{flex:1 1 auto;min-height:0}
  /* The accordion used to be pushed to the bottom of this column with margin-top:auto, to
     "spread" a tall panel. Two things were wrong with that. It opened a dead band between
     the copy and the first clause — space with nothing in it, which is worse than space at
     the end. And because the block was bottom-anchored, opening a clause grew it UPWARDS:
     everything above shifted on every click, which is the jump. Content now stacks from the
     top and clauses expand downwards, the way an accordion is expected to behave.

     min-height:0 is required — a grid item defaults to min-height:auto and refuses to
     shrink, which is what turns an overlong copy column into clipped content.
     scrollbar-gutter reserves the scrollbar's width whether or not one is showing, so a
     clause that tips the column into overflow cannot jog the text sideways. */
  .stage .info{min-height:0;overflow-y:auto;scrollbar-gutter:stable;
    padding:clamp(24px,4vh,48px) clamp(28px,3.4vw,46px)}
  .stage .info .step-tag{margin-bottom:clamp(8px,1.6vh,14px)}
  .stage .info h3{font-size:min(3.2vw,calc(var(--vhz,100vh)*0.052),46px);margin-bottom:clamp(8px,1.6vh,14px)}
  .stage .info .dpanel>p{margin-bottom:clamp(12px,2.4vh,26px)}
  .stage .demo{padding:clamp(22px,3.6vh,36px);min-height:clamp(320px,52vh,460px)}
  .acc-head{padding:clamp(10px,1.9vh,16px) 2px}
  .acc-body p{padding:0 2px clamp(10px,2vh,18px)}
}

/* .mock / .mhead / .replay / .boltwrap / .boltmap / .bolt / .torqline were the hand-drawn
   bolt-map panel that stood in for EXECUTE's real screens. That panel now shows the app's
   own bolt map — screen 5 of five — so none of them is referenced any more. */
/* the colour eases even though the text swaps instantly, so READING -> CAPTURED reads as a
   state settling rather than a flicker */
.badge{display:inline-block;border-radius:999px;padding:3px 10px;font-size:10.5px;letter-spacing:.08em;
  transition:background .3s var(--ease),color .3s var(--ease)}
.badge.red{background:rgba(225,20,20,.18);color:var(--red-2)}
.badge.ok{background:rgba(48,209,88,.15);color:var(--ok)}
.badge.amber{background:rgba(255,214,10,.13);color:var(--amber)}
/* .check / .seal lived here for the old hand-drawn INSPECT checklist. That panel now shows
   real app screens, and nothing else used them. */
.tile{background:rgba(255,255,255,.05);border:1px solid var(--line);border-radius:14px;padding:15px}
.tile .t{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-bottom:7px}
.tile .n{font-family:'Inter';font-weight:700;font-size:23px;letter-spacing:-.02em}
.bar-row{display:flex;align-items:flex-end;gap:5px;height:42px;margin-top:12px}
.bar-row i{flex:1;background:rgba(255,255,255,.12);border-radius:3px 3px 0 0;transition:height .6s var(--ease)}
.bar-row i.hot{background:var(--red-2)}
/* abstract demo elements */
.isoart{width:100%;max-width:440px;display:block;margin:0 auto 14px}
.isoart .pipe{fill:none;stroke:rgba(255,255,255,.3);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.isoart .pipe.thin{stroke-width:1.5;stroke:rgba(255,255,255,.16)}
.isoart .jnode{fill:#12141a;stroke:rgba(255,255,255,.25);stroke-width:2;transition:all .35s}
.isoart .jnode.lit{fill:rgba(225,20,20,.3);stroke:var(--red-2)}
#iso-scan{opacity:0}
.xcols{display:flex;justify-content:space-between;gap:10px;padding:0 4px 8px;color:#4a4e57;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase}
.skelrows{display:flex;flex-direction:column;gap:9px}
.skelrow{display:flex;align-items:center;gap:10px;padding:8px 4px;border-bottom:1px dashed var(--line);opacity:0;transform:translateX(-8px);transition:all .4s}
.skelrow.show{opacity:1;transform:none}
.skelrow i{display:inline-block;height:9px;border-radius:5px;background:rgba(255,255,255,.14)}
.skelrow .chip{margin-left:auto;border-radius:999px;padding:2px 9px;font-size:9.5px;letter-spacing:.1em;background:rgba(48,209,88,.14);color:var(--ok)}
.skelrow .chip.amber{background:rgba(255,214,10,.12);color:var(--amber)}
.skelrows.calc .skelrow{opacity:1;transform:none}
.skelrow .lb{flex:none;width:96px;color:var(--muted);font-size:11px;letter-spacing:.06em;text-transform:uppercase}
.skelrow .fill{height:9px;border-radius:5px;background:linear-gradient(90deg,rgba(225,20,20,.55),rgba(255,255,255,.2));transition:width .7s var(--ease)}
.codes{margin-top:14px;text-align:center;color:var(--dim);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.codes b{color:var(--white)}
.steps{display:flex;gap:8px;margin-top:14px}
.stp{flex:1;text-align:center;padding:9px 4px;border:1px dashed var(--line);border-radius:10px;color:var(--dim);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;transition:all .35s}
.stp.on{border:1px solid var(--ok);color:var(--ok)}
.stp.on.lockstep{border-color:var(--red);color:var(--red-2);font-weight:700}
.stepline{margin-top:14px;text-align:center;color:var(--dim);font-size:10.5px;letter-spacing:.08em;line-height:1.6}
.wfrow{display:flex;gap:7px;margin-bottom:12px;flex-wrap:wrap}
.wf{flex:1;min-width:80px;text-align:center;padding:8px 4px;border:1px dashed var(--line);border-radius:999px;color:var(--dim);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;transition:all .35s}
.wf.on{border:1px solid var(--red);color:var(--red-2)}
.wf.done{border:1px solid rgba(48,209,88,.5);color:var(--ok)}
.tile .st{font-size:15px;letter-spacing:.02em}
/* home pitch strip — the joint, the film, the closing question. One gap value governs
   the whole column (and .flange-band hands its bottom spacing over to it), so the three
   panels read as one deliberate rhythm rather than three accidental margins. */
/* The bottom padding was a flat 88px — two and a half times the gap between the panels above
   it, which left a visible void between the last card and the marquee band. The marquee is a
   full-bleed strip, not another section, so it should sit closer to the content than a section
   break would. Scaled rather than flat so it stays in proportion on a phone. */
.home-more{padding:var(--home-gap) 0 clamp(34px,4.5vw,52px);display:flex;flex-direction:column;gap:var(--home-gap)}
/* matched to .flange-card's 32px — the three panels now read as one column, and
   var(--r)'s 26px on two of the three broke that */
.home-more>.card{border-radius:32px}
/* Brochure strip. Deliberately slimmer than the panels either side — it is a takeaway,
   not a third pitch, so it must not read as another chapter of the page. The button is a
   ghost: the red gradient on this page belongs to "Book a live demo" and the brochure is
   a cheaper click that would otherwise win it. */
.broch{padding:22px 30px;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;color:var(--white)}
.broch h3{font-weight:700;font-size:19px;letter-spacing:-.02em}
.dl-btn{display:inline-flex;align-items:center;gap:10px;background:rgba(255,255,255,.07);border:1px solid var(--line-strong);color:var(--white);font-weight:600;font-size:15px;padding:13px 24px;border-radius:999px;white-space:nowrap;transition:all .3s var(--ease)}
.broch:hover .dl-btn{background:rgba(225,20,20,.16);border-color:rgba(225,20,20,.55)}
.dl-btn .arr{font-size:17px;line-height:1;transition:transform .3s var(--ease)}
.broch:hover .dl-btn .arr{transform:translateY(2px)}
@media(max-width:620px){
  .broch{flex-direction:column;align-items:stretch;text-align:center;padding:22px;gap:16px}
  .dl-btn{justify-content:center}
}
.home-cta{padding:44px 42px;display:flex;align-items:center;justify-content:space-between;gap:28px;flex-wrap:wrap}
.home-cta h3{font-weight:700;font-size:clamp(18px,1.8vw,22px);letter-spacing:-.02em;margin-bottom:8px}
.home-cta .hq{font-weight:800;font-size:clamp(24px,3vw,38px);letter-spacing:-.035em;line-height:1.15;margin-bottom:10px}
.home-cta .hsub{color:var(--muted);font-size:16px;max-width:540px}
.cycler2{display:block;white-space:nowrap;min-height:1.16em;font-size:.9em;font-weight:700;margin-top:4px}
.cycler2 span{display:inline-block;background:linear-gradient(135deg,#FF6257,#E11414 75%);-webkit-background-clip:text;background-clip:text;color:transparent;animation:wordIn .4s var(--ease)}
/* the film now plays in place: copy on the left, player on the right. With the module
   cards gone this is the page's middle beat and its proof, so the player takes the
   larger share of the row and the padding matches the flange card either side of it. */
/* ---- the film banner ----
   The poster IS the strip: letterboxed, scrimmed so the type stays legible, with the emblem
   reading through on the right. It replaced a full 16:9 player, which was the tallest block
   on the page and the one thing almost nobody stayed seven minutes for. Height is fixed and
   the image crops to it, so the banner never grows with the container. */
.film-cine{position:relative;height:clamp(150px,19vw,178px);padding:0;overflow:hidden;
  display:block;width:100%;text-align:left;color:var(--white);border:1px solid var(--line)}
.film-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 46%;
  transform:scale(1.04);transition:transform .7s var(--ease)}
.film-cine:hover .film-bg{transform:scale(1.09)}
/* the scrim is asymmetric on purpose — heaviest under the headline, clearing by the time it
   reaches the emblem so the artwork is still doing visible work on the right */
.film-scrim{position:absolute;inset:0;background:linear-gradient(90deg,
  rgba(7,8,11,.97) 6%,rgba(7,8,11,.82) 34%,rgba(7,8,11,.15) 68%,rgba(7,8,11,.55) 100%)}
.film-body{position:relative;height:100%;display:flex;align-items:center;gap:22px;
  padding:0 clamp(22px,3vw,34px)}
.film-txt{flex:1;min-width:0}
.film-txt .label{display:block;margin-bottom:7px}
.film-h{display:block;font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-weight:700;
  font-size:clamp(20px,2.5vw,28px);line-height:1.12;letter-spacing:-.03em}
.film-sub{display:block;color:var(--muted);font-size:clamp(13px,1.3vw,14.5px);margin-top:6px}
.film-play{flex:none;width:62px;height:62px;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--red-2),var(--red) 75%);
  box-shadow:0 12px 34px rgba(225,20,20,.5),0 0 0 1px rgba(255,255,255,.14) inset;
  transition:transform .35s var(--ease),box-shadow .35s var(--ease)}
.film-play svg{margin-left:3px}
.film-cine:hover .film-play{transform:scale(1.08);
  box-shadow:0 16px 44px rgba(225,20,20,.62),0 0 0 1px rgba(255,255,255,.2) inset}
/* the card lift would fight a full-bleed image at this height */
.film-cine:hover{transform:none}
@media(prefers-reduced-motion:reduce){
  .film-bg,.film-cine:hover .film-bg{transform:none}
  .film-cine:hover .film-play{transform:none}
}
@media(max-width:680px){
  .film-cine{height:auto}
  .film-scrim{background:linear-gradient(180deg,rgba(7,8,11,.9),rgba(7,8,11,.78))}
  .film-body{flex-direction:column;align-items:flex-start;gap:18px;padding:24px 22px}
  .film-play{width:52px;height:52px}
}
/* the film's own viewer — same furniture as .shotbox, but holding a <video> */
.filmbox video{position:relative;max-width:min(1280px,100%);max-height:100%;width:auto;height:auto;
  display:block;border-radius:14px;border:1px solid var(--line-strong);background:#000;
  box-shadow:0 40px 120px rgba(0,0,0,.85)}

/* Security page — three declarations that were inline on the markup */
.sec-intro{margin-bottom:24px}
.sec-faq{max-width:820px;margin:0}
.sec-note{margin-top:26px;color:var(--dim);font-size:13px}

/* ============ WHY TAURUS ============ */
/* two cards, not three: the 27-days card drew on the same study and made the same argument as
   the $5.04M card, so it was dropped rather than left as a repeat */
.val-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:14px}
@media(max-width:900px){.val-stats{grid-template-columns:1fr}}
.v-stat{padding:34px 32px}
.v-stat .n{font-weight:900;font-size:clamp(34px,3.6vw,52px);letter-spacing:-.045em;line-height:1}
.v-stat .d{margin-top:12px;font-size:15.5px;color:var(--muted);line-height:1.6}
.v-stat .src{margin-top:12px;font-size:10.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
/* ecosystem heading — the scroll walkthrough that used to sit here is gone */
/* no top padding of its own — .viewpad's token owns the space above every view head,
   the same way About's .vhead does */
.ehead{padding:0 0 22px}
.ehead h2{font-weight:700;font-size:clamp(26px,3vw,40px);letter-spacing:-.035em;line-height:1.05;margin-top:clamp(6px,1.2vh,10px)}
.ehead .vsub{margin-top:clamp(6px,1.2vh,10px);color:var(--muted);font-size:16px}

/* The module chooser holds the first screen on its own — head, the four modules and the
   admin bar — so the footer is a scroll away rather than sitting in view beneath it.
   This block must stay after every rule it overrides: the selectors below match the base
   ones exactly, so it wins on source order, not specificity.
   Gated like the About fold: the four-across grid stacks below 1000px, where a
   one-screen fold stops making sense. */
@media(min-width:1001px) and (min-height:560px){
  #eco-home{min-height:calc(var(--vhz,100vh) - var(--nav,84px) - var(--viewpad-top))}
  /* the grid takes the slack, so the cards grow to meet the admin bar instead of the
     leftover height pooling as dead space underneath it */
  #eco-home .eco-grid{flex:1 1 auto}
  .ehead{padding-bottom:clamp(14px,2.4vh,22px)}
  .ehead h2{font-size:min(3vw,calc(var(--vhz,100vh)*0.046),40px)}
  /* the card's bottom padding stays put — the ::after arrow is pinned 22px up from it
     and would ride into the last line of copy if it shrank */
  .eco-card{padding:clamp(24px,3.4vh,34px) clamp(24px,2.2vw,30px) 34px}
  .eco-card .n{margin-bottom:clamp(18px,4.6vh,42px)}
  /* in a taller card the extra height opens up between the eyebrow and the name rather
     than trailing under the copy; the .n margin above stays the minimum gap */
  #eco-home .eco-card{display:flex;flex-direction:column}
  /* This was margin-top:auto, which bottom-aligned the h3 + p block inside each
   card. The four paragraphs are not the same length — INSPECT runs to two lines
   where the others run to three — so its title sat a whole line lower than its
   neighbours. Titles now start at the same offset in all four; the ragged edge
   falls at the bottom of the card instead, where nothing lines up against it
   (the arrow is absolutely positioned, so it stays put). */
#eco-home .eco-card h3{margin-top:0}
#eco-home .eco-card p{margin-bottom:auto}
  .eco-admin{padding:clamp(20px,3vh,30px) clamp(26px,2.6vw,34px)}
}

/* Today vs TAURUS drag panel */
.cmp-lead{font-weight:700;font-size:clamp(17px,1.8vw,21px);letter-spacing:-.02em;margin-bottom:22px}
.cmpwrap{position:relative;border-radius:24px;overflow:hidden;border:1px solid var(--line);user-select:none;touch-action:pan-y;box-shadow:0 30px 70px rgba(0,0,0,.5)}
.cside{padding:32px 30px;min-height:400px}
@media(max-width:720px){.cside{padding:26px 20px;min-height:0}}
/* the corner tags are pinned 16px down and stand ~29px tall, so the board needs to start
   below ~45px or band 1 runs underneath "Today" and "With TAURUS" */
.cside.today{background:#0B0C10;padding-top:54px}
/* The board scales as ONE piece. aspect-ratio fixes the box's shape, every tile width is
   a % of that box, and the artwork inside each tile is a viewBox that scales with it — so
   width, height and offset all move together and nothing can escape the frame. The old
   version mixed px widths with % offsets, which is why p4 was being sliced off the bottom
   by .cmpwrap's overflow:hidden at 505px inside a 470px box.
   Band arithmetic: a tile is (width x 0.7) + 38px tall — the 120:84 viewBox plus padding
   and caption. At this aspect that is ~31% of the box for a 13%-wide tile, so three bands
   at 1% / 34% / 68% clear each other and the last one lands at ~99%. Keep tiles <= 13%
   wide or the bands collide; the wide scrap is exempt, it has no artwork. */
/* isolation is load-bearing: the tiles below use z-index to layer the collage, and
   neither this nor .cside.today creates a stacking context on its own — so those values
   escaped into .cmpwrap and painted the tiles ON TOP of .creveal, leaving the torque
   sheet, the phone and the PDF floating over a fully revealed TAURUS side. */
.scatter{position:relative;aspect-ratio:1084/450;isolation:isolate}
.scrap{position:absolute;background:#101116;border:1px solid rgba(255,255,255,.09);border-radius:10px;padding:clamp(8px,1vw,13px) clamp(10px,1.2vw,15px);color:var(--dim);line-height:1.5;box-shadow:0 10px 26px rgba(0,0,0,.4)}
.scrap b{display:block;font-size:clamp(8px,.78vw,10px);font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:#8a8f98;margin-bottom:5px}
.scrap .hand{font-family:'Caveat',cursive;font-size:clamp(14px,1.5vw,19px);color:#9BA1AA;transform:rotate(-1deg);display:block;line-height:1.25}
.pcard{position:absolute;background:#111318;border:1px solid rgba(255,255,255,.12);border-radius:10px;padding:8px 8px 6px;box-shadow:0 12px 30px rgba(0,0,0,.5)}
.pcard svg{width:100%;display:block;border-radius:6px}
.pcard b{display:block;margin-top:6px;font-size:clamp(7px,.72vw,9px);font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#8a8f98;text-align:center;line-height:1.3}

/* Four tiles a band, each band spanning the full width with ~4% clear either side, and
   the x positions staggered from band to band so no two columns line up — even coverage
   across the whole board, still a scatter rather than a grid. */
/* band 1 — tops 0-2.5%, bottoms by ~33% */
.p1{left:4%;    top:2.5%; width:12.5%; transform:rotate(-2.6deg)}
.s2{left:21%;   top:.5%;  width:20%;   transform:rotate(1.4deg);z-index:3}
.p5{left:51%;   top:0;    width:13%;   transform:rotate(-1.9deg)}
.e1{left:79%;   top:2%;   width:13%;   transform:rotate(-2.2deg)}
/* band 2 — tops 34-36.5%, bottoms by ~67% */
.p2{left:10%;   top:35%;  width:13%;   transform:rotate(1.6deg)}
.p6{left:31%;   top:34%;  width:12.5%; transform:rotate(2.2deg)}
.e2{left:55%;   top:36.5%;width:13%;   transform:rotate(-2.4deg);z-index:2}
.p7{left:76%;   top:34.5%;width:13%;   transform:rotate(-2.8deg)}
/* band 3 — tops 67.5-69%, bottoms by ~99% */
.p4{left:3%;    top:68%;  width:12.5%; transform:rotate(-1.7deg)}
.e3{left:26%;   top:69%;  width:12.5%; transform:rotate(1.9deg)}
.e4{left:48%;   top:67.5%;width:13%;   transform:rotate(1.3deg)}
.p3{left:84%;   top:68.5%;width:9.5%;  transform:rotate(2.6deg);z-index:2}

/* Phones get a plain two-column board instead. Twelve tilted tiles scattered across a
   ~280px-tall box would be unreadable, and the tilts fight the narrow gutters. */
@media(max-width:720px){
  .scatter{position:static;aspect-ratio:auto;display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:start}
  .scatter>*{position:static;left:auto;top:auto;width:auto;transform:none}
  .scatter>.scrap{grid-column:1 / -1}
}
/* z-index 2 so the reveal is unambiguously above the Today side whatever the scatter does */
.creveal{position:absolute;inset:0;overflow:hidden;z-index:2}
.cside.ctaurus{background:linear-gradient(120deg,#12060699,#0A0B0F 45%),#0A0B0F;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:left}
.cflow{display:flex;flex-direction:column;gap:11px;width:min(560px,100%)}
.frow{display:flex;align-items:center;gap:14px;background:linear-gradient(100deg,rgba(255,255,255,.07),rgba(255,255,255,.03));border:1px solid var(--line);border-radius:14px;padding:15px 18px;transition:all .3s var(--ease)}
.frow .tick{flex:none;width:22px;height:22px;border-radius:50%;background:rgba(48,209,88,.14);border:1px solid rgba(48,209,88,.45);color:var(--ok);font-size:11px;font-weight:800;display:inline-flex;align-items:center;justify-content:center}
.frow .t{font-weight:700;font-size:14px;letter-spacing:-.015em}
.frow .d{margin-left:auto;font-size:10px;font-weight:700;letter-spacing:.1em;color:var(--ok);white-space:nowrap}
.fseal{margin-top:8px;background:linear-gradient(120deg,rgba(225,20,20,.14),transparent);text-align:center;border:1px solid rgba(225,20,20,.5);border-radius:12px;padding:11px;color:var(--red-2);font-size:10.5px;font-weight:800;letter-spacing:.16em;text-transform:uppercase}
/* Everything from here up must out-rank .creveal's z-index:2, or the reveal paints over
   the divider, the handle and the corner tags. DOM order alone is not enough once a
   sibling earlier in the tree carries an explicit z-index. */
.cdivider{position:absolute;top:0;bottom:0;width:2px;background:var(--red);box-shadow:0 0 24px rgba(225,20,20,.7);pointer-events:none;z-index:4;transition:opacity .25s var(--ease)}
/* The drag hint. Bottom centre is the only spot that stays clear at every divider position. */
.chint{position:absolute;left:50%;bottom:11px;transform:translateX(-50%);z-index:6;
  display:inline-flex;align-items:center;gap:5px;white-space:nowrap;pointer-events:none;
  font-size:8.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
  background:rgba(7,8,11,.66);border:1px solid var(--line);border-radius:999px;
  padding:4px 9px;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.chint i{font-style:normal;color:var(--red-2);font-size:10px}
@media(max-width:560px){.chint{font-size:8px;padding:3px 8px;letter-spacing:.08em;bottom:9px}}

/* Tiles lift and straighten on hover — they are tilted like paper on a desk, so the motion that
   fits is picking one up. Position comes from left/top, so dropping the rotate() costs nothing.
   Set by JS, not :hover: the transparent slider covers the whole panel at z-index 6, so the
   pointer never reaches these elements. See the pointer-tracking block in app.js. */
.pcard,.scrap{transition:transform .28s var(--ease),box-shadow .28s var(--ease),border-color .28s var(--ease)}
.pcard.lift,.scrap.lift{transform:translateY(-7px) scale(1.045);z-index:6;
  box-shadow:0 26px 52px rgba(0,0,0,.72);border-color:rgba(255,255,255,.3)}
@media(prefers-reduced-motion:reduce){
  .pcard,.scrap{transition:none}
  .pcard.lift,.scrap.lift{transform:none}
}
.chandle{position:absolute;top:50%;transform:translate(-50%,-50%);width:50px;height:50px;border-radius:50%;background:var(--red);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:800;font-size:15px;box-shadow:0 8px 28px rgba(225,20,20,.5);pointer-events:none;z-index:5;transition:opacity .25s var(--ease)}
.cornertag{position:absolute;top:16px;z-index:5;font-size:10px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;padding:6px 12px;border-radius:999px;border:1px solid var(--line);background:rgba(7,8,11,.7);color:var(--dim);transition:color .3s var(--ease),border-color .3s var(--ease),background .3s var(--ease)}
.cornertag.l{left:16px}
.cornertag.r{right:16px}
/* the tag for whichever side the divider is currently giving the most room to. The pair
   is driven from the same paint() as the reveal, so the label can never disagree with
   what is actually on screen. */
.cornertag.on{color:var(--red-2);border-color:rgba(225,20,20,.45);background:rgba(225,20,20,.12)}
/* invisible, but sits above every layer in the panel so the whole artwork is the control.
   It stays opacity:0, so the focus ring has to be drawn by the wrapper instead. */
.cslider{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:ew-resize;margin:0;z-index:6}
.cmpwrap:has(.cslider:focus-visible){outline:2px solid var(--red-2);outline-offset:3px}

/* differentiators */
.diff-wide{margin-top:14px;padding:44px 42px}
.diff-wide .label{display:inline-block;margin-bottom:14px}

/* ---- "One joint, start to finish" ----
   jw- prefixed throughout: .dot and .chip already exist in this file. Single column on purpose —
   an earlier two-column version put a narrow tally beside the copy and its uppercase labels
   collided with their values between 820 and 900px. Nothing here is a space-between row that
   cannot wrap. */
.jw-modes{display:inline-flex;background:var(--panel);border:1px solid var(--line);
  border-radius:999px;padding:4px;gap:2px;margin-bottom:20px;max-width:100%;flex-wrap:wrap}
.jw-modes button{background:none;border:0;color:var(--dim);font:inherit;font-weight:600;
  font-size:13.5px;padding:11px 22px;border-radius:999px;cursor:pointer;white-space:nowrap;
  transition:background .25s var(--ease),color .25s var(--ease)}
.jw-modes button[aria-pressed="true"]{background:linear-gradient(135deg,var(--red-2),var(--red) 75%);
  color:#fff;box-shadow:0 6px 20px rgba(225,20,20,.32)}
.jw{padding:26px 28px}
.jw:hover{transform:none}
/* overflow-x:auto forces overflow-y to auto too, so the active dot's glow (6px down, 20px blur)
   was being clipped. The vertical padding gives it room; the negative margin keeps the spine
   sitting where it did. */
.jw-spine{display:flex;align-items:center;margin:-8px 0 14px;overflow-x:auto;padding:8px 2px}
.jw-dot{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;flex:none;
  border:1px solid var(--line-strong);background:var(--panel);color:var(--dim);font-size:11px;
  font-weight:800;cursor:pointer;font-variant-numeric:tabular-nums;
  transition:background .3s var(--ease),color .3s var(--ease),transform .3s var(--ease)}
.jw-dot.done{background:rgba(225,20,20,.18);border-color:rgba(225,20,20,.5);color:#ff9a90}
.jw-dot.on{background:linear-gradient(135deg,var(--red-2),var(--red) 75%);border-color:transparent;
  color:#fff;box-shadow:0 6px 20px rgba(225,20,20,.45);transform:scale(1.12)}
.jw-seg{width:24px;height:1px;background:var(--line);flex:none}
.jw-seg.done{background:rgba(225,20,20,.45)}
/* The controls must not move as the visitor clicks. Reserving space in em (not px) on the two
   variable-length elements keeps the button row fixed at every font size: the longest name runs
   to 2 lines, the longest description to 4 (offshore step 5, 215 characters). */
.jw-step{min-height:0}
.jw-count{font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--red-2);margin-bottom:8px;font-variant-numeric:tabular-nums}
.jw-name{font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-size:clamp(20px,2.5vw,29px);
  font-weight:700;letter-spacing:-.03em;line-height:1.14;margin-bottom:10px;max-width:22ch;
  min-height:2.28em}
.jw-desc{color:var(--muted);font-size:15px;margin:0 0 16px;max-width:68ch;line-height:1.62;
  min-height:6.48em}
.jw-who{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:18px}
.jw-who span{font-size:10.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:999px;padding:5px 10px;color:var(--dim)}
.jw-ctrls{display:flex;gap:10px;flex-wrap:wrap}
/* the breakdown: one segment per step, coloured by what the step actually is */
.jw-break{margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
.jw-break-hd{font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);margin-bottom:10px}
.jw-bar{display:flex;gap:2px;height:12px;border-radius:999px;overflow:hidden}
.jw-bar i{flex:1 1 0;min-width:3px;opacity:.42;
  transition:opacity .35s var(--ease),box-shadow .35s var(--ease)}
.jw-bar i.acc{background:rgba(139,146,153,.85)}
.jw-bar i.bolt{background:linear-gradient(180deg,var(--red-2),var(--red))}
.jw-bar i.insp{background:rgba(255,214,10,.8)}
.jw-bar i.test{background:rgba(255,255,255,.3)}
.jw-bar i.done{opacity:1}
/* inset, never an outer glow: a spread shadow on a 12px-tall segment bleeds over its neighbours
   and overflow:hidden traps it inside the bar, which reads as the segments overlapping */
.jw-bar i.on{opacity:1;box-shadow:0 0 0 2px rgba(255,255,255,.6) inset}
.jw-key{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:11px;font-size:11px;font-weight:600;
  letter-spacing:.04em;color:var(--dim)}
.jw-key span{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}
.jw-key i{width:9px;height:9px;border-radius:3px;flex:none}
.jw-key .k-acc{background:rgba(139,146,153,.85)}
.jw-key .k-bolt{background:var(--red)}
.jw-key .k-insp{background:rgba(255,214,10,.8)}
.jw-key .k-test{background:rgba(255,255,255,.3)}
/* the countable difference between the two modes, stated rather than buried in the prose */
.jw-figs{display:flex;flex-wrap:wrap;gap:10px 26px;margin-top:16px;padding-top:14px;
  border-top:1px solid var(--line)}
.jw-figs div{min-width:0}
.jw-figs b{display:block;font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-weight:800;
  font-size:clamp(20px,2.2vw,26px);letter-spacing:-.03em;color:var(--white);
  font-variant-numeric:tabular-nums;line-height:1.1}
.jw-figs span{display:block;margin-top:4px;font-size:10.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim)}
.jw-figs .hot b{color:#ff9a90}
.jw-figs.bump b{animation:jwFig .4s var(--ease)}
@keyframes jwFig{0%{transform:translateY(3px);opacity:.35}100%{transform:none;opacity:1}}
@media(max-width:760px){.jw-figs .rng{padding-left:0;border-left:0}}
/* the assumption is a visible control, not a hidden constant */
.jw-rate{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);max-width:520px}
.jw-rate label{display:flex;justify-content:space-between;align-items:baseline;gap:4px 12px;
  flex-wrap:wrap;font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim)}
.jw-rate label b{font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-size:15px;
  color:var(--white);letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.jw-rate input{width:100%;margin-top:9px;accent-color:var(--red)}
.jw-note{margin:8px 0 0;font-size:11.5px;color:var(--dim);line-height:1.5}
.jw-insight{margin:14px 0 0;font-size:14px;color:var(--muted);line-height:1.6;max-width:74ch}
.jw-insight b{color:var(--white);font-weight:600}
.jw-fin{margin-top:20px;border:1px solid rgba(225,20,20,.45);border-radius:18px;padding:22px 26px;
  background:radial-gradient(circle at 20% 0%,rgba(225,20,20,.18),transparent 62%)}
.jw-fin[hidden],.jw-tside[hidden]{display:none!important}
.jw-tot{font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-weight:900;
  font-size:clamp(28px,4vw,44px);letter-spacing:-.045em;line-height:1;margin-bottom:10px;
  font-variant-numeric:tabular-nums}
.jw-figs .rng b{font-size:clamp(16px,1.8vw,21px);color:var(--muted)}
.jw-figs .rng{padding-left:22px;border-left:1px solid var(--line)}
.jw-fin .big{font-family:'Space Grotesk','Inter',system-ui,sans-serif;font-weight:800;
  font-size:clamp(22px,3vw,32px);letter-spacing:-.035em;line-height:1.12}
.jw-fin p{color:var(--muted);font-size:14.5px;margin:10px 0 0;max-width:66ch}
.jw-bench{margin-top:14px;padding-top:14px;border-top:1px solid var(--line);font-size:12.5px;
  color:var(--dim);line-height:1.6;max-width:74ch}
.jw-bench b{color:var(--white)}
.jw-flip{margin-top:16px}
.jw-tside{margin-top:18px;border:1px solid rgba(48,209,88,.35);border-radius:18px;padding:18px 24px 20px;
  background:radial-gradient(circle at 20% 0%,rgba(48,209,88,.1),transparent 60%)}
.jw-tside h3{font-size:clamp(17px,2.1vw,22px);font-weight:700;margin-bottom:8px}
.jw-back{display:inline-block;background:none;border:0;padding:0;margin-bottom:12px;cursor:pointer;
  font:inherit;font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);transition:color .25s var(--ease)}
.jw-back:hover{color:var(--white)}
.jw-tline{display:flex;gap:11px;align-items:flex-start;padding:5px 0;color:var(--muted);
  font-size:13.5px;line-height:1.5}
.jw-tline .tk{color:var(--ok);font-weight:800;flex:none}
@media(prefers-reduced-motion:reduce){.jw-dot.on{transform:none}.jw-bar i{transition:none}
  .jw-figs.bump b{animation:none}}
/* below 620 the description wraps to far more than four lines, so reserved space cannot keep
   the button still — release it rather than leave a large empty gap on a phone */
@media(max-width:620px){.jw{padding:22px 18px}.jw-name{max-width:none;min-height:0}.jw-desc{min-height:0}}
.dw-big{font-weight:800;font-size:clamp(26px,3.4vw,42px);line-height:1.15;letter-spacing:-.035em;margin-bottom:14px}
.dw-sub{color:var(--muted);font-size:16.5px;max-width:640px;line-height:1.65}
/* roi */
.roi{display:block;overflow:hidden;border-radius:var(--r);padding:34px 36px 30px}
.roi:hover{transform:none}

.roi .side{padding:0}
.roi .side.out{background:rgba(0,0,0,.4);border-left:1px solid var(--line);display:flex;flex-direction:column;justify-content:center}
@media(max-width:900px){.roi .side.out{border-left:0;border-top:1px solid var(--line)}}
.roi h3{font-weight:700;font-size:24px;letter-spacing:-.025em;margin-bottom:6px}
.roi .roi-sub{color:var(--muted);font-size:15.5px}
.roi label{display:block;font-size:15px;font-weight:500;color:var(--muted);margin:26px 0 10px}
.roi input[type=range]{width:100%;accent-color:var(--red)}
.roi .val{font-family:'Space Mono',monospace;font-size:12.5px;color:var(--white)}
.roi .big-n{font-weight:900;font-size:clamp(42px,4.8vw,64px);letter-spacing:-.05em;line-height:1}
.roi .cap{margin-top:14px;color:var(--muted);font-size:15.5px;max-width:380px;line-height:1.6}
.calc-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.ctab{border:1px solid var(--line);background:rgba(255,255,255,.04);color:var(--muted);border-radius:999px;padding:11px 22px;font-size:15px;font-weight:600;cursor:pointer;transition:all .25s;font-family:inherit}
.ctab.on{background:var(--red);border-color:transparent;color:#fff;box-shadow:0 8px 26px rgba(225,20,20,.35)}
.persona-sub{color:var(--muted);font-size:15.5px;margin:0 0 6px}
.calc-split{display:grid;grid-template-columns:1.02fr .98fr;gap:40px;align-items:start}
@media(max-width:860px){.calc-split{grid-template-columns:1fr;gap:26px}}
.calc-note{display:flex;align-items:center;gap:8px;font-size:11px;letter-spacing:.05em;color:var(--dim);text-transform:uppercase}
.cinfo{position:relative;display:inline-flex}
.cinfo button{width:18px;height:18px;border-radius:50%;border:1px solid var(--line);background:rgba(255,255,255,.05);color:var(--dim);font-size:10.5px;font-weight:700;cursor:pointer;line-height:1;font-family:inherit;transition:all .2s;padding:0}
.cinfo button:hover{border-color:var(--red-2);color:var(--red-2)}
.tip{position:absolute;bottom:150%;right:-10px;width:min(360px,84vw);background:#101116;border:1px solid var(--line);border-radius:14px;padding:16px 18px;font-size:12px;line-height:1.75;color:var(--muted);letter-spacing:0;text-transform:none;opacity:0;visibility:hidden;transform:translateY(6px);transition:all .25s var(--ease);box-shadow:0 22px 50px rgba(0,0,0,.6);z-index:5}
.tip b{color:var(--white)}
.cinfo:hover .tip,.cinfo.open .tip{opacity:1;visibility:visible;transform:none}
.j-rows{display:flex;flex-direction:column;gap:11px;margin:16px 0 16px}
.j-row{display:flex;align-items:baseline;gap:8px;font-size:14.5px;color:var(--muted);border-bottom:1px dashed var(--line);padding-bottom:10px}
.j-row span{color:var(--white);font-weight:700;white-space:nowrap}
.j-row b{margin-left:auto;color:var(--red-2);font-weight:700;font-family:'Space Mono',monospace;font-size:12.5px;white-space:nowrap;padding-left:12px}
.roi .note{margin-top:22px;font-size:10.5px;font-weight:700;letter-spacing:.1em;color:var(--dim);text-transform:uppercase}

/* ============ CONTACT ============ */
.contact-hero{text-align:center;min-height:calc(var(--vhz,100vh) - var(--nav,84px) - var(--viewpad-top));display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 0 24px}
.contact-hero img.lockup{width:min(480px,78vw);max-height:calc(var(--vhz,100vh)*0.30);object-fit:contain;height:auto;margin-bottom:14px;filter:drop-shadow(0 14px 48px rgba(225,20,20,.26))}
.contact-hero h2{font-weight:700;font-size:min(4.4vw,calc(var(--vhz,100vh)*0.06),54px);line-height:1.04;letter-spacing:-.04em;margin-bottom:12px}
.contact-hero .lede{color:var(--muted);max-width:540px;margin:0 auto 20px;font-size:clamp(15px,1.3vw,17px);line-height:1.6}
/* onboarding — the three pilot steps */
.onb{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;text-align:left}
@media(max-width:900px){.onb{grid-template-columns:1fr}}
.onb .card{padding:30px 28px}
.onb .step{font-size:12px;font-weight:800;letter-spacing:.16em;color:var(--red-2);margin-bottom:14px}
/* the pilot steps were h4 under an h2 — a two-level skip; they are h3 now */
.onb h3{font-weight:700;font-size:18px;letter-spacing:-.02em;margin-bottom:8px}
.onb p{font-size:15px;color:var(--muted);line-height:1.6}
.pilot-note{margin-top:16px;font-size:13.5px;color:var(--dim);text-align:left}
.dmodal .sg{opacity:1;animation:none}
/* The card is centred already; what made it scroll was height — the form ran past the
   92vh cap and overflow-y took over. Every vertical measure in here is now sized against
   the viewport's height, so the whole form fits on a laptop screen without scrolling. The
   max-height and overflow stay as a floor for genuinely tiny windows; clipping the submit
   button would be worse than a scrollbar. */
/* align-items:center used to centre the card. When the card is taller than the
   window — a 1366x768 laptop, or a 1080p screen once the browser chrome and
   taskbar come off — a centred flex item overflows EQUALLY top and bottom, and
   the overflow above the container cannot be scrolled to. The card's heading and
   its close button ended up above the top edge, unreachable, and the modal looked
   chopped off with no visible way out.
   The container scrolls instead, and margin:auto on the card still centres it
   whenever there is room. This is immune to how tall the card gets, and to the
   body zoom that applies above 1500px. */
.dmodal{position:fixed;inset:0;z-index:210;display:flex;align-items:flex-start;justify-content:center;padding:clamp(12px,2vh,22px);overflow-y:auto;overscroll-behavior:contain}
.dmodal[hidden]{display:none}
/* fixed, not absolute: the container is now a scroll box, and an absolute
   backdrop would scroll away with it, leaving the page bare behind the card. */
.dmodal-bg{position:fixed;inset:0;background:rgba(4,5,7,.9);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.dmodal-card{position:relative;margin:auto;width:min(600px,96vw);background:linear-gradient(160deg,#101218,#0A0B0F);border:1px solid var(--line);border-radius:26px;padding:clamp(24px,3.4vh,38px) 40px clamp(20px,3vh,34px);box-shadow:0 40px 100px rgba(0,0,0,.75);animation:dIn .4s var(--ease) both}
@media(max-width:640px){.dmodal-card{padding:30px 24px 26px}}
@keyframes dIn{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}
.dclose{position:absolute;top:18px;right:18px;background:rgba(255,255,255,.07);border:1px solid var(--line);color:var(--white);border-radius:50%;width:34px;height:34px;font-size:14px;cursor:pointer;transition:all .25s}
.dclose:hover{background:var(--red);border-color:var(--red)}
.dm-title{font-weight:700;font-size:min(2.6vw,3.4vh,29px);letter-spacing:-.03em;line-height:1.15;margin:clamp(5px,1vh,10px) 0 clamp(12px,2.4vh,22px)}
@media(max-width:900px){.dm-title{font-size:min(21px,3.4vh)}}

/* demo form */
.dform{width:100%;text-align:left}
.f-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:640px){.f-row{grid-template-columns:1fr}}
.fld{margin-bottom:clamp(8px,1.5vh,14px)}
.fld label{display:block;font-size:13.5px;font-weight:600;color:var(--muted);margin-bottom:clamp(4px,.8vh,7px)}
.fld input,.fld select,.fld textarea{width:100%;background:rgba(255,255,255,.045);border:1px solid var(--line);border-radius:13px;padding:clamp(9px,1.4vh,13px) 15px;color:var(--white);font-family:inherit;font-size:15.5px;outline:0;transition:border-color .25s}
.fld input:focus,.fld select:focus,.fld textarea:focus{border-color:rgba(225,20,20,.6)}
.fld input::placeholder,.fld textarea::placeholder{color:var(--dim)}
.fld textarea{min-height:clamp(54px,9vh,86px);line-height:1.55;resize:vertical}
.lbl-opt{font-weight:500;color:var(--dim)}
.fcount{margin-top:clamp(3px,.6vh,6px);text-align:right;font-size:11.5px;font-weight:700;letter-spacing:.08em;color:var(--dim);transition:color .2s}
/* the submit gives back a little height too, rather than keeping the page-wide 16px */
.dform .btn{padding:clamp(11px,1.9vh,16px) 34px}
.fcount.near{color:var(--amber)}
.fcount.full{color:var(--red-2)}
.vhidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* the chevron is positioned from the vertical centre, not a fixed 20px from the top —
   the field's padding now flexes with viewport height and the arrow has to follow it */
.fld select{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--dim) 50%),linear-gradient(135deg,var(--dim) 50%,transparent 50%);background-position:calc(100% - 20px) calc(50% - 2px),calc(100% - 15px) calc(50% - 2px);background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.fld select option{background:#101116;color:var(--white)}
.hp{position:absolute;left:-9999px;opacity:0;height:0;overflow:hidden}
.ferr{display:none;margin-top:12px;color:var(--red-2);font-size:14px;line-height:1.6}
.ferr.show{display:block}
.fld input:invalid.touched,.fld select:invalid.touched{border-color:rgba(225,20,20,.6)}
.dthanks{display:none;text-align:left}
.dthanks.on{display:block}
.dthanks h3{font-weight:700;font-size:22px;letter-spacing:-.03em;margin-bottom:16px}
.tick-big{width:52px;height:52px;border-radius:50%;background:rgba(48,209,88,.14);border:1px solid rgba(48,209,88,.45);color:var(--ok);display:flex;align-items:center;justify-content:center;font-size:23px;margin-bottom:16px}
.dthanks-line{color:var(--muted);font-size:15.5px;line-height:1.6;max-width:44ch}
.dthanks-line b{color:var(--white);font-weight:600}
/* the two steps above the form. Height is clamped against viewport height like the rest of the
   dialog, so adding them cannot push the submit button off a short screen. */
.dsteps{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;
  margin:0 0 clamp(14px,2.4vh,22px);text-align:left}
.dsteps > div{background:rgba(255,255,255,.04);border:1px solid var(--line);border-radius:11px;
  padding:clamp(10px,1.6vh,14px) 14px}
.dsteps .nn{display:inline-grid;place-items:center;width:19px;height:19px;border-radius:50%;
  background:linear-gradient(135deg,var(--red-2),var(--red) 75%);color:#fff;font-size:10px;
  font-weight:800;margin-bottom:7px}
.dsteps b{display:block;font-size:12.5px;font-weight:600;color:var(--white);margin-bottom:3px}
.dsteps .t{display:block;font-size:11.5px;color:var(--dim);line-height:1.45}
@media(max-width:520px){.dsteps{grid-template-columns:1fr;gap:8px}}
/* a short landscape phone has no room for them beside a six-field form */
@media(max-height:620px){.dsteps{display:none}}
.nn{flex:none;width:23px;height:23px;border-radius:50%;border:1px solid var(--line);color:var(--red-2);font-size:11px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;margin-top:1px}

/* self-assessment */
.qbox{max-width:680px;padding:28px 30px}
.qprog{height:3px;background:rgba(255,255,255,.1);border-radius:3px;margin-bottom:20px;overflow:hidden}
.qprog i{display:block;height:100%;width:20%;background:linear-gradient(90deg,var(--red-2),var(--red));transition:width .4s var(--ease)}
.qn{font-family:'Space Mono',monospace;font-size:11.5px;color:var(--red-2);letter-spacing:.1em;margin-bottom:9px}
.qt{font-size:19.5px;font-weight:700;letter-spacing:-.02em;margin-bottom:18px;line-height:1.38}
.opt{display:block;width:100%;text-align:left;border:1px solid var(--line);background:rgba(255,255,255,.035);color:var(--white);border-radius:13px;padding:14px 17px;font-family:inherit;font-size:15.5px;cursor:pointer;margin-bottom:10px;transition:all .22s}
.opt:hover{border-color:rgba(225,20,20,.5);background:rgba(225,20,20,.09)}
.qres{display:none}
.qres.on{display:block}
.score{font-family:'Space Grotesk';font-weight:700;font-size:50px;letter-spacing:-.04em;line-height:1}
.verdict{font-size:19px;font-weight:700;margin:12px 0 10px;letter-spacing:-.02em}
.qres p{color:var(--muted);font-size:15.5px;line-height:1.7;margin-bottom:18px;max-width:560px}
.qres .btn{margin-right:10px}

.chip{display:inline-flex;align-items:center;gap:7px;border:1px solid rgba(48,209,88,.4);background:rgba(48,209,88,.08);color:var(--ok);border-radius:999px;padding:8px 15px;font-size:13px;font-weight:600;margin:0 8px 8px 0}
.inline-link{background:none;border:0;color:var(--red-2);font:inherit;font-weight:600;cursor:pointer;padding:0;border-bottom:1px solid rgba(225,20,20,.4);transition:all .2s}
.inline-link:hover{border-color:var(--red-2)}
.foot-link{background:none;border:0;color:var(--dim);font:inherit;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;cursor:pointer;transition:color .25s;text-decoration:none}
.foot-link:hover{color:var(--white)}
/* the footer's link cluster — keeps them together when the row wraps */
.foot-links{display:flex;align-items:center;gap:22px;flex-wrap:wrap}

/* faq */
.faq{max-width:760px;margin:0 auto;text-align:left}

.btn.play .ptri{width:0;height:0;border-left:9px solid currentColor;border-top:6px solid transparent;border-bottom:6px solid transparent;margin-right:2px;display:inline-block}
.bigfoot.in-contact{border-top:1px solid var(--line);margin-top:var(--sect-gap);padding:44px 0 8px}
.bigfoot-grid{display:grid;grid-template-columns:1.3fr .7fr;gap:44px;align-items:start}
@media(max-width:820px){.bigfoot-grid{grid-template-columns:1fr}}
/* Newsletter not configured (no NEWSLETTER_KEY in app.js): the whole band goes,
   not just the signup column. Hiding the column alone left "Connect" — a label
   and one 34px icon — stranded in a 230px band of empty space, and that icon is
   already in the main footer directly below, so it was dead space AND a
   duplicate. Set the key and the band returns with no markup change. */
.bigfoot.nl-off{display:none}
.bf-sub h3{font-weight:800;font-size:clamp(18px,1.9vw,23px);letter-spacing:-.02em;margin-bottom:8px}
.bf-sub p{color:var(--muted);font-size:15.5px;margin-bottom:20px;max-width:460px}
.bf-form{display:flex;max-width:460px;border:1px solid var(--line);border-radius:16px;overflow:hidden;background:rgba(255,255,255,.04);transition:border-color .25s}
.bf-form:focus-within{border-color:rgba(225,20,20,.6)}
.bf-form input{flex:1;background:transparent;border:0;outline:0;color:var(--white);font-family:inherit;font-size:15.5px;padding:15px 18px}
.bf-form input::placeholder{color:var(--dim)}
.bf-form button{background:transparent;border:0;color:var(--red-2);font-size:20px;padding:0 20px;transition:all .25s;cursor:pointer}
.bf-form button:hover{background:var(--red);color:#fff}
.bf-done{display:none;color:var(--ok);font-size:14px;font-weight:600;margin-top:14px}
.bf-done.show{display:block}
.bf-connect h4{font-size:11px;font-weight:800;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-bottom:16px}
.bf-icons{display:flex;gap:12px}
.bf-icons a{width:42px;height:42px;border-radius:50%;background:#F5F6F7;color:#0A0B0F;display:inline-flex;align-items:center;justify-content:center;transition:all .25s}
.bf-icons a:hover{background:var(--red);color:#fff;transform:translateY(-2px)}
/* Two rows: identity + contact on top, copyright + links underneath. The address used to
   exist only inside the Contact view, so four of the five pages ended without one — a
   buyer checking whether this is a real company had nowhere to look. */
footer{border-top:1px solid var(--line);padding:34px 0 20px;position:relative;z-index:1}
.f-top{display:flex;justify-content:space-between;align-items:stretch;gap:34px;flex-wrap:wrap;
  padding-bottom:22px;border-bottom:1px solid rgba(255,255,255,.07)}
/* Equal-height columns, each starting on the same line. The three blocks hold very different
   amounts (one image, a three-part credit, a four-line address), so flex-start left the row
   looking ragged. stretch makes the columns match the tallest, and space-between distributes
   them; the content still begins at the top of each, so the eye reads one line across. */
.f-id{display:flex;flex-direction:column;gap:12px;align-items:flex-start;justify-content:flex-start}
/* the lockup artwork, so the wordmark and the assurance line keep the brand type */
.f-mark{height:52px;width:auto;display:block;filter:drop-shadow(0 0 10px rgba(255,255,255,.1))}
.f-addr{font-style:normal;color:var(--dim);font-size:13.5px;line-height:1.8;letter-spacing:0;text-transform:none}
/* Three columns on one row: brand, the Tri-Star credit, then how to reach the company.
   The credit moved here from the Contact page so it appears on every page. */
.f-sol{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  text-align:center;gap:9px;flex:0 1 auto}
.f-sol .lbl{font-size:10px;font-weight:700;letter-spacing:.26em;text-transform:uppercase;color:var(--dim)}
.f-sol img{height:44px;width:auto;opacity:.95}
.f-sol .cco,.cco{font-weight:800;font-size:13px;letter-spacing:.09em;color:var(--white)}
/* the address and the LinkedIn mark are both ways of reaching the company, so they share
   a column and the icon sits under the last line rather than off in its own group */
.f-contact{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;
  gap:12px;text-align:right}
.f-contact .f-addr{text-align:right}
@media(max-width:900px){
  .f-sol{align-items:flex-start;text-align:left}
  .f-contact{align-items:flex-start;text-align:left}
  .f-contact .f-addr{text-align:left}
}
.f-addr a{transition:color .25s}
.f-addr a:hover{color:var(--white)}
.f-li{width:34px;height:34px;flex:none;border-radius:50%;border:1px solid var(--line);display:grid;place-items:center;color:var(--muted);transition:all .25s}
.f-li:hover{color:#fff;border-color:rgba(225,20,20,.55);background:rgba(225,20,20,.14)}
.f-bot{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;align-items:center;padding-top:17px}
.f-copy{font-size:11.5px;font-weight:600;letter-spacing:.08em;color:#5c626b}
@media(max-width:760px){
  .f-top{flex-direction:column;gap:24px}
    .f-bot{flex-direction:column;align-items:flex-start;gap:13px}
  .f-mark{height:46px}
}

/* ============ LEGAL PAGES (privacy, terms) ============
   Two views sharing one layout: a sticky contents rail and a measured column of clauses.
   Everything above the rail — .viewpad, .vhead, .label — is the site's existing furniture,
   so these pages inherit the header, footer, router and type scale for free. */
.legal-stamp{font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);margin-top:6px;display:block}
.legal{display:grid;grid-template-columns:206px minmax(0,1fr);gap:54px;align-items:start}
@media(max-width:900px){.legal{grid-template-columns:1fr;gap:24px}}
.legal-toc{position:sticky;top:calc(var(--nav,84px) + 18px);border-left:1px solid var(--line);
  padding-left:19px;display:flex;flex-direction:column;gap:1px}
@media(max-width:900px){
  .legal-toc{position:relative;top:auto;border-left:0;border-top:1px solid var(--line);
    padding:15px 0 0;flex-direction:row;flex-wrap:wrap;gap:7px 16px}
}
.legal-toc-t{font-size:10px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);margin-bottom:11px}
@media(max-width:900px){.legal-toc-t{width:100%;margin-bottom:1px}}
.legal-toc a{display:flex;gap:9px;font-size:12.5px;color:var(--dim);padding:5px 0;transition:color .22s}
.legal-toc a i{font-style:normal;font-family:'Space Mono',monospace;font-size:11px;opacity:.6}
.legal-toc a:hover{color:var(--white)}
.legal-body{max-width:76ch}
/* scroll-margin keeps a jumped-to clause clear of the sticky header */
.cl{padding-bottom:28px;margin-bottom:28px;border-bottom:1px solid var(--line);scroll-margin-top:calc(var(--nav,84px) + 20px)}
.cl:last-child{border-bottom:0;margin-bottom:0;padding-bottom:0}
.cl-n{display:inline-block;font-size:10.5px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:var(--red-2);margin-bottom:10px}
.cl h3{font-weight:700;font-size:21px;letter-spacing:-.025em;line-height:1.25;margin-bottom:12px}
.cl p{color:var(--muted);font-size:15.5px;line-height:1.72;margin-bottom:12px}
.cl p:last-child{margin-bottom:0}
.cl strong{color:var(--white);font-weight:600}
.cl a{color:var(--red-2)}
.cl a:hover{text-decoration:underline}
.cl ul{margin:0 0 12px;padding-left:20px;color:var(--muted);font-size:15.5px;display:flex;flex-direction:column;gap:6px}
.cl-tbl{border:1px solid var(--line);border-radius:16px;overflow:hidden;margin:2px 0 12px}
.cl-tbl>div{display:grid;grid-template-columns:190px minmax(0,1fr);border-bottom:1px solid var(--line)}
.cl-tbl>div:last-child{border-bottom:0}
@media(max-width:620px){.cl-tbl>div{grid-template-columns:1fr}}
.cl-tbl .k{padding:13px 16px;font-size:13.5px;font-weight:700;background:rgba(255,255,255,.035)}
.cl-tbl .v{padding:13px 16px;font-size:14.5px;color:var(--muted);border-left:1px solid var(--line)}
@media(max-width:620px){.cl-tbl .v{border-left:0;border-top:1px solid var(--line)}}
.cl-good,.cl-warn{border-radius:18px;padding:19px 21px;margin:2px 0 12px}
.cl-good{border:1px solid rgba(48,209,88,.35);background:rgba(48,209,88,.06)}
.cl-warn{border:1px solid rgba(225,20,20,.42);background:linear-gradient(120deg,rgba(225,20,20,.1),transparent)}
.cl-good .t,.cl-warn .t{display:block;font-size:11px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;margin-bottom:8px}
.cl-good .t{color:var(--ok)} .cl-warn .t{color:var(--red-2)}
.cl-good p,.cl-warn p{margin:0}
/* deliberately loud: an unfilled value must not slip out onto a published legal page */
.cl-blank{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.14em;color:var(--amber);
  border:1px dashed rgba(255,214,10,.6);border-radius:5px;padding:1px 8px}

/* ============ LARGE-DISPLAY SCALING ============
   Scales the whole interface proportionally on big screens
   (desktop monitors → TVs → projectors). Phones/laptops unchanged. */
@media (min-width:1500px){body{zoom:1.12}:root{--z:1.12}}
@media (min-width:1750px){body{zoom:1.25}:root{--z:1.25}}
@media (min-width:2100px){body{zoom:1.45}:root{--z:1.45}}
@media (min-width:2600px){body{zoom:1.7}:root{--z:1.7}}
@media (min-width:3300px){body{zoom:2.1}:root{--z:2.1}}

/* ============ PRODUCT SCREENS (EXTRACT stage) ============
   The screenshots are light UI on a near-black page. Three things stop them
   glaring: dark browser chrome around them, a slight tone-down, and a red halo
   behind, so the brightness reads as brand light rather than a stray image. */
.shots{width:100%;max-width:560px;margin:0 auto}
.shot-tabs{display:flex;gap:4px;margin-bottom:14px}
.shot-tab{flex:1;min-width:0;background:rgba(255,255,255,.035);border:1px solid var(--line);border-radius:12px;
  padding:9px 12px;text-align:left;color:var(--dim);font-family:inherit;font-size:12.5px;font-weight:600;
  cursor:pointer;transition:all .32s var(--ease);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.shot-tab .k{display:block;font-size:9.5px;font-weight:800;letter-spacing:.16em;opacity:.7;margin-bottom:4px}
.shot-tab:hover{color:var(--muted);border-color:var(--line-strong)}
.shot-tab.on{color:var(--white);border-color:rgba(225,20,20,.5);background:linear-gradient(180deg,rgba(225,20,20,.16),rgba(225,20,20,.05))}
.shot-tab.on .k{color:var(--red-2);opacity:1}

.shot-frame{position:relative;border:1px solid rgba(255,255,255,.14);border-radius:14px;overflow:hidden;
  background:#0A0B0F;box-shadow:0 26px 60px rgba(0,0,0,.7)}
.shot-halo{position:absolute;inset:-18% -10%;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse at 50% 45%,rgba(225,20,20,.2),rgba(225,20,20,.04) 48%,transparent 72%);filter:blur(16px)}
.shot-bar{position:relative;z-index:1;height:26px;background:#15171E;border-bottom:1px solid rgba(255,255,255,.08);
  display:flex;align-items:center;gap:6px;padding:0 10px}
.shot-bar i{width:8px;height:8px;border-radius:50%;background:#2C3038;flex:none}
.shot-bar b{margin-left:8px;font-family:'Space Mono',monospace;font-size:9.5px;font-weight:400;letter-spacing:.08em;color:#5C636E}

.shot-stack{position:relative;z-index:1;display:block;width:100%;aspect-ratio:1908/910;
  border:0;padding:0;background:#0A0B0F;cursor:zoom-in;overflow:hidden}
.shot-stack img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;
  transform:scale(1.012);transition:opacity .5s var(--ease),transform .8s var(--ease);
  filter:brightness(.93) saturate(.94) contrast(1.02)}
.shot-stack img.on{opacity:1;transform:none}
.shot-stack:hover img.on{filter:none}
/* the red read-line, same motif as the mock it replaced */
.shot-scan{position:absolute;top:0;bottom:0;left:-90px;width:90px;pointer-events:none;z-index:3;opacity:0;
  background:linear-gradient(90deg,transparent,rgba(225,20,20,.06) 30%,rgba(255,69,58,.5) 50%,rgba(225,20,20,.06) 70%,transparent);
  box-shadow:0 0 40px rgba(225,20,20,.45)}
/* .8s, not 1.1s — the sweep no longer gates the screen swap, so it only has to read as a
   pass across the new capture. The badge flips to CAPTURED at 820ms, just as it exits. */
.shot-scan.run{opacity:1;animation:shotSweep .8s var(--ease)}
@keyframes shotSweep{from{left:-90px}to{left:100%}}
.shot-zoom{position:absolute;right:10px;bottom:10px;z-index:4;font-size:9.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--white);background:rgba(7,8,11,.72);border:1px solid var(--line);
  border-radius:999px;padding:5px 11px;opacity:0;transition:opacity .3s var(--ease);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.shot-stack:hover .shot-zoom,.shot-stack:focus-visible .shot-zoom{opacity:1}

/* A GRID, not a flex row. Under flex, each item's position depends on its neighbours'
   widths — so the counter shifted every time the badge text changed length, and the arrow
   you just clicked moved out from under the pointer. Three fixed columns pin the counter
   to the left edge and the badge to the right, and only the caption in the middle reflows.
   The control is now in the same place on every screen of every module. */
.shot-foot{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;
  gap:12px;margin-top:13px}
/* Centred between the two pills, and guaranteed to one line. The captions are written
   short enough that the ellipsis should never appear — it is the backstop, not the plan,
   because a caption that wraps changes the row's height and nudges everything below it. */
.shot-cap{min-width:0;text-align:center;font-size:12.5px;font-weight:600;color:var(--muted);
  letter-spacing:.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* a badge is a label, not a paragraph: never shrink it, never break it across two lines */
.shot-foot .badge{justify-self:end;white-space:nowrap}
/* The caption and badge fade up on each change rather than snapping. Re-triggered by
   removing the class, forcing a reflow and re-adding it — the same idiom the EXTRACT scan
   line uses, so there is one way of doing this in the file rather than two. */
.shot-foot.swap .shot-cap,.shot-foot.swap .badge{animation:capIn .34s var(--ease) both}
@keyframes capIn{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.shot-foot.swap .shot-cap,.shot-foot.swap .badge{animation:none}}

/* ---- "‹ 01 / 03 ›" — the count, and a second way to move ----
   Every stage has a stepper of its own, but none of them says how many screens exist, and
   a spine of dim dots reads as "you are at step 1 of 3" rather than "click me". Arrows are
   unambiguous, and the fraction answers the question the steppers never did. */
/* first grid column, so its left edge is the row's left edge — a fixed anchor. Its own
   width is constant too: the fraction is always NN/NN and .sn-c is tabular-nums, so going
   from 9 to 10 screens would not nudge it either. */
.stepnav{display:inline-flex;align-items:center;gap:2px;
  border:1px solid var(--line);border-radius:999px;padding:2px;background:rgba(255,255,255,.04)}
.sn-b{width:22px;height:22px;flex:none;display:grid;place-items:center;background:none;border:0;
  border-radius:50%;color:var(--dim);font-family:inherit;font-size:15px;line-height:1;cursor:pointer;
  transition:all .22s var(--ease)}
.sn-b:hover{color:var(--white);background:rgba(225,20,20,.22)}
/* inset, so the ring hugs the button instead of floating off it as a detached circle */
.sn-b:focus-visible{outline:2px solid var(--red-2);outline-offset:-2px}
.sn-c{font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.06em;color:var(--dim);
  padding:0 5px;font-variant-numeric:tabular-nums}
.sn-c b{color:var(--white);font-weight:400}
.sn-c i{font-style:normal;opacity:.5;padding:0 1px}

/* ---- INSPECT: tablet frame ----
   The other three modules show landscape desktop captures behind browser chrome. These are
   portrait tablet screens (1200x1920), so they get a tablet instead — which is also the
   truth about the module: inspection is the step carried out at the joint, on a handheld.
   Reuses .shots / .shot-tabs / .shot-stack / .shot-foot; only the frame is new.
   Even bezels all round with a single camera dot, and a shallower corner radius than a
   phone would carry — that difference is most of what reads as "tablet". */
/* Everything centres on one axis; nothing is forced to a shared width. Tying the tab row
   to the tablet's width made the four labels wrap, so the row keeps its own natural width.

   --tabh is the single source of truth for the tablet's size: one number that the frame's
   height, the frame's width and the caption row all derive from. It is the space actually
   left in the demo column rather than a flat fraction of the viewport — 370px is the fixed
   overhead above and below it (sticky nav, view padding, the module bar, the tab row, the
   caption row and the bezel). A flat 46vh was leaving ~130px of the column unused, which
   is the empty space around the tablet. */
/* --tabh is the tablet's height, --tabasp its width/height. Both modules that use a tablet
   frame set their own aspect because their captures differ: INSPECT is 1200x1806 (.66445),
   EXECUTE 800x1184 (.67568) after the Android chrome comes off. Keeping the ratio a token
   means the frame, its width and the caption row all stay in agreement without repeating
   a magic number. */
.tablet-shots{--tabh:min(680px,calc(var(--vhz,100vh) - 370px));--tabasp:.66445;
  display:flex;flex-direction:column;align-items:center;width:100%;max-width:none;margin:0}
#e-shots{--tabasp:.67568}
/* one row, always: labels size to their own text and never wrap or ellipsise. On a narrow
   column the row scrolls sideways rather than stacking. Type scales with the tablet so the
   two stay in proportion. */
.tablet-shots .shot-tabs{width:auto;max-width:100%;flex-wrap:nowrap;justify-content:center;
  margin-bottom:16px;overflow-x:auto;scrollbar-width:none}
.tablet-shots .shot-tabs::-webkit-scrollbar{display:none}
.tablet-shots .shot-tab{flex:0 0 auto;white-space:nowrap;
  padding:clamp(9px,1.25vh,12px) clamp(13px,1.9vh,18px);font-size:clamp(11.5px,1.45vh,13.5px)}
/* The caption row sits on the tablet's own edges — 0.66445 is 1200/1806 (the crop), +28px
   the frame's padding and border under border-box — but it now carries three things, and
   a short viewport makes the tablet too narrow to hold them. min-width wins over width in
   CSS, so this reads as "the tablet's width, but never less than 400px". */
.tablet-shots .shot-foot{width:calc(var(--tabh) * var(--tabasp) + 28px);
  min-width:min(100%,400px);max-width:100%}
@media(max-width:940px){.tablet-shots{--tabh:min(640px,74vh)}}
/* inline-block so the frame shrinks to the screenshot inside it — the stack's width is
   derived from its height via aspect-ratio, and this is what lets that width win */
.tab-frame{position:relative;display:inline-block;border-radius:20px;padding:15px 13px 13px;
  background:linear-gradient(160deg,#23252c,#111318);border:1px solid rgba(255,255,255,.16);
  box-shadow:0 26px 60px rgba(0,0,0,.7),0 0 0 1px rgba(0,0,0,.5)}
.tab-cam{position:relative;z-index:2;display:block;width:5px;height:5px;border-radius:50%;
  background:rgba(255,255,255,.24);box-shadow:inset 0 0 0 1px rgba(0,0,0,.55);margin:0 auto 9px}
/* Height drives the size — the demo column runs out of height long before it runs out of
   width — and the width follows from the 1200x1806 aspect, so the crop is never distorted.
   --tabh is set on .tablet-shots above, which is also what the caption row measures from. */
.tab-stack{aspect-ratio:var(--tabasp);height:var(--tabh);width:auto;max-width:100%;
  border-radius:9px;overflow:hidden;background:#fff}
/* the outgoing screen sits a hair larger, so the incoming one settles into place instead
   of simply appearing — enough to feel deliberate, small enough not to read as movement */
.tab-stack img{object-fit:cover;object-position:top;transform:scale(1.015);
  transition:opacity .45s var(--ease),transform .55s var(--ease)}
.tab-stack img.on{transform:none}
@media(prefers-reduced-motion:reduce){.tab-stack img{transform:none;transition:none}}
@media(max-width:900px){
  .shot-tabs{gap:3px}
  .shot-tab{font-size:11.5px;padding:8px 9px}
  .shot-tab .k{font-size:9px}
}

/* ---- CALCULATE: wizard spine ----
   Mirrors the numbered stepper inside the product. Reuses .shot-frame / .shot-stack /
   .shot-foot above; only the spine itself is new. The screens are 1875x903 rather than
   the 1908x910 of the EXTRACT set, hence the aspect override. */
.wiz{width:100%;max-width:560px;margin:0 auto}
.wiz .shot-stack{aspect-ratio:1875/903}
.wiz-spine{position:relative;display:flex;justify-content:space-between;margin-bottom:20px;padding:0 4px}
/* The connecting rail — a grey track with a red fill that advanced to the active dot —
   is gone. It drew a progress bar, which is what made the steps read as "you are at 1 of 3"
   rather than three things you can click. The dots and their glow carry it now. */
.wiz-spine button{position:relative;z-index:2;background:none;border:0;padding:0;cursor:pointer;
  text-align:center;font-family:inherit}
/* An inactive dot used to be #0D0F14 behind a 20%-opacity border — near-invisible, and the
   only hover feedback in the whole component was the LABEL going one shade lighter. That
   reads as "step not reached yet", the opposite of "click me". It now rests as a visible
   button and answers on hover: the dot itself lifts, brightens and turns red. */
.wiz-spine .dot{width:27px;height:27px;border-radius:50%;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.32);
  color:var(--muted);font-size:10.5px;font-weight:800;display:flex;align-items:center;justify-content:center;
  margin:0 auto 8px;transition:all .3s var(--ease)}
.wiz-spine .t{display:block;font-size:10px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--dim);transition:color .3s var(--ease)}
.wiz-spine button.on .dot{border-color:var(--red-2);color:#fff;
  background:linear-gradient(135deg,var(--red-2),var(--red));box-shadow:0 0 22px rgba(225,20,20,.5)}
.wiz-spine button.on .t{color:var(--white)}
.wiz-spine button:hover:not(.on) .dot{border-color:rgba(225,20,20,.75);color:#fff;
  background:rgba(225,20,20,.2);transform:translateY(-2px)}
.wiz-spine button:hover:not(.on) .t{color:var(--white)}
.wiz-spine button:focus-visible{outline:2px solid var(--red-2);outline-offset:4px;border-radius:8px}
/* screens slide in rather than crossfade, so it reads as stepping forward */
.wiz .shot-stack img{transform:translateX(14px);transition:opacity .5s var(--ease),transform .6s var(--ease),filter .3s var(--ease)}
.wiz .shot-stack img.on{transform:none}
@media(max-width:900px){
  .wiz-spine .t{font-size:9px;letter-spacing:.08em}
  .wiz-spine .dot{width:24px;height:24px;font-size:10px}
}

/* ---- TAURUS ADMIN: node map ----
   Nodes drawn the way the Workflow Builder draws its stages — coloured top-bar on
   the active one, arrows between. Reuses .shot-frame / .shot-stack / .shot-foot. */
.nmap-wrap{width:100%;max-width:560px;margin:0 auto}
.nmap{display:flex;align-items:stretch;margin-bottom:18px}
.nmap-arw{flex:none;width:26px;display:flex;align-items:center;justify-content:center;color:#3A3F49;font-size:12px}
.nd{flex:1;min-width:0;position:relative;background:rgba(255,255,255,.035);border:1px solid var(--line);
  border-radius:11px;padding:10px 12px;cursor:pointer;text-align:left;font-family:inherit;
  transition:all .35s var(--ease);overflow:hidden}
.nd::before{content:'';position:absolute;left:0;right:0;top:0;height:3px;background:#2C3038;transition:background .35s var(--ease)}
.nd .t{display:block;font-size:11.5px;font-weight:700;color:var(--dim);transition:color .35s var(--ease);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nd .s{display:block;font-size:8.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#4F555E;margin-top:4px}
.nd.on{background:rgba(225,20,20,.1);border-color:rgba(225,20,20,.45)}
.nd.on::before{background:linear-gradient(90deg,var(--red-2),var(--red))}
.nd.on .t{color:var(--white)}
.nd.on .s{color:var(--red-2)}
/* same reasoning as the wizard dots: an inactive node has to answer when you point at it */
.nd:hover:not(.on) .t{color:var(--white)}
.nd:hover:not(.on){border-color:rgba(225,20,20,.6);background:rgba(255,255,255,.06);transform:translateY(-2px)}
.nd:hover:not(.on)::before{background:rgba(225,20,20,.5)}
.nd{transition:all .3s var(--ease)}
.nd:focus-visible{outline:2px solid var(--red-2);outline-offset:3px}
@media(max-width:900px){
  .nmap-arw{width:16px;font-size:10px}
  .nd{padding:8px 9px}
  .nd .t{font-size:10.5px}
  .nd .s{font-size:8px;letter-spacing:.08em}
}

/* full-size viewer — a 560px screenshot of a dense table is not readable */
.shotbox{position:fixed;inset:0;z-index:220;display:flex;align-items:center;justify-content:center;padding:28px}
.shotbox[hidden]{display:none}
.shotbox-bg{position:absolute;inset:0;background:rgba(4,5,7,.92);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
/* max-height was 92vh while the box carries 28px of padding — 92vh + 56px is taller than
   the viewport, so a portrait shot overflowed and was clipped top and bottom. A percentage
   resolves against the padding box, which is the number that actually matters. */
.shotbox img{position:relative;max-width:min(1400px,100%);max-height:100%;width:auto;height:auto;
  border:1px solid var(--line);border-radius:14px;box-shadow:0 40px 100px rgba(0,0,0,.75);
  animation:dIn .35s var(--ease) both}
/* a portrait capture is a tablet screen, so it keeps its bezel when enlarged — the frame is
   part of what the image means. border-box is global, so the padding sizes inward and the
   framed whole still obeys max-height. */
.shotbox.framed img{padding:15px;border-radius:24px;border-color:rgba(255,255,255,.16);
  background:linear-gradient(160deg,#23252c,#111318)}
.shotbox-close{position:absolute;top:20px;right:22px;z-index:2;width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,.08);border:1px solid var(--line);color:var(--white);font-size:15px;cursor:pointer;
  transition:all .25s var(--ease)}
.shotbox-close:hover{background:var(--red);border-color:var(--red)}

/* ============ BACK TO TOP ============ */
.go-top{position:fixed;right:26px;bottom:26px;width:48px;height:48px;border:0;border-radius:50%;
  background:linear-gradient(135deg,var(--red-2),var(--red) 75%);color:#fff;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  box-shadow:0 10px 30px rgba(225,20,20,.42);
  opacity:0;visibility:hidden;transform:translateX(90px);
  transition:opacity .4s var(--ease),transform .45s var(--ease),box-shadow .3s var(--ease),visibility .4s;
  z-index:150}
.go-top.show{opacity:1;visibility:visible;transform:none}
.go-top:hover{box-shadow:0 16px 42px rgba(225,20,20,.6)}
.go-top.show:hover{transform:translateY(-3px)}
.go-top:active{transform:translateY(0)}
@media(max-width:560px){.go-top{right:18px;bottom:18px;width:44px;height:44px}}

/* ============ POINTER ============
   Two parts: a small solid dot pinned exactly to the pointer, and a larger
   translucent disc that trails it. The lag is the transition on transform —
   each mousemove restarts an ease-out toward the new point, so the disc is
   always catching up. Native cursor stays visible; desktop pointers only, and
   nothing at all when the visitor asked for reduced motion. */
.cursor-dot,.cursor-disc{position:fixed;top:0;left:0;border-radius:50%;background:var(--red-2);
  pointer-events:none;opacity:0;will-change:transform}
.cursor-dot{width:8px;height:8px;margin:-4px 0 0 -4px;z-index:10000001;
  transition:opacity .25s ease,width .2s ease,height .2s ease,margin .2s ease}
.cursor-disc{width:34px;height:34px;margin:-17px 0 0 -17px;z-index:10000000;
  transition:transform .19s ease-out,opacity .3s ease,width .22s ease,height .22s ease,margin .22s ease}
.cursor-dot.on{opacity:1}
.cursor-disc.on{opacity:.22}
/* over anything clickable the disc swells and the dot tucks inside it */
.cursor-disc.hot{width:58px;height:58px;margin:-29px 0 0 -29px;opacity:.3}
.cursor-dot.hot{width:6px;height:6px;margin:-3px 0 0 -3px;opacity:.85}
.cursor-disc.down{width:26px;height:26px;margin:-13px 0 0 -13px;opacity:.38}
@media(hover:none),(pointer:coarse){.cursor-dot,.cursor-disc{display:none}}

/* responsive guards */
img,svg,canvas,video{max-width:100%}
.tip{right:0;left:auto;max-width:calc(100vw - 48px)}
@media(max-width:560px){.tip{right:-8px;width:min(340px,calc(100vw - 40px))}}
.card,.wrap{min-width:0}
@media(max-width:640px){.calc-tabs .ctab{flex:1;text-align:center;padding:10px 12px;font-size:13px}}
@media(max-width:640px){.roi{padding:24px 18px 22px}.qbox{padding:22px 18px}.dmodal-card{padding:28px 20px 24px}}
/* a headline sized off viewport width alone goes tiny on a phone — give it a wider
   slice of the screen there, still capped against height so the fold holds */
@media(max-width:760px){.hero h1{font-size:min(9.6vw,calc(var(--vhz,100vh)*0.09),48px)}.hero-sub{margin:14px auto 22px}}
@media(max-width:560px){.hero-actions{flex-direction:column;align-items:center}.hero-actions .btn{width:min(320px,90vw);justify-content:center}}
/* the card no longer caps its own height; the .dmodal container scrolls instead */
@media(max-height:620px) and (min-width:761px){.hero h1{font-size:min(5.6vw,calc(var(--vhz,100vh)*0.085),68px)}.hero-sub{margin:12px auto 18px}}