/* ---------- ground and surface tokens ----------
   The ground was #000. It is now a near-black with a slight cool cast, so the
   whole site reads a couple of notches lighter without touching layout, type,
   or the green accent identity. Every ground-coloured fill on this sheet comes
   from --ground-rgb, so the lift is one edit, not a sweep of literals.
   Four roles, deliberately distinct:
     --bg / --ground-rgb  the page ground, and any scrim that must read AS it
     --glass              raised surfaces: cards, the contact form, the end card
     --well               recessed fills: inputs, tracks, the game board (below)
     --panel              the one opaque floating surface, the mobile nav panel
   (--glass-2 is declared but nothing on the sheet uses it today; it is left in
   step with --glass rather than deleted in a tonal pass.)
   --ink-faint was lifted with the ground: at #737c86 it measured 4.44:1 on the
   new ground, under the 4.5:1 floor for the 11-13px labels it carries.
   --line-field is a form-control-only border: --line is a 1.3:1 hairline, which
   is fine for decorative rules but not for the boundary that identifies an
   input. Alpha is .55, not .5: a translucent border composites over the
   element's OWN background (the --well fill sits under it), and .5 measured
   2.90:1 where the green .tint peaks over a card. .55 holds 3.29:1 there and
   3.48:1 on the untinted card. See the measured table in the job report. */
:root{
  --ground-rgb:14,18,22;
  --bg:rgb(var(--ground-rgb));
  --green:#57e600; --green-bright:#7aea02; --green-deep:#176b00;
  --ink:#c7ced6; --ink-dim:#909aa3; --ink-faint:#828b95;
  --line:rgba(180,190,200,.13); --line-soft:rgba(180,190,200,.07);
  --line-field:rgba(180,190,200,.55);
  --glass:rgba(25,29,33,.55); --glass-2:rgba(31,35,39,.6);
  --well:rgba(0,0,0,.45); --panel:rgba(22,26,30,.94);
  --chrome:linear-gradient(180deg,#ffffff 0%,#e4eaf0 37%,#b4bec7 50%,#f7fafc 54%,#ccd5dd 77%,#eef3f7 100%);
  --chrome-soft:linear-gradient(180deg,#eef2f6 0%,#c3ccd5 55%,#dde4ea 100%);
  --maxw:1180px;
  --disp:"Clash Display","Bricolage Grotesque",system-ui,sans-serif;
  --body:"Satoshi","Hanken Grotesk",system-ui,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:auto;-webkit-text-size-adjust:100%;overflow-x:clip}
body{
  background:var(--bg); color:var(--ink); font-family:var(--body);
  font-size:17px; line-height:1.65; letter-spacing:.01em;
  overflow-x:clip; -webkit-font-smoothing:antialiased;
}
body.lenis{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto !important}
::selection{background:rgba(87,230,0,.25); color:#eafff0}
a{color:inherit;text-decoration:none}
a:focus-visible,button:focus-visible,select:focus-visible,input:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--green);outline-offset:3px;border-radius:5px}
img{max-width:100%;display:block}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
[hidden]{display:none !important}
/* skip link: first thing in the tab order on every page, parked off-screen
   until it takes focus. The nav is fixed at 74px, so it lands below that. */
.skip{position:fixed;top:14px;left:14px;z-index:100;display:inline-flex;align-items:center;
  font-family:var(--body);font-weight:600;font-size:14px;letter-spacing:.01em;padding:11px 20px;border-radius:100px;
  background:var(--green);color:#001405;transform:translateY(-220%);transition:transform .18s cubic-bezier(.22,1,.36,1)}
.skip:focus{transform:none}
main:focus{outline:none}

/* ---------- fixed ambient layers ---------- */
.ambient{position:fixed;inset:0;z-index:0;opacity:0;pointer-events:none;mix-blend-mode:screen;filter:saturate(1.08) blur(1.6px);will-change:opacity,transform}
.amv{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .9s linear}
.amv.show{opacity:1}
.scrollbar{position:fixed;top:0;left:0;height:2px;width:0;z-index:51;pointer-events:none;background:linear-gradient(90deg,var(--green-deep),var(--green) 70%,var(--green-bright));box-shadow:0 0 12px rgba(87,230,0,.7)}
.tint{position:fixed;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(80vw 60vh at 50% -8%, rgba(87,230,0,.10), transparent 60%),
    radial-gradient(60vw 50vh at 88% 16%, rgba(87,230,0,.05), transparent 60%),
    radial-gradient(70vw 60vh at 6% 90%, rgba(87,230,0,.045), transparent 60%);
}
.grain{position:fixed;inset:-50%;z-index:60;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grain 6s steps(6) infinite;}
@keyframes grain{0%{transform:translate(0,0)}20%{transform:translate(-4%,3%)}40%{transform:translate(3%,-4%)}60%{transform:translate(-3%,2%)}80%{transform:translate(4%,3%)}100%{transform:translate(0,0)}}
/* eased back with the ground lift: at .55 the corners stayed as dark as the old
   #000 page and the lift only read in the middle of the screen */
.vignette{position:fixed;inset:0;z-index:55;pointer-events:none;
  background:radial-gradient(ellipse at center,transparent 52%,rgba(0,0,0,.38) 100%);}

/* ---------- layout ---------- */
.wrap{position:relative;z-index:2}
.shell{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 28px}
section{position:relative}
.eyebrow{font-family:var(--mono);font-size:12.5px;letter-spacing:.34em;text-transform:uppercase;color:var(--ink-dim)}
.eyebrow .s{color:var(--green)}
.num{font-family:var(--mono);font-size:13px;letter-spacing:.28em;color:var(--green);opacity:.85;white-space:nowrap}
.num::after{content:"";display:inline-block;width:0;height:1px;vertical-align:middle;margin-left:14px;background:linear-gradient(90deg,var(--green),transparent);transition:width .6s .1s cubic-bezier(.22,1,.36,1)}
.r.in .num::after{width:72px}
.chrome{background:var(--chrome);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;filter:drop-shadow(0 2px 12px rgba(0,0,0,.55))}
h1,h2,h3{font-family:var(--disp);font-weight:600;line-height:1.02;letter-spacing:-.013em;text-wrap:balance}
.lead{color:var(--ink);font-size:clamp(1.05rem,1.6vw,1.22rem);line-height:1.6;max-width:60ch}

/* ---------- nav ---------- */
.nav{position:fixed;top:0;left:0;right:0;z-index:40;transition:background .25s,border-color .25s,backdrop-filter .25s;border-bottom:1px solid transparent}
.nav.stuck{background:rgba(var(--ground-rgb),.62);backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);border-bottom:1px solid var(--line-soft)}
.nav-in{display:flex;align-items:center;justify-content:space-between;height:74px;width:100%;max-width:var(--maxw);margin:0 auto;padding:0 28px}
.nav-logo{height:26px;width:auto;filter:drop-shadow(0 0 10px rgba(87,230,0,.18))}
.nav-links{display:flex;align-items:center;gap:30px}
.nav-links a.lnk{position:relative;font-size:14px;color:var(--ink-dim);letter-spacing:.02em;transition:color .18s}
.nav-links a.lnk::after{content:"";position:absolute;left:0;right:100%;bottom:-5px;height:1px;background:var(--green);box-shadow:0 0 6px rgba(87,230,0,.6);transition:right .25s cubic-bezier(.22,1,.36,1)}
.nav-links a.lnk:hover{color:var(--ink)}
.nav-links a.lnk:hover::after{right:0}
/* .btn rides on <a> and <button> alike: the appearance/background reset lands
   before .btn-primary so the primary green still wins on real buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;font-family:var(--body);font-weight:600;font-size:14.5px;letter-spacing:.01em;padding:12px 22px;border-radius:100px;cursor:pointer;border:1px solid transparent;-webkit-appearance:none;appearance:none;background:transparent;text-align:center;transition:transform .16s cubic-bezier(.22,1,.36,1),box-shadow .22s,background .22s,border-color .22s,filter .12s ease;will-change:transform}
.btn-primary{background:var(--green);color:#001405;box-shadow:0 0 0 rgba(87,230,0,0)}
.btn-primary:hover{box-shadow:0 8px 34px rgba(87,230,0,.32)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.btn-ghost:hover{border-color:rgba(87,230,0,.35);background:rgba(87,230,0,.05);color:#eafff0}
.btn:active{filter:brightness(.92)}
.nav-links a.btn-primary{color:#001405}
.menu-btn{display:none}

/* ---------- hero ---------- */
.hero{min-height:100svh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:96px 20px 44px;position:relative}
@keyframes heroRise{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:translateY(0)}}
.hero .logo-stage{animation:heroRise .85s .08s both cubic-bezier(.22,1,.36,1)}
.logo-stage{position:relative;width:min(940px,92vw);margin:2px 0 4px}
.logo-aura{position:absolute;inset:-34% -12%;z-index:-1;background:radial-gradient(52% 64% at 50% 50%,rgba(87,230,0,.22),rgba(87,230,0,.05) 46%,transparent 72%);filter:blur(18px);animation:breathe 5.5s ease-in-out infinite}
@keyframes breathe{0%,100%{opacity:.65;transform:scale(.97)}50%{opacity:1;transform:scale(1.04)}}
.logo-art{position:relative;width:100%;animation:floaty 7.5s ease-in-out infinite}
@keyframes floaty{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
.logo-base{width:100%;height:auto;display:block;animation:glowpulse 4.6s ease-in-out infinite}
@keyframes glowpulse{0%,100%{filter:drop-shadow(0 0 16px rgba(87,230,0,.16))}50%{filter:drop-shadow(0 0 32px rgba(87,230,0,.33))}}
/* chrome light-sweep clipped to the logo shape -> seamless specular, no frame */
.logo-sheen{position:absolute;inset:0;pointer-events:none;z-index:2;
  -webkit-mask:url("logo-lockup.webp") center/100% 100% no-repeat;
  mask:url("logo-lockup.webp") center/100% 100% no-repeat;
  background:linear-gradient(112deg,transparent 42%,rgba(255,255,255,.7) 49%,rgba(255,255,255,.95) 50.5%,rgba(255,255,255,.7) 52%,transparent 59%);
  background-size:280% 100%;background-position:135% 0;
  mix-blend-mode:overlay;animation:sheen 6.5s cubic-bezier(.5,0,.3,1) infinite}
@keyframes sheen{0%{background-position:140% 0}58%,100%{background-position:-50% 0}}
.hero-slogan{margin-top:clamp(24px,3.4vh,42px);font-size:clamp(2.1rem,5.6vw,3.9rem);font-weight:600;line-height:1.05;letter-spacing:-.008em}
.hero-slogan .g{color:var(--green);-webkit-text-fill-color:var(--green)}
.hero-sub{margin:22px auto 0;max-width:54ch;color:var(--ink-dim);font-size:clamp(1rem,1.5vw,1.12rem)}
.hero-cta{margin-top:36px;display:flex;gap:14px;flex-wrap:wrap;justify-content:center}
.hero-tag{margin-top:30px;font-family:var(--mono);font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-faint)}
.hero-tag b{color:var(--green);font-weight:500}
@keyframes fade{to{opacity:1}}

/* ---------- statement (scroll-revealed) ---------- */
.statement{padding:clamp(48px,8vh,96px) 0 clamp(96px,14vh,160px);text-align:center;border-bottom:1px solid var(--line-soft)}
.statement-in{display:flex;flex-direction:column;align-items:center}
.statement-h{font-family:var(--disp);font-weight:600;font-size:clamp(2.1rem,5.4vw,4rem);line-height:1.05;letter-spacing:-.012em;margin:0;max-width:20ch;filter:drop-shadow(0 2px 12px rgba(0,0,0,.5))}
.statement-tag{font-family:var(--disp);font-weight:600;font-size:clamp(1.5rem,3.6vw,2.5rem);line-height:1.08;letter-spacing:-.008em;margin:clamp(16px,2.4vh,26px) 0 0}
.statement-sub{margin:24px auto 0;max-width:52ch;color:var(--ink-dim);font-size:clamp(1.02rem,1.5vw,1.18rem);line-height:1.62}
.statement-cta{margin-top:40px;display:flex;gap:14px;flex-wrap:wrap;justify-content:center}
/* kinetic word-rise reveal */
.words span{display:inline-block;overflow:hidden;vertical-align:bottom;line-height:1.05;padding-bottom:.14em;margin-bottom:-.14em}
.words span i{display:inline-block;font-style:normal;transform:translateY(130%);transition:transform .6s cubic-bezier(.19,1,.22,1);background:var(--chrome);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
.words span.g i{background:none;-webkit-text-fill-color:var(--green);color:var(--green)}
.words.in span i{transform:translateY(0)}
.words span:nth-child(1) i{transition-delay:.04s}
.words span:nth-child(2) i{transition-delay:.09s}
.words span:nth-child(3) i{transition-delay:.14s}
.words span:nth-child(4) i{transition-delay:.2s}
.words span:nth-child(5) i{transition-delay:.25s}
.words span:nth-child(6) i{transition-delay:.3s}
.words span:nth-child(7) i{transition-delay:.35s}
.words span:nth-child(8) i{transition-delay:.4s}

/* ---------- generic section head ---------- */
.sec{padding:128px 0}
.sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;margin-bottom:54px;flex-wrap:wrap}
.sec-head .t h2{font-size:clamp(1.9rem,4vw,3.1rem);margin-top:14px}
.sec-head .d{max-width:38ch;color:var(--ink-dim);font-size:15.5px;padding-bottom:6px}

/* ---------- cards ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.card{position:relative;background:var(--glass);border:1px solid var(--line);border-radius:20px;padding:34px 30px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);overflow:hidden;transition:transform .26s cubic-bezier(.22,1,.36,1),border-color .26s,box-shadow .3s}
.card::before{content:"";position:absolute;inset:0;border-radius:20px;padding:1px;background:linear-gradient(140deg,rgba(87,230,0,.35),transparent 40%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:0;transition:opacity .25s}
.card:hover{transform:translateY(-6px);border-color:rgba(87,230,0,.22);box-shadow:0 24px 60px rgba(0,0,0,.5)}
.card:hover::before{opacity:1}
.card::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .28s;background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),rgba(87,230,0,.13),transparent 60%)}
.card:hover::after{opacity:1}
.card .ic{width:46px;height:46px;border-radius:12px;display:grid;place-items:center;border:1px solid var(--line);margin-bottom:22px;color:var(--green);background:rgba(87,230,0,.05)}
.card .ic svg{width:23px;height:23px}
.card h3{font-size:1.4rem;margin-bottom:12px}
.card p{color:var(--ink-dim);font-size:15px;line-height:1.62}
.card .tagn{position:absolute;top:24px;right:26px;font-family:var(--mono);font-size:12px;color:var(--ink-faint)}

/* ---------- how it works (numbered steps) ---------- */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:0;border:1px solid var(--line);border-radius:20px;overflow:hidden}
.step{padding:34px 26px 38px;border-right:1px solid var(--line);position:relative;transition:background .25s}
.step:last-child{border-right:none}
.step:hover{background:rgba(87,230,0,.035)}
.step .k{font-family:var(--mono);font-size:12px;color:var(--green);letter-spacing:.2em}
.step h3{font-size:1.25rem;margin:18px 0 12px}
.step p{color:var(--ink-dim);font-size:14.5px;line-height:1.6}

/* ---------- pricing ----------
   There is no price table. Public pricing was retired: every project is
   custom-quoted, so the pricing section is built from the same ruled rows
   as Care (.care-list) and there is nothing here to compare. The old
   .tiers/.tier/.care-note rules were deleted with the last markup that
   used them; nothing on the site referenced them. */
.custom-row{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;margin-top:18px}
.custom{background:var(--glass);border:1px solid var(--line);border-radius:18px;padding:28px 30px;display:flex;align-items:center;justify-content:space-between;gap:20px;transition:border-color .4s,transform .4s}
.custom:hover{border-color:rgba(87,230,0,.22);transform:translateY(-4px)}
/* the row title is an h3, not an h4: these rows are peers of the .card items
   above them in the same section, so the level follows the outline and the
   size is set here rather than borrowed from a lower heading level */
.custom h3{font-family:var(--disp);font-size:1.2rem;line-height:1.2;margin-bottom:6px}
.custom p{color:var(--ink-faint);font-size:13.5px}
.custom .q{font-family:var(--mono);color:var(--green);font-size:13px;white-space:nowrap}

/* ---------- care ----------
   Deliberately not a card grid: Care is a promise read as a list of plain
   commitments, hairline-ruled, so it reads as a contract of habit not a
   package table. No prices, no tiers, nothing to compare. */
.care-list{border-top:1px solid var(--line-soft)}
.care-row{display:grid;grid-template-columns:minmax(140px,210px) 1fr;gap:10px 44px;padding:24px 4px;border-bottom:1px solid var(--line-soft);align-items:baseline;transition:background .25s}
.care-row:hover{background:rgba(87,230,0,.02)}
.care-row .ck{font-family:var(--mono);font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--green)}
.care-row p{color:var(--ink-dim);font-size:15.5px;line-height:1.62;max-width:60ch}
.care-foot{margin-top:30px;color:var(--ink);font-size:15.5px;line-height:1.62;max-width:64ch}
/* inline links in Care prose: without this they inherit the global
   a{color:inherit;text-decoration:none} and are indistinguishable from the
   sentence around them. Same underline treatment already declared for
   .sec-head .d a; colour is inherited so each context keeps its own weight. */
.care-row p a,.care-foot a{color:inherit;text-decoration:underline;text-underline-offset:2px;transition:color .18s}
.care-row p a:hover,.care-foot a:hover{color:var(--green)}
@media(max-width:640px){
  .care-row{grid-template-columns:1fr;gap:7px;padding:20px 2px}
}

/* ---------- game ---------- */
.game-wrap{background:linear-gradient(180deg,rgba(22,30,24,.7),rgba(var(--ground-rgb),.4));border:1px solid var(--line);border-radius:24px;padding:42px 38px 46px;position:relative;overflow:hidden}
.game-wrap .gx{position:absolute;right:-60px;bottom:-60px;width:260px;height:260px;background:radial-gradient(circle,rgba(87,230,0,.10),transparent 65%);pointer-events:none}
.game-top{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px;margin-bottom:28px}
.game-top h3{font-size:1.6rem}
.game-meta{display:flex;gap:22px;align-items:center}
.combo{font-family:var(--mono);font-size:15px;color:var(--green);letter-spacing:.06em;min-width:48px;text-align:right;transition:transform .12s;text-shadow:0 0 10px rgba(87,230,0,.5)}
.combo.bump{transform:scale(1.4)}
.snd{font-family:var(--mono);font-size:11px;letter-spacing:.14em;color:var(--ink-faint);background:transparent;-webkit-appearance:none;appearance:none;border:1px solid var(--line);border-radius:100px;padding:5px 12px;cursor:pointer;user-select:none;transition:color .18s,border-color .18s}
.snd:hover{color:var(--ink)}
.snd.on{color:var(--green);border-color:rgba(87,230,0,.35)}
.breachbar{position:relative;height:13px;border-radius:8px;background:var(--well);border:1px solid var(--line);overflow:hidden;margin-bottom:16px}
.breachbar i{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:8px;background:linear-gradient(90deg,var(--green-deep),var(--green) 80%,var(--green-bright));box-shadow:0 0 16px rgba(87,230,0,.6);transition:width .3s cubic-bezier(.22,1,.36,1)}
.breachbar span{position:absolute;right:11px;top:50%;transform:translateY(-50%);font-family:var(--mono);font-size:10px;letter-spacing:.16em;color:var(--ink)}
.board{position:relative;height:300px;border-radius:16px;overflow:hidden;cursor:crosshair;user-select:none;touch-action:manipulation;
  background:radial-gradient(120% 120% at 50% 0%,rgba(87,230,0,.05),transparent 55%),repeating-linear-gradient(90deg,rgba(180,190,200,.04) 0 1px,transparent 1px 38px),repeating-linear-gradient(0deg,rgba(180,190,200,.04) 0 1px,transparent 1px 38px),var(--well);
  border:1px solid var(--line)}
.board.shake{animation:bshake .26s}
@keyframes bshake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
.board-hint{position:absolute;inset:0;display:flex;align-items:flex-end;justify-content:center;text-align:center;padding:0 34px 20px;font-family:var(--mono);font-size:12px;line-height:1.7;color:var(--ink-faint);letter-spacing:.03em}
.board-hint b{color:var(--green)}
.corners{position:absolute;inset:9px;pointer-events:none;opacity:.5;background-repeat:no-repeat;background-image:
  linear-gradient(var(--green),var(--green)),linear-gradient(var(--green),var(--green)),
  linear-gradient(var(--green),var(--green)),linear-gradient(var(--green),var(--green)),
  linear-gradient(var(--green),var(--green)),linear-gradient(var(--green),var(--green)),
  linear-gradient(var(--green),var(--green)),linear-gradient(var(--green),var(--green));
  background-position:left top,left top,right top,right top,left bottom,left bottom,right bottom,right bottom;
  background-size:16px 1.5px,1.5px 16px,16px 1.5px,1.5px 16px,16px 1.5px,1.5px 16px,16px 1.5px,1.5px 16px}
.scanline{position:absolute;left:0;right:0;top:0;height:24px;pointer-events:none;display:none;background:linear-gradient(180deg,transparent,rgba(87,230,0,.05) 55%,rgba(87,230,0,.12));animation:scan 3.2s linear infinite}
.board.live .scanline{display:block}
@keyframes scan{from{transform:translateY(-24px)}to{transform:translateY(300px)}}
.milestone{position:absolute;left:50%;top:42%;z-index:5;transform:translate(-50%,-50%) scale(.92);font-family:var(--mono);font-size:clamp(14px,2.3vw,19px);font-weight:600;letter-spacing:.3em;color:var(--green-bright);text-shadow:0 0 18px rgba(87,230,0,.75);opacity:0;pointer-events:none;white-space:nowrap;transition:opacity .22s,transform .22s}
.milestone.show{opacity:1;transform:translate(-50%,-50%) scale(1)}
.milestone.bad{color:#ff8484;text-shadow:0 0 18px rgba(255,90,90,.65)}
.countdown{position:absolute;inset:0;z-index:6;display:none;align-items:center;justify-content:center;pointer-events:none;font-family:var(--mono);font-size:64px;font-weight:600;color:var(--green);text-shadow:0 0 30px rgba(87,230,0,.65)}
.countdown.show{display:flex}
.countdown span{display:inline-block;animation:cdpop .4s ease-out}
@keyframes cdpop{0%{transform:scale(1.8);opacity:0}35%{opacity:1}100%{transform:scale(1);opacity:.92}}
.board.alarm{border-color:rgba(255,90,90,.55);box-shadow:inset 0 0 70px rgba(255,90,90,.1)}
.tower{position:absolute;inset:0;transition:transform .35s cubic-bezier(.22,1,.36,1);will-change:transform}
/* attract mode sits back behind the Play CTA so a self-playing demo can never be
   mistaken for the visitor's own run */
.tower.attract{opacity:.42}
.blk{position:absolute;left:0;height:18px;border-radius:3px;will-change:transform;
  background:linear-gradient(180deg,rgba(87,230,0,.32),rgba(87,230,0,.15));
  border:1px solid rgba(87,230,0,.6);box-shadow:0 0 12px rgba(87,230,0,.22),inset 0 1px 0 rgba(255,255,255,.16)}
.blk.cur{background:linear-gradient(180deg,rgba(122,234,2,.5),rgba(87,230,0,.26));border-color:var(--green-bright);box-shadow:0 0 18px rgba(87,230,0,.5),inset 0 1px 0 rgba(255,255,255,.28)}
.blk.base{background:linear-gradient(180deg,rgba(200,210,220,.3),rgba(180,190,200,.12));border-color:rgba(200,210,220,.55);box-shadow:inset 0 1px 0 rgba(255,255,255,.24)}
.cut{position:absolute;left:0;height:18px;border-radius:3px;pointer-events:none;will-change:transform,opacity;
  background:rgba(87,230,0,.16);border:1px solid rgba(87,230,0,.35)}
.grade{position:absolute;font-family:var(--mono);font-size:12.5px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;pointer-events:none;white-space:nowrap;transform:translate(-50%,-50%)}
.grade.p{color:var(--green-bright);text-shadow:0 0 12px rgba(87,230,0,.8)}
.grade.b{color:#ff8484;text-shadow:0 0 10px rgba(255,90,90,.6)}
.game-hint{margin-top:20px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px}
.game-hint p{font-family:var(--mono);font-size:12.5px;color:var(--ink-faint);letter-spacing:.06em}
.game-hint kbd{font-family:var(--mono);background:rgba(174,182,191,.08);border:1px solid var(--line);border-bottom-width:2px;border-radius:6px;padding:2px 8px;color:var(--ink);font-size:12px}
.formnote{color:var(--ink-faint);font-size:12.5px;margin:4px 0 14px;line-height:1.55}
.formnote a{color:var(--ink-dim)}
.sec-head .d a{color:var(--ink-dim);text-decoration:underline;text-underline-offset:2px;transition:color .18s}
.sec-head .d a:hover{color:var(--green)}
/* the single big premium Play button: the section's entry point, overlaid on the board */
#startGame{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:7;font-size:16px;font-weight:700;letter-spacing:.02em;padding:19px 44px;box-shadow:0 0 0 6px rgba(87,230,0,.09),0 16px 48px rgba(87,230,0,.32),inset 0 1px 0 rgba(255,255,255,.3);animation:ctaPulse 2.8s ease-in-out infinite}
#startGame::before{content:"";width:0;height:0;border-style:solid;border-width:7px 0 7px 12px;border-color:transparent transparent transparent currentColor}
#startGame:hover{box-shadow:0 0 0 7px rgba(87,230,0,.16),0 22px 64px rgba(87,230,0,.5),inset 0 1px 0 rgba(255,255,255,.36);filter:brightness(1.06);animation:none}
/* Play button stays rock-stable on press: keep the centering transform, feedback via brightness only (never scale/move) */
#startGame:active{transform:translate(-50%,-50%)!important;filter:brightness(1.04)}
@keyframes ctaPulse{0%,100%{box-shadow:0 0 0 6px rgba(87,230,0,.09),0 16px 48px rgba(87,230,0,.28),inset 0 1px 0 rgba(255,255,255,.3)}50%{box-shadow:0 0 0 11px rgba(87,230,0,.04),0 16px 54px rgba(87,230,0,.44),inset 0 1px 0 rgba(255,255,255,.3)}}
@media (prefers-reduced-motion:reduce){#startGame{animation:none}}
.spark{position:absolute;width:6px;height:6px;border-radius:50%;background:var(--green-bright);pointer-events:none;box-shadow:0 0 8px var(--green)}
.spark.red{background:#ff8a8a;box-shadow:0 0 8px rgba(255,90,90,.8)}
/* ---------- end card (win + lose share one component) ----------
   Built to survive a screenshot: the mark, the score, and the verdict all sit
   inside .ec-frame, so a crop of just the frame is still unmistakably ours. */
.endcard{display:none}
/* animates 0 -> 1 without ever setting a base opacity of 0: if animations are
   suppressed the card is simply visible, never an invisible dead end */
@keyframes ecIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.endcard.show{display:block;animation:ecIn .5s cubic-bezier(.22,1,.36,1) both}
/* focused programmatically at run end (tabindex="-1") so no ring for that; keyboard focus still shows one */
.endcard:focus{outline:2px solid var(--green);outline-offset:4px;border-radius:20px}
@supports selector(:focus-visible){.endcard:focus:not(:focus-visible){outline:none}}
.ec-frame{position:relative;overflow:hidden;text-align:center;border-radius:20px;padding:38px 34px 34px;
  border:1px solid var(--line);background:radial-gradient(120% 90% at 50% 0%,rgba(87,230,0,.07),transparent 60%),var(--glass)}
.endcard[data-state="win"] .ec-frame{border-color:rgba(87,230,0,.42);box-shadow:0 0 0 1px rgba(87,230,0,.1),0 26px 70px rgba(87,230,0,.14),inset 0 1px 0 rgba(255,255,255,.05)}
.endcard[data-state="lose"] .ec-frame{border-color:rgba(255,120,120,.26)}
.ec-head{display:flex;align-items:center;justify-content:center;gap:14px;flex-wrap:wrap;margin-bottom:26px}
.ec-logo{height:20px;width:auto;opacity:.9;filter:drop-shadow(0 0 8px rgba(87,230,0,.18))}
.ec-stamp{font-family:var(--mono);font-size:10.5px;letter-spacing:.24em;text-transform:uppercase;color:var(--ink-faint);border-left:1px solid var(--line);padding-left:14px}
/* the score is the hero: it is the thing worth screenshotting */
.ec-scoreline{display:flex;align-items:baseline;justify-content:center;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.ec-num{font-family:var(--disp);font-weight:700;font-size:clamp(3.6rem,11vw,5.6rem);line-height:.9;letter-spacing:-.02em;
  background:var(--chrome);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
.endcard[data-state="win"] .ec-num{background:linear-gradient(180deg,#d9ffcb,var(--green) 62%,var(--green-deep));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.ec-den{font-family:var(--mono);font-size:12px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-faint)}
.endcard h3{font-size:clamp(1.5rem,3.4vw,1.95rem);margin-bottom:12px}
.ec-when-win,.ec-when-lose{display:none}
.endcard[data-state="win"] .ec-when-win{display:inline}
.endcard[data-state="lose"] .ec-when-lose{display:inline}
/* one static line per score band; the script only flips data-band */
.ec-line{display:none;color:var(--ink-dim);font-size:15.5px;line-height:1.6;max-width:52ch;margin:0 auto 24px}
.ec-line .ec-n{color:var(--ink);font-weight:600}
.endcard[data-band="zero"] .ec-line[data-band="zero"],
.endcard[data-band="low"] .ec-line[data-band="low"],
.endcard[data-band="mid"] .ec-line[data-band="mid"],
.endcard[data-band="high"] .ec-line[data-band="high"],
.endcard[data-band="near"] .ec-line[data-band="near"],
.endcard[data-band="win"] .ec-line[data-band="win"]{display:block}
.ec-actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
@media(max-width:560px){
  .ec-frame{padding:30px 20px 28px}
  .ec-actions .btn{width:100%}
}

/* ---------- contact ---------- */
.contact{display:grid;grid-template-columns:1fr 1fr;gap:50px;align-items:start}
.contact .left h2{font-size:clamp(2rem,4.4vw,3.4rem);margin:16px 0 18px}
.contact .left p{color:var(--ink-dim);max-width:42ch;margin-bottom:26px}
.contact .pts{display:flex;flex-direction:column;gap:14px}
.contact .pt{display:flex;gap:13px;align-items:center;font-size:15px;color:var(--ink)}
.contact .pt .d{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 10px var(--green);flex:none}
form.cf,.cf-sent{background:var(--glass);border:1px solid var(--line);border-radius:22px;padding:32px 30px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
/* the form and its success panel share one grid cell, so swapping them never
   reflows the two-column contact layout */
.contact form.cf,.contact .cf-sent{grid-column:2;grid-row:1}
@media(max-width:920px){.contact form.cf,.contact .cf-sent{grid-column:1;grid-row:auto}}
.field{margin-bottom:18px}
.field label{display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-dim);margin-bottom:9px}
.field input,.field textarea,.field select{width:100%;background:var(--well);border:1px solid var(--line-field);border-radius:12px;padding:13px 16px;color:var(--ink);font-family:var(--body);font-size:15px;outline:none;transition:border-color .3s,box-shadow .3s}
.field input:focus,.field textarea:focus,.field select:focus{border-color:rgba(87,230,0,.55);box-shadow:0 0 0 3px rgba(87,230,0,.1)}
.field input,.field textarea,.field select{transition:border-color .2s,box-shadow .2s}
.field textarea{resize:vertical;min-height:120px}
form.cf .btn{width:100%;margin-top:6px}
/* submission problems are stated, never swallowed: this is where an over-long
   message or a rate-limit refusal is shown in words */
.formerr{margin:0 0 14px;padding:12px 15px;border-radius:12px;font-size:14px;line-height:1.55;
  color:#ffd9d9;background:rgba(255,90,90,.08);border:1px solid rgba(255,90,90,.34)}
.formerr[hidden]{display:none}
.hp{position:absolute;left:-9999px;top:-9999px;opacity:0;pointer-events:none}
.sent{text-align:center;padding:34px 6px 26px}
.sent .tick{width:52px;height:52px;margin:0 auto 18px;border-radius:50%;display:grid;place-items:center;border:1px solid rgba(87,230,0,.5);background:rgba(87,230,0,.08);color:var(--green);font-size:24px;box-shadow:0 0 24px rgba(87,230,0,.25)}
.sent h3{font-family:var(--disp);font-weight:600;font-size:1.5rem;margin-bottom:10px}
.sent p{color:var(--ink-dim);font-size:15px;max-width:38ch;margin:0 auto}
.field select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:38px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath fill='none' stroke='%23909aa3' stroke-width='1.6' d='M1 1.5l5 5 5-5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:calc(100% - 15px) center}
/* custom properties DO reach here -- background is not an inherited property but
   --bg is, so var(--bg) resolves. What varies is whether the platform honours an
   option background at all: several native pickers ignore it, literal or token
   alike. Using the token means this can never drift from the ground. */
.field select option{background:var(--bg);color:var(--ink)}
.work-cta{margin-top:26px;display:flex;justify-content:center}
.offer{margin-top:26px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:rgba(87,230,0,.05);border:1px solid rgba(87,230,0,.22);border-radius:14px;padding:16px 20px}
.offer .otag{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--green);border:1px solid rgba(87,230,0,.3);border-radius:100px;padding:5px 11px;white-space:nowrap}
.offer p{color:var(--ink);font-size:14.5px;line-height:1.55;margin:0;max-width:none}
.offer p b{color:var(--green);font-weight:600}
.offer p a{color:var(--ink-dim);text-decoration:underline;text-underline-offset:2px;transition:color .18s}
.offer p a:hover{color:var(--green)}

/* ---------- footer ---------- */
footer{border-top:1px solid var(--line-soft);padding:56px 0 42px;margin-top:30px}
.foot{display:flex;justify-content:space-between;align-items:center;gap:24px 30px;flex-wrap:wrap}
.foot-logo{display:inline-flex;cursor:pointer;transition:transform .25s cubic-bezier(.22,1,.36,1)}
.foot-logo:hover{transform:translateY(-2px)}
.foot-logo:hover img{opacity:1;filter:drop-shadow(0 0 12px rgba(87,230,0,.32))}
.foot img{height:24px;width:auto;opacity:.92;transition:opacity .25s,filter .25s;filter:drop-shadow(0 0 8px rgba(87,230,0,.16))}
.foot-tag{font-family:var(--mono);font-size:12px;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-dim);white-space:nowrap}
.foot-tag .g{color:var(--green)}
.foot-base{margin-top:30px;padding-top:22px;border-top:1px solid var(--line-soft);display:flex;justify-content:space-between;align-items:center;gap:10px 26px;flex-wrap:wrap;font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;color:var(--ink-faint);line-height:1.8}
.foot-base .lgl{color:var(--ink-faint);border-bottom:1px solid rgba(180,190,200,.25);transition:color .18s,border-color .18s}
.foot-base .lgl:hover{color:var(--green);border-color:rgba(87,230,0,.5)}
@media(max-width:560px){
  .foot{flex-direction:column;justify-content:center;text-align:center;gap:18px}
  .foot-base{flex-direction:column;align-items:center;text-align:center;gap:6px}
}

/* ---------- reveal anim ---------- */
.r{opacity:0;transform:translateY(22px);transition:opacity .55s cubic-bezier(.22,1,.36,1),transform .55s cubic-bezier(.22,1,.36,1)}
.r.in{opacity:1;transform:none}
.r.d1{transition-delay:.05s}.r.d2{transition-delay:.1s}.r.d3{transition-delay:.15s}.r.d4{transition-delay:.2s}

/* ---------- responsive ---------- */
/* the nav carries five labels and the CTA now, so the 30px gap is tightened
   once before the labels drop out entirely at 920px */
@media(max-width:1080px){.nav-links{gap:22px}}
@media(max-width:980px){.nav-links{gap:17px}.nav-links a.lnk{font-size:13.5px}}
@media(max-width:920px){
  .grid-3{grid-template-columns:1fr}
  .steps{grid-template-columns:1fr 1fr}
  .step:nth-child(2){border-right:none}
  .grid-2,.custom-row,.contact{grid-template-columns:1fr}
  /* the header labels give way to the disclosure menu, which switches itself
     on beside its own rules further down this file -- putting the display
     toggle here instead would be overridden by the base rule below */
  .nav-links .lnk{display:none}
  .nav-links{gap:12px}
}
@media(max-width:560px){
  .nav-in{padding:0 20px}
  .nav-links .btn-primary{padding:11px 16px;font-size:13.5px}
}
/* small phones: the header carries the logo, the CTA and the menu on one
   line. Every value here only ever SHRINKS what is already fitting at 480,
   so the row cannot be pushed to overflow by it. Nothing is removed --
   the CTA stays reachable in the header at every width. */
@media(max-width:430px){
  .nav-logo{height:22px}
  .nav-links{gap:9px}
  .nav-links .btn-primary{padding:10px 13px;font-size:13px}
  /* the matching .mnav>summary shrink lives beside its base rule further
     down: an equal-specificity base declared later would beat it here */
}
@media(max-width:560px){
  .steps{grid-template-columns:1fr}.step{border-right:none;border-bottom:1px solid var(--line)}
  .shell{padding:0 20px}.sec{padding:86px 0}
  .statement{padding-top:18vh}
  .game-wrap{padding:30px 22px 34px}
  .game-meta{gap:14px}
  .sec-head{margin-bottom:40px}
  .statement-sub{padding:0 6px}
  .contact .left p{margin-bottom:22px}
}
@media(prefers-reduced-motion:reduce){
  *{animation-duration:.001s !important;animation-iteration-count:1 !important}
  .r{opacity:1;transform:none;transition:none}
  .words span i{transform:none !important}
}

/* ==========================================================================
   MULTI-PAGE ADDITIONS
   Everything above this line is the stylesheet inherited from the live
   single-page build. It changes only when a component leaves the site: the
   proof card's rules went out with the proof section, and the hero sheen
   mask path is stylesheet-relative now that the sheet is an external file.
   Nothing below introduces a new visual language: every rule either extends
   an existing selector to a second context (the nav link treatment reused in
   the footer, the .card made a link) or restates values already declared
   above (the doorway card's mono line is .custom .q; the subpage closer is
   .statement-cta). No new fonts, colours, radii, or motion curves.
   ========================================================================== */

/* -- current-page state: the nav underline that already exists on hover,
      held open for the page you are on -- */
.nav-links a.lnk[aria-current="page"]{color:var(--ink)}
.nav-links a.lnk[aria-current="page"]::after{right:0}

/* -- footer link row: the same .lnk treatment as the nav.
      Load-bearing, not decoration: .nav-links .lnk is hidden below 920px,
      so on a phone the footer is the complete route between pages. -- */
.foot-links{display:flex;align-items:center;gap:26px;flex-wrap:wrap;justify-content:center}
.foot-links a.lnk{position:relative;font-size:14px;color:var(--ink-dim);letter-spacing:.02em;transition:color .18s}
.foot-links a.lnk::after{content:"";position:absolute;left:0;right:100%;bottom:-5px;height:1px;background:var(--green);box-shadow:0 0 6px rgba(87,230,0,.6);transition:right .25s cubic-bezier(.22,1,.36,1)}
.foot-links a.lnk:hover{color:var(--ink)}
.foot-links a.lnk:hover::after{right:0}
.foot-links a.lnk[aria-current="page"]{color:var(--ink)}
.foot-links a.lnk[aria-current="page"]::after{right:0}
@media(max-width:560px){.foot-links{gap:18px 22px}}

/* -- doorway cards: the existing .card, made a link. .card already carries
      the lift, the border bloom and the cursor spotlight; this only makes
      the whole card the hit area. -- */
a.card{display:block}
a.card:hover h3{color:#eafff0}
/* the small mono line that says where a card goes: the treatment already
   used by .custom .q above */
.card .q{display:block;margin-top:18px;font-family:var(--mono);color:var(--green);font-size:13px;letter-spacing:.02em}

/* -- page opener: the existing .statement block used as a subpage head.
      Only the top padding changes, because on a subpage it sits directly
      under the fixed 74px nav instead of below a full-height hero. -- */
.statement.page{padding-top:calc(74px + clamp(40px,7vh,74px))}
@media(max-width:560px){.statement.page{padding-top:132px}}

/* -- anchor landing: the nav is fixed at 74px, so a section scrolled to its
      own top sits behind it. Lenis handles the scripted path (offset -84 in
      site.js); this covers the two paths Lenis never sees -- a URL opened
      with a fragment, and the reduced-motion fallback to scrollIntoView.
      Same 74px + 10px as the nav rule above. -- */
section[id]{scroll-margin-top:84px}

/* -- closing block on subpages: .statement-cta spacing, at a section end -- */
.end-cta{margin-top:44px;display:flex;gap:14px;flex-wrap:wrap;justify-content:center}

/* -- capability list: what a build can carry. Deliberately not cards --
      these are names on a menu, not features to compare, so they take the
      hairline rule of .care-list with a green check mark, set two-up
      instead of one long stack.
      No new colour, type size, or rule weight: every value here is restated
      from .care-row (15.5px ink on --line-soft) plus the green accent.
      Grid rows stretch, so both columns' rules land on the same baseline. -- */
.caps{display:grid;grid-template-columns:repeat(2,1fr);gap:0 44px;border-top:1px solid var(--line-soft);list-style:none}
.caps li{position:relative;padding:17px 4px 17px 30px;border-bottom:1px solid var(--line-soft);color:var(--ink);font-size:15.5px;line-height:1.5;transition:background .25s}
.caps li:hover{background:rgba(87,230,0,.02)}
.caps li::before{content:"\2713";position:absolute;left:4px;top:17px;color:var(--green);font-size:13px;line-height:1.5}
@media(max-width:640px){
  .caps{grid-template-columns:1fr}
  .caps li{padding:15px 2px 15px 28px}
  .caps li::before{left:2px;top:15px}
}

/* -- mobile header menu --
      A native <details>, deliberately: it opens, closes, takes focus and
      announces itself with no JavaScript at all, which is the same standard
      the rest of this page is now held to. Hidden above 920px, where the
      header carries the labels itself. site.js only closes it after an
      in-page anchor; every other path resets it by loading a new page. -- */
.mnav{display:none;position:relative}
@media(max-width:920px){.mnav{display:block}}
.mnav>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--body);font-weight:600;font-size:13.5px;letter-spacing:.02em;color:var(--ink);
  padding:11px 16px;border:1px solid var(--line);border-radius:100px;transition:border-color .22s,color .18s}
.mnav>summary::-webkit-details-marker{display:none}
.mnav>summary::after{content:"";width:8px;height:8px;border-right:1.5px solid var(--green);border-bottom:1.5px solid var(--green);transform:translateY(-2px) rotate(45deg);transition:transform .22s cubic-bezier(.22,1,.36,1)}
.mnav[open]>summary{border-color:rgba(87,230,0,.35)}
.mnav[open]>summary::after{transform:translateY(1px) rotate(-135deg)}
.mnav>summary:focus-visible{outline:2px solid var(--green);outline-offset:3px}
@media(max-width:430px){.mnav>summary{padding:10px 13px;font-size:13px}}
/* The panel hangs off a FIXED bar, so the document cannot be scrolled to
   reach anything that falls past the bottom of the screen -- in landscape or
   at high zoom that would strand the last links. It gets its own height bound
   and its own scroll instead. */
.mnav-panel{position:absolute;right:0;top:calc(100% + 12px);min-width:228px;display:flex;flex-direction:column;
  max-height:calc(100vh - 98px);max-height:calc(100dvh - 98px);overflow-y:auto;overscroll-behavior:contain;
  padding:10px;border:1px solid var(--line);border-radius:18px;background:var(--panel);
  backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);
  box-shadow:0 24px 60px rgba(0,0,0,.6)}
.mnav-panel a{padding:14px;border-radius:12px;font-size:15px;color:var(--ink-dim);transition:color .18s,background .18s}
.mnav-panel a:hover{color:var(--ink);background:rgba(87,230,0,.06)}
.mnav-panel a[aria-current="page"]{color:var(--green)}

/* ==========================================================================
   NO-SCRIPT FALLBACK
   Every reveal on this site starts hidden (.r at opacity 0, .words rolled
   below its own line) and is opened by site.js adding .in. With scripting
   off nothing ever adds .in, so the whole page read as blank: nav, footer
   and background only. Each page now stamps html.js from an inline script
   in the head, before first paint. These rules only ever match when that
   stamp is absent, and they drop the animated start states so everything
   renders in its final position with no transition to wait for.
   ========================================================================== */
html:not(.js) .r{opacity:1;transform:none;transition:none}
html:not(.js) .words span i{transform:none;transition:none}
html:not(.js) .num::after{width:72px}
/* two blocks that are script, not content: the contact form posts over fetch
   and would silently swallow an enquiry if it submitted itself, and The Stack
   is a canvas-less game with a dead start button. Both are pulled, and the
   contact section shows the direct email route instead. */
html:not(.js) #cf,html:not(.js) #game{display:none}
.nojs{display:none}
html:not(.js) .nojs{display:block}
.contact .cf-nojs{grid-column:2;grid-row:1;background:var(--glass);border:1px solid var(--line);border-radius:22px;padding:32px 30px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.contact .cf-nojs h3{font-size:1.5rem;margin-bottom:12px}
.contact .cf-nojs p{color:var(--ink-dim);font-size:15px;line-height:1.6;margin:0}
.contact .cf-nojs a{color:var(--green);text-decoration:underline;text-underline-offset:3px}
@media(max-width:920px){.contact .cf-nojs{grid-column:1;grid-row:auto}}
