:root{
  --lime:#72B908; --lime-bright:#8BCF3A; --green:#2E944F; --emerald:#37933B;
  --forest:#0D5F33; --forest-deep:#084223; --forest-ink:#062E19;
  --bg:#F6F8F7; --surface:#FFFFFF; --ink:#1C2A22; --body:#3E4E44; --faint:#5C6E63;
  --line:#E2EAE4; --line-strong:#CBD9CF;
  /* landing layout (2026-09-27 redesign) */
  --sage:#F2F5F2; --sage-line:#E3E8E4; --muted:#56645B;
  --btn-green:#217F44; --btn-green-hover:#1a6837;
  --r-card:18px; --r-panel:28px; --r-lg:24px; --r-md:18px; --r-sm:12px;
  --gutter:clamp(20px,8.33vw,120px);
  --shadow-sm:0 1px 2px rgba(13,95,51,.05),0 2px 8px rgba(13,95,51,.05);
  --ease-out:cubic-bezier(.22,1,.36,1);
  --z-nav:50;
  --nav-h:72px;
  --font-display:'Satoshi',system-ui,sans-serif; --font-body:'Satoshi',system-ui,sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}
body{font-family:var(--font-body);background:var(--surface);color:var(--muted);font-size:16.5px;line-height:1.6;overflow-x:hidden}
h1,h2,h3,h4{font-family:var(--font-display);color:var(--ink);line-height:1.1;text-wrap:balance;letter-spacing:-.02em;font-weight:500}
p{text-wrap:pretty}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
ul,ol{list-style:none}
button,input,textarea{font:inherit;color:inherit}
::selection{background:rgba(139,207,58,.35)}
:focus-visible{outline:2.5px solid var(--green);outline-offset:3px;border-radius:4px}
.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}
.skip-link{position:absolute;left:16px;top:-60px;z-index:100;padding:10px 16px;border-radius:99px;background:var(--btn-green);color:#fff;font-weight:600}
.skip-link:focus{top:12px}

/* 1200px of content, with the 120px desktop gutter inside the max-width */
.wrap{max-width:calc(1200px + 2 * var(--gutter));margin:0 auto;padding:0 var(--gutter)}
.section{padding:clamp(64px,7.2vw,104px) 0;scroll-margin-top:var(--nav-h)}
.section-follow{padding-top:0}
/* two white sections in a row share one gap instead of stacking both paddings */
.section:not(.section-sage) + .section:not(.section-sage){padding-top:0}
.section-sage{background:var(--sage)}

/* ---------- type scale ---------- */
.h2-sm{font-size:clamp(1.75rem,2.4vw,2.125rem);margin-bottom:32px}
.h2-lg{font-size:clamp(2.25rem,4.2vw,3.75rem);letter-spacing:-.035em;margin-bottom:40px}
.sec-head{max-width:640px;margin:0 auto clamp(40px,4.5vw,64px);text-align:center}
.sec-head h1,.sec-head h2{font-size:clamp(2rem,3.1vw,2.75rem);letter-spacing:-.03em;margin-bottom:14px}
.sec-head p{font-size:1.1rem}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;border:1.5px solid transparent;cursor:pointer;border-radius:99px;font-weight:600;line-height:1.2;white-space:nowrap;transition:transform .25s var(--ease-out),background .25s,border-color .25s,color .25s}
.btn:active{transform:scale(.97)}
/* white on --btn-green is ~5:1 (white on plain --green is only ~3.8:1) */
.btn-primary{background:var(--btn-green);color:#fff;padding:12px 24px;font-size:.95rem}
.btn-primary:hover{background:var(--btn-green-hover)}
.btn-ghost{background:var(--surface);color:var(--forest);padding:12px 24px;font-size:.95rem;border-color:var(--line-strong)}
.btn-ghost:hover{border-color:var(--green)}

/* ---------- nav ---------- */
/* Frosted glass. Over the hero photo (.over-hero, toggled by app.js) it is a
   dark green tint with white text; past the hero it becomes light glass with
   dark text. The blur keeps whatever scrolls underneath from competing with
   the links either way. */
.nav{position:fixed;top:0;left:0;right:0;z-index:var(--z-nav);background:rgba(255,255,255,.72);-webkit-backdrop-filter:blur(18px) saturate(1.5);backdrop-filter:blur(18px) saturate(1.5);border-bottom:1px solid rgba(255,255,255,.6);box-shadow:0 1px 0 rgba(13,95,51,.07);transition:background .35s,border-color .35s,box-shadow .35s}
.nav.scrolled:not(.over-hero){box-shadow:0 10px 30px -22px rgba(13,95,51,.55)}
.nav.over-hero{background:rgba(6,46,25,.24);border-bottom-color:rgba(255,255,255,.16);box-shadow:none}
.nav.over-hero .brand-text{color:#fff}
.nav.over-hero .brand-text small{color:rgba(255,255,255,.8)}
.nav.over-hero .menu-toggle{color:#fff}
.nav.over-hero .btn-ghost{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.5);color:#fff}
.nav.over-hero .btn-ghost:hover{background:rgba(255,255,255,.22);border-color:#fff}
/* desktop bar only: the phone drawer is a solid white panel, so its links stay dark */
@media (min-width:1181px){
  .nav.over-hero .nav-links a{color:rgba(255,255,255,.92)}
  .nav.over-hero .nav-links a:hover{color:#fff;background:rgba(255,255,255,.14)}
  .nav.over-hero .nav-links a[aria-current]{color:#fff}
  .nav.over-hero .nav-links a::after{background:var(--lime-bright)}
}
.nav-inner{display:flex;align-items:center;gap:40px;height:var(--nav-h)}
.nav-inner nav{flex:1;min-width:0}
.brand{flex-shrink:0;display:flex;align-items:center;gap:10px}
/* white disc so the green mark reads on both the dark and the light glass;
   same size as the footer logo (.foot-brand img) */
.brand img{flex-shrink:0;width:48px;height:48px;object-fit:contain;background:#fff;border-radius:50%;padding:6px;transition:box-shadow .35s}
/* on the light glass the white disc would melt into the bar and only the
   mark would show, so the logo looked smaller than the footer's; a faint
   ring + shadow keeps the full 48px circle visible */
.nav:not(.over-hero) .brand img{box-shadow:0 0 0 1px var(--sage-line),0 3px 10px -4px rgba(13,95,51,.45)}
.brand-text{font-weight:700;font-size:1.2rem;line-height:1.1;color:var(--ink);letter-spacing:-.01em}
.brand-text small{display:block;margin-top:2px;font-weight:500;font-size:.68rem;letter-spacing:0;color:var(--muted)}
.nav-links{display:flex;align-items:center;gap:2px}
.nav-links a{display:block;padding:8px 12px;border-radius:99px;font-size:.93rem;font-weight:500;color:var(--body);transition:color .2s,background .2s}
.nav-links a:hover{color:var(--forest);background:var(--sage)}
.nav-cta{flex-shrink:0;display:flex;align-items:center;gap:10px}
.nav-cta .btn{padding:10px 22px;font-size:.92rem}
.nav-drawer-only{display:none}
.nav-stay .lbl-short{display:none}
.menu-toggle{display:none;background:none;border:0;cursor:pointer;padding:8px;border-radius:10px;color:var(--ink)}
/* desktop: brand | links | CTAs, with equal-width outer columns so the links
   sit on the page's centre line. The max-content minimums mean that when the
   bar is too narrow to balance, the links shift over instead of anything
   wrapping. Must come after the base rules above to override them. */
@media (min-width:1181px){
  .nav-inner{display:grid;grid-template-columns:minmax(max-content,1fr) auto minmax(max-content,1fr);gap:24px}
  .brand{justify-self:start}
  .nav-links{justify-content:center}
  .nav-cta{justify-self:end}
}

/* ---------- Google-style search (hero) ---------- */
/* One pill bar; when suggestions are open it squares off at the bottom and
   the list continues it, the way Google's box does. z-index keeps the list
   above whatever follows the hero. */
.gsearch{position:relative;z-index:5;width:100%;max-width:640px;margin:0 auto;text-align:left}
/* display only (no input): no hover/focus states, text can't be selected */
.gsearch-bar{display:flex;align-items:center;gap:6px;height:58px;padding:0 7px 0 20px;background:var(--surface);border:1px solid var(--sage-line);border-radius:29px;box-shadow:0 12px 32px -14px rgba(6,46,25,.55);cursor:default;user-select:none;-webkit-user-select:none}
.gsearch-ico{flex-shrink:0;color:var(--muted)}
.gsearch-text{flex:1;min-width:0;padding:0 6px;font-size:1.06rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsearch-go{flex-shrink:0;width:44px;height:44px;display:grid;place-items:center;border-radius:50%;background:var(--btn-green)}
/* magnifier-glass-icon.svg as a mask, so it takes the button's white */
.gsearch-mag{width:18px;height:18px;background:#fff;-webkit-mask:url("../img/magnifier-glass-icon.b80190e60ff0.svg") center/contain no-repeat;mask:url("../img/magnifier-glass-icon.b80190e60ff0.svg") center/contain no-repeat}
.gsearch-actions{display:flex;justify-content:center;flex-wrap:wrap;gap:12px;margin-top:20px}
/* frosted secondary button over the photo; a plain outline on the light CTA */
.btn-soft{padding:12px 24px;font-size:.95rem;background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.45);color:#fff;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.btn-soft:hover{background:rgba(255,255,255,.24);border-color:#fff}

/* ---------- hero ---------- */
/* The campus photo fills the hero behind the glass nav, right down to the
   hero's bottom edge (no fade into the page). The padding only clears
   the fixed nav (plus an equal gap top and bottom), so the copy is centred
   in the visible area below the nav. Scrim: checked against the
   brightest part of the photo (the sky over the gate) -- white text stays
   above 4.5:1 with it. */
.hero{--hero-gap:clamp(20px,3vw,32px);position:relative;isolation:isolate;min-height:100vh;min-height:100svh;display:flex;align-items:center;padding:calc(var(--nav-h) + var(--hero-gap)) 0 var(--hero-gap);text-align:center;color:rgba(255,255,255,.88);scroll-margin-top:0}
.hero-inner{width:100%}
.hero-bg{position:absolute;inset:0;z-index:-1;overflow:hidden;background:var(--forest-deep)}
.hero-bg img{position:absolute;inset:-12% 0 auto;width:100%;height:124%;object-fit:cover}
.hero-bg::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(6,46,25,.6),rgba(6,46,25,.66) 50%,rgba(6,46,25,.74))}
.hero h1{max-width:1000px;margin:0 auto;font-size:clamp(2.75rem,5.6vw,5rem);line-height:1.02;letter-spacing:-.04em;color:#fff}
.hero-sub{max-width:600px;margin:24px auto 36px;font-size:clamp(1.06rem,1.4vw,1.25rem);line-height:1.55}
.hero-caption{margin-top:18px;font-size:.9rem;color:rgba(255,255,255,.82)}

/* ---------- product block ---------- */
/* The six feature cards in a 3x2 grid. */
.product{position:relative}
.feat-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}

/* feature card: visual on top, then the title and text, left-aligned */
.feat{display:flex;flex-direction:column;padding:16px 16px 28px;background:var(--surface);border:1px solid var(--sage-line);border-radius:var(--r-lg);box-shadow:0 1px 2px rgba(13,95,51,.04),0 18px 40px -24px rgba(13,95,51,.3);transition:border-color .2s,transform .3s var(--ease-out),box-shadow .3s}
.feat:hover{border-color:var(--line-strong);transform:translateY(-4px);box-shadow:0 1px 2px rgba(13,95,51,.05),0 26px 48px -24px rgba(13,95,51,.42)}
.feat .viz{flex:none;height:160px;min-height:0;border-radius:14px}
.feat-text{padding:22px 10px 0}
.feat-text h3{font-size:1.18rem;font-weight:600;letter-spacing:-.015em;line-height:1.3}
.feat-text p{margin-top:8px;font-size:.97rem;line-height:1.6}

/* plus that turns into an x (FAQ) */
.pm{position:relative;flex-shrink:0;width:24px;height:24px;transition:transform .3s var(--ease-out)}
.pm::before,.pm::after{content:"";position:absolute;left:50%;top:50%;width:12px;height:2px;border-radius:2px;background:currentColor;transform:translate(-50%,-50%)}
.pm::after{transform:translate(-50%,-50%) rotate(90deg)}
[aria-expanded="true"] > .pm{transform:rotate(45deg)}

/* ---------- feature visuals ---------- */
.viz{position:relative;flex:1;min-height:110px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:16px;border-radius:12px;background:var(--surface);border:1px solid var(--sage-line);overflow:hidden}
.mini-search{display:flex;align-items:center;gap:8px;width:100%;max-width:280px;padding:8px 14px;border:1px solid var(--line-strong);border-radius:99px;font-size:.84rem;color:var(--ink);white-space:nowrap;overflow:hidden}
.mini-search svg{flex-shrink:0;color:var(--muted)}
mark{background:rgba(139,207,58,.35);color:var(--ink);border-radius:4px;padding:0 2px}
.term-row{display:flex;flex-wrap:wrap;justify-content:center;gap:6px}
.term{padding:3px 10px;border-radius:99px;background:rgba(139,207,58,.2);color:var(--forest-deep);font-size:.76rem;font-weight:600}
.viz-chart{padding:28px 20px 16px}
.viz-chart svg{position:absolute;inset:28px 20px 16px;width:calc(100% - 40px);height:calc(100% - 44px);overflow:visible}
.viz-chart .grid{stroke:var(--sage-line);stroke-width:1;vector-effect:non-scaling-stroke}
.viz-chart polyline{fill:none;stroke:var(--btn-green);stroke-width:2.5;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.viz-chart .plot{position:absolute;inset:28px 20px 16px}
.viz-chart .pt{position:absolute;width:12px;height:12px;border-radius:50%;background:var(--btn-green);border:3px solid #fff;box-shadow:0 0 0 1px var(--btn-green);transform:translate(-50%,-50%)}
.viz-chart .callout{position:absolute;transform:translate(-78%,calc(-100% - 14px));padding:4px 10px;border-radius:99px;background:var(--forest-deep);color:#fff;font-size:.78rem;font-weight:600;white-space:nowrap;font-variant-numeric:tabular-nums}
.syn{display:flex;align-items:center;gap:8px;max-width:100%;font-size:.8rem;font-weight:600}
.syn span{padding:4px 10px;border-radius:99px;border:1px solid var(--line-strong);color:var(--ink);white-space:nowrap}
.syn .alt{border-color:transparent;background:rgba(139,207,58,.2);color:var(--forest-deep);white-space:normal}
.syn i{font-style:normal;color:var(--forest)}
.viz-stack{align-items:stretch;gap:8px;padding:16px}
.viz-stack span{display:flex;align-items:center;gap:10px;height:32px;padding:0 12px 0 10px;border-radius:8px;border:1px solid var(--sage-line);background:var(--sage);min-width:0}
/* magnifier-glass-icon.svg as a mask, so it takes the brand green */
.viz-stack .mag{flex-shrink:0;width:14px;height:14px;background:var(--btn-green);-webkit-mask:url("../img/magnifier-glass-icon.b80190e60ff0.svg") center/contain no-repeat;mask:url("../img/magnifier-glass-icon.b80190e60ff0.svg") center/contain no-repeat}
.viz-stack b{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.78rem;font-weight:500;color:var(--ink)}
.viz-dots svg{width:100%;max-width:260px;height:auto}
.viz-dots .far{fill:var(--line-strong)}
.viz-dots .ring{fill:rgba(139,207,58,.14);stroke:rgba(114,185,8,.55);stroke-width:1.2;stroke-dasharray:4 4}
.viz-dots .near{fill:var(--green)}
.viz-dots .links line{stroke:rgba(46,148,79,.35);stroke-width:1.2;stroke-linecap:round}
.viz-dots .links .spoke{stroke:var(--green);stroke-width:1.6}
.viz-dots .links .reach{stroke:var(--line-strong);stroke-width:1}
.viz-dots .you{fill:var(--forest-deep);stroke:#fff;stroke-width:2.5}
/* hybrid engine: the old full-width screenshot panel, shrunk to a card visual */
.viz-shot{display:block;padding:0;background:var(--sage)}
.viz-shot img{position:absolute;top:16px;left:16px;width:max(150%,480px);max-width:none;height:auto;border-radius:10px;border:1px solid var(--sage-line);box-shadow:var(--shadow-sm)}

/* ---------- dark section ---------- */
.dark{padding:clamp(56px,6vw,88px) 0;background:var(--forest-deep);color:rgba(255,255,255,.78)}
.bignum{margin:clamp(48px,5vw,72px) 0 clamp(28px,3vw,40px);text-align:center}
.bignum-n{font-size:clamp(4rem,7.8vw,7rem);font-weight:500;line-height:1;letter-spacing:-.045em;color:#fff;font-variant-numeric:tabular-nums}
.bignum-cap{margin-top:14px;font-size:1.1rem}
/* compact on purpose: the whole dark block should be about one screen */
.proof{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}
/* model metric: its name, the value, then what it means */
.metric{display:flex;flex-direction:column;gap:10px;padding:20px 22px;border-radius:var(--r-card);background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12)}
.metric-name{font-size:1rem;font-weight:600;line-height:1.3;color:#fff}
.metric-n{font-size:clamp(2.2rem,3vw,2.75rem);font-weight:500;line-height:1;letter-spacing:-.03em;color:#fff;font-variant-numeric:tabular-nums}
.metric-desc{margin-top:auto;font-size:.88rem;line-height:1.5}

/* ---------- how it works ---------- */
/* boxes split by hairlines, each with its step number in the top-left corner:
   one row of four on desktop, 2x2 on tablets, compact rows on phones */
.steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border:1px solid rgba(255,255,255,.14);border-radius:20px;overflow:hidden}
.steps li{padding:24px 24px 26px}
.steps li + li{border-left:1px solid rgba(255,255,255,.14)}
.step-n{width:36px;height:36px;margin-bottom:14px;display:grid;place-items:center;border-radius:50%;background:var(--lime-bright);color:var(--forest-ink);font-size:.95rem;font-weight:700}
.steps h3{font-size:1.06rem;font-weight:600;letter-spacing:-.01em;color:#fff}
.steps p{margin-top:6px;font-size:.92rem;line-height:1.5}
/* lands like the other sections: the heading sits one section-padding below the nav */
.how{scroll-margin-top:calc(var(--nav-h) + clamp(56px,6vw,88px))}
.dark .sec-head{margin-bottom:clamp(28px,3vw,40px)}
.dark .sec-head h2{color:#fff}

/* ---------- team ---------- */
/* Its own page (/team/): a sage page with white cards. No hero, so the top
   padding clears the fixed nav. Photos sit in a white ring, and the social
   links are square icon buttons (the label is in each aria-label). */
.team-page{padding-top:calc(var(--nav-h) + clamp(40px,5vw,72px));background:var(--sage)}
.team-page .sec-head{max-width:760px}
.team-page .sec-head h1{font-size:clamp(2.5rem,4.4vw,3.75rem);font-weight:700;letter-spacing:-.035em;margin-bottom:18px}
.team-page .sec-head p{font-size:clamp(1.06rem,1.3vw,1.25rem)}
.team-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}
.team-card{display:flex;flex-direction:column;align-items:center;padding:clamp(32px,3vw,44px) clamp(24px,2.4vw,36px);text-align:center;background:var(--surface);border:1px solid rgba(13,95,51,.06);border-radius:var(--r-panel);box-shadow:0 1px 2px rgba(13,95,51,.04),0 18px 44px -18px rgba(13,95,51,.22);transition:box-shadow .35s}
.team-card:hover{box-shadow:0 1px 2px rgba(13,95,51,.05),0 28px 56px -20px rgba(13,95,51,.34)}
.team-avatar{width:clamp(128px,11vw,152px);aspect-ratio:1;margin-bottom:24px;border-radius:50%;overflow:hidden;background:var(--sage);border:5px solid #fff;box-shadow:0 0 0 1px rgba(13,95,51,.08),0 12px 28px -12px rgba(13,95,51,.4)}
.team-avatar img{width:100%;height:100%;object-fit:cover;transition:scale .5s var(--ease-out)}
.team-card:hover .team-avatar img{scale:1.07}
.team-avatar img.avatar-top{object-position:center 20%}
.team-card h2{margin-bottom:14px;font-size:clamp(1.2rem,1.5vw,1.375rem);font-weight:600;letter-spacing:-.015em}
.team-desc{font-size:1rem;line-height:1.6;color:var(--body)}
.team-links{display:flex;justify-content:center;gap:12px;margin-top:auto;padding-top:24px}
.team-links a{display:grid;place-items:center;width:40px;height:40px;border-radius:10px;border:1px solid rgba(33,127,68,.3);background:var(--surface);color:var(--btn-green);transition:background .2s,border-color .2s,color .2s}
.team-links a:hover{border-color:var(--green);color:var(--forest)}
/* Wide enough for three cards in a row: the page is one screen tall (the
   footer is left out) and never scrolls. The stage is whatever height the
   heading leaves; each card is as big as both the stage height and a third
   of its width allow, and everything inside scales with the card. At
   1920px wide the cards come out ~543px with ~186px photos. */
@media (min-width:1061px) and (min-height:560px){
  /* --team-k: card height / width (a touch taller than square, for the
     four-line bios); the cards spread wider than the site's 1200px column */
  .team-page{--team-max:1690px;--team-gap:30px;--team-k:1.03;--team-gutter:min(var(--gutter),5.6vw);display:flex;flex-direction:column;height:100vh;height:100svh;padding:calc(var(--nav-h) + clamp(20px,4.5vh,56px)) 0 clamp(24px,5vh,64px)}
  .team-page .wrap{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;width:100%;max-width:calc(var(--team-max) + 2 * var(--team-gutter));padding:0 var(--team-gutter)}
  .team-page .sec-head{margin-bottom:clamp(20px,4.5vh,52px)}
  .team-page .sec-head h1{font-size:clamp(2.1rem,min(4.4vw,7.2vh),3.75rem);margin-bottom:clamp(8px,1.6vh,18px)}
  /* never taller than a width-bound card, so on tall screens the heading
     and cards stay together, centred, instead of leaving a gap between */
  .team-stage{flex:1;min-height:0;max-height:calc((min(100vw,var(--team-max) + 2 * var(--team-gutter)) - 2 * var(--team-gutter) - 2 * var(--team-gap)) / 3 * var(--team-k));container-type:size}
  .team-grid{--side:min(calc((100cqw - 2 * var(--team-gap)) / 3),calc(100cqh / var(--team-k)));height:100%;gap:var(--team-gap);grid-template-columns:repeat(3,var(--side));justify-content:center;align-content:center}
  /* the padding is a share of the card's width; inside it, cqi is the
     card's content width (86% of the card) */
  .team-card{aspect-ratio:1 / var(--team-k);container-type:inline-size;padding:calc(var(--side) * .075) calc(var(--side) * .07) calc(var(--side) * .065)}
  .team-avatar{width:40cqi;margin-bottom:4.5cqi;border-width:1.2cqi}
  .team-card h2{margin-bottom:3.6cqi;font-size:5.5cqi}
  .team-desc{font-size:4cqi;line-height:1.55}
  .team-links{gap:2.6cqi;padding-top:3.6cqi}
  .team-links a{width:10.2cqi;height:10.2cqi;border-radius:2.4cqi}
  .team-links svg{width:4.4cqi;height:4.4cqi}
}
/* landing page: just the strip, where "Popular searches" used to be */
.partners-plain{padding:clamp(32px,4vw,56px) 0 clamp(24px,3vw,40px)}
/* each partner: logo, then its name beside it, read left to right */
.partners-plain .marquee-track,.partners-plain .marquee-list{gap:clamp(40px,5vw,72px)}
.partner{flex-shrink:0;display:flex;align-items:center;gap:16px;text-align:left}
.partner img{flex-shrink:0;width:72px;height:72px;object-fit:contain;transition:transform .45s var(--ease-out)}
.partner span{white-space:nowrap;font-size:.95rem;font-weight:600;line-height:1.35;color:var(--ink)}

/* ---------- faq ---------- */
.faq{border-top:1px solid var(--sage-line)}
.faq-item{border-bottom:1px solid var(--sage-line)}
.faq h3{font-size:inherit;letter-spacing:0}
.faq button{width:100%;display:flex;align-items:center;justify-content:space-between;gap:24px;padding:24px 0;background:none;border:0;cursor:pointer;text-align:left;font-size:clamp(1.06rem,1.4vw,1.25rem);font-weight:600;line-height:1.35;letter-spacing:-.01em;color:var(--ink)}
.faq button:hover{color:var(--forest)}
.faq .pm{color:var(--forest)}
.faq-body p{max-width:72ch;padding-bottom:26px;font-size:1rem;line-height:1.65}

/* ---------- footer ---------- */
footer{background:var(--forest-deep);color:#B9D6C4;padding:64px 0 30px}
/* the original three-column grid, kept after the Project column was removed
   so Quick links stays in its old spot beside the brand (third track empty) */
.foot-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:40px;margin-bottom:48px}
.foot-brand{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.foot-brand img{width:48px;height:48px;object-fit:contain;background:#fff;border-radius:50%;padding:6px}
.foot-brand span{font-weight:700;font-size:1.25rem;color:#fff}
.foot-grid p{font-size:.9rem;max-width:40ch}
.foot-h{margin-bottom:16px;font-size:.92rem;font-weight:600;letter-spacing:0;color:#fff}
.foot-links{display:flex;flex-direction:column;gap:10px;font-size:.9rem}
.foot-links a{transition:color .2s}
.foot-links a:hover{color:var(--lime-bright)}
.foot-bottom{padding-top:24px;border-top:1px solid rgba(255,255,255,.12);font-size:.82rem;color:#A9CBB5}

/* ---------- motion ---------- */
/* Everything here is scoped to html.anim, which the <head> gate only sets
   with IntersectionObserver and no reduced-motion preference. app.js adds
   .in when an element scrolls into view and sets --d, its stagger delay
   within the batch that entered together. Moving parts use the individual
   translate/scale properties so they never fight a component's own transform. */
.anim [data-reveal]{opacity:0;translate:0 24px}
.anim [data-reveal].in{opacity:1;translate:none}

/* hero: words rise out of their line, then the copy and search box follow */
.anim .hero h1 .w{display:inline-block;overflow:hidden;vertical-align:top;padding:0 .06em .12em;margin:0 -.06em -.12em}
.anim .hero h1 .w > span{display:inline-block;translate:0 110%;animation:rise-in .9s var(--ease-out) forwards;animation-delay:calc(var(--i) * 70ms + 80ms)}
.anim .hero-sub,.anim .hero .gsearch,.anim .hero-caption{opacity:0;animation:fade-up .8s var(--ease-out) forwards}
.anim .hero-sub{animation-delay:.45s}
.anim .hero .gsearch{animation-delay:.6s}
/* the photo settles in behind the copy on load */
.anim .hero-bg img{animation:settle 2.6s var(--ease-out) both}
@keyframes settle{from{scale:1.12}}
.anim .hero-caption{animation-delay:.75s}
@keyframes rise-in{to{translate:none}}
@keyframes fade-up{from{opacity:0;translate:0 18px}to{opacity:1;translate:none}}


/* hybrid engine card: the results screenshot drifts slowly, like someone reading down it */
.anim .feat.in .viz-shot img{animation:read-down 16s ease-in-out 1.2s infinite alternate}
@keyframes read-down{to{translate:-12% -90px}}

/* feature cards: each visual plays once as its card enters */
.anim .viz-keyword mark{background:linear-gradient(rgba(139,207,58,.45),rgba(139,207,58,.45)) no-repeat 0 0 / 0 100%;transition:background-size .6s ease calc(var(--d,0ms) + .5s)}
.anim .viz-keyword mark + mark{transition-delay:calc(var(--d,0ms) + .85s)}
.anim .feat.in .viz-keyword mark{background-size:100% 100%}
.anim .term,.anim .syn span,.anim .viz-dots .you{opacity:0;scale:.8;transition:opacity .4s ease,scale .5s cubic-bezier(.34,1.56,.64,1)}
.anim .term{transition-delay:calc(var(--d,0ms) + 1.1s)}
.anim .term + .term{transition-delay:calc(var(--d,0ms) + 1.2s)}
.anim .term + .term + .term{transition-delay:calc(var(--d,0ms) + 1.3s)}
.anim .feat.in .term,.anim .feat.in .syn span,.anim .feat.in .viz-dots .you{opacity:1;scale:1}
.anim .viz-chart svg{clip-path:inset(0 100% 0 0);transition:clip-path 1.5s var(--ease-out) calc(var(--d,0ms) + .3s)}
.anim .feat.in .viz-chart svg{clip-path:inset(0 0 0 0)}
.anim .viz-chart .pt{scale:0;transition:scale .5s cubic-bezier(.34,1.56,.64,1) calc(var(--d,0ms) + 1.4s)}
.anim .viz-chart .callout{opacity:0;translate:0 8px;transition:opacity .5s ease calc(var(--d,0ms) + 1.6s),translate .6s var(--ease-out) calc(var(--d,0ms) + 1.6s)}
.anim .feat.in .viz-chart .pt{scale:1}
.anim .feat.in .viz-chart .callout{opacity:1;translate:none}
.anim .feat.in .viz-chart .pt::after{content:"";position:absolute;inset:-6px;border-radius:50%;border:2px solid var(--btn-green);opacity:0;animation:halo 2.4s ease-out calc(var(--d,0ms) + 2s) infinite}
@keyframes halo{0%{opacity:.6;scale:.6}100%{opacity:0;scale:1.8}}
.anim .syn span{transition-delay:calc(var(--d,0ms) + .4s)}
.anim .syn .alt{transition-delay:calc(var(--d,0ms) + .8s)}
.anim .syn + .syn span{transition-delay:calc(var(--d,0ms) + .7s)}
.anim .syn + .syn .alt{transition-delay:calc(var(--d,0ms) + 1.1s)}
.anim .feat.in .syn i{display:inline-block;animation:nudge 2.6s ease-in-out calc(var(--d,0ms) + 1.6s) infinite}
@keyframes nudge{50%{scale:1.3}}
.anim .viz-stack span{opacity:0;translate:0 10px;transition:opacity .5s ease,translate .6s var(--ease-out)}
/* each row: the magnifier pops, then its title is revealed left to right */
.anim .viz-stack .mag{scale:0;transition:scale .45s cubic-bezier(.34,1.56,.64,1)}
.anim .viz-stack b{clip-path:inset(0 100% 0 0);transition:clip-path .8s var(--ease-out)}
.anim .viz-stack span:nth-child(1){transition-delay:calc(var(--d,0ms) + .3s)}
.anim .viz-stack span:nth-child(2){transition-delay:calc(var(--d,0ms) + .5s)}
.anim .viz-stack span:nth-child(3){transition-delay:calc(var(--d,0ms) + .7s)}
.anim .viz-stack span:nth-child(1) .mag{transition-delay:calc(var(--d,0ms) + .5s)}
.anim .viz-stack span:nth-child(2) .mag{transition-delay:calc(var(--d,0ms) + .7s)}
.anim .viz-stack span:nth-child(3) .mag{transition-delay:calc(var(--d,0ms) + .9s)}
.anim .viz-stack span:nth-child(1) b{transition-delay:calc(var(--d,0ms) + .65s)}
.anim .viz-stack span:nth-child(2) b{transition-delay:calc(var(--d,0ms) + .85s)}
.anim .viz-stack span:nth-child(3) b{transition-delay:calc(var(--d,0ms) + 1.05s)}
.anim .feat.in .viz-stack span{opacity:1;translate:none}
.anim .feat.in .viz-stack .mag{scale:1}
.anim .feat.in .viz-stack b{clip-path:inset(0 0 0 0)}
.anim .viz-dots circle{transform-box:fill-box;transform-origin:center}
.anim .viz-dots .near circle{opacity:0;transition:opacity .6s ease calc(var(--d,0ms) + .4s),translate 1.1s var(--ease-out) calc(var(--d,0ms) + .4s)}
.anim .viz-dots .near circle:nth-child(1){translate:-60px -30px}
.anim .viz-dots .near circle:nth-child(2){translate:60px -36px}
.anim .viz-dots .near circle:nth-child(3){translate:-50px 34px}
.anim .viz-dots .near circle:nth-child(4){translate:64px 30px}
.anim .feat.in .viz-dots .near circle{opacity:1;translate:none}
.anim .viz-dots .you{transition-delay:calc(var(--d,0ms) + 1.2s)}
/* the links draw once the matches have settled: spokes, then the ring between
   the matches, then out to the far titles */
.anim .viz-dots .links line{stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset .5s ease-out calc(var(--d,0ms) + 1.6s)}
.anim .viz-dots .links line:not(.spoke){transition-delay:calc(var(--d,0ms) + 2s)}
.anim .viz-dots .links .reach{transition:stroke-dashoffset .7s ease-out calc(var(--d,0ms) + 2.3s)}
.anim .feat.in .viz-dots .links line{stroke-dashoffset:0}
.anim .feat.in .viz-dots .ring{animation:breathe 3.2s ease-in-out calc(var(--d,0ms) + 1.4s) infinite}
.anim .feat.in .viz-dots .far circle{animation:twinkle 5s ease-in-out infinite alternate}
.anim .viz-dots .far circle:nth-child(2n){animation-duration:6.5s;animation-delay:-2s}
.anim .viz-dots .far circle:nth-child(3n){animation-duration:4.2s;animation-delay:-1s}
@keyframes breathe{50%{scale:1.08}}
@keyframes twinkle{to{opacity:.45}}

/* how it works: the boxes fade up in turn and each number pops in after its box */
.anim .steps li{opacity:0;translate:0 14px;transition:opacity .6s ease,translate .7s var(--ease-out),background .3s}
.anim .steps .step-n{scale:0;transition:scale .5s cubic-bezier(.34,1.56,.64,1),transform .3s var(--ease-out)}
.anim .steps li:nth-child(2){transition-delay:.15s,.15s,0s}
.anim .steps li:nth-child(3){transition-delay:.3s,.3s,0s}
.anim .steps li:nth-child(4){transition-delay:.45s,.45s,0s}
.anim .steps li:nth-child(1) .step-n{transition-delay:.25s,0s}
.anim .steps li:nth-child(2) .step-n{transition-delay:.4s,0s}
.anim .steps li:nth-child(3) .step-n{transition-delay:.55s,0s}
.anim .steps li:nth-child(4) .step-n{transition-delay:.7s,0s}
.anim .steps.in li{opacity:1;translate:none}
.anim .steps.in .step-n{scale:1}

/* ---------- scroll effects ---------- */
/* reading progress along the bottom edge of the nav (width set by app.js) */
.nav-progress{position:absolute;left:0;right:0;bottom:-1px;height:2px;pointer-events:none}
.nav-progress i{display:block;height:100%;background:var(--lime);transform:scaleX(0);transform-origin:left}
/* current section (aria-current, set by app.js) and hover share one underline */
.nav-links a{position:relative}
.nav-links a::after{content:"";position:absolute;left:12px;right:12px;bottom:3px;height:2px;border-radius:2px;background:var(--btn-green);transform:scaleX(0);transition:transform .3s var(--ease-out)}
.nav-links a:hover::after,.nav-links a[aria-current]::after{transform:none}
.nav-links a[aria-current]{color:var(--forest)}


/* headlines light up word by word; --f (0..1) comes from app.js */
.anim [data-scroll-fill] .sw{opacity:calc(.18 + .82 * var(--f, 0));transition:opacity .12s linear}

/* marquee: without motion it is a plain horizontally scrollable strip */
.marquee{overflow-x:auto;scrollbar-width:none;-webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.marquee::-webkit-scrollbar{display:none}
.marquee + .marquee{margin-top:12px}
.marquee-track{display:flex;gap:12px;width:max-content;padding:4px var(--gutter)}
.marquee-list{display:flex;gap:12px;flex-shrink:0}
.marquee-list[aria-hidden]{display:none}
.anim .marquee{overflow:hidden}
.anim .marquee-track{padding:4px 0;will-change:transform}
.anim .marquee-list[aria-hidden]{display:flex}

/* pointer tilt: --rx/--ry come from app.js, --lift from :hover below */
[data-tilt]{transform:perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) translateY(var(--lift,0px))}
/* one transition list for cards that both reveal and react to hover, so
   neither set of properties silently drops the other's */
[data-tilt][data-tilt],.anim [data-reveal]{transition:opacity .7s var(--ease-out) var(--d,0ms),translate .8s var(--ease-out) var(--d,0ms),transform .45s var(--ease-out),border-color .3s,box-shadow .35s,background-color .3s}

/* ---------- hover ---------- */
/* Pointer devices only, so a tap on a phone never leaves a card stuck lifted. */
@media (hover:hover){
  .btn-primary:hover{transform:translateY(-2px);box-shadow:0 12px 24px -12px rgba(33,127,68,.8)}
  .btn-ghost:hover{transform:translateY(-2px);background:var(--sage)}
  .brand img{transition:transform .5s var(--ease-out),box-shadow .35s}
  .brand:hover img{transform:rotate(-12deg) scale(1.06)}
  .feat:hover .viz-shot img{animation-play-state:paused}
  [data-tilt]:hover{--lift:-6px}
  .feat:hover .viz{border-color:var(--line-strong)}
  .metric:hover{border-color:rgba(255,255,255,.3);background-color:rgba(255,255,255,.08)}
  .steps li:hover{background:rgba(255,255,255,.045)}
  .steps li:hover .step-n{transform:scale(1.12)}
  .team-links a:hover{background:var(--btn-green);border-color:var(--btn-green);color:#fff}
  .partner:hover img{transform:rotate(-8deg) scale(1.06)}
  .faq button:hover > span{translate:6px 0}
  .faq button:hover .pm{background:var(--sage)}
  .foot-links a:hover{background-size:100% 1px}
}
.steps li{transition:background .3s}
.step-n{transition:transform .3s var(--ease-out)}
.faq button > span{transition:translate .3s var(--ease-out)}
.faq .pm{width:34px;height:34px;border-radius:50%;transition:transform .3s var(--ease-out),background .2s}
.foot-links a{background:linear-gradient(currentColor,currentColor) no-repeat 0 100% / 0 1px;transition:background-size .3s var(--ease-out),color .2s}

/* ---------- responsive ---------- */
/* the full bar (tagline + 5 links + 2 CTAs) needs ~1000px of content width */
@media (max-width:1180px){
  /* the brand may shrink (its tagline wraps) so the bar never overflows */
  .nav-inner{justify-content:space-between;gap:12px}
  .brand{min-width:0;flex-shrink:1}
  .nav-inner nav{flex:0}
  .nav-links{position:fixed;top:var(--nav-h);left:0;right:0;flex-direction:column;align-items:stretch;gap:4px;padding:14px var(--gutter) 22px;background:var(--surface);border-bottom:1px solid var(--sage-line);box-shadow:0 12px 24px -12px rgba(13,95,51,.18);transform:translateY(-130%);visibility:hidden;transition:transform .35s var(--ease-out),visibility 0s linear .35s}
  .nav-links.open{transform:none;visibility:visible;transition:transform .35s var(--ease-out),visibility 0s}
  .nav-links a{padding:12px 14px;font-size:1rem}
  .nav-drawer-only{display:block;border-top:1px solid var(--sage-line);margin-top:6px;padding-top:6px}
  .nav-drawer-only + .nav-drawer-only{border-top:0;margin-top:0;padding-top:0}
  .nav-drawer-signup a{color:var(--forest);font-weight:600}
  /* signed-out CTAs fold into the drawer; the signed-in destination stays */
  .nav-cta .btn:not(.nav-stay){display:none}
  .menu-toggle{display:block}
}
@media (max-width:1060px){
  .team-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .proof{grid-template-columns:repeat(2,minmax(0,1fr));max-width:880px;margin:0 auto}
  .steps{grid-template-columns:repeat(2,minmax(0,1fr))}
  .steps li + li{border-left:0}
  .steps li:nth-child(even){border-left:1px solid rgba(255,255,255,.14)}
  .steps li:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.14)}
  .feat-list{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:720px){
  :root{--gutter:20px}
  .team-grid,.steps,.feat-list{grid-template-columns:minmax(0,1fr)}
  .feat-list{gap:16px}
  .dark{padding:48px 0}
  .dark .sec-head{margin-bottom:24px}
  .dark .sec-head h2{font-size:1.75rem;margin-bottom:8px}
  .dark .sec-head p{font-size:1rem}
  /* each step one compact row: number beside the title, text under it */
  .steps li{display:grid;grid-template-columns:32px minmax(0,1fr);column-gap:14px;padding:16px 18px;border-left:0!important;border-bottom:1px solid rgba(255,255,255,.14)}
  .steps li:last-child{border-bottom:0}
  .step-n{grid-row:span 2;width:32px;height:32px;margin:0;font-size:.88rem}
  .steps h3{align-self:center}
  .steps p{margin-top:2px;font-size:.88rem}
  .bignum{margin:36px 0 20px}
  .bignum-n{font-size:3.25rem}
  .bignum-cap{margin-top:8px;font-size:.95rem}
  .proof{gap:10px}
  .metric{padding:16px;gap:8px}
  .team-grid{max-width:440px;margin:0 auto}
  .partner{gap:12px}
  .partner img{width:56px;height:56px}
  .partner span{font-size:.9rem}
  .gsearch-bar{height:52px;padding-left:16px}
  .gsearch-go{width:40px;height:40px}
  .gsearch-actions .btn{flex:1}
  .foot-grid{grid-template-columns:minmax(0,1fr);gap:32px}
}
@media (max-width:560px){
  /* every name on one line, so the four values line up: the font follows
     the card's width (cqi) so the longest, "Root Mean Square Error", fits */
  .metric{container-type:inline-size;padding-inline:12px}
  .metric-name{font-size:clamp(.56rem,8.4cqi,.85rem);white-space:nowrap}
  .metric-n{font-size:2rem}
  .metric-desc{display:none}
  /* the full name stays visible on phones: smaller, balanced over two lines */
  .brand{gap:8px}
  .brand-text small{font-size:.58rem;line-height:1.25;max-width:14em;text-wrap:balance}
  .nav-cta{gap:6px}
  .nav-cta .nav-stay{padding:8px 13px;font-size:.82rem}
  .nav-stay .lbl-long{display:none}
  .nav-stay .lbl-short{display:inline}
  .faq button{padding:20px 0}
}
