:root{
  --canvas:#e6e3e2;
  --cloud:#f2efed;
  --panel:rgba(255,255,255,.42);
  --panel-border:rgba(11,18,32,.14);
  --line:rgba(11,18,32,.22);
  --accent:#3fd6ff;
  --accent-hover:#6fe1ff;
  --accent-deep:#0a8fb8;
  --accent-muted:rgba(63,214,255,.22);
  --text-primary:#0b1220;
  --text-secondary:#26334a;
  --slate:#0b1220;
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-soft:cubic-bezier(.4,0,.2,1);
  --tshadow:0 1px 2px rgba(255,255,255,.55),0 6px 24px rgba(255,255,255,.45);
  /* the rendered width of the hero video under cover, anchored to its bottom edge */
  --vw-cover:max(100vw, 177.78vh);
  /* the strip's top band duplicates the bottom of the hero frame; this is that band's height at the video's scale */
  --overlap:calc(0.2544 * var(--vw-cover));
  /* each section's top and bottom padding, so two sections sit twice this apart (160px on desktop, 96px on phones) */
  --section-pad:clamp(48px,6vw,80px);
  --display:"Bricolage Grotesque",system-ui,sans-serif;
  --body:"Instrument Sans",system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,monospace;
}
*{box-sizing:border-box}
html,body{overflow-x:hidden;overflow-x:clip}
html{scroll-behavior:smooth}
body{margin:0;background:var(--canvas);color:var(--text-primary);font-family:var(--body);font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;opacity:0;transition:opacity .9s var(--ease-soft)}
body.ready{opacity:1}
h1,h2,h3{font-family:var(--display);line-height:1.02;letter-spacing:-.02em;margin:0;font-weight:800}
p{margin:0}
a{color:inherit}
code{font-family:var(--mono)}
.skip{position:absolute;left:-999px;top:8px;background:var(--slate);color:#fff;padding:10px 14px;border-radius:8px;z-index:100}
.skip:focus{left:12px}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:6px}
.wrap{width:min(1180px,calc(100% - 48px));margin:0 auto}
.kicker{font-family:var(--mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary);display:inline-flex;align-items:baseline;gap:10px}
.kicker::before{content:"";width:18px;height:2px;background:var(--accent-deep);align-self:center;border-radius:2px}
/* the pill: a silver face with an incandescent core that follows the pointer */
.pill{position:relative;display:inline-block;border-radius:999px;text-decoration:none;isolation:isolate;-webkit-tap-highlight-color:transparent;cursor:pointer;text-shadow:none}
.pill::after{content:"";position:absolute;inset:-7px -10px;border-radius:999px;background:radial-gradient(180px 54px at var(--fx,var(--pill-default-x,190px)) 50%,rgba(255,100,15,.88) 0%,rgba(250,70,10,.6) 28%,rgba(235,50,0,.3) 55%,rgba(200,30,0,.1) 78%,transparent 96%);filter:blur(8px) brightness(var(--glow-brightness,1));opacity:var(--glow-opacity,1);pointer-events:none;z-index:0}
.pill::before{content:"";position:absolute;inset:-4px -6px;border-radius:999px;background:radial-gradient(140px 46px at var(--fx,var(--pill-default-x,190px)) 50%,rgba(255,145,35,1) 0%,rgba(255,95,15,.92) 28%,rgba(245,55,0,.55) 58%,rgba(220,35,0,.18) 80%,transparent 96%);filter:blur(3.5px) brightness(var(--glow-brightness,1));opacity:var(--glow-opacity,1);pointer-events:none;z-index:0}
.pill-face{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;height:44px;padding:0 26px 0 24px;border-radius:999px;overflow:hidden;background-color:#cecfd4;background-image:linear-gradient(180deg,#d8d9de 0%,#c6c8cd 100%);box-shadow:inset 0 1px 1px rgba(255,255,255,.95),inset 0 -1px 1px rgba(0,0,0,.1),0 10px 30px rgba(11,18,32,.14);border:1px solid rgba(255,255,255,.55);color:#481e0c;transition:box-shadow .25s var(--ease-out)}
.pill-flare{position:absolute;left:0;top:50%;width:154px;height:50px;border-radius:50%;background:radial-gradient(ellipse at center,#ffffff 0%,#ffffff 20%,#fffef0 32%,#fff3cb 46%,#fed895 62%,rgba(255,195,115,.4) 78%,rgba(255,160,60,0) 100%);filter:blur(4px) brightness(var(--flare-brightness,1.45));opacity:var(--flare-opacity,1);pointer-events:none;z-index:1;transform:translate(calc(var(--fx,var(--pill-default-x,190px)) - 50%),-50%) scale(var(--orb-sx,.72),var(--orb-sy,.92));transition:transform .08s cubic-bezier(.2,.8,.4,1),filter .12s ease-out}
.pill-label{position:relative;z-index:2;font:500 12px/1 var(--body);letter-spacing:.075em;text-transform:uppercase;white-space:nowrap;color:#481e0c;display:inline-flex;align-items:center;gap:9px}
.pill-arrow{display:inline-block;font-size:14px;font-weight:600;line-height:1}
.pill:hover .pill-face{box-shadow:inset 0 1px 1px #ffffff,inset 0 -1px 1px rgba(0,0,0,.08),0 14px 36px rgba(11,18,32,.18)}
.pill:focus-visible{outline:2px solid var(--accent-deep);outline-offset:6px}
.pill:focus-visible .pill-face{outline:none}
.pill-sm .pill-face{height:36px;padding:0 20px 0 18px}
.pill-sm .pill-label{font-size:11px;letter-spacing:.06em}

/* the quiet secondary action */
.ghost{display:inline-flex;align-items:center;gap:9px;color:var(--text-primary);text-decoration:none;font:500 14.5px/1 var(--body);padding:12px 2px;border-bottom:1px solid rgba(11,18,32,.45);transition:border-color .28s var(--ease-soft),color .28s var(--ease-soft);text-shadow:none}
.ghost:hover{border-bottom-color:var(--accent-deep);color:var(--accent-deep)}
.ghost svg{width:14px;height:14px;flex:0 0 auto}
@media (pointer:coarse){.ghost{min-height:44px}}

/* nav */
.nav{position:fixed;top:0;left:0;right:0;z-index:50;height:68px;background:transparent;transition:background .3s var(--ease-soft),border-color .3s var(--ease-soft),backdrop-filter .3s var(--ease-soft)}
.nav.solid{background:rgba(242,239,237,.82);-webkit-backdrop-filter:saturate(150%) blur(14px);backdrop-filter:saturate(150%) blur(14px);border-bottom:1px solid rgba(11,18,32,.10)}
.nav-in{display:flex;align-items:center;gap:clamp(14px,2.4vw,34px);height:68px;position:relative}
.brand{display:inline-flex;align-items:center;gap:11px;text-decoration:none;color:var(--text-primary);font-family:var(--display);font-weight:800;font-size:17px;letter-spacing:-.015em;flex:0 0 auto;white-space:nowrap}
.brand .mark{width:34px;height:34px;display:block;flex:0 0 auto;--mark-accent:var(--accent-deep)}
.nav-links{display:flex;align-items:center;gap:clamp(14px,2.2vw,32px);margin:0 0 0 clamp(20px,3.6vw,56px);padding:0;list-style:none}
.nav-links a{display:inline-flex;align-items:center;color:var(--text-primary);text-decoration:none;font:400 14px/1.5 var(--body);padding:8px 4px;transition:color .2s var(--ease-soft),opacity .2s var(--ease-soft)}
.nav-links a:hover{color:var(--accent-deep)}
.nav-ext{width:11px;height:11px;margin-left:6px;flex:0 0 auto;opacity:.7}
.nav-cta{margin-left:auto;flex:0 0 auto}
.nav-try + .nav-cta{margin-left:calc(16px - clamp(14px,2.4vw,34px))}
.nav-star{display:inline-flex;align-items:center;gap:7px;color:var(--text-primary);font:400 14px/1.5 var(--body);text-decoration:none;white-space:nowrap;padding:8px 6px;transition:color .2s var(--ease-soft)}
.nav-star:hover{color:var(--accent-deep)}
.nav-star-gh{width:16px;height:16px;flex:0 0 auto;fill:currentColor;transition:transform .2s var(--ease-soft)}
.nav-star:hover .nav-star-gh{transform:scale(1.08)}
.nav-star .nav-window{fill:none;width:17px;height:17px}
.nav-toggle{display:none;margin-left:auto;align-items:center;gap:9px;height:40px;padding:0 14px;background:rgba(255,255,255,.35);border:1px solid rgba(11,18,32,.22);border-radius:10px;color:var(--text-primary);font:500 13px/1 var(--body);letter-spacing:.02em;cursor:pointer;transition:border-color .25s var(--ease-soft),background .25s var(--ease-soft)}
.nav-toggle:hover{background:rgba(255,255,255,.6);border-color:rgba(11,18,32,.4)}
.nav-toggle .bars{position:relative;display:block;width:16px;height:10px;flex:0 0 auto}
.nav-toggle .bars::before,.nav-toggle .bars::after{content:"";position:absolute;left:0;right:0;height:1.5px;background:currentColor;border-radius:2px;transition:transform .3s var(--ease-soft)}
.nav-toggle .bars::before{top:0}
.nav-toggle .bars::after{bottom:0}
.nav.open .nav-toggle .bars::before{transform:translateY(4.25px) rotate(45deg)}
.nav.open .nav-toggle .bars::after{transform:translateY(-4.25px) rotate(-45deg)}
@media (max-width:880px){
  .nav-links{position:absolute;top:68px;left:-24px;right:-24px;display:none;flex-direction:column;align-items:stretch;gap:0;margin:0;padding:8px 24px 18px;background:rgba(242,239,237,.96);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);border-bottom:1px solid rgba(11,18,32,.12);box-shadow:0 30px 64px rgba(11,18,32,.18)}
  .nav.open .nav-links{display:flex}
  .nav.open{background:rgba(242,239,237,.96)}
  body.menu-open::after{content:"";position:fixed;inset:0;z-index:40;background:rgba(11,18,32,.28);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
  .nav-links li + li{border-top:1px solid rgba(11,18,32,.12)}
  .nav-links a{display:flex;padding:14px 0;font-size:16px}
  .nav-toggle{display:inline-flex}
  .nav-cta{margin-left:14px}
}
@media (max-width:620px){.nav-toggle{height:42px}}
/* the demo and GitHub links move into the menu on phones, where the bar holds only the mark and the menu */
.nav-links .nav-phone{display:none}
.nav-phone svg{width:16px;height:16px;flex:0 0 auto;margin-right:10px;align-self:center}
@media (max-width:600px){.nav-star{display:none}.nav-links .nav-phone{display:list-item}}

/* hero */
.hero{position:relative;height:100vh;height:100svh;min-height:560px}
.hero .media{position:absolute;inset:0;overflow:hidden}
.hero .content,.hero .cue{z-index:3}
.hero video,.hero .poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 100%}
.hero .poster{background:url("hero-poster.jpg") center bottom/cover no-repeat}
.hero video{opacity:0;transition:opacity 1.4s var(--ease-soft)}
.hero.video-ready video{opacity:1}
.hero .content{position:absolute;inset:0;display:flex;align-items:center}
.hero .copy{max-width:680px;padding-top:40px;text-shadow:var(--tshadow)}
.hero h1{font-size:clamp(38px,5.6vw,84px);margin:18px 0 22px}
.hero h1 .w{display:inline-block}
.hero h1 .hw{display:block;font-size:1.22em;letter-spacing:-.035em;margin-bottom:.06em}
.hero h1 .tag{display:block;font-weight:600;max-width:13ch}
.hero .sub{font-size:clamp(17px,1.4vw,21px);color:var(--text-secondary);max-width:46ch;margin-bottom:34px}
.hero .actions{display:flex;gap:26px;flex-wrap:wrap;align-items:center}
.hero .cue{position:absolute;left:50%;bottom:26px;transform:translateX(-50%);font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary);display:flex;flex-direction:column;align-items:center;gap:8px}
.hero .cue i{width:1px;height:34px;background:linear-gradient(var(--text-secondary),transparent);display:block;animation:cue 2.6s ease-in-out -.8s infinite}
@keyframes cue{0%{transform:scaleY(.2);transform-origin:top;opacity:0}40%{transform:scaleY(1);opacity:1}100%{transform:scaleY(1);transform-origin:bottom;opacity:0}}
@media (max-height:560px){.hero .cue{display:none}}
/* hero entrance: each word drifts down into place */
.hero .copy>*{opacity:0;transform:translateY(-14px);transition:opacity 1.1s var(--ease-out),transform 1.1s var(--ease-out)}
.hero.in .copy>*{opacity:1;transform:none}
.hero.in .copy>:nth-child(2){transition-delay:.15s}
.hero.in .copy>:nth-child(3){transition-delay:.3s}
.hero.in .copy>:nth-child(4){transition-delay:.45s}
.hero.in .copy>:nth-child(5){transition-delay:.6s}
.hero .copy .w{opacity:0;transform:translateY(-.35em);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out);transition-delay:calc(.25s + var(--i,0)*.08s)}
.hero.in .copy .w{opacity:1;transform:none}

/* the cloud sea under the hero */
.sea{position:relative;z-index:2;margin-top:calc(-1 * var(--overlap));padding-top:var(--overlap);overflow:hidden;background:transparent}
.sea-bg{position:absolute;top:0;left:50%;transform:translateX(-50%);width:var(--vw-cover);height:100%;background:url("cloud-sea.jpg") top center/100% auto repeat-y;-webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 var(--overlap));mask-image:linear-gradient(to bottom,transparent 0,#000 var(--overlap));pointer-events:none}
/* static mist across the join and through the page (it used to drift; the drift forced every frosted panel to re-blur each frame) */
.mist{position:absolute;left:0;right:0;top:0;height:100%;pointer-events:none;overflow:hidden}
.mist i{position:absolute;display:block;width:60vw;height:24vh;border-radius:50%;background:radial-gradient(ellipse at center,rgba(255,255,255,.55),rgba(255,255,255,0) 70%);filter:blur(18px);opacity:.75}
.mist i:nth-child(1){top:calc(var(--overlap) - 14vh);left:-10vw}
.mist i:nth-child(2){top:calc(var(--overlap) + 6vh);left:30vw;width:50vw}
.mist i:nth-child(3){top:38%;left:10vw;width:70vw;opacity:.5}
.mist i:nth-child(4){top:70%;left:-5vw;width:55vw;opacity:.45}
.sea .wrap{position:relative;z-index:1}
/* the hero's lower part is already empty cloud, so 01 starts one --section-pad below it */
section.block{padding:var(--section-pad) 0}
.head{max-width:720px;margin-bottom:44px}
.head h2{font-size:clamp(32px,4.2vw,58px);margin:0 0 16px;max-width:16ch}
.head h2.h-wide{max-width:24ch;text-wrap:balance}
.head p{color:var(--text-secondary);max-width:52ch;font-size:18px}
.head.center{margin-left:auto;margin-right:auto;text-align:center}
.head.center h2,.head.center p{margin-left:auto;margin-right:auto}

/* the bento: each clip with the code it writes beside it, four dark boxes like the software itself, on three
   tracks (380 240 520 at full width). Top row: the canvas clip (filmed 760x406, 640 wide) and its pipeline code
   on the right (520, so most lines fit). Bottom row: the Polars clip (filmed 440x396, 380 wide) and its Polars
   code across the other two (780). Both clips come out 342 tall and set the rows' heights; a code panel
   (contain:size) only fills its row. */
.bento{display:grid;grid-template-columns:380fr 240fr 520fr;grid-template-areas:"canvas canvas canvas-code" "polars polars-code polars-code";gap:20px}
.at-canvas{grid-area:canvas}.at-polars{grid-area:polars}.at-canvas-code{grid-area:canvas-code}.at-polars-code{grid-area:polars-code}
.clip,.code-sync{overflow:hidden;border-radius:16px;border:1px solid rgba(255,255,255,.12);box-shadow:0 24px 60px -20px rgba(11,18,32,.5)}
.clip{position:relative;margin:0;display:flex;flex-direction:column;background:#131621}
.clip video{display:block;width:100%;object-fit:cover;background:#131621;cursor:pointer}
.at-canvas video{aspect-ratio:760/406}
.at-polars video{aspect-ratio:440/396}
/* the code a clip writes, in step with it: new lines type in over a fading highlight, and a long line wraps
   under its number rather than being cut off */
.code-sync{contain:size;display:flex;flex-direction:column;background:#0e1119}
.code-sync pre{position:relative;flex:1;min-height:0;margin:0;padding:14px 0;overflow:hidden;font-family:var(--mono);font-size:11.5px;line-height:1.62;color:#dfe6f0}
.code-sync .ln{display:flex;padding-right:16px}
.code-sync .ln i{flex:none;width:40px;padding-right:12px;text-align:right;font-style:normal;color:#48546a;user-select:none}
.code-sync .ln .tx{flex:1;min-width:0;white-space:pre-wrap;word-break:break-all}
.code-sync .ln.add{animation:code-glow 2.4s ease-out var(--d,0s) both}
.code-sync .ln.add .tx{animation:code-type calc(var(--n) * 14ms) steps(var(--n)) var(--d,0s) both}
@keyframes code-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes code-glow{from{background:rgba(63,214,255,.16)}to{background:rgba(63,214,255,0)}}
.tk-com{color:#6f7c91}.tk-num{color:#f4c989}
@media (max-width:820px){
  .bento{grid-template-columns:1fr;grid-template-areas:"canvas" "canvas-code" "polars" "polars-code"}
  .code-sync{height:250px}
  .code-sync pre{font-size:11px}
  .code-sync .ln i{width:32px;padding-right:10px}
}
/* a software clip plays only on screen; clicking it pauses it, and its play button shows only while it is
   paused or has keyboard focus */
.clip-toggle{position:absolute;inset:0;margin:auto;z-index:1;width:56px;height:56px;display:grid;place-items:center;border:0;border-radius:50%;
  background:rgba(11,18,32,.66);color:#fff;cursor:pointer;opacity:0;pointer-events:none;transition:opacity .25s var(--ease-soft)}
.clip-toggle:focus-visible,.clip.held .clip-toggle{opacity:1;pointer-events:auto}
.clip-toggle svg{width:20px;height:20px;fill:currentColor}
.clip-toggle .i-play,.clip.held .clip-toggle .i-pause{display:none}
.clip.held .clip-toggle .i-play{display:block}

.nowrap{white-space:nowrap}
/* performance: four numbered frosted cards, each a small line drawing of one mechanism that animates in
   with its card */
.perf{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.perf-card{padding:18px 20px 22px;background:var(--panel);border:1px solid var(--panel-border);border-radius:18px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);box-shadow:0 20px 60px rgba(11,18,32,.10)}
.perf-card h3{font-size:22px;margin:6px 0 8px}
.perf-card p{font-size:15px;line-height:1.5;color:var(--text-secondary)}
.perf-art{display:block;width:100%;height:auto;margin:0 0 14px;overflow:visible}
.perf-art text{font-family:var(--mono);font-size:10px;letter-spacing:.06em;fill:var(--text-secondary)}
/* 01: a wide table, and the four columns a step reads rising out of it */
.art-columns .cols rect{fill:rgba(11,18,32,.10)}
.art-columns .read rect{fill:var(--accent-deep);transform-box:fill-box;transform-origin:50% 100%;transform:scaleY(0)}
.perf.in .art-columns .read rect{animation:perf-rise .9s var(--ease-out) calc(.35s + var(--i) * .16s) forwards}
.art-columns .scan{stroke:rgba(11,18,32,.22);stroke-width:1.4}
@keyframes perf-rise{to{transform:scaleY(1)}}
/* 02: results upstream of an edit are kept; the edited step and what follows rerun */
.art-cache .link{stroke:rgba(11,18,32,.28);stroke-width:2}
.art-cache .kept{fill:var(--text-primary)}
.art-cache .redo{fill:#fff;stroke:var(--accent-deep);stroke-width:2.4}
.art-cache .edit{fill:none;stroke:var(--accent-deep);stroke-width:1.6;opacity:0;transform-box:fill-box;transform-origin:50% 50%}
.art-cache .brace{fill:none;stroke:rgba(11,18,32,.35);stroke-width:1.4}
.art-cache text{text-anchor:middle}
.perf.in .art-cache .edit{animation:perf-ping 2.8s ease-out 1s infinite}
.perf.in .art-cache .redo{animation:perf-redo 2.8s ease-in-out calc(1s + var(--i,0) * .3s) infinite}
@keyframes perf-ping{0%{opacity:.9;transform:scale(.7)}70%,100%{opacity:0;transform:scale(1.5)}}
@keyframes perf-redo{0%,60%,100%{fill:#fff}25%{fill:rgba(63,214,255,.45)}}
/* 03: slices flow through one at a time while memory stays flat */
.art-chunks .flow rect{fill:var(--text-primary);opacity:.85}
.perf.in .art-chunks .flow{animation:perf-flow 2.4s linear infinite}
.art-chunks .gate{stroke:var(--accent-deep);stroke-width:2;stroke-dasharray:3 4}
.art-chunks .mem{stroke:var(--accent-deep);stroke-width:2.6;stroke-linecap:round}
@keyframes perf-flow{to{transform:translateX(44px)}}
/* 04: one query fans out to eight lanes that fill side by side, then join */
.art-cores .fan{fill:none;stroke:rgba(11,18,32,.22);stroke-width:1.2}
.art-cores .lane rect{fill:rgba(11,18,32,.10)}
.art-cores .run rect{fill:var(--accent-deep);transform-box:fill-box;transform-origin:0 50%;transform:scaleX(0)}
.art-cores .end{fill:var(--text-primary)}
.art-cores .join{transform-box:fill-box;transform-origin:50% 50%}
.perf.in .art-cores .run rect{animation:perf-core 3.6s cubic-bezier(.3,.2,.5,1) calc(.4s + var(--d)) infinite}
.perf.in .art-cores .join{animation:perf-join 3.6s ease-out .4s infinite}
@keyframes perf-core{0%{transform:scaleX(0);opacity:1}50%{transform:scaleX(1);opacity:1}80%{opacity:1}94%,100%{transform:scaleX(1);opacity:0}}
@keyframes perf-join{0%,60%{fill:var(--text-primary);transform:scale(1)}68%{fill:var(--accent-deep);transform:scale(1.5)}90%,100%{fill:var(--text-primary);transform:scale(1)}}
/* trace: a take filmed to match the user's own screen recording, cropped to the app below its toolbar
   and then its top third (1920x628): the traced path on the canvas, its dashed lines moving, and the
   trace beside it easing up through the calculation, pausing on each large card */
.trace-clip video{aspect-ratio:1920/628}
/* modelling: a bento of five cards, each chart drawn the way a notebook draws it, with axes, legends and the
   demo's own factor names: train, tune and the efficient frontier across the top; the diagnostics (wide) and the
   model registry below. Every chart starts fully drawn; the reveals run only with motion on. Each card takes two
   rows of the grid, its chart and its text, on a subgrid, so the charts in a row share one height and the
   headings under them line up */
.ml{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:20px}
.ml-card{grid-column:span 4;grid-row:span 2;display:grid;grid-template-rows:subgrid;padding:12px 12px 22px;background:var(--panel);border:1px solid var(--panel-border);border-radius:18px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);box-shadow:0 20px 60px rgba(11,18,32,.10)}
.ml-card.rv:nth-child(2),.ml-card.rv:nth-child(5){transition-delay:.1s}
.ml-card.rv:nth-child(3){transition-delay:.2s}
.ml-card .txt{padding:0 8px}
.ml-card h3{font-size:22px;margin:0 0 8px}
.ml-card p{font-size:15px;line-height:1.5;color:var(--text-secondary)}
.ml-wide{grid-column:span 7}
.ml-reg{grid-column:span 5}
.ml-wide p{max-width:64ch}
.ml-panes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.ml-panes .ml-plot{padding:10px}
.ml-panes .ml-top{font-size:9.5px}
.ml-panes .ml-key{gap:4px 9px}
.ml-panes .ml-key i{margin-right:4px}
/* each chart sits on a brighter plot, headed by its name and legend */
.ml-plot{background:rgba(255,255,255,.6);border:1px solid rgba(11,18,32,.08);border-radius:12px;padding:10px 12px}
.ml-top{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 10px;margin-bottom:10px;font-family:var(--mono);font-size:10.5px;line-height:1.4;color:var(--text-secondary);white-space:nowrap}
.ml-top b{font-weight:500;color:var(--text-primary)}
.ml-key{display:inline-flex;flex-wrap:wrap;gap:4px 12px}
.ml-key i{display:inline-block;vertical-align:middle;position:relative;top:-1px;margin-right:5px;width:12px;height:2px;border-radius:2px}
.ml-key .k-dark{background:var(--text-primary)}
.ml-key .k-deep{background:var(--accent-deep)}
.ml-key .k-sq{width:8px;height:8px;border-radius:2px}
.ml-key .k-faint{background:rgba(11,18,32,.14)}
.ml-key .k-dot{width:7px;height:7px;border-radius:50%;background:var(--text-primary)}
.ml-key .k-ring{width:10px;height:10px;border-radius:50%;border:2px solid var(--accent-deep);background:#fff}
.ml-key .k-grad{width:34px;height:6px;border-radius:3px;margin:0 6px;background:linear-gradient(90deg,rgba(38,51,74,.4),var(--accent-deep))}
.ml-art{display:block;width:100%;height:auto;overflow:visible}
.ml-art text{font-family:var(--mono);font-size:9.5px;fill:var(--text-secondary)}
.ml-art .nm{font-size:10px;fill:var(--text-primary)}
.ml-art .tag{fill:var(--accent-deep)}
.ml-art .grid{stroke:rgba(11,18,32,.07);stroke-width:1}
.ml-art .axis{fill:none;stroke:rgba(11,18,32,.3);stroke-width:1.2}
.ml-art .pick{fill:#fff;stroke:var(--accent-deep);stroke-width:2.4}
.ml-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:12px;font-family:var(--mono);font-size:10.5px;line-height:1}
.ml-chips span{padding:5px 7px;border:1px solid rgba(11,18,32,.12);border-radius:6px;color:var(--text-secondary);background:rgba(255,255,255,.5)}
.ml-chips .on{background:var(--text-primary);border-color:var(--text-primary);color:#fff}
.ml-chips.params span{border-color:rgba(10,143,184,.35)}
.ml-chips b{font-weight:500;color:var(--accent-deep)}
/* 01: training and validation loss; the best iteration is where validation bottoms out */
.art-train .train,.art-train .valid{fill:none;stroke-width:2.2;stroke-linecap:round}
.art-train .train{stroke:var(--text-primary)}
.art-train .valid{stroke:var(--accent-deep)}
.art-train .best{stroke:rgba(10,143,184,.55);stroke-width:1.3;stroke-dasharray:3 4}
/* 02: the trials, and the best so far stepping down to the winner */
.art-tune .trials circle{fill:var(--text-primary);opacity:.5}
.art-tune .bestline{fill:none;stroke:var(--accent-deep);stroke-width:2;stroke-linejoin:round}
/* 04: double lift, a SHAP beeswarm coloured by the factor's value, and a GLM's relativities over exposure */
.art-lift .act{fill:var(--text-primary);opacity:.8}
.art-lift .exp{fill:var(--accent-deep)}
.art-shap .zero{stroke:rgba(11,18,32,.28);stroke-width:1;stroke-dasharray:2 3}
.art-shap .lo{fill:rgba(38,51,74,.4)}
.art-shap .md{fill:rgba(10,143,184,.55)}
.art-shap .hi{fill:var(--accent-deep)}
.art-ave .expo{fill:rgba(11,18,32,.1)}
.art-ave .exp{fill:none;stroke:var(--accent-deep);stroke-width:2;stroke-linejoin:round}
.art-ave .act{fill:none;stroke:var(--text-primary);stroke-width:1.6;stroke-linejoin:round}
.art-ave .pts circle{fill:#fff;stroke:var(--text-primary);stroke-width:1.6}
/* 05: the model registry, each model's version and the artifact its run logged */
.ml-reg .ml-plot{display:flex;flex-direction:column}
.ml-reg-t{flex:1 1 auto;width:100%;table-layout:fixed;border-collapse:collapse;font-family:var(--mono);font-size:10.5px;color:var(--text-primary)}
.ml-reg-t th{font-weight:400;font-size:9px;letter-spacing:.04em;color:rgba(38,51,74,.72);text-align:left;padding:0 8px 7px 0}
.ml-reg-t th:nth-child(1){width:30%}
.ml-reg-t th:nth-child(2){width:11%}
.ml-reg-t td{height:27px;padding:0 8px 0 0;border-top:1px solid rgba(11,18,32,.07);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ml-reg-t td:last-child{padding-right:0}
.ml-reg-t .ver{display:inline-block;padding:2px 6px;border:1px solid rgba(10,143,184,.35);border-radius:5px;font-size:10px;line-height:1.2;color:var(--accent-deep);background:rgba(255,255,255,.5)}
.ml-reg-t .doc{width:11px;height:13px;margin-right:6px;vertical-align:-2px;fill:none;stroke:var(--accent-deep);stroke-width:1.2;stroke-linejoin:round}
.ml-reg-t .file{font-size:9.5px;color:var(--text-secondary)}
/* 03: profit against volume; current prices sit inside the frontier, and the chosen point moves along it */
.art-frontier .area{fill:rgba(63,214,255,.09)}
.art-frontier .others circle{fill:rgba(11,18,32,.15)}
.art-frontier .curve{fill:none;stroke:var(--text-primary);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.art-frontier .fpts circle{fill:var(--text-primary)}
.art-frontier .shaft{fill:none;stroke:var(--accent-deep);stroke-width:1.4;stroke-dasharray:3 4;stroke-linecap:round}
.art-frontier .head{fill:none;stroke:var(--accent-deep);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.art-frontier .cur{fill:#fff;stroke:rgba(11,18,32,.55);stroke-width:1.6}
.art-frontier .lab{fill:var(--text-primary)}
.art-frontier .sel .ring{fill:#fff;stroke:var(--accent-deep);stroke-width:2.6}
.art-frontier .sel .halo{fill:rgba(63,214,255,.35);opacity:0;transform-box:fill-box;transform-origin:50% 50%}
@keyframes ml-draw{to{stroke-dashoffset:0}}
@keyframes ml-show{to{opacity:1}}
@keyframes ml-in{to{opacity:1;transform:none}}
@keyframes ml-pop{0%{opacity:0;transform:scale(.3)}70%{opacity:1;transform:scale(1.25)}100%{opacity:1;transform:scale(1)}}
@keyframes ml-trial{0%{opacity:0;transform:scale(0)}100%{opacity:.5;transform:scale(1)}}
@keyframes ml-halo{0%{opacity:.7;transform:scale(.5)}80%,100%{opacity:0;transform:scale(1.7)}}
@keyframes ml-choose{0%{opacity:0;transform:translate(158px,45.5px)}4%,30%{opacity:1;transform:translate(158px,45.5px)}32.2%{transform:translate(160.4px,46.4px)}34.4%{transform:translate(167.3px,49.2px)}36.6%{transform:translate(178px,53.9px)}38.8%{transform:translate(191.5px,60.6px)}41%{transform:translate(206.5px,69px)}43.2%{transform:translate(221.4px,78.6px)}45.4%{transform:translate(234.9px,88.1px)}47.6%{transform:translate(245.7px,96.4px)}49.8%{transform:translate(252.6px,102px)}52%,78%{opacity:1;transform:translate(254.9px,104px)}80.2%{transform:translate(252.6px,102px)}82.4%{transform:translate(245.7px,96.4px)}84.6%{transform:translate(234.9px,88.1px)}86.8%{transform:translate(221.4px,78.6px)}89%{transform:translate(206.5px,69px)}91.2%{transform:translate(191.5px,60.6px)}93.4%{transform:translate(178px,53.9px)}95.6%{transform:translate(167.3px,49.2px)}97.8%{transform:translate(160.4px,46.4px)}100%{opacity:1;transform:translate(158px,45.5px)}}
.art-frontier .sel{transform:translate(158px,45.5px)}
@media (prefers-reduced-motion:no-preference){
  .art-lift .rise,.art-ave .rise{transform-box:fill-box;transform-origin:50% 100%;transform:scaleY(0)}
  .ml-card.in .art-lift .rise,.ml-card.in .art-ave .rise{animation:perf-rise .9s var(--ease-out) calc(.3s + var(--i) * .07s) forwards}
  .art-train .train,.art-train .valid,.art-tune .bestline,.art-ave .exp,.art-ave .act,.art-frontier .curve{stroke-dasharray:300;stroke-dashoffset:300}
  .ml-card.in .art-train .train{animation:ml-draw 1.8s var(--ease-out) .3s forwards}
  .ml-card.in .art-train .valid{animation:ml-draw 1.8s var(--ease-out) .45s forwards}
  .art-train .best,.art-train .tag,.art-tune .tag{opacity:0}
  .ml-card.in .art-train .best,.ml-card.in .art-train .tag{animation:ml-show .5s ease-out 1.9s forwards}
  .art-train .pick,.art-tune .pick{opacity:0;transform-box:fill-box;transform-origin:50% 50%}
  .ml-card.in .art-train .pick{animation:ml-pop .5s var(--ease-out) 2.1s forwards}
  .art-tune .trials circle{opacity:0;transform-box:fill-box;transform-origin:50% 50%}
  .ml-card.in .art-tune .trials circle{animation:ml-trial .4s var(--ease-out) calc(.3s + var(--i) * .07s) forwards}
  .ml-card.in .art-tune .bestline{animation:ml-draw 2.6s linear .35s forwards}
  .ml-card.in .art-tune .pick{animation:ml-pop .5s var(--ease-out) 3s forwards}
  .ml-card.in .art-tune .tag{animation:ml-show .5s ease-out 3.1s forwards}
  .ml-chips.params span{opacity:0;transform:translateY(4px)}
  .ml-card.in .ml-chips.params span{animation:ml-in .5s var(--ease-out) 3.2s forwards}
  .ml-card.in .ml-chips.params span:nth-child(2){animation-delay:3.3s}
  .ml-card.in .ml-chips.params span:nth-child(3){animation-delay:3.4s}
  .art-shap circle{opacity:0;transform:translateX(var(--dx))}
  .ml-card.in .art-shap circle{animation:ml-in 1.2s var(--ease-out) calc(.4s + var(--r) * .12s) forwards}
  .ml-card.in .art-ave .exp{animation:ml-draw 1.4s var(--ease-out) .6s forwards}
  .ml-card.in .art-ave .act{animation:ml-draw 1.4s var(--ease-out) .8s forwards}
  .art-ave .pts circle{opacity:0;transform-box:fill-box;transform-origin:50% 50%}
  .ml-card.in .art-ave .pts circle{animation:ml-pop .4s var(--ease-out) calc(.8s + var(--i) * .1s) forwards}
  .ml-reg-t tbody tr{opacity:0;transform:translateY(-6px)}
  .ml-card.in .ml-reg-t tbody tr{animation:ml-in .6s var(--ease-out) calc(.3s + var(--i) * .18s) forwards}
  .ml-reg-t .file,.ml-reg-t .doc{opacity:0}
  .ml-card.in .ml-reg-t .file,.ml-card.in .ml-reg-t .doc{animation:ml-show .6s ease-out calc(1.1s + var(--i) * .18s) forwards}
  .art-frontier .others circle,.art-frontier .cur,.art-frontier .lab,.art-frontier .area,.art-frontier .moves,.art-frontier .sel{opacity:0}
  .ml-card.in .art-frontier .others circle{animation:ml-show .6s ease-out calc(.2s + var(--i) * .03s) forwards}
  .ml-card.in .art-frontier .cur,.ml-card.in .art-frontier .lab{animation:ml-show .6s ease-out .4s forwards}
  .art-frontier .fpts circle{opacity:0;transform-box:fill-box;transform-origin:50% 50%}
  .ml-card.in .art-frontier .fpts circle{animation:ml-pop .45s var(--ease-out) calc(.7s + var(--i) * .12s) forwards}
  .ml-card.in .art-frontier .curve{animation:ml-draw 1.6s var(--ease-soft) .8s forwards}
  .ml-card.in .art-frontier .area{animation:ml-show 1s ease-out 1.8s forwards}
  .ml-card.in .art-frontier .moves{animation:ml-show .6s ease-out 2.4s forwards}
  .ml-card.in .art-frontier .sel{animation:ml-choose 9s ease-in-out 2.8s infinite}
  .ml-card.in .art-frontier .sel .halo{animation:ml-halo 2.4s ease-out 3s infinite}
}
@media (max-width:980px){
  .ml{grid-template-columns:minmax(0,1fr);max-width:560px;margin:0 auto}
  .ml-card,.ml-wide,.ml-reg{grid-column:auto}
  .ml-panes{grid-template-columns:minmax(0,1fr)}
  .ml-art{max-width:400px;margin:0 auto}
}
@media (max-width:600px){
  /* too narrow for three columns: each model and its version on one line, its artifact under them */
  .ml-reg-t,.ml-reg-t tbody{display:block}
  .ml-reg-t thead{display:none}
  .ml-reg-t tr{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:5px 8px;padding:8px 0;border-top:1px solid rgba(11,18,32,.07)}
  .ml-reg-t tr:first-child{border-top:0;padding-top:0}
  .ml-reg-t td{height:auto;padding:0;border-top:0}
  .ml-reg-t td:last-child{grid-column:1/-1}
}
/* end modelling */
@media (max-width:1100px){.perf{grid-template-columns:repeat(2,1fr)}}
@media (max-width:600px){.perf{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){
  .art-columns .read rect{transform:none}
  .art-cores .run rect{transform:none}
}

/* release: the Git clip (2:1) and, beside it on the right, the CI/CD run read top to bottom; the run is
   sized to fit the clip's height */
.ship-row{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:20px;align-items:stretch}
.ship-clip video{aspect-ratio:2/1}
/* CI/CD: the three generated workflows as one run, animated by site.js on a loop while on screen: each job's
   data-run and data-done times make it spin, then pass; data-show times bring in the rest. Styled as GitHub
   Actions in its dark theme (GitHub's own colours, font and status icons), a dark card like the clip beside it */
.cicd{--gh-bg:#0d1117;--gh-border:#30363d;--gh-fg:#e6edf3;--gh-muted:#7d8590;--gh-green:#3fb950;--gh-button:#238636;--gh-amber:#d29922;
  display:flex;flex-direction:column;justify-content:space-between;padding:16px 20px;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif;
  background:var(--gh-bg);border:1px solid var(--gh-border);border-radius:16px;box-shadow:0 24px 60px -20px rgba(11,18,32,.5)}
.cicd-stage,.cicd-link{transition:opacity .5s var(--ease-soft)}
.cicd.reset .cicd-stage,.cicd.reset .cicd-link{opacity:.35}
.cicd-stage{display:flex;flex-direction:column;min-width:0}
.cicd-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.cicd-head{font-weight:600;font-size:14px;color:var(--gh-fg);white-space:nowrap}
.cicd-file{font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;font-size:12px;color:var(--gh-muted);white-space:nowrap}
/* GitHub's Run workflow button, turning into its green primary button when pressed */
.cicd-run{font-size:12px;font-weight:500;line-height:18px;padding:0 10px;border-radius:6px;border:1px solid rgba(240,246,252,.1);background:#21262d;
  color:#c9d1d9;transition:background .3s,color .3s,border-color .3s}
.cicd-run.on{background:var(--gh-button);border-color:rgba(240,246,252,.1);color:#fff}
.cicd-jobs{list-style:none;margin:7px 0 0;padding:0;display:flex;flex-direction:column;gap:3px}
.cicd-jobs.two{display:grid;grid-template-columns:1fr 1fr;gap:3px 12px}
.cicd-jobs li{position:relative;display:flex;align-items:center;gap:8px;min-height:21px;font-size:14px;color:var(--gh-muted);transition:color .3s}
.cicd-jobs li.run,.cicd-jobs li.done{color:var(--gh-fg)}
/* one after another: a thread joins the chain's status marks */
.cicd-jobs.chain li:not(:last-child):not(.cicd-trigger)::before{content:"";position:absolute;left:7.25px;top:18px;width:1.5px;height:calc(100% - 7px);background:var(--gh-border)}
/* GitHub's status icons: queued a hollow grey circle, in progress an amber ring turning, success a green circle
   with the check cut out */
.cicd-jobs .st{flex:none;position:relative;width:16px;height:16px;border-radius:50%;border:1.5px solid var(--gh-muted);box-sizing:border-box;background:transparent}
.cicd-jobs li.run .st{border:2px solid var(--gh-amber);border-right-color:transparent;animation:cicd-spin .8s linear infinite}
.cicd-jobs li.done .st{border-color:var(--gh-green);background:var(--gh-green)}
.cicd-jobs li.done .st::after{content:"";position:absolute;left:3.9px;top:1.4px;width:3.6px;height:7px;border:solid var(--gh-bg);border-width:0 2px 2px 0;transform:rotate(45deg)}
@keyframes cicd-spin{to{transform:rotate(360deg)}}
/* down from one stage to the next, under the status marks */
.cicd-link{display:block;width:16px;height:16px;margin:2px 0;overflow:visible}
.cicd-link path{fill:none;stroke:var(--gh-muted);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:100;stroke-dashoffset:100;transition:stroke-dashoffset .6s var(--ease-out)}
.cicd-link.on path{stroke-dashoffset:0}
/* the release tag, as GitHub shows a tag */
.cicd-tag{margin-left:auto;font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;font-size:12px;line-height:18px;padding:0 8px;border-radius:2em;
  border:1px solid var(--gh-border);color:var(--gh-muted);opacity:0;transform:translateY(3px);transition:opacity .4s,transform .4s var(--ease-out)}
.cicd-tag.on{opacity:1;transform:none}
@media (max-width:980px){.ship-row{grid-template-columns:1fr}}

/* code colours for the code panels (site.js tags the tokens) */
.tk-kw{color:#7cc9e6}.tk-fn{color:#f3f6fa}.tk-str{color:#b5e7f6}.tk-dec{color:#c9d2df}.tk-cls{color:#ffffff}.tk-op{color:#8b97a9}

/* install: a terminal on the cloud */
.term{max-width:640px;margin:0 auto;background:var(--slate);color:#dfe6f0;border-radius:16px;overflow:hidden;box-shadow:0 24px 60px rgba(11,18,32,.22)}
.term .bar{display:flex;gap:6px;padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.09)}
.term .bar i{width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.18)}
.term .bar i:first-child{background:var(--accent-deep)}
.term .body{padding:12px 12px 16px}
.term .row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 12px;border-radius:10px;transition:background .4s}
.term .row:hover{background:rgba(255,255,255,.04)}
.term .cmd{font-family:var(--mono);font-size:15px;color:#f3f6fa}
.term .cmd::before{content:"$";color:var(--accent-deep);margin-right:12px}
.term .cmd .caret{display:inline-block;width:8px;height:1.05em;background:#dfe6f0;vertical-align:-.15em;margin-left:6px;animation:blink 1.1s steps(2,start) infinite}
@keyframes blink{to{visibility:hidden}}
.copy-btn{font-family:var(--mono);font-size:12px;letter-spacing:.06em;padding:7px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.22);background:transparent;color:#c9d2df;cursor:pointer;transition:border-color .4s,color .4s,background .4s;min-width:82px}
.copy-btn:hover{border-color:#fff;color:#fff;background:rgba(255,255,255,.06)}
.copy-btn.ok{border-color:var(--accent);color:var(--accent)}
@media (pointer:coarse){.copy-btn{min-height:44px}}

/* cta, with the frontier surface faint behind it. The surface hangs from the section's middle, so the top
   padding stays 56px more than the bottom to keep the arc where it was placed around the headline */
.cta{text-align:center;padding:calc(var(--section-pad) * 2 + 56px) 0 calc(var(--section-pad) * 2);position:relative}
.cta .surface{position:absolute;left:50%;top:50%;width:min(640px,150vw);height:auto;aspect-ratio:1;color:var(--text-primary);--mark-accent:var(--accent-deep);transform:translate(-74%,-52.5%);opacity:0;pointer-events:none;transition:opacity 2.2s var(--ease-out),transform 2.2s var(--ease-out)}
.cta .rv.in~.surface,.cta.in .surface{opacity:.09;transform:translate(-74%,-56.5%)}
.cta .rv{position:relative;z-index:1}
.cta h2{font-size:clamp(36px,5vw,68px);max-width:14ch;margin:0 auto 22px;text-shadow:var(--tshadow)}
.cta .actions{display:flex;gap:26px;justify-content:center;flex-wrap:wrap;align-items:center}

/* footer */
footer{position:relative;z-index:2;background:var(--slate);color:#c9d2df;padding:56px 0 40px}
footer .wrap{display:flex;justify-content:space-between;gap:30px;flex-wrap:wrap;align-items:flex-start}
footer .brand{color:#fff}
footer .brand .mark{width:36px;height:36px;--mark-accent:var(--accent)}
footer ul{list-style:none;margin:0;padding:0;display:flex;gap:22px;flex-wrap:wrap}
footer a{color:#c9d2df;text-decoration:none;font-size:15px}
footer a:hover{color:#fff}
footer .fine a{font-size:inherit}
footer .fine{width:100%;margin-top:34px;padding-top:22px;border-top:1px solid rgba(255,255,255,.12);font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:#8b97a9;display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px}

/* reveals */
.rv{opacity:0;transform:translateY(22px);transition:opacity 1s var(--ease-out),transform 1s var(--ease-out)}
.rv.in{opacity:1;transform:none}
.rv .part{opacity:0;transform:translateY(16px);transition:opacity .9s var(--ease-out),transform .9s var(--ease-out)}
.rv.in .part{opacity:1;transform:none}
.rv.in .part:nth-child(2){transition-delay:.1s}.rv.in .part:nth-child(3){transition-delay:.2s}.rv.in .part:nth-child(4){transition-delay:.3s}.rv.in .part:nth-child(5){transition-delay:.4s}.rv.in .part:nth-child(6){transition-delay:.5s}
.rv.settled .part{transition-delay:0s!important}

body.paused *,body.paused *::before,body.paused *::after{animation-play-state:paused!important}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important;transition-delay:0s!important}
  body{opacity:1}
  .hero .copy>*,.hero .copy .w,.rv,.rv .part{opacity:1!important;transform:none!important}
  .cta .surface{opacity:.09;transform:translate(-74%,-56.5%)}
  html{scroll-behavior:auto}
}

/* sub pages: the cloud, a heading on it, and the copy in a frosted panel */
.sea.flat{margin-top:0;padding-top:0}
.sea.flat .sea-bg{-webkit-mask-image:none;mask-image:none}
.pg{padding:calc(68px + 12vh) 0 14vh;min-height:100vh;box-sizing:border-box}
.pg h1{font-size:clamp(38px,5.4vw,72px);max-width:14ch;margin:16px 0 36px}
.pg-actions{margin:-8px 0 36px}
.pg-panel{background:var(--panel);border:1px solid var(--panel-border);border-radius:24px;padding:clamp(26px,3.6vw,44px);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 20px 60px rgba(11,18,32,.10);max-width:860px}
.pg-panel .lede{font-size:18px;color:var(--text-secondary);max-width:52ch;margin-bottom:28px;padding-bottom:28px;border-bottom:1px solid var(--line)}
/* libraries: a card each (after Huly's pricing cards), topped by a small drawing of what the library
   does on a brighter plot, in the Performance cards' style: they draw in with the card, then each keeps
   one slow loop. Every drawing's resting state is its finished one, so reduced motion shows it whole */
/* three libraries fit one screen: less air above, the heading on one line where it fits */
.pg-libs{padding-top:calc(68px + 5vh);padding-bottom:6vh}
.pg-libs h1{max-width:none;margin:12px 0 28px}
.libs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(5,auto);column-gap:28px}
.lib-cell{grid-row:span 5;display:grid;grid-template-rows:subgrid}
.lib-cell.rv:nth-child(2){transition-delay:.1s}
.lib-cell.rv:nth-child(3){transition-delay:.2s}
.lib-card{grid-row:1/-1;display:grid;grid-template-rows:subgrid;padding:26px 28px 18px;background:var(--panel);border:1px solid var(--panel-border);border-radius:24px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);box-shadow:0 20px 60px rgba(11,18,32,.10)}
.lib-card h2{font-size:clamp(26px,2.4vw,32px)}
.lib-line{color:var(--text-secondary);font-size:15.5px;margin-top:8px}
.lib-list{list-style:none;margin:18px 0 0;padding:18px 0 0;border-top:1px solid var(--line);display:grid;gap:9px;align-content:start}
.lib-list li{position:relative;padding-left:26px;font-size:15px;line-height:1.4}
.lib-list li::before{content:"";position:absolute;left:2px;top:.3em;width:10px;height:5px;border-left:2px solid var(--accent-deep);border-bottom:2px solid var(--accent-deep);transform:rotate(-45deg)}
.lib-actions{align-self:end;display:flex;flex-wrap:wrap;gap:4px 24px;margin-top:14px}
.lib-plot{margin:-12px -14px 20px;padding:12px 12px 10px;background:rgba(255,255,255,.6);border:1px solid rgba(11,18,32,.08);border-radius:14px}
.lib-art{display:block;width:100%;height:auto;overflow:visible}
.lib-art .grid path{stroke:rgba(11,18,32,.07);stroke-width:1}
.lib-art .axis{fill:none;stroke:rgba(11,18,32,.3);stroke-width:1.2}
/* Haute: a small pipeline, its wires traced the way the canvas animates a trace */
.art-pipe .wires path{fill:none;stroke:rgba(11,18,32,.16);stroke-width:1.6}
.art-pipe .flow path{fill:none;stroke:var(--accent-deep);stroke-width:1.6;stroke-dasharray:4 4}
.art-pipe .node rect{fill:rgba(255,255,255,.95);stroke:rgba(11,18,32,.2);stroke-width:1.2}
.art-pipe .node path{fill:none;stroke:rgba(11,18,32,.28);stroke-width:2;stroke-linecap:round}
.art-pipe .model rect{stroke:var(--accent-deep)}
.art-pipe .model path:nth-of-type(1){stroke:var(--accent-deep)}
.art-pipe .out rect{fill:var(--text-primary);stroke:var(--text-primary)}
.art-pipe .out path{stroke:rgba(255,255,255,.55)}
.art-pipe .port circle{fill:#fff;stroke:rgba(11,18,32,.35);stroke-width:1.2}
/* RustyStats: a GLM's fit through the data, its iterations closing in on it */
.art-fit .pts circle{fill:var(--text-primary);opacity:.42}
.art-fit .it{fill:none;stroke:var(--accent-deep);stroke-width:1.3;stroke-dasharray:3 4;opacity:0}
.art-fit .fit{fill:none;stroke:var(--accent-deep);stroke-width:2.4;stroke-linecap:round}
/* Price Contour: the efficient frontier, drawn like the mark: the chosen point rides the curve, the
   dominated quotes fall away below it */
.art-front .dom circle{fill:var(--text-primary)}
.art-front .front{fill:none;stroke:var(--text-primary);stroke-width:2.2;stroke-linecap:round}
.art-front .pick{fill:#fff;stroke:var(--accent-deep);stroke-width:2.4;offset-path:path("M18 86C22 60 40 36 76 24S170 12 228 10");offset-distance:40%;offset-rotate:0deg}
@media (prefers-reduced-motion:no-preference){
  .lib-cell.in .art-pipe .node{animation:lib-pop .5s var(--ease-out) calc(.3s + var(--i) * .15s) both}
  .lib-cell.in .art-pipe .flow,.lib-cell.in .art-pipe .port{animation:lib-fade .6s ease-out .95s both}
  .lib-cell.in .art-pipe .flow path{animation:lib-flow 2s linear infinite}
  .lib-cell.in .art-fit .pts circle{animation:lib-pop .4s var(--ease-out) calc(.3s + var(--i) * .04s) both}
  .lib-cell.in .art-fit .it1{animation:lib-it1 9s ease-in-out 1.3s infinite both}
  .lib-cell.in .art-fit .it2{animation:lib-it2 9s ease-in-out 1.3s infinite both}
  .lib-cell.in .art-fit .it3{animation:lib-it3 9s ease-in-out 1.3s infinite both}
  .lib-cell.in .art-fit .fit{animation:lib-conv 9s ease-in-out 1.3s infinite both}
  .lib-cell.in .art-front .front{animation:lib-draw 1.6s var(--ease-out) .3s both}
  .lib-cell.in .art-front .dom circle{animation:lib-pop .4s var(--ease-out) calc(.7s + var(--i) * .05s) both}
  .lib-cell.in .art-front .pick{animation:lib-fade .5s ease-out 1.7s both,lib-ride 7s ease-in-out 2.2s infinite alternate}
}
.lib-art .node,.lib-art .pts circle,.lib-art .dom circle{transform-box:fill-box;transform-origin:50% 50%}
@keyframes lib-pop{from{opacity:0;transform:scale(.4)}}
@keyframes lib-fade{from{opacity:0}}
@keyframes lib-flow{to{stroke-dashoffset:-16}}
@keyframes lib-draw{from{stroke-dasharray:100;stroke-dashoffset:100}to{stroke-dasharray:100;stroke-dashoffset:0}}
@keyframes lib-ride{from{offset-distance:40%}to{offset-distance:80%}}
@keyframes lib-it1{0%{opacity:0}4%{opacity:.7}12%,84%{opacity:.25}94%,100%{opacity:0}}
@keyframes lib-it2{0%,9%{opacity:0}13%{opacity:.7}21%,84%{opacity:.25}94%,100%{opacity:0}}
@keyframes lib-it3{0%,18%{opacity:0}22%{opacity:.7}30%,84%{opacity:.25}94%,100%{opacity:0}}
@keyframes lib-conv{0%,26%{opacity:.25}34%,88%{opacity:1}100%{opacity:.25}}
.lib-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 24px;margin-top:20px;padding:14px 26px;background:var(--panel);border:1px solid var(--panel-border);border-radius:18px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.lib-foot p{color:var(--text-secondary)}
.lib-soon{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase}
@media (max-width:1080px){.libs{grid-template-columns:minmax(0,640px)}.lib-cell+.lib-cell{margin-top:24px}.lib-foot{max-width:640px}}
@media (max-width:600px){.lib-card{padding:24px 22px 18px}}
.legal h2{font-size:21px;font-weight:600;letter-spacing:-.01em;margin:30px 0 10px}
.legal .lede+h2{margin-top:0}
.legal p{color:var(--text-secondary);max-width:68ch}
.legal p+p{margin-top:12px}
.legal a{color:var(--text-primary);text-underline-offset:3px}
.legal code{font-family:var(--mono);font-size:.9em}
.pg-note{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-secondary);margin-top:30px;padding-top:22px;border-top:1px solid var(--line)}
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:28px}
.svc h2{font-size:22px;margin-bottom:8px;text-wrap:balance}
.svc p{color:var(--text-secondary);font-size:15.5px}
@media (max-width:820px){.svc-grid{grid-template-columns:1fr;gap:22px}}

/* playground: one frosted window on the cloud, which Haute opens in */
.pg-play h1{max-width:none;margin-bottom:32px}
.play{position:relative;display:flex;flex-direction:column;height:clamp(420px,58vh,620px);background:var(--panel);border:1px solid var(--panel-border);border-radius:18px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 20px 60px rgba(11,18,32,.10);overflow:hidden}
.play-bar{display:flex;align-items:center;gap:6px;min-height:46px;padding:0 14px;border-bottom:1px solid var(--panel-border)}
.play-bar>i{width:9px;height:9px;border-radius:50%;background:rgba(11,18,32,.18);flex:0 0 auto}
.play-bar>i:first-child{background:var(--accent-deep)}
.play-title{margin-left:8px;font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:var(--text-secondary);white-space:nowrap}
.play-tools{margin-left:auto;display:flex;align-items:center;gap:22px}
.play-timer{font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:var(--text-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}
.play-btn{font:500 13px/1 var(--body);color:var(--text-primary);background:none;border:0;border-bottom:1px solid rgba(11,18,32,.45);border-radius:0;padding:6px 1px;cursor:pointer;text-decoration:none;white-space:nowrap;transition:color .2s var(--ease-soft),border-color .2s var(--ease-soft)}
.play-btn:hover{color:var(--accent-deep);border-bottom-color:var(--accent-deep)}
.play-btn[hidden],.play-timer[hidden]{display:none}
/* full screen: the same window, filling the monitor */
.play:fullscreen{border-radius:0;border-width:0;background:var(--canvas)}
.play-body{position:relative;flex:1;display:grid;place-items:center;overflow:hidden}
.play-mark{position:absolute;left:50%;top:50%;width:900px;max-width:none;color:var(--text-primary);--mark-accent:var(--accent-deep);opacity:.08;transform:translate(-80%,-34.7%);pointer-events:none}
.play-mark path,.play-mark circle[stroke]{stroke-width:2.2}
.play-view{grid-area:1/1;display:none;flex-direction:column;align-items:center;text-align:center;padding:28px;position:relative}
.play[data-state=idle] .v-idle,.play[data-state=starting] .v-starting,.play[data-state=ended] .v-ended,.play[data-state=busy] .v-busy{display:flex}
.play[data-state=running] .v-running{display:block;position:absolute;inset:0;padding:0}
.play[data-state=starting] .play-mark,.play[data-state=running] .play-mark{display:none}
.play-start{display:inline-flex;align-items:center;justify-content:center;height:46px;padding:0 26px;border:0;border-radius:10px;background:var(--slate);color:#fff;font:500 15px/1 var(--body);letter-spacing:.01em;cursor:pointer;box-shadow:0 10px 30px rgba(11,18,32,.16);transition:background-color .2s var(--ease-soft)}
.play-start:hover{background:#1f2c44}
.play-small{display:none;margin-top:22px;font-size:15px;color:var(--text-secondary)}
/* starting: a spinner, shown only if the handover takes more than a moment */
.play[data-state=starting] .v-starting{animation:play-appear .3s .25s both}
.play-spinner{width:34px;height:34px;border-radius:50%;border:2.5px solid rgba(11,18,32,.14);border-top-color:var(--accent-deep);animation:play-spin .9s linear infinite}
.play-loading{margin-top:18px;font-size:16px;color:var(--text-secondary)}
@keyframes play-spin{to{transform:rotate(360deg)}}
@keyframes play-appear{from{opacity:0}}
@media (prefers-reduced-motion:reduce){.play-spinner{animation-duration:2.4s}}
.play-slot{position:absolute;inset:16px;border:1.5px dashed rgba(11,18,32,.28);border-radius:12px;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-secondary)}
.play-frame{position:absolute;inset:0;width:100%;height:100%;border:0;background:#fff}
.play-msg-h{font-size:clamp(28px,3vw,40px);margin-bottom:12px}
.play-msg{color:var(--text-secondary);max-width:44ch;margin-bottom:28px}
/* running: the window leaves the page and fills the screen under the nav */
body.playing{overflow:hidden}
body.playing .nav{background:rgba(242,239,237,.82);-webkit-backdrop-filter:saturate(150%) blur(14px);backdrop-filter:saturate(150%) blur(14px);border-bottom:1px solid rgba(11,18,32,.10)}
body.playing .play-head{visibility:hidden}
body.playing .play{position:fixed;top:80px;left:12px;right:12px;bottom:12px;height:auto;z-index:45}
@media (max-width:720px){
  .play{height:clamp(440px,64vh,560px)}
  .play-small{display:block}
  .play-mark{display:none}
  body.playing .play{top:68px;left:0;right:0;bottom:0;border-radius:0;border-width:0}
  body.playing .play-title{display:none}
}
