:root{--bg:#07080d;--bg2:#0c0e16;--fg:#ecedf2;--dim:#a4a8b6;--mute:#6b6f7d;--line:rgba(255,255,255,.09);--a1:#7c5cff;--a2:#3a8dff;--a3:#c9b8ff;--a4:#d1613a;--maxw:1240px}
*{box-sizing:border-box}html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--fg);font-family:Inter,system-ui,sans-serif;font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:var(--a3);text-decoration:none;transition:color .35s cubic-bezier(.4,0,.2,1)}a:hover{color:#fff}
.disp{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,95%);letter-spacing:-.02em;line-height:1.04;margin:0}
.disp .cd{font-stretch:var(--cdw,62%);font-weight:400;font-size:var(--cds,1.22em);color:var(--a3);letter-spacing:.005em}
.disp .cdi{font-stretch:var(--cdw,62%);font-weight:400;font-size:var(--cds,1.22em);font-style:italic;color:var(--a3)}
.mono,.eyebrow{font-family:'JetBrains Mono',monospace}
.eyebrow{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);display:inline-flex;align-items:center;gap:8px}
.eyebrow::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--a4);box-shadow:0 0 10px var(--a4)}
.wrap{max-width:var(--maxw);margin:0 auto;padding-inline:32px}
.btn{display:inline-flex;align-items:center;gap:10px;padding:14px 28px;border-radius:999px;background:var(--a1);color:#fff;font-size:13.5px;font-weight:500;letter-spacing:.01em;border:1px solid transparent;transition:background .45s cubic-bezier(.4,0,.2,1),transform .45s cubic-bezier(.2,.8,.2,1),border-color .45s cubic-bezier(.4,0,.2,1),color .45s cubic-bezier(.4,0,.2,1)}
.btn:hover{color:#fff;transform:translateY(-2px);background:color-mix(in oklch,var(--a1) 84%,white)}
/* orange variant — the 10% pop accent, for the one CTA that should win a page */
.btn.pop{background:var(--a4);box-shadow:0 10px 34px -16px color-mix(in oklch,var(--a4) 50%,transparent)}
.btn.pop:hover{background:color-mix(in oklch,var(--a4) 88%,white);box-shadow:0 14px 40px -16px color-mix(in oklch,var(--a4) 62%,transparent)}
.btn.ghost{background:none;border:1px solid var(--line);color:var(--dim)}
.btn.ghost:hover{border-color:var(--a3);color:#fff;box-shadow:none}
.nav{position:fixed;inset-inline:0;top:0;z-index:100;padding:18px 32px;display:flex;align-items:center;justify-content:space-between;--navp:0;background:rgba(7,8,13,calc(var(--navp)*.82));backdrop-filter:blur(calc(var(--navp)*14px));-webkit-backdrop-filter:blur(calc(var(--navp)*14px));border-bottom:1px solid rgba(255,255,255,calc(var(--navp)*.09))}
.nav .mark{display:inline-flex;align-items:center;color:var(--fg);line-height:0}
.nav .links{display:flex;gap:28px;font-size:13.5px}
.nav .links a{color:var(--dim);transition:color .3s}.nav .links a:hover{color:#fff}.nav .links a.on{color:#fff}
#hero .hero-ripple{position:absolute;inset:0;z-index:1;pointer-events:none}
.nav .links a.on::after{content:'';position:absolute;left:50%;bottom:-9px;width:5px;height:5px;margin-left:-2.5px;border-radius:50%;background:var(--a1);box-shadow:0 0 10px var(--a1)}
@media(max-width:720px){.nav .links{display:none}}
/* page hero (interior pages) */
.phero{position:relative;padding-block:186px 104px;overflow:hidden}
.phero canvas[data-cosmos]{position:absolute;inset:0;width:100%;height:100%}
.phero .inner{position:relative;z-index:2}
.phero h1{font-size:clamp(38px,5.4vw,80px);max-width:17ch;margin-top:24px;text-wrap:balance}
.phero .lede{color:var(--dim);max-width:56ch;text-wrap:pretty;margin-top:26px;line-height:1.7;font-size:16.5px}
/* home hero */
#hero{position:relative;min-height:100vh;min-height:100dvh;display:flex;align-items:center;overflow:var(--heroflow,hidden)}
#hero canvas,#hero [data-stars3d]{position:absolute;left:0;right:0;top:0;height:calc(100% + var(--heroover,0px));width:100%}
.phero{overflow:var(--heroflow,hidden)}
.phero canvas[data-cosmos]{height:calc(100% + var(--heroover,0px))}
.phero{border-bottom:1px solid var(--heroline,var(--line))}
#hero .inner{position:relative;z-index:2;padding-block:120px 110px}
#hero h1{font-size:clamp(46px,6.9vw,102px);max-width:13ch}
#hero .sub{color:var(--dim);margin-top:30px;max-width:46ch;line-height:1.7;font-size:16.5px}
#hero .ctas{display:flex;gap:14px;margin-top:38px;flex-wrap:wrap}
#hero .cue{position:absolute;bottom:34px;left:50%;transform:translateX(-50%);z-index:2;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--mute);display:flex;flex-direction:column;align-items:center;gap:10px}
#hero .cue i{width:1px;height:38px;background:linear-gradient(180deg,var(--a3),transparent);animation:cue 2.2s ease-in-out infinite}
@keyframes cue{0%,100%{opacity:.2;transform:scaleY(.55)}50%{opacity:1;transform:scaleY(1)}}
#hero .hint{position:absolute;bottom:34px;left:32px;z-index:2;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
@media(max-height:700px){#hero .hint,#hero .cue{display:none}}
/* reveal (GSAP owns motion) */
.rv{opacity:1}
.rv.d1,.rv.d2,.rv.d3{}
/* clients marquee */
.clients{border-block:1px solid var(--line);padding-block:26px;overflow:hidden;position:relative}
.clients .fade{position:absolute;inset-block:0;width:120px;z-index:2;pointer-events:none}
.clients .fade.l{left:0;background:linear-gradient(90deg,var(--bg),transparent)}
.clients .fade.r{right:0;background:linear-gradient(270deg,var(--bg),transparent)}
.mq{display:flex;gap:64px;width:max-content;animation:mq 36s linear infinite}
.mq span{font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.22em;text-transform:uppercase;color:var(--mute);white-space:nowrap}
@keyframes mq{to{transform:translateX(-50%)}}
.shead{padding-block:200px 90px}
.shead h2{font-size:clamp(38px,5.2vw,74px);max-width:20ch;margin-top:22px;text-wrap:balance}
.shead .lede{color:var(--dim);max-width:58ch;text-wrap:pretty;margin-top:22px;line-height:1.7}
/* work cards */
.stack{display:flex;flex-direction:column}
.wcard{position:sticky;top:86px;border:1px solid var(--line);border-radius:20px;background:linear-gradient(180deg,#0c0e16,#090b12);overflow:hidden;margin-bottom:40px;display:grid;grid-template-columns:1fr 1.25fr;min-height:460px;color:inherit}
@media(max-width:860px){.wcard{grid-template-columns:1fr}}
.wcard .meta{padding:44px 40px;display:flex;flex-direction:column;justify-content:space-between;gap:30px}
.wcard .num{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.wcard h3{font-size:clamp(26px,3vw,40px);margin-top:14px}
.wcard p{color:var(--dim);font-size:14.5px;line-height:1.65;margin:14px 0 0;max-width:36ch}
.wcard .tags{display:flex;gap:8px;flex-wrap:wrap}
.wcard .tags span{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);border:1px solid var(--line);border-radius:999px;padding:6px 13px}
.wcard .visual{position:relative;min-height:300px;border-left:1px solid var(--line)}
@media(max-width:860px){.wcard .visual{border-left:0;border-top:1px solid var(--line)}}
.wcard .visual .ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.v1{background:radial-gradient(120% 100% at 80% 20%,rgba(124,92,255,.28),transparent 60%),radial-gradient(100% 100% at 20% 90%,rgba(58,141,255,.18),transparent 60%)}
.v2{background:radial-gradient(120% 100% at 20% 20%,rgba(58,141,255,.26),transparent 60%),radial-gradient(100% 100% at 85% 85%,rgba(201,184,255,.14),transparent 55%)}
.v3{background:radial-gradient(130% 110% at 55% 10%,rgba(201,184,255,.2),transparent 55%),radial-gradient(100% 100% at 15% 80%,rgba(124,92,255,.22),transparent 60%)}
.v4{background:radial-gradient(120% 100% at 70% 80%,rgba(124,92,255,.22),transparent 60%),radial-gradient(100% 100% at 25% 15%,rgba(201,184,255,.16),transparent 55%)}
.v5{background:radial-gradient(110% 100% at 15% 30%,rgba(58,141,255,.24),transparent 60%),radial-gradient(100% 100% at 80% 90%,rgba(124,92,255,.18),transparent 55%)}
.v6{background:radial-gradient(130% 100% at 50% 100%,rgba(201,184,255,.18),transparent 55%),radial-gradient(100% 100% at 85% 10%,rgba(58,141,255,.2),transparent 60%)}
/* capabilities rows */
.caps{border-top:1px solid var(--line)}
.cap{display:grid;grid-template-columns:110px 1fr 1.1fr;gap:32px;padding:64px 0;border-bottom:1px solid var(--line);align-items:baseline;transition:background .4s}
.cap:hover{background:rgba(255,255,255,.015)}
@media(max-width:860px){.cap{grid-template-columns:60px 1fr}.cap .desc{grid-column:2}}
.cap .n{font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.18em;color:var(--mute)}
.cap h3{font-size:clamp(26px,3.2vw,42px)}
.cap .desc{color:var(--dim);font-size:14.5px;line-height:1.7;max-width:44ch}
.cap .desc .list{margin-top:14px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--mute);line-height:2}
/* process */
.proc{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden}
@media(max-width:960px){.proc{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.proc{grid-template-columns:1fr}}
.proc .step{background:var(--bg);padding:38px 30px 46px}
.proc .step .n{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.proc .step h4{font-size:24px;margin:18px 0 0;font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%)}
.proc .step p{color:var(--dim);font-size:14px;line-height:1.65;margin:12px 0 0}
/* quote */
.quote{padding:230px 0;text-align:center}
.quote blockquote{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,102%);font-size:clamp(26px,3.6vw,46px);line-height:1.25;letter-spacing:-.005em;max-width:26ch;margin:26px auto 0}
.quote blockquote em{font-stretch:62%;font-weight:400;font-style:normal;color:var(--a3);font-size:1.16em}
.quote .who{margin-top:30px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute)}
/* cta */
#cta{position:relative;overflow:hidden;text-align:center;padding:250px 0;border-top:1px solid var(--line)}
#cta canvas{position:absolute;inset:0;width:100%;height:100%}
#cta .inner{position:relative;z-index:2}
#cta h2{font-size:clamp(44px,7vw,104px);max-width:14ch;margin:24px auto 0}
#cta p{color:var(--dim);max-width:44ch;margin:26px auto 0;line-height:1.7}
#cta .btn{margin-top:40px}
/* how we work */
.hww{padding-bottom:170px}
.hwsteps{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(28px,4vw,56px)}
.hwstep{display:flex;flex-direction:column}
/* drawn figure, same treatment as the three rules on About — no frame, no fill:
   the illustration sits directly on the page like the rest of the figure set */
.hwv{margin:0 0 22px;padding:0;border:0;background:none}
.hwv svg{width:100%;height:auto;aspect-ratio:340/240;display:block;max-width:330px;overflow:visible}
.hwn{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.hwstep h3{margin:13px 0 0;font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%);font-size:24px}
.hwstep p{color:var(--dim);font-size:14.5px;line-height:1.7;margin:12px 0 0;max-width:38ch;text-wrap:pretty}
@media(max-width:860px){.hwsteps{grid-template-columns:1fr;gap:52px}.hwv svg{max-width:280px}}
/* stats */
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden}
@media(max-width:640px){.stats{grid-template-columns:1fr}}
.stats .cell{background:var(--bg);padding:44px 34px 50px}
.stats .big{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,102%);font-size:clamp(48px,6vw,84px);line-height:1}
.stats .big b{font-stretch:62%;font-weight:400;color:var(--a3)}
.stats .k{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);margin-top:16px}
/* contact form */
.cform{max-width:640px}
.cform label{display:block;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);margin:34px 0 10px}
.cform input,.cform textarea{width:100%;background:none;border:0;border-bottom:1px solid var(--line);color:var(--fg);font:inherit;font-size:18px;padding:10px 0;outline:none;transition:border-color .3s}
.cform input:focus,.cform textarea:focus{border-bottom-color:var(--a3)}
.cform textarea{min-height:110px;resize:vertical}
/* footer */
footer{border-top:1px solid var(--line);padding:130px 0 70px}
footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:40px}
@media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
footer .fmark{font-family:Archivo,sans-serif;font-stretch:var(--dsw,102%);font-weight:var(--dwt,300);font-size:clamp(56px,7vw,110px);line-height:.95;letter-spacing:-.01em;color:var(--fg)}
footer .fmark .cd{font-stretch:62%;font-weight:400;color:var(--a3)}
footer h5{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);font-weight:500;margin:0 0 18px}
footer .col a{display:block;color:var(--dim);font-size:14px;margin-bottom:10px}
footer .legal{margin-top:70px;padding-top:26px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.1em;color:var(--mute)}
/* warp + transition */
#warp{will-change:transform,opacity}
/* ambient nebula + cursor lens */
/* No mix-blend-mode: this fixed, full-viewport layer sits at z-index:0 behind the
   content, over the near-black page — screen blend there is visually ~a no-op, but
   a fixed blend layer forces the compositor to re-blend the WHOLE viewport every
   scroll frame (measured: case pages dropped to 4-30fps, full-viewport repaint).
   Normal blend lets it stay a cheap static composited layer. */
#nebfx{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:var(--nebfx,1);transition:opacity .6s}
#nebfx b{position:absolute;border-radius:50%;filter:blur(70px);will-change:transform}
#nebfx .n1{width:52vmax;height:52vmax;background:radial-gradient(circle,rgba(124,92,255,.16),transparent 68%)}
#nebfx .n2{width:44vmax;height:44vmax;background:radial-gradient(circle,rgba(58,141,255,.12),transparent 68%)}
#nebfx .n3{width:30vmax;height:30vmax;background:radial-gradient(circle,color-mix(in oklch,var(--a4) 7.5%,transparent),transparent 68%)}
#warp{position:relative;z-index:1}
#lens{position:fixed;top:0;left:0;width:var(--lenssize,300px);height:var(--lenssize,300px);margin:calc(var(--lenssize,300px)/-2) 0 0 calc(var(--lenssize,300px)/-2);z-index:80;pointer-events:none;border-radius:50%;backdrop-filter:blur(var(--lensblur,4px)) saturate(var(--lenssat,150%)) brightness(var(--lensbright,116%));-webkit-backdrop-filter:blur(var(--lensblur,4px)) saturate(var(--lenssat,150%)) brightness(var(--lensbright,116%));mask-image:radial-gradient(circle,rgba(0,0,0,1) 26%,rgba(0,0,0,.5) 54%,transparent 73%);-webkit-mask-image:radial-gradient(circle,rgba(0,0,0,1) 26%,rgba(0,0,0,.5) 54%,transparent 73%);opacity:0;transition:opacity .5s;will-change:transform}
#lens.on{opacity:var(--lensop,1)}
#lens.dim{opacity:0}
#lens.pop{opacity:0;transition:opacity .1s linear}
#lens{transition:opacity .55s cubic-bezier(.4,0,.2,1)}
.plan,.gpiece .gframe,.prac .row{--mx:50%;--my:50%}
.plan{position:relative;overflow:hidden;transition:transform .55s cubic-bezier(.2,.8,.2,1),border-color .55s cubic-bezier(.4,0,.2,1)}
.plan::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .5s cubic-bezier(.4,0,.2,1);background:radial-gradient(340px circle at var(--mx) var(--my),rgba(201,184,255,.13),rgba(124,92,255,.05) 42%,transparent 70%)}
.plan:hover::before{opacity:1}
.plan:hover{transform:translateY(-6px);border-color:rgba(201,184,255,.34)}
.plan.hot:hover{border-color:color-mix(in oklch,var(--a4) 60%,transparent)}
.plan>*{position:relative;z-index:1}
.gpiece .gframe::before{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;transition:opacity .55s cubic-bezier(.4,0,.2,1);background:radial-gradient(420px circle at var(--mx) var(--my),rgba(255,255,255,.1),transparent 66%)}
.gpiece:hover .gframe::before{opacity:1}
.prac .row{transition:background .6s cubic-bezier(.4,0,.2,1)}
.prac .row:hover{background:radial-gradient(700px circle at var(--mx) var(--my),rgba(124,92,255,.05),transparent 68%)}
.ripple{position:fixed;top:0;left:0;width:240px;height:240px;margin:-120px 0 0 -120px;z-index:81;pointer-events:none;border-radius:50%;backdrop-filter:blur(11px);-webkit-backdrop-filter:blur(11px);mask-image:radial-gradient(circle,transparent 44%,rgba(0,0,0,.85) 56%,transparent 74%);-webkit-mask-image:radial-gradient(circle,transparent 44%,rgba(0,0,0,.85) 56%,transparent 74%);box-shadow:0 0 60px rgba(201,184,255,.1) inset}
@media(hover:none){#lens,.ripple{display:none}}
/* Anything clickable opts out of the cursor lens: a blur sitting on the control
   you are about to press reads as the page obscuring itself. Handled by widening
   the existing dim test in novas.js rather than adding a second effect — it costs
   nothing, and suppressing the click ripple on controls removes a backdrop-filter
   layer, so this is cheaper than what it replaces, not more expensive. */
/* orbit timeline */
.orbit{position:relative}
.orbit .osticky{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden}
.orbit .oring{position:absolute;left:calc(22vw - 200vmin);top:50%;width:200vmin;height:200vmin;transform:translateY(-50%);border:1px solid var(--line);border-radius:50%}
.orbit .oring::after{content:'';position:absolute;right:-4.5px;top:50%;width:9px;height:9px;border-radius:50%;background:var(--a4);box-shadow:0 0 16px var(--a4);transform:translateY(-50%)}
.orbit .owheel{position:absolute;left:calc(22vw - 200vmin);top:50%;width:200vmin;height:200vmin;margin-top:-100vmin;will-change:transform}
.orbit .oyear{position:absolute;left:50%;top:50%;font-family:'JetBrains Mono',monospace;font-weight:300;letter-spacing:.14em;font-size:clamp(20px,2.2vw,33px);color:var(--fg);white-space:nowrap;padding-right:0;transform-origin:100% 50%}
.orbit .oyear i{display:inline-block;font-style:normal;transform:scale(var(--yscale,1));transform-origin:100% 50%;transition:color .5s}
.orbit .oyear.on{color:var(--fg)}
/* rolodex: items are driven continuously from scroll, so no CSS transition here
   (it would fight the rAF loop). They rotate on a shared perspective, so the
   outgoing card is tilted away rather than sitting flat over the incoming one. */
.orbit .ocopy{position:absolute;left:36.5vw;right:auto;width:min(46ch,40vw);top:50%;transform:translateY(-50%);height:60svh;max-width:none;perspective:1200px;perspective-origin:20% 50%}
.orbit .oitem{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;opacity:0;backface-visibility:hidden;transform-style:preserve-3d;transform-origin:50% 50%;will-change:transform,opacity;pointer-events:none}
.orbit .oitem.on{opacity:1}
.orbit .oitem h3{font-size:clamp(30px,4vw,56px);max-width:20ch;text-wrap:balance}
.orbit .oitem p{color:var(--dim);margin-top:18px;line-height:1.7;font-size:15px;max-width:46ch;text-wrap:pretty}
.orbit .ochips{display:flex;flex-wrap:wrap;gap:10px;margin-top:30px;max-width:44ch}
.orbit .ochips span{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:9px 15px}
.orbit.caps-orbit{height:300vh}
/* v2: number rail hugs the left edge, copy in the middle, figure bleeding off
   the right — the figure is meant to be cropped by the viewport, not fitted */
/* the arc's apex is the layout datum: the ring box is 200vmin wide, so parking
   its left edge at (apex - 200vmin) puts the crest exactly at 22vw everywhere */
/* v2 sits over the figure, so this pane is painted flat in the page colour
   rather than letting the ambient nebula pool behind the artwork */
.orbit.v2 .osticky{background:var(--bg)}
.orbit.v2 .ofig{position:absolute;right:-5vw;top:50%;width:min(26vw,360px);height:min(50vh,420px);transform:translateY(-50%);pointer-events:none}
.orbit.v2 .ofigi{position:absolute;inset:0;opacity:0;transition:opacity .5s;will-change:opacity}
.orbit.v2 .ofigi.on{opacity:.72}
.orbit.v2 .ofigi svg{width:100%;height:100%;display:block;overflow:visible}
@media(max-width:1100px){.orbit.v2 .ofig{display:none}}
@media(max-width:1000px){.orbit .oring,.orbit .owheel{left:calc(27vw - 200vmin)}.orbit .ocopy{left:38vw;right:32px;width:auto}}
@media(max-width:860px){.orbit.v2 .ocopy{left:32px;right:32px}}
.orbit.caps-orbit .oitem h3{font-size:clamp(32px,4.4vw,62px)}
@media(max-width:860px){.orbit .ocopy{left:32px;right:32px;width:auto;max-width:none}.orbit .oring,.orbit .owheel{opacity:.35}}
/* polish */
::selection{background:rgba(124,92,255,.4);color:#fff}
.wcard{transition:border-color .5s,transform .6s cubic-bezier(.2,.8,.2,1)}
.wcard:hover{border-color:rgba(255,255,255,.16)}
.wcard .visual{overflow:hidden}
.wcard .visual::before{content:'';position:absolute;inset:-10%;background:inherit;transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.wcard:hover .visual::before{transform:scale(1.05)}
.nav .links a{position:relative}
.nav .links a::after{content:none}
.btn .ar{display:inline-block;transition:transform .35s cubic-bezier(.2,.8,.2,1)}
.btn:hover .ar{transform:translateX(5px)}
.cap{cursor:default}
.cap h3{transition:transform .5s cubic-bezier(.2,.8,.2,1),color .4s}
.cap:hover h3{transform:translateX(10px)}
/* case study */
.cmeta{display:flex;gap:64px;flex-wrap:wrap;margin-top:60px;border-top:1px solid var(--line);padding-top:36px}
.cmeta .kv .k{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)}
.cmeta .kv .v{margin-top:10px;font-size:15px;color:var(--fg)}
.intro{padding-block:170px 60px}
.intro p{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,95%);font-size:clamp(24px,2.8vw,38px);line-height:1.35;letter-spacing:-.01em;color:var(--fg);max-width:30ch;margin:0}
.chap{padding-block:130px 0}
.chap .cnum{font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.2em;color:var(--a4)}
.chap h4{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,95%);font-size:clamp(28px,3.6vw,52px);margin:20px 0 0;line-height:1.05}
.chap .body{color:var(--dim);line-height:1.75;font-size:15.5px;max-width:62ch;margin-top:28px}
.cimgs{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-top:70px}
@media(max-width:760px){.cimgs{grid-template-columns:1fr}}
.cimg{aspect-ratio:16/10;border:1px solid var(--line);border-radius:18px;position:relative;overflow:hidden;display:flex;align-items:flex-end;padding:22px;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.nextcase{display:block;border-top:1px solid var(--line);margin-top:170px;padding:110px 0;text-align:center;color:inherit}
.nextcase .k{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--mute)}
.nextcase .t{font-family:Archivo,sans-serif;font-weight:var(--dwt,300);font-stretch:var(--dsw,95%);font-size:clamp(40px,6vw,92px);margin-top:20px;transition:color .4s,letter-spacing .5s}
.nextcase:hover .t{color:var(--a3);letter-spacing:.01em}
/* faq */
.faq{border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{transition:color .4s cubic-bezier(.4,0,.2,1);cursor:pointer;list-style:none;display:flex;align-items:baseline;gap:36px;padding:38px 0;font-family:Archivo,sans-serif;font-weight:300;font-stretch:var(--dsw,95%);font-size:clamp(19px,2.1vw,27px);color:var(--fg)}
.faq summary::-webkit-details-marker{display:none}
.faq summary .fn{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;color:var(--mute)}
.faq summary .fx{margin-left:auto;color:var(--mute);transition:transform .5s cubic-bezier(.2,.8,.2,1),color .4s cubic-bezier(.4,0,.2,1);font-family:Inter;font-weight:300}
.faq details[open] .fx{transform:rotate(45deg)}
.faq details .ans{overflow:hidden}
.faq details p{color:var(--dim);font-size:14.5px;line-height:1.7;max-width:60ch;margin:0 0 38px;padding-left:calc(36px + 2.5em)}
@media(max-width:640px){.faq details p{padding-left:0}}
/* pricing */
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;align-items:stretch}
@media(max-width:960px){.plans{grid-template-columns:1fr;max-width:520px;margin-inline:auto}}
.plan{border:1px solid var(--line);border-radius:24px;padding:30px 28px 28px;display:flex;flex-direction:column;background:linear-gradient(180deg,rgba(255,255,255,.022),transparent 42%)}
.plan.hot{border-color:color-mix(in oklch,var(--a4) 40%,transparent);background:linear-gradient(180deg,color-mix(in oklch,var(--a4) 5%,transparent),transparent 46%)}
.plan .pn{position:absolute;top:18px;right:20px;font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);border:1px solid var(--line);border-radius:999px;padding:5px 11px;background:rgba(7,8,13,.5)}
.plan.hot .pn{color:var(--a4);border-color:color-mix(in oklch,var(--a4) 44%,transparent)}
.plan .phead{display:flex;align-items:center;gap:14px;padding-right:96px}
.plan .pmark{width:36px;height:36px;flex:none;display:grid;place-items:center;border-radius:11px;background:rgba(201,184,255,.09);box-shadow:inset 0 0 0 1px rgba(201,184,255,.16);color:var(--a3)}
.plan.hot .pmark{background:color-mix(in oklch,var(--a4) 10%,transparent);box-shadow:inset 0 0 0 1px color-mix(in oklch,var(--a4) 24%,transparent);color:var(--a4)}
.plan .pmark svg{width:20px;height:20px;display:block;fill:currentColor}
.plan h3{font-size:26px;margin:0;font-stretch:88%}
.plan .pd{color:var(--dim);font-size:13.5px;line-height:1.6;margin-top:16px;min-height:3.2em}
.plan .rule{height:1px;margin:24px 0;background-image:radial-gradient(circle,rgba(255,255,255,.22) 1px,transparent 1px);background-size:6px 1px;background-repeat:repeat-x}
.plan ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px;flex:1}
.plan li{padding:0;border:0;font-size:13.5px;color:var(--dim);display:flex;gap:12px;align-items:flex-start;line-height:1.45}
.plan li::before{content:'';width:14px;height:14px;flex:none;margin-top:2px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.8 6.4l2.7 2.7 5.7-6' fill='none' stroke='%23c9b8ff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-size:13px 13px;background-position:center;background-repeat:no-repeat}
.plan.hot li::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.8 6.4l2.7 2.7 5.7-6' fill='none' stroke='%23ff8a52' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.plan .price{margin-top:0;font-family:Archivo,sans-serif;font-weight:300;font-stretch:84%;font-size:38px;line-height:1;letter-spacing:-.02em;white-space:nowrap}
.plan .price small{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.14em;color:var(--mute);margin-left:9px;text-transform:uppercase}
.plan .btn{margin-top:20px;justify-content:center;width:100%}
.prac{border-top:1px solid var(--line)}
.prac .row{display:grid;grid-template-columns:1fr 1fr;gap:56px;padding-block:90px;border-bottom:1px solid var(--line)}
@media(max-width:860px){.prac .row{grid-template-columns:1fr;gap:34px}}
.prac .n{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.prac h3{font-size:clamp(30px,4vw,58px);margin-top:16px;text-wrap:balance}
.prac .lede2{color:var(--dim);line-height:1.7;font-size:15.5px;max-width:none;margin-top:22px;text-wrap:pretty;columns:2;column-gap:40px}
@media(max-width:860px){.prac .lede2{columns:1}}
.prac .cols2{display:grid;grid-template-columns:1fr 1fr;gap:40px}
@media(max-width:560px){.prac .cols2{grid-template-columns:1fr}}
.prac ul{list-style:none;margin:0;padding:0}
.prac h5{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);font-weight:500;margin:0 0 16px}
.prac{overflow-x:clip}
.prac .row{grid-template-columns:var(--figcol-a,minmax(0,1fr)) var(--figcol-b,.46fr);column-gap:64px;row-gap:40px;align-items:start}
.prac .cols2{grid-column:var(--figcopy,1)}
/* figure side and size are tweakable; box follows the figure's own ratio so the
   drawing fills its column rather than being height-constrained in a wider box */
.prac .pill{grid-column:var(--figside,2);grid-row:1/span 2;align-self:var(--figalign,center);position:relative;margin:0;padding:0;border:0;background:none;overflow:visible;display:flex;flex-direction:column;align-items:center;gap:14px;opacity:var(--figop,.85);transition:opacity .55s cubic-bezier(.4,0,.2,1);transform:translateZ(0);contain:paint}
.prac .pill svg{width:100%;height:auto;aspect-ratio:440/560;max-height:min(var(--figvh,58svh),var(--figmax,460px));max-width:100%;display:block}
.prac .pill figcaption{display:none}
.prac .row:hover .pill{opacity:1}
.prac .row:hover .pill .ink{stroke:#e6dfff}
.prac .row:hover .pill .inkfine{stroke:#e6dfff}
/* figure chrome is role-scoped below; only the reveal mechanics are shared */
.wash path{opacity:0;transition:opacity .8s cubic-bezier(.4,0,.2,1)}
@media(prefers-reduced-motion:reduce){.wash path{transition:none}}
/* ── figure roles. One system, two treatments, chosen by whether the figure
   follows a flow. The role is declared on the figure in figure-layouts.js and
   novas.js puts the matching class on the <svg>. ── */
/* EMBLEM — stands alone as a symbol: even weight, ghost underlay, full star
   set, no tint fills. Nothing ranks anything because there is no flow. */
.fig.emblem .wash{display:none}
.fig.emblem .ghost,.fig.emblem .ghostfine{fill:none;stroke:rgba(201,184,255,.42);stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}
.fig.emblem .ink,.fig.emblem .inkfine{fill:none;stroke:var(--a3);stroke-width:1.5;opacity:1;stroke-linecap:round;stroke-linejoin:round;transition:stroke .5s cubic-bezier(.4,0,.2,1)}
.fig.emblem .inkglow{fill:none;stroke:var(--a1);stroke-width:7;opacity:.16;stroke-linecap:round;stroke-linejoin:round}
.fig.emblem .star path{stroke:#fff;opacity:.6}
.fig.emblem .star circle:last-child{fill:#fff}
/* DIAGRAM — parts in a flow: split weights and tint fills rank the elements,
   glow softened and blurred in user units, three stars. */
.fig.diagram .ghost,.fig.diagram .ghostfine{display:none}
.fig.diagram .ink{fill:none;stroke:var(--a3);stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;transition:stroke .5s cubic-bezier(.4,0,.2,1)}
.fig.diagram .inkfine{fill:none;stroke:var(--a3);stroke-width:.6;opacity:.4;stroke-linecap:round;stroke-linejoin:round;transition:stroke .5s cubic-bezier(.4,0,.2,1)}
.fig.diagram .inkglow{fill:none;stroke:var(--a1);stroke-width:10;opacity:.24;stroke-linecap:round;stroke-linejoin:round}
.fig.diagram .wash path.on{opacity:calc(var(--wa,.13)*1.1*var(--wsc,1))}
.fig.diagram .star path{opacity:.22}
/* the scroll-draw reveals each star as the line reaches it; the role decides how
   bright it lands */
.star{opacity:0;transition:opacity .55s cubic-bezier(.4,0,.2,1)}
.fig.emblem .star.on{opacity:1}
.fig.diagram .star.on{opacity:.34}
.bg{opacity:.55}
@media(max-width:860px){.prac .row{grid-template-columns:1fr}.prac .cols2{grid-column:auto}.prac .pill{grid-column:auto;grid-row:auto}.prac .pill svg{max-height:min(38svh,320px)}}.prac li{padding:9px 0;color:var(--dim);font-size:14px;line-height:1.5;display:flex;gap:12px;border-bottom:1px solid rgba(255,255,255,.045)}
.prac li::before{content:'';width:4px;height:4px;border-radius:50%;background:var(--a1);align-self:center;flex:none}
.secta{padding-block:52px 0}
.jump{display:flex;gap:10px;flex-wrap:wrap;margin-top:36px}
.jump a{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:9px 16px;transition:border-color .3s,color .3s}
.jump a:hover{border-color:var(--a3);color:#fff}
/* crew */
.crew{display:grid;grid-template-columns:repeat(4,1fr);gap:24px}
@media(max-width:1080px){.crew{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.crew{grid-template-columns:1fr}}
.member{border:1px solid var(--line);border-radius:18px;padding:36px 30px 38px}
.member .av img{width:100%;height:100%;object-fit:cover;object-position:50% 22%;display:block;filter:grayscale(1) contrast(1.06);transition:filter .5s cubic-bezier(.4,0,.2,1)}
.member:hover .av img{filter:grayscale(0) contrast(1)}
.member .av{width:76px;height:76px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;font-family:Archivo,sans-serif;font-stretch:var(--dsw,95%);font-size:20px;color:#fff;background:linear-gradient(135deg,var(--a1),var(--a2))}
.member h4{font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,95%);font-size:21px;margin:22px 0 0}
.member .r{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);margin-top:8px}
.member p{color:var(--dim);font-size:13.5px;line-height:1.65;margin:16px 0 0}
/* orange 10%: accents that punctuate */
.stats .big b{color:var(--a4)}
.faq summary .fn,.cmeta .kv .k{color:var(--a4)}
.gpiece:hover .gn{color:#fff}
.cform input:focus,.cform textarea:focus{border-bottom-color:var(--a4)}
#hero .cue i{background:linear-gradient(180deg,var(--a4),transparent)}
.btn.ghost:hover{border-color:var(--a4);color:#fff}
.nextcase:hover .t{color:var(--a4)}

.mark{display:inline-flex;align-items:center;gap:11px;color:var(--fg)}
.mark .logohori{height:30px;width:auto;display:block;color:var(--logotext,var(--fg));transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .6s cubic-bezier(.2,.8,.2,1)}
.mark:hover .logohori{opacity:.82;transform:translateX(2px)}
.fmark .markglyph{width:44px;color:var(--a3);margin-bottom:22px}

@media(max-width:760px){.mark .logohori{height:24px}}


#hero::after,.phero::after{content:'';position:absolute;left:0;right:0;bottom:0;height:var(--heroveil,42vh);pointer-events:none;z-index:1;background:linear-gradient(180deg,rgba(7,8,13,0) 0%,rgba(7,8,13,.06) 18%,rgba(7,8,13,.2) 36%,rgba(7,8,13,.44) 54%,rgba(7,8,13,.7) 72%,rgba(7,8,13,.9) 88%,rgba(7,8,13,1) 100%)}
#hero .inner,.phero .inner{position:relative;z-index:2}
/* hero figure — a constellation in the starfield, right half of interior heroes */
.phero{--herofig:1}
/* definite figure track — an `auto` track sized from content collapses once the
   SVG is swapped for a raster canvas (width:100% in an auto track is circular) */
.phero .inner.withfig{display:grid;grid-template-columns:minmax(0,1fr) clamp(240px,34vw,500px);column-gap:56px;align-items:center}
/* width drives height (aspect-ratio), so cap WIDTH to keep the figure inside the
   hero — a max-height here would just letterbox and leave dead space */
/* The figure is static once drawn, but it overlaps an animating starfield canvas.
   Without its own compositing layer every canvas frame re-rasterises the figure's
   gradient halos and glow stroke — the cause of scroll stutter. contain:paint +
   a promoted layer means it is rasterised once and only composited thereafter. */
.phero .herofig{position:relative;justify-self:end;width:100%;max-width:min(500px,54vh);opacity:.62;pointer-events:none;transform:translateZ(0);contain:layout style}
.phero .herofig svg{display:block;width:100%;height:auto;aspect-ratio:620/470;overflow:visible}
.phero .herofig figcaption{display:none}
@media(max-width:900px){.phero{padding-block:150px 84px}.phero .inner.withfig{grid-template-columns:1fr}.phero .herofig{display:none}}
.faq details .ans{will-change:height}



.mark .logohori path.lg-word{fill:var(--logotext,#c9b8ff)}
.mark .logohori path.lg-comet{fill:var(--logomark,#7c5cff)}
.mark:hover .logohori path.lg-comet{fill:var(--a4)}

/* staggered gallery */
.gal{display:grid;grid-template-columns:1fr 1fr;column-gap:clamp(36px,6vw,120px);align-items:start}
.gpiece{display:flex;flex-direction:column;gap:20px;border-bottom:0;padding-block:0;width:auto;margin:0}
.gpiece .gframe{order:-1;margin-top:0}
.gpiece:nth-child(6n+1){grid-column:2;margin-top:0}
.gpiece:nth-child(6n+2){grid-column:1;margin-top:clamp(180px,26vw,420px)}
.gpiece:nth-child(6n+3){grid-column:2;margin-top:clamp(90px,12vw,190px)}
.gpiece:nth-child(6n+4){grid-column:1;margin-top:clamp(120px,16vw,260px)}
.gpiece:nth-child(6n+5){grid-column:2;margin-top:clamp(70px,10vw,160px)}
.gpiece:nth-child(6n+6){grid-column:1;margin-top:clamp(60px,8vw,130px)}
.gpiece:nth-child(6n+1) .gframe{aspect-ratio:4/5}
.gpiece:nth-child(6n+2) .gframe{aspect-ratio:16/11}
.gpiece:nth-child(6n+3) .gframe{aspect-ratio:1}
.gpiece:nth-child(6n+4) .gframe{aspect-ratio:3/4}
.gpiece:nth-child(6n+5) .gframe{aspect-ratio:16/10}
.gpiece:nth-child(6n+6) .gframe{aspect-ratio:5/6}
.gpiece:nth-child(6n+2),.gpiece:nth-child(6n+4){margin-right:clamp(0px,4vw,70px)}
.gpiece:nth-child(6n+3),.gpiece:nth-child(6n+5){margin-left:clamp(0px,5vw,90px)}
.gpiece .cap2{gap:18px;align-items:baseline}
.gpiece h3{font-size:clamp(26px,2.9vw,42px)}
.gpiece .gsub{margin-top:0;font-size:14.5px;max-width:38ch;line-height:1.65}
.gpiece .gtags{margin-top:2px}
.gwide,.gtall{aspect-ratio:auto}
.gduo{display:contents}
@media(max-width:860px){.gal{grid-template-columns:1fr}.gpiece,.gpiece:nth-child(n){grid-column:1;margin:0 0 clamp(70px,12vw,110px);width:100%}.gpiece:nth-child(n) .gframe{aspect-ratio:4/3}}
/* The 6n rhythm above composes SIX pieces. With two, its per-position columns
   and ratios put 01 on the right and 02 far below on the left, at mismatched
   ratios — so a two-item grid gets its own rhythm: reading order preserved,
   both frames on one ratio so they read as a pair. */
.gal.two .gpiece:nth-child(1){grid-column:1;margin-top:0;margin-right:clamp(0px,4vw,70px);margin-left:0}
.gal.two .gpiece:nth-child(2){grid-column:2;margin-top:clamp(90px,13vw,200px);margin-left:clamp(0px,5vw,90px);margin-right:0}
/* Both frames share ONE box, in either orientation. They had different ratios
   (a 4:5 hold beside a 1920/890 wide frame) and the taller card read as the more
   important project purely because it occupied roughly twice the area — an
   accident of asset shape, not an editorial decision. The offset stagger does
   the rhythm; size does not do the ranking.

   ORIENTATION TWEAK: landscape (16:10) is the default, portrait (4:5) is the
   alternative, and each mode uses the asset that FITS it rather than forcing one
   source into both — the 2.157:1 hero contained in a 4:5 box would letterbox
   about 63% of the frame, so portrait swaps to the full-page shot, natively 3:4. */
.gal.two .gpiece:nth-child(1) .gframe,
.gal.two .gpiece:nth-child(2) .gframe{aspect-ratio:16/10}
html[data-thumbs="portrait"] .gal.two .gpiece:nth-child(1) .gframe,
html[data-thumbs="portrait"] .gal.two .gpiece:nth-child(2) .gframe{aspect-ratio:4/5}
/* Orientation only swaps WHICH artifact is inset — the figure is the card art in
   both modes, so neither image is full-bleed any more and the old rules that
   sized them to the frame are gone. They out-specified .inset and stretched the
   specimen to fill the whole card. */
.gpar img.lsc,.gpar img.prt{display:none}
.gpar img.inset.lsc{display:block}
html[data-thumbs="portrait"] .gpar img.inset.lsc{display:none}
html[data-thumbs="portrait"] .gpar img.inset.prt{display:block}
/* awaiting art: a designed hold, not an empty gradient. The hatch rides on an
   inner <i> rather than on .gpar itself, for two reasons: both of .gframe's
   pseudo-elements are already taken (::before by the hover spotlight, ::after by
   the hover scale overlay), AND the parallax rig measures slack from .gpar's
   first child — with an empty .gpar there is nothing to move and --py pins at 0
   forever, so the card silently loses its drift. The <i> is oversized like an
   image would be, so the hold drifts exactly as real art will. */
.gframe.ph .gpar i{position:absolute;inset:-9% 0;width:100%;height:118%;display:block;background-image:repeating-linear-gradient(135deg,rgba(201,184,255,.06) 0 2px,transparent 2px 11px);transform:translate3d(0,var(--py,0px),0)}
/* ── figure-led thumbnails ──────────────────────────────────────────────
   A screenshot alone makes a flat, characterless thumbnail, and a hatched hold
   makes none at all. The card's own case figure carries the frame instead —
   drawn large, tinted, from the same illustration system as the case pages — and
   the real artifact sits inset at small size as evidence. That reads as a
   deliberate cover rather than a cropped browser window, and it degrades
   gracefully: a case with no imagery yet still gets a real thumbnail. ── */
/* Figure-led cards do NOT drift. The rig measures slack from .gpar's first child
   and a figure sized to the frame has none, so a data-par here would sit dead at
   0 while looking live — the exact trap the hatched hold fell into. Motion on
   these cards is the hover scale and the figure's own draw-in instead. */
.gpar .gfig{position:absolute;inset:0;margin:0;display:flex;align-items:center;justify-content:center;padding:clamp(14px,3.5%,34px)}
.gpar .gfig svg{width:100%;height:auto;max-height:100%;overflow:visible;display:block}
/* the inset is the artifact itself: small, cornered, on its own rule so it reads
   as a specimen pinned to the cover rather than the cover's subject. Height is
   FIXED as a share of the frame rather than left to the source's ratio — a
   portrait page shot at height:auto grew past the frame's bottom edge. */
.gpar img.inset{position:absolute;inset:auto 8% 11% auto;width:46%;height:34%;object-fit:cover;object-position:50% 0;border:1px solid rgba(201,184,255,.22);border-radius:4px;box-shadow:0 22px 50px -22px rgba(0,0,0,.75);filter:none;transform:none;z-index:2}
html[data-thumbs="portrait"] .gpar img.inset{height:26%}
@media(max-width:560px){.gpar img.inset{width:54%;inset:auto 7% 10% auto}}
.gframe .phn{position:absolute;left:50%;top:50%;translate:-50% -50%;z-index:2;font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);text-align:center;padding-inline:24px}
@media(max-width:860px){.gal.two .gpiece:nth-child(n){grid-column:1;margin:0 0 clamp(70px,12vw,110px)}.gal.two .gpiece:nth-child(n) .gframe{aspect-ratio:4/3}}
.gpiece{color:inherit}
.gpiece .gn{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.gpiece h3{color:var(--fg);transition:color .45s cubic-bezier(.4,0,.2,1)}
.gpiece:hover h3{color:var(--a3)}
.gpiece .gsub{color:var(--dim)}
.gpiece .gtags{display:flex;gap:8px;flex-wrap:wrap}
.gpiece .gtags span{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);border:1px solid var(--line);border-radius:999px;padding:6px 13px;transition:border-color .45s cubic-bezier(.4,0,.2,1),color .45s cubic-bezier(.4,0,.2,1)}
.gpiece:hover .gtags span{border-color:rgba(201,184,255,.28);color:var(--dim)}
.gframe{position:relative;overflow:hidden;border-radius:22px;border:1px solid var(--line)}
/* project art drifts inside its frame on scroll — same rig as the team portraits:
   the image is oversized to 138% of the frame and initParallax clamps --py to the
   real slack each frame so it can never expose the frame background */
.gpar{position:absolute;inset:0;z-index:1;overflow:hidden;pointer-events:none}
.gpar img{position:absolute;inset:-19% 0;width:100%;height:138%;object-fit:cover;display:block;filter:grayscale(1) contrast(1.04) brightness(.92);transform:translate3d(0,var(--py,0px),0);transition:filter .7s cubic-bezier(.4,0,.2,1)}
/* A figure-led card shows its FRAME as the card background — the SVG is
   transparent and covers ~70% — while a photo card occludes the identical
   gradient completely at 136% cover. So the shared v1/v4 tint read as a violet
   glow on one card and as nothing on the other, which is the unequal-prominence
   problem again in the colour channel. Neutralise the tint wherever the art
   cannot hide it; the accent still arrives on hover with everything else. */
.gframe:has(.gfig){background:var(--bg2)}
.gpiece:hover .gpar img{filter:grayscale(0) contrast(1) brightness(1)}
/* A figure-led card carries no <img>, so the grayscale-at-rest device above never
   touched it and it sat at full accent saturation beside a muted photo card — the
   same unequal-prominence problem the shared box fixed in the size channel,
   reappearing in the contrast channel. The figure gets the equivalent rest state
   and resolves on the same hover, so weight is matched however a card is built. */
.gpar .gfig{filter:grayscale(.88) contrast(1.04) brightness(.94);transition:filter .5s cubic-bezier(.4,0,.2,1)}
.gpiece:hover .gpar .gfig{filter:grayscale(0) contrast(1) brightness(1)}
.gpar::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(7,8,13,.62),transparent 44%)}
.gframe::after{content:'';position:absolute;inset:0;background:inherit;transition:transform 1.15s cubic-bezier(.2,.8,.2,1)}
.gpiece:hover .gframe::after{transform:scale(1.045)}
.gframe .lab{position:absolute;left:24px;bottom:22px;z-index:2;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}
.gframe .view{position:absolute;right:24px;bottom:22px;z-index:2;display:flex;align-items:center;gap:10px;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--fg);opacity:0;transform:translateY(8px);transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .5s cubic-bezier(.2,.8,.2,1)}
.gpiece:hover .gframe .view{opacity:1;transform:none}
.gpiece .gframe::before{z-index:3}

/* ── compact section heads ── */
.shead.tight{padding-block:120px 52px}
/* ── hosting: the stack, as one connected object ── */
.layers{display:grid;grid-template-columns:.78fr 1fr;gap:clamp(32px,5vw,64px);align-items:start;padding-bottom:120px}
.lstack{position:sticky;top:120px}
.lrail{position:relative;display:flex;flex-direction:column;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden}
.lrail::after{content:'';position:absolute;left:0;top:0;width:2px;height:calc(100% / 3);background:var(--a1);box-shadow:0 0 14px var(--a1);transform:translateY(calc(var(--i,0) * 100%));transition:transform .5s cubic-bezier(.4,0,.2,1);z-index:2}
.ltab{all:unset;box-sizing:border-box;cursor:pointer;background:var(--bg);display:grid;grid-template-columns:auto 1fr;column-gap:14px;row-gap:7px;padding:24px 26px;width:100%;transition:background .45s cubic-bezier(.4,0,.2,1)}
.ltab .ln{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4);padding-top:5px}
.ltab .lt{font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%);font-size:clamp(19px,1.6vw,23px);color:var(--dim);transition:color .35s}
.ltab .lh{grid-column:2;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
.ltab:hover{background:color-mix(in oklch,var(--bg) 88%,var(--a1))}
.ltab.on{background:color-mix(in oklch,var(--bg) 80%,var(--a1))}
.ltab.on .lt{color:#fff}
.lfig{margin:0;padding:0;border:0;background:none;grid-column:2;grid-row:1;align-self:start}
.lfig svg{width:100%;height:auto;aspect-ratio:440/300;display:block}
.lnote{margin-top:22px;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--mute);line-height:1.9;max-width:34ch}
.lpanels{position:relative;min-height:330px}
.lpanel{display:none}
.lpanel.on{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.82fr);column-gap:44px;align-items:start;animation:lfade .55s cubic-bezier(.4,0,.2,1)}
@keyframes lfade{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.lpanel .lede2{grid-column:1;grid-row:1;color:var(--dim);line-height:1.7;font-size:15.5px;max-width:42ch;margin-bottom:34px}
.lcols{grid-column:1/-1;grid-row:2;display:grid;grid-template-columns:1fr 1fr;gap:40px}
.lcols h5{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);font-weight:500;margin:0 0 14px}
.lcols ul{list-style:none;margin:0;padding:0}
.lcols li{padding:9px 0;color:var(--dim);font-size:14px;line-height:1.5;display:flex;gap:12px;border-bottom:1px solid rgba(255,255,255,.045)}
.lcols li::before{content:'';width:4px;height:4px;border-radius:50%;background:var(--a1);align-self:center;flex:none}
@media(max-width:860px){.layers{grid-template-columns:1fr;gap:40px}.lstack{position:static}.lpanel.on{grid-template-columns:1fr}.lfig{grid-column:1;grid-row:auto;max-width:340px;margin-bottom:30px}.lcols{grid-column:1;grid-row:auto;grid-template-columns:1fr;gap:24px}.lpanels{min-height:0}}
/* ── flight-plan flow diagram ── */
.flow{position:relative;height:330px;margin-bottom:110px}
.flowline{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.flowline path{fill:none;stroke:var(--line);stroke-width:1;vector-effect:non-scaling-stroke}
.flowline path.fl2{stroke:var(--a3);opacity:.75;stroke-dasharray:180;stroke-dashoffset:180;transition:stroke-dashoffset 1.9s cubic-bezier(.33,1,.68,1) .15s}
.flow.in .flowline path.fl2{stroke-dashoffset:0}
.flow.rv{opacity:1}
.fstep{position:absolute;width:23%;left:calc(var(--x) * 1% - 11.5%);top:calc(var(--y) * 1% + 26px)}
.fstep::before{content:'';position:absolute;top:-30px;left:50%;width:9px;height:9px;margin-left:-4.5px;border-radius:50%;background:var(--a1);box-shadow:0 0 0 5px color-mix(in oklch,var(--bg) 70%,transparent),0 0 16px var(--a1)}
.fstep .n{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.fstep h4{font-size:22px;margin:12px 0 0;font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%)}
.fstep p{color:var(--dim);font-size:14px;line-height:1.65;margin:10px 0 0;text-wrap:pretty}
@media(max-width:860px){.flow{height:auto;display:grid;grid-template-columns:1fr 1fr;gap:44px 30px;margin-bottom:80px;padding-top:8px}.flowline{display:none}.fstep{position:static;width:auto;left:auto;top:auto}.fstep::before{position:static;display:block;margin:0 0 16px}}
@media(max-width:560px){.flow{grid-template-columns:1fr}}
/* ── three rules, one line ── */
.rules{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(28px,4vw,56px);position:relative;padding-bottom:20px}
.rfig{margin:0 0 24px;padding:0;border:0;background:none}
.rfig svg{width:100%;height:auto;aspect-ratio:340/240;display:block;max-width:330px;overflow:visible}
.rul{position:relative}
.rmark{width:58px;height:58px;border-radius:50%;border:1px solid var(--line);background:var(--bg);display:grid;place-items:center;position:relative;z-index:1}
.rmark svg{width:26px;height:26px;fill:var(--a3);opacity:.9}
.rul .n{display:block;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.rul h4{font-size:24px;margin:14px 0 0;font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%)}
.rul p{color:var(--dim);font-size:14.5px;line-height:1.7;margin:12px 0 0;max-width:38ch;text-wrap:pretty}
@media(max-width:860px){.rules{grid-template-columns:1fr;gap:52px}.rfig svg{max-width:280px}}
/* ── case study: short and sticky. A fixed spine of small dense blocks rather
   than prose chapters — the payoff is front-loaded because nobody reads down. ── */
.cclaim{padding-block:70px 0}
.cclaim>p{font-family:Archivo,sans-serif;font-weight:300;font-stretch:98%;font-size:clamp(26px,3.4vw,42px);line-height:1.18;letter-spacing:-.02em;margin:0;text-wrap:balance;max-width:20ch}
/* the emphasis has to be a different CUT, not the same face recoloured — the
   claim is Archivo 300, so the lift is italic at a heavier weight.
   Direct child only: .proves sits inside .cclaim and must not inherit this. */
.cclaim>p em{font-style:italic;font-weight:400;color:var(--a3)}
/* the block the whole page exists for */
.proves{margin-top:64px;padding:34px 0 0;border-top:1px solid var(--line);display:grid;grid-template-columns:minmax(0,220px) 1fr;gap:26px 44px;align-items:start}
.proves .pk{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--a4)}
/* body is Inter 300; the lead sentence steps to Archivo 500 a shade larger, so
   it separates by type rather than by colour alone */
.proves p{margin:0;font-family:Inter,system-ui,sans-serif;font-weight:300;font-size:clamp(17px,1.7vw,21px);line-height:1.55;color:var(--fg);max-width:52ch;text-wrap:pretty}
/* body is Inter; the lead sentence steps to Archivo, heavier and a shade larger,
   so it separates by type rather than by colour alone */
.proves p b{font-family:Archivo,sans-serif;font-weight:500;font-stretch:96%;font-size:1.08em;letter-spacing:-.012em;color:var(--a3)}
/* the page opens on the work: a full-bleed band directly under the hero, before
   any prose. #warp is already edge-to-edge, so no 100vw escape — that would
   include the scrollbar gutter and overflow by its width on classic scrollbars. */
.clead{position:relative;aspect-ratio:21/9;max-height:62svh;border-block:1px solid var(--line);overflow:hidden;display:flex;align-items:flex-end;background:linear-gradient(140deg,rgba(124,92,255,.16),rgba(58,141,255,.07) 46%,rgba(7,8,13,0) 78%),var(--bg2)}
.clead::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(7,8,13,.72),transparent 52%);pointer-events:none}
/* Both sit outside .wrap (their band is full-bleed), so they must carry the page
   column's own geometry — a viewport-relative inset tracks the window edge while
   every sibling tracks a centred 1240px column, and the two diverge without
   limit above that width. A lead holding a real screenshot also puts its caption
   BELOW the band: inside, it lands on the shot's own footer type. */
.clead .lab,.cleadwrap figcaption{width:100%;max-width:1240px;margin-inline:auto;padding-inline:32px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)}
.clead .lab{position:relative;z-index:1;margin-block:0 clamp(18px,2.6vw,32px)}
.cleadwrap{margin:0}
.cleadwrap figcaption{margin-block:14px 0}
.cleadwrap .clead.hasmedia::after{content:none}
@media(max-width:560px){.clead .lab,.cleadwrap figcaption{padding-inline:22px}}
/* a lead can carry real footage or a still; it sits under the scrim and label */
.clead video,.clead img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
/* Parallax needs vertical overshoot to move into, and every pixel of overshoot
   is a pixel cropped — so screenshots get 118%, not the 138% used for portraits.
   Background only where an image actually fills the box, or this would beat the
   .v1/.v4 placeholder gradients on specificity and flatten them. */
.cimg:has(img){background:var(--bg2)}
/* SCREENSHOTS hold still and fill exactly. Drift on a UI shot fights the thing
   it is showing — the interface has its own alignment, and moving it inside a
   fixed frame reads as a rendering fault rather than depth. */
.cimg img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 50%;display:block}
/* full-page shots anchor to the top: the masthead identifies them */
.cimgs.pages .cimg img,.cshot.page .cimg img{object-position:50% 0}
/* DECORATIVE photography and the hero band drift: 118% gives the shared
   [data-par] rig slack, and on texture a crop costs nothing. */
.cimg.deco img,.clead img{inset:-9% 0;height:118%;transform:translate3d(0,var(--py,0px),0)}
/* B-roll is GRADED so it can never be read as a screenshot of the work, and the
   grade is BLACK AND WHITE — settled decision, not a default.
   The tinted alternatives were explored and dropped: a Novas violet wash fought
   the client's own accent (BIMNovate's is azul-turquesa #67c2c5), and tinting
   toward the client's colour instead makes the treatment re-tune per case, which
   is not a system. Neutral works beside any palette a client brings.
   Deliberately no mix-blend-mode — a blended layer over a filtered image forces
   its own compositing pass per frame, and with a dozen large photos plus sticky
   columns that locked the renderer outright. */
.cimg.deco img{filter:grayscale(1) contrast(1.07) brightness(.82)}
.cimg.deco::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(200deg,rgba(255,255,255,.03),rgba(7,8,13,.3))}
/* no captions: with only two real cases there is no comparison to label, and a
   monospace line under every frame turned the page into an inventory. The alt
   text still carries the description for anyone who needs it. */
.cshot{margin:0;display:flex;flex-direction:column}
.cshot .cimg{width:100%}
.cshot figcaption{display:none}
.cimg span{position:relative;z-index:2}
.cimg:has(img)::before{content:none}
/* the img is a later child, so it paints over a ::before scrim — lift the scrim */
.cimg::before{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(7,8,13,.82),rgba(7,8,13,.35) 26%,transparent 52%);pointer-events:none}
.cimgs.pages .cimg{aspect-ratio:1100/1474}
@media(max-width:760px){.cimgs.pages .cimg{aspect-ratio:16/10}}/* the band takes the capture's own ratio so a screen recording is not cropped.
   No opaque fill: if the video stalls or is still buffering the poster shows,
   and failing that the designed gradient does — never a grey box. */
.clead.hasmedia{aspect-ratio:2.156/1;max-height:80svh}
@media(max-width:640px){.clead{aspect-ratio:4/3}}
/* scope sits in the hero, directly under the meta strip — what the engagement
   actually covered should be legible before any prose */
.cscope{margin-top:30px;border-top:1px solid var(--line);padding-top:24px}
.cscope .sk{display:block;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--a4);margin-bottom:18px}
.cscope ul{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:8px}
.cscope li{display:inline-flex;align-items:center;gap:9px;font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.07em;color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:8px 15px 8px 12px;background:rgba(255,255,255,.014);transition:border-color .4s cubic-bezier(.4,0,.2,1),color .4s}
.cscope li:hover{border-color:rgba(201,184,255,.3);color:var(--fg)}
.cscope svg{width:13px;height:13px;flex:none;color:var(--a3);overflow:visible}
.cscope svg *{fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.cscope svg .f{fill:currentColor;stroke:none}
@media(max-width:760px){.cscope ul{gap:7px}}
.csec{padding-block:78px 0}
.csec>.wrap>.ck{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--mute);display:block;margin-bottom:26px}
.cprob{max-width:64ch;font-size:16.5px;line-height:1.75;color:var(--dim);text-wrap:pretty}
.cprob b{color:var(--fg);font-weight:400}
.cbuilt{display:grid;grid-template-columns:repeat(3,1fr);gap:38px 40px}
/* each capability cell carries a small mark — the grid was a wall of text */
.cbuilt>div{border-top:1px solid var(--line);padding-top:18px}
.cbuilt figure{margin:0 0 16px;max-width:150px}
.cbuilt figure svg{width:100%;height:auto;aspect-ratio:160/110;display:block;overflow:visible}
.cbuilt h5{margin:0;font-family:Archivo,sans-serif;font-weight:400;font-stretch:98%;font-size:16.5px;letter-spacing:-.01em}
.cbuilt p{margin:8px 0 0;font-size:13.5px;line-height:1.6;color:var(--dim);text-wrap:pretty;max-width:30ch}
.cnums{display:grid;grid-template-columns:repeat(3,1fr);gap:34px;padding-block:40px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.cnums .n{font-family:Archivo,sans-serif;font-weight:300;font-stretch:88%;font-size:clamp(34px,4.4vw,54px);letter-spacing:-.03em;line-height:1;color:var(--a3)}
.cnums .l{margin-top:12px;font-size:13.5px;line-height:1.6;color:var(--dim);max-width:26ch}
.ctest{margin-top:56px;max-width:60ch}
.ctest blockquote{margin:0;font-family:Archivo,sans-serif;font-weight:300;font-stretch:98%;font-size:clamp(19px,2.2vw,26px);line-height:1.45;letter-spacing:-.015em;text-wrap:pretty}
.ctest .who{margin-top:20px;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute)}
.cstack{display:flex;flex-wrap:wrap;gap:8px}
.cstack span{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.06em;color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:8px 14px}
.clive{margin-top:34px}
@media(max-width:980px){.cbuilt{grid-template-columns:repeat(2,1fr)}.proves{grid-template-columns:1fr;gap:16px}}
@media(max-width:640px){.cbuilt,.cnums{grid-template-columns:1fr}.cnums{gap:28px}}
@media(max-width:560px){.cclaim{padding-top:44px}.csec{padding-top:56px}.proves{margin-top:44px}}
/* a case figure runs full measure with a station legend under it — the page
   needs visual beats between the text blocks, not more paragraphs */
.cfig{margin:0;padding-block:64px 0}
.cfig svg{width:100%;height:auto;aspect-ratio:620/320;display:block;overflow:visible;max-width:620px;margin-inline:auto}
/* diagram and legend share the row — full-measure the figure reads as a poster
   rather than an explanatory aside, and dwarfs the copy around it */
.cfigrow{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);gap:clamp(30px,5vw,68px);align-items:center;padding-block:64px 0}
.cfigrow .cfig{padding-block:0}
.cfigrow .cfig svg{max-width:none}
.cfigrow .csteps{margin-top:0;border-top:0;padding-top:0;grid-template-columns:1fr;gap:0}
.cfigrow .csteps.three{grid-template-columns:1fr}
.cfigrow .csteps>div{border-top:1px solid var(--line);padding-block:16px}
.cfigrow .csteps>div:first-child{border-top:0;padding-top:0}
.cfigrow .csteps .d{max-width:40ch}
@media(max-width:900px){.cfigrow{grid-template-columns:1fr;gap:30px}.cfigrow .cfig svg{max-width:520px}}
.csteps{display:grid;grid-template-columns:repeat(4,1fr);gap:20px 30px;margin-top:34px;border-top:1px solid var(--line);padding-top:22px}
.csteps.three{grid-template-columns:repeat(3,1fr)}
.csteps .n{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.2em;color:var(--a4)}
.csteps .t{margin-top:8px;font-family:Archivo,sans-serif;font-weight:400;font-stretch:98%;font-size:15px}
.csteps .d{margin-top:5px;font-size:13px;line-height:1.55;color:var(--dim)}
@media(max-width:700px){.csteps{grid-template-columns:1fr 1fr}}
/* the problem section pairs its copy with an on-site shot — concrete and rebar
   are literally what the copy is about, so the image argues rather than decorates */
.cprobrow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.56fr);gap:clamp(30px,5vw,72px);align-items:start}
.cprobrow .cshot .cimg{aspect-ratio:1000/1600}
@media(max-width:860px){.cprobrow{grid-template-columns:1fr;gap:34px}.cprobrow .cshot{max-width:420px}}
/* ── editorial furniture: a full-measure statement that breaks the reading
   rhythm, and an offset b-roll strip of small texture shots ── */
.cpull{padding-block:96px 0}
.cpull p{margin:0;font-family:Archivo,sans-serif;font-weight:300;font-stretch:92%;font-size:clamp(30px,5.4vw,72px);line-height:1.04;letter-spacing:-.035em;text-wrap:balance;max-width:16ch}
.cpull p em{font-style:italic;font-weight:400;color:var(--a3)}
.cpull .attr{margin-top:26px;padding-top:18px;border-top:1px solid var(--line);font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);max-width:34ch}
/* three small frames on a stagger — texture between the big set pieces */
.broll{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2.4vw,34px);align-items:start;padding-block:76px 0}
.broll .cshot:nth-child(1){margin-top:0}
.broll .cshot:nth-child(2){margin-top:clamp(28px,6vw,86px)}
.broll .cshot:nth-child(3){margin-top:clamp(12px,2.6vw,38px)}
.broll .cimg{aspect-ratio:4/5}
.broll .cshot:nth-child(2) .cimg{aspect-ratio:1/1}
.broll figcaption{font-size:9.5px}
@media(max-width:700px){.broll{grid-template-columns:1fr 1fr}.broll .cshot:nth-child(3){display:none}}
/* Woven evidence: every screenshot is paired with a smaller site photo on an
   offset, sides alternating down the page. The b-roll is the rhythm between the
   UI shots rather than a block of its own. */
.cweave{display:grid;gap:clamp(18px,2.8vw,44px);align-items:center;padding-block:72px 0}
.cweave.a{grid-template-columns:1.9fr 1fr}
.cweave.b{grid-template-columns:1fr 1.9fr}
.cweave.c{grid-template-columns:1.14fr .72fr 1.14fr}
.cweave .sm{margin-top:clamp(24px,6vw,84px)}
.cweave .sm .cimg{aspect-ratio:3/4}
.cweave .lg .cimg{aspect-ratio:1600/918}
.cweave.c .lg .cimg{aspect-ratio:1100/1474}
@media(max-width:860px){.cweave.a,.cweave.b,.cweave.c{grid-template-columns:1fr 1fr}.cweave .sm{margin-top:0}.cweave.c .lg:last-child{grid-column:1/-1;max-width:60%}}
@media(max-width:560px){.cweave.a,.cweave.b,.cweave.c{grid-template-columns:1fr}.cweave.c .lg:last-child{max-width:none}}
/* ── compact cross-sell band ── */
.band{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,72px);align-items:end;padding-block:78px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.band h2{font-size:clamp(30px,3.4vw,46px);margin:18px 0 0;max-width:22ch;text-wrap:balance}
.band .lede{color:var(--dim);max-width:52ch;text-wrap:pretty;line-height:1.7;margin:0}
.band .go{margin-top:22px}
.band.top{align-items:start}
@media(max-width:1180px){.origins .band.top{min-height:0}.origins .band.top>div:first-child{align-self:start}}
.band .lede + .lede{margin-top:20px}
@media(max-width:860px){.band{grid-template-columns:1fr;gap:26px;align-items:start;padding-block:60px}}

.ai{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(28px,3.4vw,52px) clamp(28px,3vw,48px)}
.aij{border-top:1px solid var(--line);padding-top:22px}
.aij .n{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;color:var(--a4)}
.aij h4{font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,102%);font-size:21px;margin:12px 0 0}
.aij p{color:var(--dim);font-size:14px;line-height:1.7;margin:12px 0 0;text-wrap:pretty}
.cols2 li b{display:block;color:var(--fg);font-weight:500;margin-bottom:5px;font-size:14.5px}
.prac li:has(b){display:block;padding-left:16px;position:relative}
.prac li:has(b)::before{position:absolute;left:0;top:11px}
.prac li:has(b) i{font-style:normal;display:block;color:var(--dim)}
@media(max-width:980px){.ai{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.ai{grid-template-columns:1fr}}

/* ── crew: large staggered portraits, image drifts inside a fixed frame ── */
.crewx{display:grid;grid-template-columns:repeat(2,minmax(0,450px));justify-content:center;gap:clamp(56px,7vw,110px) clamp(40px,6vw,110px)}
.cx:nth-child(even){margin-top:clamp(50px,9vw,150px)}
.cxfig{position:relative;overflow:hidden;border-radius:18px;aspect-ratio:450/550;max-width:450px;background:var(--bg2);border:1px solid var(--line)}
.cxfig img{position:absolute;inset:-19% 0;width:100%;height:138%;object-fit:cover;object-position:50% 50%;display:block;filter:grayscale(1) contrast(1.05) brightness(.92);transform:translate3d(0,var(--py,0px),0) scale(var(--pz,1));transition:filter .7s cubic-bezier(.4,0,.2,1)}
.cx:hover .cxfig img{filter:grayscale(0) contrast(1) brightness(1)}
.cxfig::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(7,8,13,.55),transparent 46%);pointer-events:none}
.cx h4{font-family:Archivo,sans-serif;font-weight:400;font-stretch:var(--dsw,95%);font-size:clamp(22px,2.2vw,30px);margin:26px 0 0;text-wrap:balance}
.cx .r{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--a4);margin-top:10px}
.cx p{color:var(--dim);font-size:14.5px;line-height:1.75;margin:18px 0 0;max-width:48ch;text-wrap:pretty}
@media(max-width:1040px){.crewx{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:760px){.crewx{grid-template-columns:minmax(0,450px);justify-content:start;gap:64px}.cx:nth-child(even){margin-top:0}}
/* ── origins: a distant star flaring — a hard point of light and two hairline
   shells expanding off it. Deliberately small and mostly line, not glow: the
   first pass was a purple blob that read as a lens flare. ── */
.origins{position:relative}
.nova{position:absolute;left:calc(22vw + 190px);top:50%;width:340px;aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none;z-index:0}
.nova i{position:absolute;left:50%;top:50%;border-radius:50%;display:block;transform:translate(-50%,-50%)}
.nova .core{width:5px;height:5px;background:#fff;box-shadow:0 0 6px 1px rgba(255,255,255,.9),0 0 26px 6px rgba(201,184,255,.42),0 0 60px 22px rgba(124,92,255,.13);opacity:calc(.25 + var(--b,0) * .75);transform:translate(-50%,-50%) scale(calc(.7 + var(--b,0) * .8))}
.nova .shell,.nova .shell2{width:300px;height:300px;border:1px solid rgba(201,184,255,.22)}
.nova .shell{transform:translate(-50%,-50%) scale(calc(.16 + var(--b,0) * .72));opacity:calc(var(--b,0) * (1 - var(--b,0)) * 2.6)}
.nova .shell2{border-color:rgba(209,97,58,.18);transform:translate(-50%,-50%) scale(calc(.06 + var(--b,0) * .42));opacity:calc(var(--b,0) * (1 - var(--b,0) * .8) * 2)}
.nova .dust{width:300px;height:300px;border:0;background:radial-gradient(circle,rgba(124,92,255,.11),transparent 58%);filter:blur(14px);opacity:calc(var(--b,0) * .8);transform:translate(-50%,-50%) scale(calc(.4 + var(--b,0) * .5))}
.origins .wrap{position:relative;z-index:1}
@media(max-width:1180px){.nova{left:min(46vw,340px);width:min(52vw,300px)}}
@media(max-width:860px){.nova{left:auto;right:-8vw;top:34%;width:min(64vw,280px);opacity:.75}}


/* hero wordmark line: sized off the viewport so it holds on one line */
#hero h1.oneline{max-width:none;font-size:min(7vw,104px);line-height:1}
@media(max-width:640px){#hero h1.oneline{font-size:min(10vw,58px)}}

/* ═══════════════ mobile & touch pass ═══════════════ */
/* ── nav: hamburger + full-screen overlay. The sheet sits at z-index 99, under
   the fixed bar, so the logo and the toggle stay live over it and the bar's
   scroll-driven --navp backdrop keeps working underneath. ── */
.navtog{display:none}
@media(max-width:720px){
.nav{padding:13px 20px}
.nav>.btn{display:none}
.navtog{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;margin-right:-11px;padding:0;border:0;border-radius:0;background:none;color:var(--fg);cursor:pointer;-webkit-tap-highlight-color:transparent}
.navtog i{position:relative;display:block;width:18px;height:0;background:none}
.navtog i::before,.navtog i::after{content:'';position:absolute;height:1.5px;border-radius:2px;background:currentColor;transition:transform .5s cubic-bezier(.2,.8,.2,1),width .5s cubic-bezier(.2,.8,.2,1),left .5s cubic-bezier(.2,.8,.2,1)}
.navtog i::before{top:-3.5px;left:0;width:18px}
.navtog i::after{top:3.5px;left:5px;width:13px}
.nav.open .navtog i::before{transform:translateY(3.5px) rotate(45deg)}
.nav.open .navtog i::after{left:0;width:18px;transform:translateY(-3.5px) rotate(-45deg)}
}
.navsheet{position:fixed;inset:0;z-index:99;display:flex;background:rgba(7,8,13,.94);backdrop-filter:blur(20px) saturate(120%);-webkit-backdrop-filter:blur(20px) saturate(120%);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .42s cubic-bezier(.4,0,.2,1),visibility 0s linear .42s;overscroll-behavior:contain}
.navsheet.on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .42s cubic-bezier(.4,0,.2,1),visibility 0s}
@media(min-width:721px){.navsheet{display:none}}
/* sheet backdrop: an arc echoing the orbit ring with a spark sweeping its crest,
   over two slow nebula glows — the same vocabulary as the hero and the carousel */
.nsfx{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0;opacity:0;transition:opacity .9s cubic-bezier(.4,0,.2,1)}
.navsheet.on .nsfx{opacity:1}
.nsring,.nsorb{position:absolute;left:50%;top:14vh;width:170vw;height:170vw;margin-left:-85vw}
.nsring{border:1px solid rgba(201,184,255,.14);border-radius:50%}
.nsorb{animation:nssweep 11s cubic-bezier(.45,0,.55,1) infinite alternate}
.nsorb b{position:absolute;left:50%;top:-4px;width:7px;height:7px;margin-left:-3.5px;border-radius:50%;background:var(--a3);box-shadow:0 0 12px var(--a3),0 0 32px rgba(124,92,255,.55)}
.nsg{position:absolute;border-radius:50%;filter:blur(64px)}
.nsg1{left:-24vw;top:4vh;width:76vw;height:76vw;background:radial-gradient(circle,rgba(124,92,255,.24),transparent 66%);animation:nsdrift 19s ease-in-out infinite alternate}
.nsg2{right:-26vw;bottom:2vh;width:68vw;height:68vw;background:radial-gradient(circle,rgba(58,141,255,.17),transparent 66%);animation:nsdrift 25s ease-in-out infinite alternate-reverse}
@keyframes nssweep{from{transform:rotate(-19deg)}to{transform:rotate(19deg)}}
@keyframes nsdrift{from{transform:translate3d(0,0,0)}to{transform:translate3d(7vw,-5vh,0)}}
.nsinner{position:relative;z-index:1;margin-top:auto;width:100%;padding:0 22px calc(30px + env(safe-area-inset-bottom));display:flex;flex-direction:column}
.nslinks{display:flex;flex-direction:column;border-top:1px solid var(--line)}
.nslinks a{display:flex;align-items:baseline;gap:16px;padding:17px 0;min-height:56px;border-bottom:1px solid var(--line);font-family:Archivo,sans-serif;font-weight:300;font-stretch:95%;letter-spacing:-.02em;font-size:clamp(28px,8.4vw,38px);line-height:1.1;color:var(--fg);opacity:0;transform:translateY(18px);transition:opacity .5s cubic-bezier(.4,0,.2,1),transform .6s cubic-bezier(.2,.8,.2,1),color .3s}
.nslinks a .nsn{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.2em;color:var(--mute);flex:none}
.nslinks a.on{color:var(--a3)}
.nslinks a.on .nsn{color:var(--a4)}
.navsheet.on .nslinks a{opacity:1;transform:none}
.navsheet.on .nslinks a:nth-child(1){transition-delay:.06s}
.navsheet.on .nslinks a:nth-child(2){transition-delay:.11s}
.navsheet.on .nslinks a:nth-child(3){transition-delay:.16s}
.navsheet.on .nslinks a:nth-child(4){transition-delay:.21s}
.navsheet.on .nslinks a:nth-child(5){transition-delay:.26s}
.navsheet.on .nslinks a:nth-child(6){transition-delay:.31s}
.nscta{margin-top:26px;justify-content:center;padding:17px 28px;font-size:14px;opacity:0;transform:translateY(18px);transition:opacity .5s cubic-bezier(.4,0,.2,1) .36s,transform .6s cubic-bezier(.2,.8,.2,1) .36s,background .45s cubic-bezier(.4,0,.2,1)}
.navsheet.on .nscta{opacity:1;transform:none}
.nsfoot{margin-top:24px;font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);opacity:0;transition:opacity .5s cubic-bezier(.4,0,.2,1) .44s}
.navsheet.on .nsfoot{opacity:1}
@media(prefers-reduced-motion:reduce){.navsheet,.nslinks a,.nscta,.nsfoot{transition-duration:.01ms!important;transition-delay:0s!important}.nsorb,.nsg1,.nsg2{animation:none}}

/* ── orbit on phones: the ring hangs from above so its BOTTOM crest sweeps a
   shallow valley across the top of the stage — highest at the screen edges,
   lowest at centre — with the numerals hung below the line and the copy centred
   beneath. The wheel is mirrored on X so the numerals still run 01→5 left-to-right
   and scroll advances the right way; the glyphs un-mirror themselves. Base -90°,
   the mirror and the centring all live in the independent `rotate` /
   `translate` properties because the rAF loop owns `transform`. ── */
@media(max-width:720px){
/* svh, not dvh: dvh re-resolves as mobile browser chrome collapses, which would
   resize the sticky stage every frame of a scroll-up and jitter the wheel. svh is
   the stable small-viewport height, and the section is 3× the same unit. */
.orbit.caps-orbit{height:300vh;height:300svh}
.orbit .oring{left:50%;top:calc(112px - 200vmin);width:200vmin;height:200vmin;translate:-50% 0;transform:none;opacity:1}
.orbit .oring::after{left:50%;right:auto;top:auto;bottom:-4.5px;transform:translateX(-50%)}
.orbit .owheel{left:50%;top:calc(112px - 200vmin);width:200vmin;height:200vmin;margin-top:0;translate:-50% 0;rotate:-90deg;scale:-1 1;opacity:1}
.orbit .oyear{font-size:21px;letter-spacing:.1em;--ooff:18px}
/* the wheel is mirrored (see above) so the numeral is un-mirrored here, and the
   glyph stays upright: --ycount is the wheel+item angle written by the rAF loop,
   +90deg undoes the wheel's base rotation */
.orbit .oyear i{rotate:calc(var(--ycount,0deg) - 90deg);scale:-1 1;transform-origin:50% 50%}
.orbit .ocopy,.orbit.v2 .ocopy{left:0;right:0;top:25svh;bottom:auto;width:auto;max-width:none;height:52svh;transform:none;padding:0;perspective:1000px;perspective-origin:50% 50%;text-align:center}
/* the gutter has to live on the item: .oitem is inset:0 against .ocopy, so any
   padding on .ocopy is resolved past and bypassed */
.orbit .oitem{align-items:center;padding-inline:24px}
.orbit .oitem .eyebrow{display:none}
.orbit.caps-orbit .oitem h3,.orbit .oitem h3{font-size:clamp(30px,8.6vw,40px);max-width:15ch;margin-inline:auto}
.orbit .oitem p{max-width:34ch;margin-inline:auto;font-size:15px}
.orbit .ochips{justify-content:center;max-width:none;margin-top:26px}
}

/* ── services flight plan: the drawn line comes back vertically on phones ── */
@media(max-width:560px){
.flow{grid-template-columns:1fr;gap:0;position:relative;padding-left:34px;margin-bottom:64px}
.flow::before{content:'';position:absolute;left:4px;top:14px;bottom:14px;width:1px;background:linear-gradient(180deg,transparent,var(--a3) 7%,var(--a3) 93%,transparent);opacity:.45;transform-origin:50% 0;transform:scaleY(0);transition:transform 1.7s cubic-bezier(.33,1,.68,1) .15s}
.flow.in::before{transform:scaleY(1)}
.fstep{position:relative;padding-block:20px}
.fstep::before{position:absolute;left:-34px;top:28px;margin:0;display:block}
}
@media(prefers-reduced-motion:reduce){.flow::before{transition:none;transform:scaleY(1)}}

/* ── phone scale: the vertical rhythm was authored for desktop-narrow ── */
@media(max-width:560px){
.wrap{padding-inline:22px}
.shead{padding-block:104px 44px}
.shead.tight{padding-block:78px 36px}
.shead h2{font-size:clamp(30px,8.6vw,40px);margin-top:18px}
.shead .lede{margin-top:18px;font-size:15.5px}
.phero{padding-block:118px 62px}
.phero h1{margin-top:18px}
.phero .lede{margin-top:20px;font-size:15.5px}
#hero .inner{padding-block:104px 92px}
#hero .sub{margin-top:22px;font-size:15.5px}
#hero .ctas{margin-top:28px;gap:10px}
#hero .ctas .btn{flex:1 1 140px;justify-content:center}
#hero .hint{display:none}
.clients{padding-block:20px}
.mq{gap:44px}
.cap{padding:44px 0;gap:22px}
.quote{padding:118px 0}
#cta{padding:128px 0}
.hww{padding-bottom:96px}
.hwsteps{gap:44px}
.hwv svg{max-width:240px}
.secta{padding-block:36px 0}
#cta h2{font-size:clamp(34px,10.2vw,48px)}
#cta p{margin-top:20px}
#cta .btn{margin-top:30px}
.wcard{border-radius:16px;margin-bottom:28px}
.wcard .meta{padding:30px 24px}
.gpiece{margin-bottom:64px}
.gframe{border-radius:16px}
.gframe .lab,.gframe .view{left:18px;right:18px;bottom:16px}
.gframe .view{left:auto}
.prac .row{padding-block:56px}
.plans{gap:16px}
.plan{border-radius:18px;padding:26px 22px 24px}
.plan .phead{padding-right:80px}
.member{border-radius:14px;padding:28px 24px 30px}
.layers{padding-bottom:76px}
.ltab{padding:20px 20px}
.intro{padding-block:96px 40px}
.chap{padding-block:74px 0}
.cimgs{margin-top:44px;gap:18px}
.cimg{border-radius:14px;padding:18px}
.cmeta{gap:26px 40px;margin-top:40px;padding-top:28px}
.nextcase{margin-top:96px;padding:74px 0}
.cform label{margin-top:26px}
.cform input,.cform textarea{font-size:16px}
footer{padding:84px 0 46px}
footer .cols{grid-template-columns:1fr 1fr;gap:34px 20px}
footer .fmark{font-size:clamp(44px,13.6vw,64px)}
footer .legal{margin-top:46px}
.nova{display:none}
}

/* ── touch: hover-only affordances re-keyed to scroll-into-view (.inview is set
   by initTouchStates in novas.js, only under hover:none) at reduced intensity ── */
@media(hover:none){
.plan.inview::before{opacity:.55}
.plan.inview{border-color:rgba(201,184,255,.2)}
.plan.hot.inview{border-color:color-mix(in oklch,var(--a4) 46%,transparent)}
.gpiece.inview .gframe::before{opacity:.45}
.gpiece.inview .gframe .view{opacity:1;transform:none}
.gpiece.inview h3{color:var(--a3)}
.gpiece.inview .gtags span{border-color:rgba(201,184,255,.2)}
.prac .row.inview{background:radial-gradient(700px circle at 50% 46%,rgba(124,92,255,.045),transparent 68%)}
.prac .row.inview .pill{opacity:1}
.gpiece.inview .gpar img{filter:grayscale(0) contrast(1) brightness(1)}
.gpiece.inview .gpar .gfig{filter:grayscale(0) contrast(1) brightness(1)}
.cx.inview .cxfig img{filter:grayscale(0) contrast(1) brightness(1)}
.member.inview .av img{filter:grayscale(0) contrast(1)}
/* hit targets */
.jump a{padding:13px 18px}
.orbit .ochips span{padding:12px 16px}
.wcard .tags span,.gpiece .gtags span{padding:9px 14px}
.faq summary{padding:30px 0;min-height:44px;gap:24px}
/* footer links are 21px of line box; 7px padding reached only 35px. min-height
   is the reliable way to clear 44 without changing the visual rhythm much. */
footer .col a{padding-block:11px;margin-bottom:0;min-height:44px;display:flex;align-items:center}
.cmeta{gap:26px 40px}
}

/* ══════════ CASE PAGE — spine & plates ══════════
   The locked case-study layout. Shared by every case page, so the structure is
   defined once here rather than per page. Load-bearing notes are kept inline. */
/* ── C · SPINE & PLATES ───────────────────────────────────────────────
   The synthesis, and where each half earns its place:

   From A — the asymmetric spine. Text never centres, so there is one
   left edge the eye tracks the whole way down. More distinctive than a
   centred measure, which every studio case study already uses.

   From B — full-bleed plates. Images are the page's structure, not
   decoration hung inside a column. Plates are SIBLINGS of the sections
   rather than children, so they reach the viewport edge with no negative
   margins and therefore no risk of page-wide horizontal scroll.

   New here — the rail is navigation, not a label. It lists every chapter
   and lights the current one, which is the only thing that makes a long
   scrolling case study feel navigable rather than endless. */

/* ── rail: one FIXED chapter index for the whole case body. Sticky-per-block
   was the obvious build and it was wrong — the rail lives inside a spine block,
   so it vanished the moment a full-bleed plate interrupted the grid, which is
   exactly when a reader most wants to know where they are. Fixed, aligned to
   the wrap's own left edge with the same max-width math, so it tracks the text
   column at every viewport instead of floating loose. ── */
/* the spine is a plain block: the chapter grid inside it does the composing.
   It was a 2-col grid when the rail lived in-flow; leaving that in place after
   the rail went fixed squeezed every chapter into a .26fr column.
   padding-left overrides .wrap's padding-inline on the left, so the 32px gutter
   has to be added back explicitly or the column slides under the rail. */
.cspine{display:block;padding-left:var(--railpad)}
/* A chapter can OPT OUT of the rail's gutter. --railpad bakes in the wrap's own
   32px gutter (because .cspine's padding-left replaces .wrap's left padding
   entirely), so cancelling the whole value would strip the page gutter too and
   land glyphs on the viewport edge. Reclaim the rail strip only, keep the 32px,
   and the wide section lines up with the hero and its own right edge.
   The rail fades while such a section holds the screen (see [data-norail]), so
   nothing collides and nothing is cramped to protect a table of contents. */
.cch.wide{margin-left:calc(-1 * (var(--railpad) - 32px))}
@media(max-width:900px){.cch.wide{margin-left:0}}
/* padding-left REPLACES .wrap's left padding rather than adding to it, so the
   mobile value has to restate the wrap gutter — zeroing it put every chapter
   flush against the left edge while the right kept its 22px. Mirrors .wrap:
   32px down to 560, 22px below. */
@media(max-width:900px){.cspine{padding-left:32px}}
@media(max-width:560px){.cspine{padding-left:22px}}
/* ONE source of truth for the rail's footprint. The rail's width and the
   spine's left padding were two independent expressions (clamp(120,15vw,190)
   and clamp(0,15vw,232)) that drifted into each other by exactly the wrap's
   gutter, so rail labels painted over the chapter text. Both now derive from
   --rail, and the spine adds back the 32px gutter that its own padding-left
   overrides away from .wrap. --railpad is the whole reserved strip, so a
   section can cancel it exactly and reclaim the full measure. */
:root{--rail:clamp(120px,15vw,190px);--railpad:calc(var(--rail) + 32px + clamp(18px,2.5vw,44px))}
.crail{position:fixed;top:clamp(70px,34vh,220px);left:max(32px,calc((100vw - var(--maxw))/2 + 32px));width:var(--rail);z-index:40;font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.18em;text-transform:uppercase;opacity:0;transition:opacity .5s cubic-bezier(.4,0,.2,1);pointer-events:none}
.crail.live{opacity:1;pointer-events:auto}
.crail ol{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.crail a{display:grid;grid-template-columns:22px 1fr;gap:9px;color:var(--mute);transition:color .4s cubic-bezier(.4,0,.2,1)}
.crail a .n{color:var(--line)}
.crail a:hover{color:var(--dim)}
.crail a.on{color:var(--fg)}
.crail a.on .n{color:var(--a4)}
@media(max-width:900px){.crail{display:none}}

/* ── hero: A's hard-left display type, B's ruled ledger ── */
.chero{padding-block:clamp(112px,16vw,196px) clamp(38px,5vw,64px)}
.chero .ek{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--a4)}
.chero h1{font-family:Archivo,sans-serif;font-weight:200;font-stretch:88%;font-size:clamp(54px,12.5vw,176px);line-height:.86;letter-spacing:-.05em;margin:clamp(14px,2vw,24px) 0 0}
.chero .sub{margin:clamp(20px,3vw,32px) 0 0;max-width:42ch;font-size:16.5px;line-height:1.6;color:var(--dim);text-wrap:pretty}
.cledger{margin-top:clamp(38px,5.5vw,68px);border-top:1px solid var(--line);border-bottom:1px solid var(--line);display:grid;grid-template-columns:repeat(4,1fr)}
.cledger div{padding:19px clamp(12px,2vw,24px);border-left:1px solid var(--line)}
.cledger div:first-child{border-left:0;padding-left:0}
.cledger .k{font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)}
.cledger .v{margin-top:7px;font-size:13.5px;line-height:1.4}
@media(max-width:760px){.cledger{grid-template-columns:1fr 1fr}.cledger div:nth-child(3){border-left:0;padding-left:0}.cledger div:nth-child(n+3){border-top:1px solid var(--line)}}
.cscopes{margin-top:24px;display:flex;flex-wrap:wrap;gap:8px}
.cscopes span{font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);border-radius:100px;padding:7px 13px}

/* ── chapter grid: a main measure and a WORKING outer margin.
   The first build gave each chapter one centred column and left the right third
   empty, which reads as a slide, not a spread. Magazines don't leave that space
   blank — they put marginalia in it. So every chapter is main + margin: text and
   the argument on the left at a real reading measure, texture art and small notes
   in the right column, and anything that earns the full width spans both. ── */
.cch{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.4fr);column-gap:clamp(20px,3.4vw,58px);align-items:start;padding-block:clamp(70px,10vw,132px) 0}
.cch>.cmain{grid-column:1;min-width:0}
.cch>.cmargin{grid-column:2;min-width:0;padding-top:clamp(6px,1.4vw,18px)}
.cch>.span{grid-column:1/-1;min-width:0}
@media(max-width:900px){.cch{grid-template-columns:1fr}.cch>.cmain,.cch>.cmargin,.cch>.span{grid-column:1}.cch>.cmargin{max-width:420px;margin-top:38px}}
.cch .ck2{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--a4);display:none}
.cbig{font-family:Archivo,sans-serif;font-weight:250;font-stretch:93%;font-size:clamp(29px,4.4vw,62px);line-height:1.06;letter-spacing:-.032em;margin:0;text-wrap:balance}
.cbig em{font-style:italic;font-weight:400;color:var(--a3)}
.ctxt{margin:26px 0 0;font-size:15.5px;line-height:1.74;color:var(--dim);text-wrap:pretty}
.ctxt b{color:var(--fg);font-weight:400}
.ctxt+.ctxt{margin-top:16px}
@media(max-width:900px){.cch .ck2{display:block;margin-bottom:16px}}

/* proof, on the accent rule */
.cprv{margin-top:40px;padding-left:22px;border-left:1px solid var(--a1)}
.cprv .pk{font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--a4)}
.cprv p{margin:12px 0 0;font-size:16px;line-height:1.62;color:var(--fg);text-wrap:pretty}
.cprv p b{font-family:Archivo,sans-serif;font-weight:500;font-stretch:96%;font-size:1.06em;color:var(--a3)}

/* ── plates: reserved for the TWO moments that earn the full width — the site
   itself, and the one screen that shows the system working. Everything else sits
   on the grid inside the text column, so the page has a baseline to return to
   and the full-bleed moments still land. ── */
.cplate{margin-top:clamp(46px,7vw,100px);border-block:1px solid var(--line)}
.cplate .cimg{border:0;border-radius:0;aspect-ratio:1600/918}
.cplate.lead .cimg{aspect-ratio:1920/890}
/* in-column art: aligned to the text, so it reads as evidence in the argument
   rather than an interruption of it */
.cfull{margin-top:clamp(38px,5.5vw,78px)}
.cfull .cimg{aspect-ratio:1600/918}
.cgrid{display:grid;gap:clamp(15px,2.2vw,30px);margin-top:clamp(38px,5.5vw,78px)}
.cgrid.pages{grid-template-columns:1fr 1fr}
.cgrid.pages .cimg{aspect-ratio:1100/1474}
@media(max-width:640px){.cgrid.pages{grid-template-columns:1fr}}
/* margin art stacks at its own portrait ratio — one per row, not a mini-grid */
.cgrid.tex{grid-template-columns:1fr;gap:clamp(16px,2.4vw,32px)}
.cgrid.tex .cimg{aspect-ratio:3/4}
.cgrid.tex .cshot:nth-child(2){margin-top:0}
.cplate .cap{padding:13px clamp(20px,4vw,44px);font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}
.cplate .cap b{color:var(--dim);font-weight:400}
/* margin facts: a small ruled list, the kind of thing a spread puts in its
   outer column instead of leaving it white */
.cfacts{margin:0;display:grid;gap:0}
.cfacts>div{padding-block:12px;border-top:1px solid var(--line)}
.cfacts>div:last-child{border-bottom:1px solid var(--line)}
.cfacts dt{font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)}
.cfacts dd{margin:6px 0 0;font-size:13.5px;line-height:1.45;color:var(--fg)}
/* ── three surfaces: the page's central claim is that brand, deck and site were
   one engagement, and until now only the site was in evidence. One row proves it
   — same language, three places it lands. Deliberately NOT three new chapters:
   the deck matters here as proof the system travels, not as a deck. ── */
.csurf{margin-top:clamp(38px,5.5vw,78px)}
.csurf .sh{font-family:Archivo,sans-serif;font-weight:300;font-stretch:96%;font-size:clamp(20px,2.4vw,30px);letter-spacing:-.022em;margin:0 0 clamp(20px,2.6vw,32px);line-height:1.14}
.csurf .sh em{font-style:italic;font-weight:400;color:var(--a3)}
.csurf .row3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(14px,2vw,26px)}
/* These three are DOCUMENTS, not texture: a slide and a system sheet cropped by
   object-fit:cover lose the very thing they are evidence of — the 16:9 slide was
   losing a third of its width and the headline with it. They sit CONTAINED on a
   paper mat instead, so each artifact is whole and its own proportion reads. */
.csurf .row3 .cimg{aspect-ratio:4/3;background:#f4f5f7;display:flex;align-items:center;justify-content:center}
.csurf .row3 .cimg img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;object-position:50% 50%}
.csurf .n{font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:var(--a4);display:block;margin-bottom:9px}
@media(max-width:760px){.csurf .row3{grid-template-columns:1fr}}
/* awaiting export: a designed hold that names what belongs there, rather than an
   empty box or a stand-in image that would misrepresent the work */
.cimg.hold{background:var(--bg2)}
.cimg.hold::before{content:'';position:absolute;inset:0;z-index:1;background-image:repeating-linear-gradient(135deg,rgba(201,184,255,.055) 0 2px,transparent 2px 11px)}
.cimg.hold .hn{position:absolute;inset:auto 18px 16px;z-index:2;font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);line-height:1.5}
.cimg.hold .hn b{display:block;color:var(--dim);font-weight:400;margin-bottom:4px}
/* a caption under in-column art, matching the plate captions' voice */
.cshot .icap{margin-top:11px;font-family:'JetBrains Mono',monospace;font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);display:block}
.cshot .icap b{color:var(--dim);font-weight:400}
.cduo{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line)}
.cduo .cimg{aspect-ratio:1100/1474}
@media(max-width:700px){.cduo{grid-template-columns:1fr}}

/* spec-sheet rows from A */
/* the site-wide .cbuilt is a 2-up card grid; this page wants a single ruled
   ledger, so the columns are reset explicitly rather than inherited */
.cbuilt{display:block;margin-top:clamp(28px,4vw,48px);border-top:1px solid var(--line)}
/* horizontal variant: cells stack figure over label over copy and run three
   across, so the section reads as a system laid out rather than a list read
   down. The ruled single-column ledger is kept for narrow viewports.
   The copy carries NO measure cap here — the column is the measure. Capping it
   at 34ch inside a 416px cell left 127px of dead space at the right of every
   cell while the rule above ran the full width, which is what made the whole
   section look left-leaning. Three columns earlier keeps the line length honest
   (~41ch) instead, so text and rule share one right edge. */
.cbuilt.across{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0 clamp(20px,3vw,44px);border-top:0}
.cbuilt.across .row{display:block;border-bottom:0;border-top:1px solid var(--line);padding-block:24px 30px}
.cbuilt.across .rfig{flex-direction:column;align-items:flex-start;gap:16px}
.cbuilt.across .rfig figure{flex:0 0 auto;width:clamp(52px,5vw,68px)}
.cbuilt.across .row p{margin-top:12px;max-width:none}
@media(max-width:860px){.cbuilt.across{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.cbuilt.across{grid-template-columns:1fr}}
.cbuilt .row{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:clamp(14px,3vw,44px);padding-block:21px;border-bottom:1px solid var(--line);align-items:start}
/* the capability marks ride WITH their label rather than in a column of their
   own — a separate figure column would have set a third rhythm across a row
   that already has two */
.cbuilt .rfig{display:flex;align-items:center;gap:14px}
.cbuilt .rfig figure{margin:0;flex:0 0 clamp(44px,4.4vw,60px)}
.cbuilt .rfig svg{width:100%;height:auto;aspect-ratio:160/110;display:block;overflow:visible}
.cbuilt .rfig h5{margin:0}
.cbuilt h5{font-family:Archivo,sans-serif;font-weight:400;font-stretch:98%;font-size:16px;margin:0;letter-spacing:-.012em}
.cbuilt p{margin:0;font-size:13.5px;line-height:1.62;color:var(--dim);text-wrap:pretty}
@media(max-width:700px){.cbuilt .row{grid-template-columns:1fr;gap:6px}}
.clivec{padding-block:clamp(56px,8vw,100px) clamp(88px,12vw,150px)}

@media(max-width:640px){
/* the margin photography stacked full-width at 461px each, which is most of a
   phone screen per texture shot. Two up halves the scroll cost and the images
   are atmosphere, not detail — they lose nothing at half width. */
.cmargin .cgrid.tex{grid-template-columns:1fr 1fr;gap:12px;max-width:none}
.cmargin{max-width:none}
}

/* thumbnail orientation tweak — a review control, not site chrome */
.thumbtw{position:fixed;right:clamp(14px,2vw,26px);bottom:clamp(14px,2vw,26px);z-index:80;display:flex;align-items:center;gap:2px;padding:5px;border:1px solid var(--line);border-radius:999px;background:rgba(9,10,17,.86);backdrop-filter:blur(14px)}
.thumbtw .lb{font-family:'JetBrains Mono',monospace;font-size:8.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);padding:0 8px 0 6px}
.thumbtw button{appearance:none;border:0;cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);background:transparent;border-radius:999px;padding:7px 11px;display:flex;align-items:center;gap:7px;transition:color .3s,background .3s}
.thumbtw button i{display:block;border:1px solid currentColor;border-radius:2px;opacity:.7}
.thumbtw button i.ls{width:13px;height:8px}
.thumbtw button i.pt{width:8px;height:11px}
.thumbtw button:hover{color:var(--fg)}
.thumbtw button.on{color:var(--fg);background:rgba(255,255,255,.07)}
@media(max-width:560px){.thumbtw{right:12px;bottom:12px;left:12px;justify-content:center}.thumbtw .lb{display:none}.thumbtw button{flex:1 1 0;min-height:44px;justify-content:center}}
