/* ═══════════════════════════════════════════════════════════════════════
   Cerevision v2 — pass 3

   Changes this pass, all from review:
     · Space Grotesk out, Figtree in. Grotesk's flat terminals read cold
       and "generated"; Figtree is rounder and carries real weight at 800
       and 900, which is what "softer and fatter" was asking for.
     · Type sizes up across the board.
     · The CTAs sit on a shaped plate with a blob behind them instead of
       floating loose under the copy.
     · The portfolio is four large cards driven one at a time by a pinned
       scroll, not a sixteen-up grid.
     · The process is a winding path with square nodes on it, not a row.

   NO `prefers-color-scheme: dark` ANYWHERE. Pass 1 shipped one by habit
   and the whole site rendered near-black on the reviewer's machine.
   ═══════════════════════════════════════════════════════════════════════ */

@font-face{font-family:"Fig";src:url(/assets/figtree.woff2) format("woff2");font-weight:300 900;font-display:swap}
@font-face{font-family:"Mono";src:url(/assets/jetbrains-mono.woff2) format("woff2");font-weight:100 800;font-display:swap}

:root{
  --sky-1:#E8ECFB; --sky-2:#F6E9EC; --sky-3:#DDEEEA; --sky-4:#EFEAF8;

  --card:#FCFBFE; --card-2:#F2F1F9;
  --ink:#141A3C; --ink-2:#5A6186; --ink-3:#9AA0BD; --line:#E4E4F2;

  --brand:#6260FF; --brand-2:#3447AA; --hot:#F5822A;
  --mint:#03363D; --sage:#BDD9D7; --blush:#FBEAEB; --lav:#E4E4FF;

  --r:20px; --r-lg:30px; --r-card:38px;
  --sh-sm:0 8px 24px -12px rgba(20,26,60,.24);
  --sh:0 26px 60px -30px rgba(20,26,60,.38);
  --sh-lg:0 50px 110px -46px rgba(20,26,60,.5);

  --pad:clamp(20px,4.5vw,68px);
  --maxw:1180px;
}

*,*::before,*::after{box-sizing:border-box}

/* [hidden] is a plain attribute selector, so ANY class that sets display
   beats it — .btn{display:inline-flex} and .sent{display:flex} both did,
   and both shipped visible while the markup said hidden. This makes the
   attribute win everywhere so the mistake cannot be made again. */
[hidden]{display:none!important}
/* Every icon in this project is an <i data-icon> holding an <svg>. The <i> was
   left inline, so the glyph sat on the text baseline instead of in the middle
   of whatever box it was put in — which is why icons all over the site looked
   a few pixels high, and why the ones inside a round or square plate sat in
   the corner of it. One rule, everywhere, rather than a width/height patch per
   component. */
/* The fallback nobody sees until the codec fails — dark ink on the dark
   player, which is exactly when you need to be able to read it. */
.film__fall{color:#EDEDF7;font-size:15px}
html{scroll-behavior:smooth}
body{
  margin:0;color:var(--ink);
  font-family:"Fig",system-ui,sans-serif;font-size:17.5px;line-height:1.6;font-weight:500;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
  padding:clamp(8px,1.5vw,20px);
}
/* The page background is a layer of its own, not the body's own paint.
 *
 * It was five gradients on the body with `background-attachment:fixed`. On a
 * desktop that is free. On iOS Safari `background-attachment:fixed` is the
 * classic scroll killer: the whole fixed image is re-resolved against the
 * scroll position as you move, and here that is five radial gradients over a
 * 16,000px document. Same picture, but as one fixed element the compositor
 * can hold still and never repaint.
 *
 * Elad reported the page catching on random sections while scrolling and I
 * could not reproduce it — not with wheel, touch, address-bar resizes or
 * frame timing, all of which came back clean in Chromium on a server. This is
 * the strongest remaining explanation that is specific to a real iPhone, and
 * it costs nothing to rule out. */
body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(58% 40% at 12% 4%,  var(--sky-4) 0%, transparent 62%),
    radial-gradient(52% 38% at 92% 12%, var(--sky-3) 0%, transparent 60%),
    radial-gradient(60% 42% at 82% 88%, var(--sky-2) 0%, transparent 64%),
    radial-gradient(56% 40% at 8%  76%, var(--sky-1) 0%, transparent 62%),
    linear-gradient(168deg,#EFF2FD 0%,#F7F1F2 42%,#EAF3F0 72%,#EEEAF9 100%);
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}

/* `clip`, not `hidden`. Both clip the decorative shapes to the rounded card,
   but `hidden` makes this a scroll container, and an ancestor scroll
   container silently kills `position:sticky` in every descendant — which is
   why the legal contents list never actually stuck to the side of the page
   however correct its own CSS looked. */
.shell{position:relative;background:var(--card);border-radius:var(--r-card);
  box-shadow:var(--sh-lg);overflow:clip}

.tab{position:absolute;top:0;left:clamp(14px,3vw,46px);z-index:40;background:var(--card);
  border-radius:0 0 var(--r) var(--r);padding:14px clamp(16px,2.4vw,28px) 15px;
  display:flex;align-items:center;gap:11px;box-shadow:var(--sh-sm)}
.tab img{width:30px;height:30px;border-radius:9px}
.tab span{font-weight:800;font-size:19.5px;letter-spacing:-.03em}

.nav{position:fixed;top:clamp(16px,2.4vw,32px);right:clamp(16px,3.2vw,50px);z-index:60;
  display:flex;align-items:center;gap:5px;padding:6px;background:rgba(20,26,60,.95);
  border-radius:999px;box-shadow:0 18px 40px -16px rgba(20,26,60,.55)}
.nav a{display:inline-flex;align-items:center;gap:8px;padding:11px 19px;border-radius:999px;
  font-size:14.5px;font-weight:700;color:rgba(255,255,255,.78);transition:background .22s,color .22s}
.nav a:hover{background:rgba(255,255,255,.13);color:#fff}
.nav .ghost{background:rgba(255,255,255,.12)}
.nav .cta{background:var(--hot);color:#fff}
.nav .cta:hover{background:#ff9440}
.nav a:focus-visible{outline:3px solid #fff;outline-offset:2px}
@media (max-width:1080px){ .nav a:not(.cta):not(.ghost){display:none} }
@media (max-width:820px){ .nav a:not(.cta){display:none} .nav{padding:5px} }

/* ──────────────────────────────────────────────────────── shared ── */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--pad)}
.h1{font-weight:900;font-size:clamp(52px,9.2vw,128px);line-height:.9;letter-spacing:-.05em;
  margin:0;text-wrap:balance}
.h2{font-weight:900;font-size:clamp(40px,7vw,92px);line-height:.94;letter-spacing:-.046em;
  margin:0;text-wrap:balance}
.h1 em,.h2 em{font-style:normal;color:var(--brand)}
.eyebrow{display:inline-flex;align-items:center;gap:9px;margin:0 0 22px;
  background:var(--lav);color:var(--brand-2);border-radius:999px;padding:9px 18px;
  font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase}
.lead{margin:24px 0 0;max-width:50ch;color:var(--ink-2);font-size:clamp(17px,2vw,20.5px)}

/* ── buttons: shaped, not default ────────────────────────────────── */
/* A pill on its own reads like a component library default. These sit on
   a plate with a blob behind them, and the primary is a squircle rather
   than a capsule, so the pair reads as drawn rather than picked. */
.ctaplate{position:relative;display:inline-flex;flex-wrap:wrap;gap:12px;align-items:center;
  margin-top:38px;padding:14px 16px;border-radius:26px;background:var(--card);
  box-shadow:var(--sh-sm);border:1.5px solid var(--line)}
.ctaplate__blob{position:absolute;z-index:0;width:120px;height:120px;left:-34px;bottom:-38px;
  background:var(--lav);border-radius:46% 54% 38% 62%/56% 42% 58% 44%;pointer-events:none}
.ctaplate>.btn{position:relative;z-index:1}

.btn{display:inline-flex;align-items:center;gap:10px;padding:18px 30px;
  border-radius:22px;font-weight:800;font-size:16.5px;letter-spacing:-.015em;
  border:2px solid transparent;
  transition:transform .28s cubic-bezier(.16,1,.3,1),box-shadow .28s,background .28s}
.btn--hot{background:var(--hot);color:#fff;box-shadow:0 12px 26px -10px rgba(245,130,42,.7)}
.btn--hot:hover{transform:translateY(-3px) rotate(-1deg);box-shadow:0 20px 38px -12px rgba(245,130,42,.8)}
.btn--ghost{border-color:var(--ink);color:var(--ink);background:transparent}
.btn--ghost:hover{transform:translateY(-3px) rotate(1deg);background:var(--ink);color:#fff}
.btn:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
/* The half-second between pressing Log in and the dashboard arriving. The
   button has to acknowledge the press, or the wait reads as a dead click. */
.btn.is-busy{pointer-events:none}
.btn.is-busy i{animation:btnGo .42s cubic-bezier(.16,1,.3,1) forwards}
@keyframes btnGo{to{transform:translateX(10px);opacity:0}}

.dash{position:absolute;pointer-events:none;overflow:visible}
.dash path{fill:none;stroke:var(--ink-3);stroke-width:2.6;stroke-linecap:round;
  stroke-dasharray:8 12;opacity:.5}
.dash circle{fill:var(--hot);stroke:var(--card);stroke-width:4}

/* ═══════════════════════════════════════════════════════ 01 · hero ══ */
.hero{position:relative;padding:clamp(120px,14vw,190px) 0 clamp(70px,9vw,110px);overflow:hidden}
.hero .wrap{position:relative;z-index:2}
.hero__grid{display:grid;grid-template-columns:1.32fr .68fr;gap:clamp(24px,5vw,60px);align-items:center}
.hero__sub{margin:28px 0 0;max-width:40ch;color:var(--ink-2);font-size:clamp(17px,2.1vw,22px)}

.shape{position:absolute;z-index:1;pointer-events:none}
.s1{top:14%;right:-3%;width:clamp(120px,15vw,240px);aspect-ratio:1;background:var(--lav);
    border-radius:44% 56% 52% 48%/48% 44% 56% 52%}
.s2{bottom:12%;right:15%;width:clamp(56px,7vw,108px);aspect-ratio:1;background:var(--hot);
    border-radius:28px;transform:rotate(18deg);opacity:.92}
.s3{top:22%;right:22%;width:clamp(38px,4.6vw,68px);aspect-ratio:1;background:var(--sage);border-radius:50%}
.hero__dash{top:8%;right:0;width:56%;height:84%;z-index:1}

.s4{bottom:26%;right:36%;width:clamp(26px,3vw,44px);aspect-ratio:1;background:var(--brand);
    border-radius:12px;transform:rotate(-14deg);opacity:.85}

/* the three true numbers */
.stats{list-style:none;margin:38px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:clamp(18px,3vw,42px)}
.stats li{display:flex;flex-direction:column;gap:2px}
.stats b{font-weight:900;font-size:clamp(30px,3.6vw,44px);letter-spacing:-.045em;line-height:1;
  color:var(--ink)}
.stats span{font-size:13.5px;font-weight:600;color:var(--ink-2);max-width:16ch;line-height:1.35}
.stats li:nth-child(1) b{color:var(--brand)}
.stats li:nth-child(2) b{color:var(--hot)}
.stats li:nth-child(3) b{color:#2FA89A}

/* the studio's own claims, as a band across the hero's foot */
.claims{position:relative;z-index:2;margin-top:clamp(46px,6vw,72px);
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(10px,1.6vw,18px)}
.claim{background:var(--card);border:2px solid var(--line);border-radius:22px;
  padding:20px 22px;box-shadow:var(--sh-sm);display:flex;flex-direction:column;gap:4px}
.claim b{font-weight:900;font-size:clamp(18px,2.1vw,24px);letter-spacing:-.032em}
.claim span{font-size:14px;color:var(--ink-2);font-weight:600}
.claim:nth-child(1){background:var(--lav);border-color:transparent}
.claim:nth-child(2){background:var(--blush);border-color:transparent}
.claim:nth-child(3){background:var(--sage);border-color:transparent}
@media (max-width:760px){ .claims{grid-template-columns:1fr} }

/* ── the examples, redesigned: a stack of real browser windows ──────── */
/* The tilted colour pills read as decoration. A browser chrome says
   "this is a site we shipped" without a caption. */
.hero__aside{position:relative;height:clamp(320px,36vw,430px)}
.win{position:absolute;left:0;right:0;border-radius:16px;overflow:hidden;
  background:var(--card);box-shadow:var(--sh);border:1.5px solid var(--line)}
.win__bar{display:flex;align-items:center;gap:6px;padding:9px 12px;background:var(--card-2);
  border-bottom:1px solid var(--line)}
.win__bar i{width:8px;height:8px;border-radius:99px;background:var(--ink-3);opacity:.45}
.win__url{margin-inline-start:8px;flex:1;height:16px;border-radius:99px;background:var(--card);
  border:1px solid var(--line);display:flex;align-items:center;padding:0 9px;
  font-family:"Mono",ui-monospace,monospace;font-size:8.5px;font-weight:700;color:var(--ink-3);
  letter-spacing:.04em;overflow:hidden;white-space:nowrap}
.win__body{height:clamp(96px,11vw,132px);position:relative;padding:16px 18px;
  display:flex;flex-direction:column;justify-content:flex-end}
.win__name{font-weight:900;font-size:clamp(17px,1.9vw,22px);letter-spacing:-.03em;color:#fff}
.win__tag{font-family:"Mono",ui-monospace,monospace;font-size:9px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.75);margin-top:3px}
.win.is-light .win__name{color:var(--ink)}
.win.is-light .win__tag{color:var(--ink-2)}
.win:nth-child(1){top:0;   transform:rotate(-3deg) translateX(-5%) scale(.93);z-index:1}
.win:nth-child(2){top:26%; transform:rotate(2deg)  translateX(6%);  z-index:2}
.win:nth-child(3){top:54%; transform:rotate(-1.5deg);               z-index:3}

/* ════════════════════════════════════════════════════ 02 · work ══ */
/* Pinned: the copy holds still on the left while one big card at a time
   is driven across the stage. Four, not sixteen. */
.work{position:relative;background:var(--card-2)}
.work__inner{max-width:var(--maxw);margin:0 auto;padding:clamp(70px,9vw,120px) var(--pad);
  display:grid;grid-template-columns:.85fr 1.15fr;gap:clamp(28px,5vw,64px);align-items:center;
  min-height:100svh}
.work__copy{position:relative;z-index:2}
.work__dots{display:flex;gap:8px;margin-top:34px}
.work__dots i{width:34px;height:5px;border-radius:99px;background:var(--line);transition:background .35s}
.work__dots i.on{background:var(--brand)}

.work__stage{position:relative;height:clamp(400px,52vw,560px)}
.pcard{
  position:absolute;inset:0;border-radius:var(--r-lg);overflow:hidden;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:clamp(24px,3.4vw,40px);box-shadow:var(--sh-lg);
}
.pcard__fill{position:absolute;inset:0;z-index:-2}
.pcard::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(146deg,rgba(255,255,255,.2) 0%,transparent 46%),
             linear-gradient(0deg,rgba(0,0,0,.5) 0%,transparent 58%)}
.pcard__tag{align-self:flex-start;font-family:"Mono",ui-monospace,monospace;font-size:10.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.9);
  background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.3);
  border-radius:999px;padding:6px 13px;margin-bottom:16px}
.pcard__name{font-weight:900;font-size:clamp(32px,4.4vw,58px);letter-spacing:-.04em;color:#fff;margin:0;line-height:1}
.pcard__body{margin:14px 0 0;max-width:42ch;color:rgba(255,255,255,.84);font-size:clamp(15px,1.6vw,18px)}
.pcard.is-light .pcard__name{color:var(--ink)}
.pcard.is-light .pcard__body{color:var(--ink-2)}
.pcard.is-light .pcard__tag{color:var(--ink-2);background:rgba(20,26,60,.07);border-color:rgba(20,26,60,.16)}
.pcard.is-light::after{background:linear-gradient(146deg,rgba(255,255,255,.5) 0%,transparent 46%)}

@media (max-width:900px){
  .work__inner{grid-template-columns:1fr;min-height:0}
  .work__stage{height:clamp(340px,84vw,460px)}
}

/* ═══════════════════════════════════════════════════ 03 · route ══ */
.route{position:relative;padding:clamp(80px,10vw,140px) 0 clamp(70px,9vw,120px)}
.route__head{text-align:center;margin-bottom:clamp(44px,6vw,76px)}
.route__head .eyebrow{margin-left:auto;margin-right:auto}

/* Four numbered circles down a path, cards alternating either side.
   The path is a real element with a real background, never an SVG — an SVG
   here lost its `fill:none` behind a stale stylesheet once and rendered as
   a solid black column down the middle of the page. */
.path{position:relative}
/* The path bows out between one circle and the next instead of running
   straight down — the winding-road shape, which is the whole reason this
   is a route and not a table. The circles stay on the centre line; it is
   the line between them that swings, so no card has to move to make room.
   Geometry is measured and written by drawPath() in site.js. */
.path__svg{position:absolute;inset:0;width:100%;height:100%;z-index:1;
  pointer-events:none;overflow:visible}
/* Dashed, like every other path drawn on this site. */
.path__base{stroke:var(--ink-3);stroke-width:2.6;stroke-linecap:round;
  stroke-dasharray:8 12;opacity:.45}
/* The travelled part. Its dash length is set in pixels by drawPath() from
   the curve's real length — it is NOT declared here.

   It used to say `stroke-dasharray:1 1` and lean on `pathLength="1"` to
   normalise that to the whole path. It did not: the computed value came
   out as a literal 1px dash on a 2000px line, so the "reveal" was a
   one-pixel shift and the line simply appeared, whole, which is exactly
   what it looked like. Measure the length, use the length. */
.path__lit{stroke:url(#pathgrad);stroke-width:4;stroke-linecap:round}

/* The alternation puts a gap between consecutive cards on its own — they are
   on opposite sides — so the row gap can be tight. Anything larger and the
   four steps stop reading as one route. */
.nodes{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;
  gap:clamp(12px,1.6vw,20px);position:relative;z-index:2}

/* Card, gutter for the circle, card. Odd steps take the left column and even
   the right; the circle always sits in the middle one, on the spine. */
/* The middle column is the road. It is wide because the line has to have
   somewhere to bend — at 120px the curve had about 20px of free space either
   side of the circles and read as a straight line with a wobble. */
.node{display:grid;grid-template-columns:1fr clamp(80px,16vw,240px) 1fr;align-items:center}
.node__card{grid-column:1;text-align:end;
  background:var(--card);border:2px solid var(--line);border-radius:26px;
  padding:clamp(22px,2.6vw,30px);box-shadow:var(--sh-sm);
  transition:transform .4s cubic-bezier(.16,1,.3,1),box-shadow .4s,border-color .4s}

/* ── each step arrives as the line reaches it ────────────────────── */
/* Only under `.is-anim`, which the script adds when it has actually taken
   charge of the reveal. Without GSAP, or with reduced motion, the class is
   never set and every step is simply there — the page is never left with
   its content hidden waiting for an animation that will not run. */
.route.is-anim .node__card{
  opacity:0;
  /* in from its own side, so the pair reads as opening away from the path */
  transform:translateX(-34px) scale(.97);
  transition:opacity .6s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
.route.is-anim .node--r .node__card{transform:translateX(34px) scale(.97)}
.route.is-anim .node.is-lit .node__card{opacity:1;transform:none}

.route.is-anim .node__dot{transform:scale(.4);opacity:0;
  transition:transform .55s cubic-bezier(.34,1.5,.5,1),opacity .3s,
             background .5s,border-color .5s,color .5s,box-shadow .5s}
.route.is-anim .node.is-lit .node__dot{opacity:1;transform:scale(1.06)}

/* The icon lands last, a beat after its card. */
.route.is-anim .node__ic{opacity:0;transform:translateY(8px) rotate(-8deg);
  transition:opacity .45s .18s,transform .55s .18s cubic-bezier(.34,1.5,.5,1),
             background .4s,color .4s}
.route.is-anim .node.is-lit .node__ic{opacity:1;transform:none}

/* The body and the meta follow the heading rather than all appearing at
   once — the card assembles instead of blinking on. */
.route.is-anim .node__t,
.route.is-anim .node__b,
.route.is-anim .node__meta{opacity:0;transform:translateY(10px);
  transition:opacity .5s cubic-bezier(.16,1,.3,1),transform .6s cubic-bezier(.16,1,.3,1)}
.route.is-anim .node.is-lit .node__t{opacity:1;transform:none;transition-delay:.1s}
.route.is-anim .node.is-lit .node__b{opacity:1;transform:none;transition-delay:.17s}
.route.is-anim .node.is-lit .node__meta{opacity:1;transform:none;transition-delay:.24s}

@media (prefers-reduced-motion:reduce){
  .route.is-anim .node__card,.route.is-anim .node__dot,.route.is-anim .node__ic,
  .route.is-anim .node__t,.route.is-anim .node__b,.route.is-anim .node__meta{
    opacity:1;transform:none;transition:none}
}
.node--r .node__card{grid-column:3;text-align:start}
.node__card:hover{box-shadow:var(--sh);transform:translateY(-4px)}
.node.is-lit .node__card{border-color:var(--c)}

/* The circle: the number is the marker, so the card does not repeat it. */
.node__dot{grid-column:2;grid-row:1;justify-self:center;z-index:3;
  width:clamp(54px,6.4vw,72px);aspect-ratio:1;border-radius:999px;
  display:flex;align-items:center;justify-content:center;
  background:var(--card);border:4px solid var(--line);color:var(--ink-3);
  box-shadow:var(--sh-sm);
  transition:background .5s cubic-bezier(.16,1,.3,1),border-color .5s,color .5s,transform .5s}
.node__dot b{font-family:"Mono",ui-monospace,monospace;font-weight:800;
  font-size:clamp(15px,1.7vw,19px);letter-spacing:-.02em}
/* Lit as the path reaches it — a filled rail running past a grey circle
   reads as a circle that failed to load. */
.node.is-lit .node__dot{background:var(--c);border-color:var(--card);color:#fff;
  transform:scale(1.06);box-shadow:0 14px 30px -10px var(--c)}

.node:nth-child(1){--c:var(--brand)}
.node:nth-child(2){--c:#C4574B}
.node:nth-child(3){--c:#2FA89A}
.node:nth-child(4){--c:var(--hot)}

.node__ic{display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:14px;background:var(--card-2);color:var(--c);
  margin-bottom:14px;transition:background .4s,color .4s}
.node__ic i{font-size:21px}
.node.is-lit .node__ic{background:var(--c);color:#fff}
.node__t{margin:0;font-weight:800;font-size:clamp(21px,2.4vw,29px);letter-spacing:-.034em}
.node__b{margin:10px 0 0;font-size:16.5px;line-height:1.6;color:var(--ink-2)}
/* Everything is visible at once now, so the meta row has to sit quietly
   under the body rather than compete with it. */
.node__meta{display:flex;flex-wrap:wrap;gap:10px 26px;margin:18px 0 0;padding-top:14px;
  border-top:1px solid var(--line);
  font-family:"Mono",ui-monospace,monospace;font-size:10.5px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--brand-2)}
.node__meta > div{display:flex;flex-direction:column;gap:3px}
.node--r .node__meta{justify-content:flex-start}
.node:not(.node--r) .node__meta{justify-content:flex-end}
.node__meta dt{opacity:.5;font-size:9px;color:var(--ink-3)}
.node__meta dd{margin:0}

@media (max-width:820px){
  /* Alternation needs two usable columns. Below this there is one, so the
     path moves to the left edge and every card hangs off the same side —
     the same route, read straight down. */
  /* The line is drawn through the circles wherever they are, so it needs no
     mobile position of its own — it follows them into the gutter. It only
     needs a much smaller bow down here, which drawPath() handles. */
  .path{--gut:clamp(26px,7vw,34px)}
  .node{grid-template-columns:var(--gut) 1fr;column-gap:clamp(20px,5vw,30px)}
  .node__card,.node--r .node__card{grid-column:2;text-align:start}
  .node__dot{grid-column:1;grid-row:1;justify-self:center;
    width:clamp(42px,11vw,52px)}
  .node__meta,.node:not(.node--r) .node__meta{justify-content:flex-start}
  .node__ic{width:38px;height:38px;border-radius:12px;margin-bottom:11px}
  .node__ic i{font-size:18px}
}

/* ═════════════════════════════════════════════════ 04 · promise ══ */
/* ── where the tint starts and stops ──────────────────────────────── */
/* The four tinted sections used to begin and end on a dead straight line
   across the page: the colour simply changed, mid-scroll, with nothing to
   explain it. These carve an arc of the card colour into each end of the
   tinted block, so the two colours meet on a curve — the tint starts later in
   the middle of the page than it does at the edges. It is one wide, very flat
   ellipse per edge, not an SVG, so it costs nothing and scales with the page.
   Every tinted section has an untinted one above and below it, which is what
   makes this work; if that alternation ever breaks, so does this. */
.promise,.film,.pricing,.contact{position:relative}
.promise::before,.film::before,.pricing::before,.contact::before,
.promise::after,.film::after,.pricing::after,.contact::after{
  content:"";position:absolute;left:-6%;width:112%;
  height:clamp(26px,5.5vw,62px);background:var(--card);pointer-events:none;z-index:2}
.promise::before,.film::before,.pricing::before,.contact::before{
  top:0;border-radius:0 0 50% 50% / 0 0 100% 100%}
.promise::after,.film::after,.pricing::after,.contact::after{
  bottom:0;border-radius:50% 50% 0 0 / 100% 100% 0 0}
/* The content has to clear the arcs it is sitting between. */
.promise > .wrap,.film > .wrap,.pricing > .wrap,.contact > .wrap{position:relative;z-index:3}

.promise{position:relative;padding:clamp(80px,10vw,140px) 0;background:var(--card-2);overflow:hidden}
.promise .wrap{position:relative;z-index:2}
.p1{top:-6%;left:-4%;width:clamp(150px,20vw,320px);aspect-ratio:1;background:var(--blush);
    border-radius:52% 48% 40% 60%/44% 58% 42% 56%}
.p2{bottom:-8%;right:-3%;width:clamp(120px,16vw,250px);aspect-ratio:1;background:var(--sage);
    border-radius:42% 58% 56% 44%/58% 44% 56% 42%}
/* Four items in an auto-fit grid gave three across and one orphan. A
   fixed 2×2 keeps it square at every width above the phone breakpoint. */
.promise__grid{margin-top:clamp(40px,5vw,64px);display:grid;
  grid-template-columns:repeat(2,1fr);gap:clamp(14px,2vw,22px)}
@media (max-width:760px){ .promise__grid{grid-template-columns:1fr} }
.pr{background:var(--card);border:2px solid var(--line);border-radius:26px;
  padding:clamp(24px,3vw,34px);box-shadow:var(--sh-sm);
  transition:transform .35s cubic-bezier(.16,1,.3,1),border-color .3s,box-shadow .35s}
.pr:hover{transform:translateY(-6px);border-color:var(--brand);box-shadow:var(--sh)}
.pr__ic{width:54px;height:54px;border-radius:17px;display:flex;align-items:center;justify-content:center;
  margin-bottom:18px}
.pr:nth-child(1) .pr__ic{background:var(--lav);color:var(--brand-2)}
.pr:nth-child(2) .pr__ic{background:var(--blush);color:#B4483F}
.pr:nth-child(3) .pr__ic{background:var(--sage);color:var(--mint)}
.pr:nth-child(4) .pr__ic{background:#FDEBD8;color:#B4651A}
.pr__ic i{font-size:25px}
.pr h3{margin:0;font-weight:800;font-size:clamp(20px,2.2vw,25px);letter-spacing:-.032em}
.pr p{margin:11px 0 0;color:var(--ink-2);font-size:16px;line-height:1.55}

/* ════════════════════════════════════════════════════ 05 · services ══ */
.services{position:relative;padding:clamp(80px,10vw,140px) 0}
.services__head{text-align:center;margin-bottom:clamp(40px,5vw,64px)}
.services__head .eyebrow{margin-left:auto;margin-right:auto}
.services__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,2vw,22px)}
@media (max-width:820px){ .services__grid{grid-template-columns:1fr} }
.svc{border-radius:26px;padding:clamp(26px,3vw,36px);border:2px solid transparent;
  transition:transform .35s cubic-bezier(.16,1,.3,1),box-shadow .35s}
.svc:hover{transform:translateY(-7px);box-shadow:var(--sh)}
.svc:nth-child(1){background:var(--lav)}
.svc:nth-child(2){background:var(--blush)}
.svc:nth-child(3){background:var(--sage)}
.svc__ic{width:56px;height:56px;border-radius:18px;background:rgba(255,255,255,.72);
  display:flex;align-items:center;justify-content:center;margin-bottom:20px;color:var(--ink)}
.svc__ic i{font-size:26px}
.svc h3{margin:0;font-weight:900;font-size:clamp(21px,2.3vw,27px);letter-spacing:-.034em}
.svc p{margin:11px 0 0;color:var(--ink-2);font-size:16px;line-height:1.55}

/* ════════════════════════════════════════════════════════ 05 · film ══ */
.film{position:relative;padding:clamp(80px,10vw,140px) 0;background:var(--card-2);overflow:hidden}
.f1{top:-10%;left:-6%;width:clamp(160px,22vw,340px);aspect-ratio:1;background:var(--lav);
    border-radius:50% 50% 38% 62%/48% 56% 44% 52%}
.film__head{position:relative;z-index:2;text-align:center;margin-bottom:clamp(36px,4.5vw,58px)}
.film__head .eyebrow{margin-left:auto;margin-right:auto}
.film__steps{position:relative;z-index:2;list-style:none;margin:clamp(24px,3vw,38px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(10px,1.4vw,16px);counter-reset:fs}
@media (max-width:820px){ .film__steps{grid-template-columns:1fr 1fr} }
@media (max-width:480px){ .film__steps{grid-template-columns:1fr} }
.film__steps li{counter-increment:fs;background:var(--card);border:2px solid var(--line);
  border-radius:18px;padding:16px 18px;display:flex;flex-direction:column;gap:5px}
.film__steps li::before{content:counter(fs,decimal-leading-zero);
  font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;color:var(--brand)}
.film__steps b{font-weight:800;font-size:16.5px;letter-spacing:-.024em}
.film__steps span{font-size:14px;color:var(--ink-2);line-height:1.45}

/* ═════════════════════════════════════════════════════ 06 · pricing ══ */
.pricing{position:relative;padding:clamp(80px,10vw,140px) 0;background:var(--card-2)}
.pricing__grid{margin-top:clamp(40px,5vw,64px);display:grid;
  grid-template-columns:repeat(2,1fr);gap:clamp(16px,2.4vw,26px);align-items:stretch}
@media (max-width:820px){ .pricing__grid{grid-template-columns:1fr} }
/* `align-items:start` on the grid let each card be its own height, so the two
   plans sat at different lengths and read as lopsided. They stretch to match
   now, and the card is a column so its button is pinned to the bottom of
   whichever card is taller — that is what makes the pair look deliberate. */
.plan{background:var(--card);border:2px solid var(--line);border-radius:30px;
  padding:clamp(28px,3.4vw,42px);box-shadow:var(--sh-sm);position:relative;
  display:flex;flex-direction:column}
.plan ul{flex:1}
.plan .btn{align-self:stretch;justify-content:center;margin-top:auto}
.plan.is-featured{border-color:var(--ink);box-shadow:var(--sh)}
.plan__flag{position:absolute;top:-13px;inset-inline-end:26px;background:var(--hot);color:#fff;
  border-radius:99px;padding:6px 15px;font-family:"Mono",ui-monospace,monospace;
  font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase}
.plan h3{margin:0;font-weight:900;font-size:clamp(24px,2.7vw,32px);letter-spacing:-.036em}
.plan__price{margin:6px 0 0;font-weight:900;font-size:clamp(34px,4.4vw,54px);
  letter-spacing:-.046em;line-height:1;color:var(--brand)}
.plan.is-featured .plan__price{color:var(--hot)}
.plan__lede{margin:14px 0 0;color:var(--ink-2);font-size:16.5px}
.plan ul{list-style:none;margin:22px 0 26px;padding:0;display:flex;flex-direction:column;gap:11px}
.plan li{display:flex;gap:11px;align-items:flex-start;font-size:16px;color:var(--ink-2)}
.plan li i{color:#2FA89A;font-size:19px;flex-shrink:0;margin-top:1px}

/* ═════════════════════════════════════════════════════════ 07 · faq ══ */
.faq{padding:clamp(80px,10vw,140px) 0}
.faq__inner{display:grid;grid-template-columns:.75fr 1.25fr;gap:clamp(30px,5vw,64px);align-items:start}
@media (max-width:900px){ .faq__inner{grid-template-columns:1fr} }
.faq__all{display:inline-flex;align-items:center;gap:9px;margin-top:26px;
  font-weight:800;font-size:16.5px;color:var(--brand);
  border-bottom:2px solid transparent;transition:border-color .25s,gap .25s}
.faq__all:hover{border-color:var(--brand);gap:13px}
.faq__all i{font-size:18px}

/* Open, not collapsed. Four short answers behind four clicks was four
   clicks to read the thing the section exists to say. */
/* One column, one answer at a time. The 2x2 of outlined boxes put all four
   answers on screen at once and the questions had to fight them for
   attention. */
.faq__list{display:flex;flex-direction:column}
.fq{border-top:1px solid var(--line);position:relative}
.fq:last-child{border-bottom:1px solid var(--line)}
/* The open one is marked on the edge rather than by a box: a rail that grows
   out of the hairline it was already sitting on. */
.fq::before{content:"";position:absolute;inset-inline-start:0;top:0;bottom:0;width:2px;
  background:var(--brand);transform:scaleY(0);transform-origin:top;
  transition:transform .5s cubic-bezier(.32,.72,0,1)}
.fq.on::before{transform:scaleY(1)}
.fq__q{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:clamp(14px,2vw,22px);width:100%;text-align:start;border:0;background:none;
  font:inherit;cursor:pointer;color:var(--ink);
  padding:clamp(18px,2.2vw,26px) clamp(6px,1vw,14px);
  font-weight:800;font-size:clamp(17px,1.9vw,21px);letter-spacing:-.028em;
  transition:padding-inline-start .5s cubic-bezier(.32,.72,0,1),color .3s}
.fq.on .fq__q,.fq__q:hover{padding-inline-start:clamp(16px,1.8vw,24px)}
.fq__q:hover{color:var(--brand-2)}
.fq__q:focus-visible{outline:3px solid var(--brand);outline-offset:-3px;border-radius:12px}
.fq__n{font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;
  letter-spacing:.14em;color:var(--ink-3);transition:color .3s}
.fq.on .fq__n{color:var(--brand)}
/* a plus that becomes a minus, rather than a chevron that spins */
.fq__x{position:relative;width:26px;height:26px;border-radius:99px;flex-shrink:0;
  background:var(--card-2);transition:background .35s cubic-bezier(.32,.72,0,1)}
.fq.on .fq__x{background:var(--lav)}
.fq__x i{position:absolute;top:50%;left:50%;width:11px;height:2px;border-radius:2px;
  background:var(--ink-2);transform:translate(-50%,-50%);
  transition:transform .45s cubic-bezier(.32,.72,0,1),background .35s}
.fq__x i:last-child{transform:translate(-50%,-50%) rotate(90deg)}
.fq.on .fq__x i{background:var(--brand)}
.fq.on .fq__x i:last-child{transform:translate(-50%,-50%) rotate(0deg)}
.fq__a{height:0;overflow:hidden;transition:height .55s cubic-bezier(.32,.72,0,1)}
.fq__a p{margin:0;padding:0 clamp(6px,1vw,14px) clamp(20px,2.4vw,28px)
  clamp(42px,5vw,62px);color:var(--ink-2);font-size:16px;line-height:1.65;max-width:62ch}
@media (max-width:620px){ .fq__a p{padding-inline-start:clamp(6px,1vw,14px)} }

/* ═════════════════════════════════════════════════════ 08 · contact ══ */
.contact{position:relative;padding:clamp(80px,10vw,150px) 0;background:var(--card-2);overflow:hidden}
.c1{top:-8%;right:-5%;width:clamp(180px,24vw,380px);aspect-ratio:1;background:var(--lav);
    border-radius:48% 52% 42% 58%/56% 44% 56% 44%}
.contact__inner{position:relative;z-index:2;display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(30px,5vw,64px);align-items:center}
/* The steps run under both columns, so the row above them is the pair and
   nothing has to stretch to match the other's height. */
.contact__inner > .applysteps{align-self:start}
@media (max-width:900px){ .contact__inner{grid-template-columns:1fr} }
.form{background:var(--card);border:2px solid var(--line);border-radius:30px;
  padding:clamp(24px,3vw,36px);box-shadow:var(--sh);display:flex;flex-direction:column;gap:14px}
.form__row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:460px){ .form__row{grid-template-columns:1fr} }
.form label{display:flex;flex-direction:column;gap:7px;font-size:13.5px;font-weight:700;
  color:var(--ink-2)}
.form input,.form textarea{font:inherit;font-size:16px;font-weight:500;color:var(--ink);
  background:var(--card-2);border:2px solid var(--line);border-radius:15px;padding:13px 15px;
  transition:border-color .25s,background .25s;resize:vertical}
.form input:focus,.form textarea:focus{outline:none;border-color:var(--brand);background:var(--card)}
/* 2 Sep: required-field validation on the apply wizard — a field goes red
   and shakes once when Continue/Send is pressed with it empty (or, for
   email, not shaped like one); back.js clears it the moment the field is
   corrected rather than waiting for a second rejection. */
.form input.is-bad,.form textarea.is-bad{border-color:#B3261E;animation:formshake .4s}
@keyframes formshake{
  25%{transform:translateX(-5px)}50%{transform:translateX(5px)}75%{transform:translateX(-3px)}
}
.form .btn{justify-content:center;margin-top:4px}
.form__note{margin:0;font-family:"Mono",ui-monospace,monospace;font-size:10.5px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);text-align:center}
.form__lede{margin:0 0 4px;font-size:14.5px;line-height:1.55;color:var(--ink-2)}
.form__lede b{color:var(--ink);font-weight:800}
.form__err{margin:0;font-size:13.5px;font-weight:700;color:#B3261E}
/* The confirmation replaces the form rather than sitting under it: the thing
   you were doing is finished, and leaving the fields there invites a second
   send of the same message. */
.form__ok{display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;
  padding:clamp(14px,2vw,26px) 0}
.form__ok i{width:52px;height:52px;border-radius:99px;display:flex;align-items:center;
  justify-content:center;background:var(--sage);color:var(--mint)}
.form__ok svg{width:24px;height:24px}
.form__ok b{font-size:20px;font-weight:900;letter-spacing:-.035em}
.form__ok p{margin:0;font-size:14.5px;line-height:1.6;color:var(--ink-2);max-width:34ch}
.form__ok .btn{margin-top:4px}

/* The four steps after the button. They had no styles at all — a browser's
   own numbered list, with each title running straight into its body text. */
.applysteps{grid-column:1/-1;list-style:none;margin:clamp(34px,5vw,60px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2.4vw,32px);
  counter-reset:ap;border-top:1px solid var(--line);padding-top:clamp(22px,3vw,34px)}
.applysteps li{display:flex;flex-direction:column;gap:5px}
.applysteps li::before{counter-increment:ap;content:counter(ap,decimal-leading-zero);
  font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;
  letter-spacing:.14em;color:var(--brand);margin-bottom:3px}
.applysteps b{font-weight:800;font-size:16px;letter-spacing:-.024em}
.applysteps span{font-size:14px;line-height:1.55;color:var(--ink-2)}
@media (max-width:900px){ .applysteps{grid-template-columns:1fr 1fr} }
@media (max-width:520px){ .applysteps{grid-template-columns:1fr;gap:18px} }

.foot{padding:clamp(48px,6vw,80px) 0 clamp(28px,3vw,40px);border-top:1px solid var(--line)}
.foot__top{display:grid;grid-template-columns:1fr 1.4fr;gap:clamp(28px,4vw,60px);
  padding-bottom:clamp(30px,4vw,48px)}
@media (max-width:820px){ .foot__top{grid-template-columns:1fr} }
.foot__brand{display:flex;gap:14px;align-items:flex-start}
.foot__brand img{border-radius:12px}
.foot__brand b{display:block;font-weight:900;font-size:20px;letter-spacing:-.03em}
.foot__brand span{display:block;margin-top:3px;color:var(--ink-2);font-size:15px;max-width:30ch}
.foot__cols{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2.4vw,30px)}
.foot__cols h4{margin:0 0 12px;font-family:"Mono",ui-monospace,monospace;font-size:10.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.foot__cols a{display:block;padding:5px 0;color:var(--ink-2);font-size:15.5px;font-weight:600;
  transition:color .2s}
.foot__cols a:hover{color:var(--brand)}
.foot__bar{display:flex;flex-wrap:wrap;gap:10px 24px;justify-content:space-between;
  align-items:center;padding-top:22px;border-top:1px solid var(--line);
  color:var(--ink-2);font-size:14.5px}
.foot__mono{font-family:"Mono",ui-monospace,monospace;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3)}

/* ── the trust row, from the live footer ──────────────────────────── */
/* Marks, not logos: the real charge runs through PayPal, and these say what
   PayPal itself accepts. Drawn in CSS rather than shipped as brand images —
   nobody's trademark artwork is being redistributed for a preview. */
.foot__trust{display:flex;flex-wrap:wrap;gap:16px 24px;align-items:center;
  justify-content:space-between;padding-top:26px;margin-top:34px;
  border-top:1px solid var(--line)}
.paym{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.paym__l{font-size:12.5px;color:var(--ink-3);font-weight:600}
.paym__m{display:inline-flex;align-items:center;justify-content:center;
  width:42px;height:26px;border-radius:6px;border:1px solid var(--line);
  background:#fff;font-size:9.5px;font-weight:800;letter-spacing:-.01em}
.paym__m--visa{color:#1A1F71;font-style:italic;font-family:Georgia,serif;font-size:11px}
.paym__m--pp{color:#003087;font-size:8.5px}
/* U+F8FF renders the Apple logo only on Apple's own system fonts; this site
   ships Figtree, so everywhere else it drew an empty box. Drawn instead. */
.paym__m--ap{background:#000;color:#fff;border-color:rgba(0,0,0,.2);font-size:10px;gap:1px}
.paym__m--ap svg{width:9px;height:9px;margin-top:-1px}
/* Mastercard's two discs, overlapped. */
.paym__m--mc{gap:0}
.paym__m--mc i{width:13px;height:13px;border-radius:99px;display:block}
.paym__m--mc i:first-child{background:#EB001B}
.paym__m--mc i:last-child{background:#F79E1B;margin-left:-5px;mix-blend-mode:multiply}

.socials{display:flex;align-items:center;gap:9px}
.socials a{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
  border-radius:999px;border:1.5px solid var(--line);color:var(--ink-2);
  transition:background .22s,color .22s,border-color .22s,transform .22s}
.socials a:hover{background:var(--ink);color:#fff;border-color:var(--ink);transform:translateY(-2px)}
.socials svg{width:17px;height:17px}
@media (max-width:520px){
  .foot__trust{justify-content:center;gap:14px}
  .paym__l{width:100%;text-align:center}
  .paym{justify-content:center;width:100%}
  .socials{width:100%;justify-content:center}
}

/* ───────────────────────────────────────────────────────── stub ── */
.stub{padding:clamp(56px,7vw,96px) var(--pad);text-align:center}
.stub .eyebrow{margin-bottom:14px}
.stub p{max-width:56ch;margin:0 auto;color:var(--ink-2);font-size:15.5px}

/* Every icon is an <i data-icon> holding an <svg>.
   The wrapper used to be pinned to 1em while components sized the svg inside
   it — `.dnote__ic svg{width:18px}` in an <i> that was 15px — so the glyph sat
   off the middle of whatever plate it was on, all over the site. The wrapper
   hugs its svg now and centres it, and 1em is only the default size, which any
   component rule still overrides. */
[data-icon]{display:inline-flex;align-items:center;justify-content:center;
  flex-shrink:0;line-height:0}
[data-icon] > svg{display:block;width:1em;height:1em}
.eyebrow [data-icon]{font-size:14px}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
}

/* ═══════════════════════════════════════════════════════ mobile ══ */
@media (max-width:940px){
  .hero__grid{grid-template-columns:1fr}
  .hero__aside{display:none}
  .hero__dash,.s1,.s2,.s3{display:none}
  /* Was 104–150px of clearance for a nav pill that floated over the top of
     the hero. On a phone the nav is at the bottom and the logo tab is in
     the flow, so that clearance was just an empty screen to scroll past
     before the headline started. */
  .hero{padding-top:clamp(28px,7vw,56px)}
  .ctaplate{width:100%;justify-content:stretch}
  .ctaplate .btn{flex:1;justify-content:center}
}
@media (max-width:820px){
  /* The pill itself is hidden on a phone now — see the tab bar at the end
     of this file, which replaced it. */
  .tab{position:static;border-radius:0;box-shadow:none;padding:16px 20px 0;background:transparent}
}
@media (max-width:520px){
  body{padding:6px}
  .shell{border-radius:26px}
  .h1{font-size:clamp(38px,11.5vw,56px)}
  .h2{font-size:clamp(31px,9.5vw,44px)}
  .stats{gap:16px}
  .stats b{font-size:30px}
  .ctaplate{padding:12px}
  .btn{padding:16px 22px;font-size:15.5px}
}


/* ═══════════════════════════════════════════════════ sub-pages ══ */
/* The inner pages share the homepage's chrome exactly — same nav, same
   shell, same footer, same tokens — so the set reads as one site. */
.phead{position:relative;padding:clamp(120px,13vw,180px) 0 clamp(40px,5vw,64px);overflow:hidden}
.phead .wrap{position:relative;z-index:2}
.ph1{top:-14%;right:-4%;width:clamp(150px,20vw,300px);aspect-ratio:1;background:var(--lav);
  border-radius:48% 52% 40% 60%/54% 46% 54% 46%}
.h1--page{font-size:clamp(42px,7.4vw,96px)}

/* ── legal ── */
.legal{display:grid;grid-template-columns:250px 1fr;gap:clamp(28px,4vw,60px);
  padding-bottom:clamp(60px,8vw,110px);align-items:start}
@media (max-width:900px){ .legal{grid-template-columns:1fr} .legal__toc{display:none} }
/* Seventeen sections do not fit beside the page, so the list has its own
   scroll and the script keeps the current one near the middle of it — the
   whole list travels with you rather than the marker running off the end.
   `scroll-behavior:smooth` is on the list, not the page, so the two do not
   fight each other. */
.legal__toc{position:sticky;top:104px;display:flex;flex-direction:column;gap:2px;
  max-height:calc(100svh - 140px);overflow-y:auto;scroll-behavior:smooth;
  scrollbar-width:none;padding-inline-end:4px;
  /* fades at both ends, so it reads as a list that continues */
  -webkit-mask-image:linear-gradient(transparent,#000 22px,#000 calc(100% - 22px),transparent);
  mask-image:linear-gradient(transparent,#000 22px,#000 calc(100% - 22px),transparent)}
.legal__toc::-webkit-scrollbar{display:none}
.legal__toc h4{margin:0 0 12px;font-family:"Mono",ui-monospace,monospace;font-size:10.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);
  position:sticky;top:0;background:var(--card-2);padding:4px 0;z-index:1}
.legal__toc a{position:relative;padding:8px 12px 8px 16px;border-radius:12px;font-size:14px;
  font-weight:600;color:var(--ink-2);
  transition:color .25s,background .25s,padding .25s}
.legal__toc a::before{content:"";position:absolute;left:5px;top:50%;transform:translateY(-50%);
  width:3px;height:0;border-radius:99px;background:var(--brand);
  transition:height .3s cubic-bezier(.16,1,.3,1)}
.legal__toc a:hover{color:var(--ink);background:var(--card-2)}
/* The marker, in our own language: the lavender pill and the brand bar that
   grows into place, the same pairing the eyebrows and pills use. */
.legal__toc a.on{color:var(--brand-2);background:var(--lav);font-weight:800;padding-left:20px}
.legal__toc a.on::before{height:60%}
/* Re-asserted AFTER the block above. The hide lives up in the 900px query
   with the grid change, but this rule set `display:flex` later in the file
   and a media query adds no specificity — so the list came back on phones,
   where there is no column to put it in. */
@media (max-width:900px){ .legal__toc{display:none} }
.legal__main{display:flex;flex-direction:column;gap:14px}
.legal__sec{background:var(--card);border:2px solid var(--line);border-radius:24px;
  padding:clamp(22px,3vw,34px);scroll-margin-top:104px;
  transition:border-color .4s,box-shadow .4s}
/* Clicking an entry marks the block you were sent to, so it is obvious which
   of seventeen near-identical cards you just landed on. It fades by itself —
   a highlight that stays is just a different default state. */
.legal__sec.is-marked{border-color:var(--brand);box-shadow:0 0 0 4px var(--lav)}
.legal__sec h2{margin:0 0 14px;font-weight:900;font-size:clamp(20px,2.4vw,27px);letter-spacing:-.032em}
.legal__body{color:var(--ink-2);font-size:16.5px;line-height:1.68}
.legal__body p{margin:0 0 12px}
.legal__body p:last-child{margin-bottom:0}
.legal__body ul,.legal__body ol{margin:0 0 12px;padding-left:20px;display:flex;flex-direction:column;gap:7px}
.legal__body strong{color:var(--ink);font-weight:800}
.legal__body a{color:var(--brand);font-weight:600;text-decoration:underline;text-underline-offset:3px}

/* ── faq page: a split, not a stack ──────────────────────────────── */
/* Eleven identical closed bars is a page you have to read all of to find
   the one line you came for. Groups down the left, the answer held on the
   right at full size — picking a question no longer pushes the rest of the
   page down, because the answer never moves. */
.faqpage{padding-bottom:clamp(60px,8vw,110px)}
.faqx{display:grid;grid-template-columns:minmax(280px,.86fr) 1.14fr;
  gap:clamp(20px,3vw,44px);align-items:start}

.faqx__side{display:flex;flex-direction:column;gap:10px;position:sticky;
  top:clamp(16px,3vw,32px)}
.faqg{border:2px solid var(--line);border-radius:22px;background:var(--card);
  overflow:hidden;transition:border-color .35s,box-shadow .35s}
.faqg.is-on{border-color:var(--brand);box-shadow:var(--sh-sm)}
.faqg__h{width:100%;display:grid;grid-template-columns:1fr auto;gap:2px 12px;
  text-align:start;cursor:pointer;font:inherit;color:inherit;background:none;border:0;
  padding:18px 20px;transition:background .25s}
.faqg__h:hover{background:var(--card-2)}
.faqg__n{font-weight:800;font-size:19px;letter-spacing:-.03em}
.faqg__c{grid-column:2;grid-row:1;align-self:center;
  min-width:26px;height:26px;border-radius:999px;background:var(--card-2);color:var(--ink-3);
  display:flex;align-items:center;justify-content:center;
  font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;
  transition:background .3s,color .3s}
.faqg.is-on .faqg__c{background:var(--brand);color:#fff}
.faqg__note{grid-column:1;font-size:13.5px;color:var(--ink-3);line-height:1.4}
.faqg__h:focus-visible{outline:3px solid var(--brand);outline-offset:-3px}

/* The question list belongs to its group and only exists while that group is
   the open one. Collapsed by max-height so the panel animates rather than
   snapping between two heights. */
.faqg__list{list-style:none;margin:0;padding:0;max-height:0;opacity:0;overflow:hidden;
  transition:max-height .5s cubic-bezier(.16,1,.3,1),opacity .35s}
.faqg.is-on .faqg__list{max-height:520px;opacity:1}
.faqq{width:100%;text-align:start;cursor:pointer;font:inherit;background:none;border:0;
  border-top:1px solid var(--line);color:var(--ink-2);
  padding:13px 20px;font-size:15px;font-weight:600;line-height:1.4;
  transition:background .22s,color .22s,padding .3s}
.faqq:hover{background:var(--card-2);color:var(--ink)}
.faqq.is-on{background:var(--lav);color:var(--brand-2);font-weight:800}
.faqq:focus-visible{outline:3px solid var(--brand);outline-offset:-3px}

/* A fixed floor, because the answers run from one line (the NDA) to six.
   Without it the panel resized on every click and the footer walked up and
   down the page under the cursor. */
.faqa{background:var(--card);border:2px solid var(--line);border-radius:26px;
  padding:clamp(24px,3.4vw,42px);box-shadow:var(--sh-sm);
  min-height:clamp(340px,32vw,440px);display:flex;flex-direction:column;
  align-items:flex-start}
.faqa__tag{display:inline-block;background:var(--lav);color:var(--brand-2);
  border-radius:999px;padding:7px 15px;
  font-family:"Mono",ui-monospace,monospace;font-size:10px;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase}
.faqa__q{margin:16px 0 0;font-weight:900;font-size:clamp(25px,3.2vw,40px);
  line-height:1.06;letter-spacing:-.04em;text-wrap:balance}
.faqa__a p{margin:18px 0 0;font-size:clamp(16.5px,1.5vw,18.5px);line-height:1.66;
  color:var(--ink-2)}
.faqa__foot{margin:26px 0 0;padding-top:20px;border-top:1px solid var(--line);
  font-size:14.5px;color:var(--ink-3);width:100%;margin-top:auto}
.faqa__foot a{color:var(--brand);font-weight:700}
.faqa__foot a:hover{text-decoration:underline}
/* Replayed by script on every change, so a new answer is seen to arrive
   rather than silently swapping under the cursor. */
.faqa.is-in .faqa__tag,.faqa.is-in .faqa__q,.faqa.is-in .faqa__a{
  animation:faqIn .5s cubic-bezier(.16,1,.3,1) backwards}
.faqa.is-in .faqa__q{animation-delay:.04s}
.faqa.is-in .faqa__a{animation-delay:.08s}
@keyframes faqIn{from{opacity:0;transform:translateY(10px)}}

@media (max-width:900px){
  /* One column: the groups sit on top, the answer under them. Nothing is
     sticky — a sticky side column on a phone is a column that eats the
     screen. */
  .faqx{grid-template-columns:1fr;gap:16px}
  .faqx__side{position:static;top:auto}
  .faqg__n{font-size:17px}
  .faqg__note{font-size:12.5px}
  .faqa{padding:22px 20px}
}
@media (prefers-reduced-motion:reduce){
  .faqa.is-in .faqa__tag,.faqa.is-in .faqa__q,.faqa.is-in .faqa__a{animation:none}
  .faqg__list{transition:none}
}

/* ── portfolio grid ── */
.deck{max-width:var(--maxw);margin:0 auto clamp(60px,8vw,110px);
  display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:clamp(15px,2vw,24px)}
.card{position:relative;border-radius:var(--r-lg);overflow:hidden;aspect-ratio:4/3;
  display:flex;flex-direction:column;justify-content:flex-end;padding:22px;
  box-shadow:var(--sh);isolation:isolate;
  transition:transform .4s cubic-bezier(.16,1,.3,1),box-shadow .4s}
.card:hover{transform:translateY(-8px) scale(1.015);box-shadow:var(--sh-lg)}
.card__fill{position:absolute;inset:0;z-index:-2}
.card::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(146deg,rgba(255,255,255,.22) 0%,transparent 44%),
             linear-gradient(0deg,rgba(0,0,0,.34) 0%,transparent 52%)}
.card__name{font-weight:900;font-size:clamp(19px,2.1vw,24px);letter-spacing:-.028em;color:#fff;margin:0}
.card__tag{align-self:flex-start;margin-top:10px;font-family:"Mono",ui-monospace,monospace;
  font-size:10px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.86);background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.28);border-radius:999px;padding:5px 11px}
.card.is-light .card__name{color:var(--ink)}
.card.is-light .card__tag{color:var(--ink-2);background:rgba(20,26,60,.07);border-color:rgba(20,26,60,.14)}
.card.is-light::after{background:linear-gradient(146deg,rgba(255,255,255,.5) 0%,transparent 44%)}


/* ═══════════════════════════════════════════════ portfolio bento ══ */
/* A sixteen-up grid of equal tiles is a contact sheet, not a portfolio.
   This is a bento: three tile sizes on a twelve-column grid, each one a
   browser window rather than a colour swatch, and the brief is revealed
   on the tile instead of on a page the visitor has to go and find. */
.pfilter{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:clamp(22px,3vw,34px)}
.pfilter button{font:inherit;font-size:14px;font-weight:700;cursor:pointer;
  padding:10px 18px;border-radius:999px;border:2px solid var(--line);background:var(--card);
  color:var(--ink-2);transition:border-color .22s,color .22s,background .22s,transform .22s}
.pfilter button:hover{transform:translateY(-2px);color:var(--ink)}
.pfilter button.on{background:var(--ink);border-color:var(--ink);color:#fff}
.pfilter button:focus-visible{outline:3px solid var(--brand);outline-offset:3px}

.bento{display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(12px,1.6vw,20px);
  margin-bottom:clamp(50px,7vw,96px)}
.bt{grid-column:span 3;position:relative;border-radius:24px;overflow:hidden;
  background:var(--card);border:2px solid var(--line);box-shadow:var(--sh-sm);
  display:flex;flex-direction:column;min-height:230px;
  transition:transform .42s cubic-bezier(.16,1,.3,1),box-shadow .42s,border-color .3s}
.bt:hover{transform:translateY(-8px);box-shadow:var(--sh-lg);border-color:transparent;z-index:2}
/* The arrival, as a CSS animation rather than a tween — see page.js reveal():
   it cannot be left half-done. No `opacity` in the transition list above any
   more, it was fighting this. */
@keyframes bt-rise{from{opacity:0;transform:translateY(26px)}}
.bt.is-rise{animation:bt-rise .6s cubic-bezier(.22,1,.36,1) var(--d,0s) backwards}
@media (prefers-reduced-motion:reduce){.bt.is-rise{animation:none}}
.bt.is-wide{grid-column:span 6}
.bt.is-tall{grid-column:span 3;min-height:480px}
.bt.is-hero{grid-column:span 6;min-height:480px}
.bt.is-hidden{display:none}
@media (max-width:1000px){
  .bt,.bt.is-tall{grid-column:span 6} .bt.is-wide,.bt.is-hero{grid-column:span 12}
  .bt.is-tall,.bt.is-hero{min-height:320px}
}
@media (max-width:600px){ .bt,.bt.is-wide,.bt.is-tall,.bt.is-hero{grid-column:span 12;min-height:220px} }

.bt__bar{display:flex;align-items:center;gap:6px;padding:11px 14px;background:var(--card-2);
  border-bottom:1px solid var(--line);flex-shrink:0}
.bt__bar i{width:8px;height:8px;border-radius:99px;background:var(--ink-3);opacity:.42}
.bt__url{margin-inline-start:8px;flex:1;height:20px;border-radius:99px;background:var(--card);
  border:1px solid var(--line);display:flex;align-items:center;padding:0 10px;
  font-family:"Mono",ui-monospace,monospace;font-size:9.5px;font-weight:700;color:var(--ink-3);
  white-space:nowrap;overflow:hidden}
.bt__body{flex:1;position:relative;display:flex;flex-direction:column;justify-content:flex-end;
  padding:22px;isolation:isolate;background-size:cover;background-position:top center}
/* A screenshot is busier than the swatch it replaced — the name and tag
   still have to read over whatever the product's own UI put at the bottom
   of the frame, so this darkens more, and over the whole tile rather than
   fading out halfway, than the flat-colour version needed. */
.bt__body::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(150deg,rgba(255,255,255,.14) 0%,transparent 40%),
             linear-gradient(0deg,rgba(0,0,0,.72) 0%,rgba(0,0,0,.22) 62%,rgba(0,0,0,.38) 100%)}
.bt__name{margin:0;font-weight:900;font-size:clamp(20px,2.2vw,27px);letter-spacing:-.032em;color:#fff}
.bt__tag{align-self:flex-start;margin-top:9px;font-family:"Mono",ui-monospace,monospace;
  font-size:9.5px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.88);background:rgba(255,255,255,.17);
  border:1px solid rgba(255,255,255,.3);border-radius:999px;padding:5px 11px}
.bt.is-light .bt__name{color:var(--ink)}
.bt.is-light .bt__tag{color:var(--ink-2);background:rgba(20,26,60,.07);border-color:rgba(20,26,60,.15)}
.bt.is-light .bt__body::after{background:linear-gradient(150deg,rgba(255,255,255,.5) 0%,transparent 46%)}

/* the brief slides up over the window on hover */
.bt__brief{position:absolute;inset:0;z-index:3;padding:24px;display:flex;flex-direction:column;
  justify-content:flex-end;gap:10px;background:rgba(20,26,60,.93);color:#fff;
  transform:translateY(101%);transition:transform .42s cubic-bezier(.16,1,.3,1)}
.bt:hover .bt__brief,.bt:focus-within .bt__brief{transform:translateY(0)}
.bt__brief b{font-weight:900;font-size:19px;letter-spacing:-.03em}
.bt__brief p{margin:0;font-size:14.5px;line-height:1.5;color:rgba(255,255,255,.82)}
.bt__brief ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:5px}
.bt__brief li{font-size:13px;color:rgba(255,255,255,.7);padding-left:14px;position:relative}
.bt__brief li::before{content:"";position:absolute;left:0;top:8px;width:5px;height:5px;
  border-radius:99px;background:var(--hot)}
@media (hover:none){ .bt__brief{display:none} }

.pnote{text-align:center;color:var(--ink-3);font-size:14px;font-weight:600;
  margin:0 0 clamp(50px,7vw,90px)}

/* ═══════════════════════════════════════════════ video player ══ */
/* Chrome's default controls are Chrome's design, not ours. This block
   lived in back.css, which the homepage does not load — so the player
   rendered completely unstyled and overflowed its section. Styles must
   sit in the stylesheet the page actually pulls. */
.vp{position:relative;z-index:2;max-width:100%;border-radius:30px;overflow:hidden;background:#0B0E1F;
  border:3px solid var(--ink);box-shadow:var(--sh-lg)}
.vp video{width:100%;height:auto;display:block;cursor:pointer}
.vp__big{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(11,14,31,.28);border:0;cursor:pointer;transition:opacity .3s}
.vp.is-playing .vp__big{opacity:0;pointer-events:none}
.vp__big span{width:92px;height:92px;border-radius:999px;background:var(--hot);color:#fff;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 18px 40px -12px rgba(245,130,42,.8);
  transition:transform .3s cubic-bezier(.16,1,.3,1)}
.vp__big:hover span{transform:scale(1.08)}
.vp__big svg{width:34px;height:34px;margin-inline-start:4px}
.vp__bar{position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:14px;
  padding:16px 20px;background:linear-gradient(0deg,rgba(11,14,31,.9),transparent);
  opacity:0;transform:translateY(8px);transition:opacity .28s,transform .28s}
.vp:hover .vp__bar,.vp.is-paused .vp__bar,.vp:focus-within .vp__bar{opacity:1;transform:none}
.vp__btn{width:38px;height:38px;border-radius:12px;border:0;cursor:pointer;flex-shrink:0;
  background:rgba(255,255,255,.14);color:#fff;display:flex;align-items:center;justify-content:center}
.vp__btn:hover{background:rgba(255,255,255,.26)}
.vp__btn svg{width:18px;height:18px}
.vp__seek{flex:1;height:6px;border-radius:999px;background:rgba(255,255,255,.22);cursor:pointer;
  position:relative}
.vp__seek i{display:block;height:100%;border-radius:999px;background:var(--hot);width:0}
.vp__seek::after{content:"";position:absolute;top:50%;left:var(--p,0%);width:14px;height:14px;
  border-radius:999px;background:#fff;transform:translate(-50%,-50%) scale(0);
  transition:transform .2s}
.vp:hover .vp__seek::after{transform:translate(-50%,-50%) scale(1)}
.vp__t{font-family:"Mono",ui-monospace,monospace;font-size:12px;font-weight:700;color:#fff;
  font-variant-numeric:tabular-nums;flex-shrink:0}
.vp__btn:focus-visible,.vp__seek:focus-visible{outline:3px solid var(--hot);outline-offset:3px}


/* ═══════════════════════════════════════════════════════ mobile ══ */
/* One block, all pages. Everything above is desktop-first, so this is
   where the layout is actually made to work on the device most of the
   traffic arrives on. */
@media (max-width:820px){
  .h1--page{font-size:clamp(34px,10vw,52px)}
  .phead{padding-top:clamp(92px,20vw,130px)}
  .lead{font-size:16.5px}

  /* the pinned work stage cannot pin on a phone */
  .work__inner{min-height:0;padding-block:clamp(56px,12vw,80px)}
  .work__stage{height:auto}
  .work__dots{display:none}

  /* the route rail keeps its colour but loses the inset gutter */
  .route,.promise,.services,.pricing,.faq,.contact,.film{padding-block:clamp(56px,12vw,84px)}

  /* the bento drops to a single readable column */
  .bento{grid-template-columns:1fr;gap:12px}
  .bt,.bt.is-wide,.bt.is-tall,.bt.is-hero{grid-column:span 1;min-height:210px}
  .pfilter{gap:7px}
  .pfilter button{font-size:13px;padding:8px 14px}

  /* the film */
  .vp{border-width:2px;border-radius:20px}
  .vp__big span{width:66px;height:66px}
  .vp__big svg{width:24px;height:24px}
  .vp__bar{opacity:1;transform:none;padding:11px 13px;gap:9px}
  .vp__t{font-size:10.5px}
  .vp__btn{width:32px;height:32px;border-radius:10px}
  .film__steps{gap:9px}

  /* footer — three columns all the way down; see the note in the 520 block */
  .foot__cols{gap:18px 12px}
}

@media (max-width:520px){
  .eyebrow{font-size:10px;padding:8px 14px}
  .lead,.hero__sub{font-size:16px}
  .stats{gap:14px}
  .stats b{font-size:27px}
  .stats span{font-size:12.5px}
  .claim b{font-size:17px}
  .pr,.svc,.plan{padding:22px}
  .legal__sec{padding:20px;border-radius:18px}
  .legal__body{font-size:15.5px}
  .fq{padding:18px}
  .fq p{font-size:15px}
  .node__card{padding:20px 18px}
  .node__t{font-size:20px}
  /* Two columns, not one. Ten links stacked single file made the footer
     1026px tall on a 844px screen — you scrolled a whole extra screen of
     link, and the three headings stopped reading as three groups. */
  /* Three, not two and not one. Ten links stacked single file made the footer
     1026px tall on a 844px screen. Two columns fixed the height but left
     Legal alone on a second row with a hole beside it — the three groups are
     4, 3 and 3 links, so three columns is the shape the content already has,
     and at this width the longest label ("Portfolio") still fits a third. */
  .foot__cols{grid-template-columns:repeat(3,1fr);gap:14px 10px}
  .foot__cols h4{margin-bottom:8px}
  .foot__cols a{padding:3px 0;font-size:14px}
  /* One rule, above the trust row rather than below it. Below, it ran hard
     under the social buttons and looked like it was underlining them. */
  .foot__trust{border-top:1px solid var(--line);padding-top:24px;margin-top:28px;
    justify-content:center;text-align:center}
  .foot__bar{border-top:0;padding-top:14px}
}


/* ═══════════════════════════════════════════ the phone's navigation ══ */
/* Built by sidenav.js on the eight public pages. The desktop pill stays
   exactly as it was — everything here is behind the 820px query below and
   is `display:none` until then.

   This was a bar across the bottom of the screen. A bottom bar is the single
   strongest signal that something is a wrapped app rather than a site, and it
   charged 74px of a 640px screen for the impression. The rail costs 46px of
   width instead, off a column that was not using it. */
.srail,.sdraw{display:none}

@media (max-width:820px){
  .nav{display:none}

  /* No padding on the card any more. The four-icon rail needed a 54px strip
     reserved down the right, and reserving it meant every full-width tinted
     section — the film, the manifesto — was inset on one side only and stopped
     short of the card's edge, which read as the whole site having slid left.
     A single button in the corner needs no strip. */
  .foot{padding-bottom:76px}   /* room for the chat bubble */

  /* The card floats on the page background with a gutter all round, which is
     right at the top and sides and wrong at the bottom: scrolled to the end
     you got a strip of the background under the card and the site visibly
     stopped. It runs off the bottom edge instead. */
  body{padding-bottom:0}
  .shell{border-bottom-left-radius:0;border-bottom-right-radius:0}

  /* Contact is tinted and now ends on a curve; the footer's own straight
     hairline ran across immediately under it and undid the join. The curve
     is the join. */
  .foot{border-top:0}

  /* ── the button ── */
  /* Top right, level with the wordmark on the other side. */
  .srail{position:fixed;z-index:150;
    right:max(9px,env(safe-area-inset-right));
    top:max(12px,env(safe-area-inset-top));
    width:52px;height:52px;flex:none;display:flex;align-items:center;
    justify-content:center;border:0;padding:0;cursor:pointer;
    color:#fff;background:var(--ink);border-radius:20px;
    box-shadow:0 18px 40px -16px rgba(20,26,60,.55);
    /* It arrives rather than appearing. */
    transform:translateX(150%);
    transition:transform .62s cubic-bezier(.16,1,.3,1),
               background .34s,box-shadow .34s,color .34s,border-radius .34s}
  .srail.is-in{transform:none}

  /* Open, it sheds the dark plate so nothing sits on the arc behind it and
     the X is left in the corner, where a close button is looked for. */
  .srail.is-open{background:transparent;box-shadow:none;color:var(--ink)}
  .srail:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

  .srail__bars{display:block;position:relative;width:19px;height:13px}
  .srail__bars i{position:absolute;left:0;height:2px;border-radius:2px;background:currentColor;
    transition:transform .42s cubic-bezier(.16,1,.3,1),opacity .2s,width .42s cubic-bezier(.16,1,.3,1)}
  /* Three bars of different lengths, so the closed state is not a hamburger
     out of a component library. The middle one is what leaves; the outer two
     equalise and cross. */
  .srail__bars i:nth-child(1){top:0;width:19px}
  .srail__bars i:nth-child(2){top:5.5px;width:12px}
  .srail__bars i:nth-child(3){top:11px;width:16px}
  .srail.is-open .srail__bars i:nth-child(1){width:19px;transform:translateY(5.5px) rotate(45deg)}
  .srail.is-open .srail__bars i:nth-child(2){opacity:0;transform:translateX(-6px)}
  .srail.is-open .srail__bars i:nth-child(3){width:19px;transform:translateY(-5.5px) rotate(-45deg)}

  /* ── the arc ── */
  /* `pointer-events` is the important half of this. The overlay is only taken
     out of the page by its `hidden` attribute, and that is applied 420ms after
     the close so the fade has something to run on. Anything that eats that
     timer — navigating away, a frozen tab, a restore from the back/forward
     cache — leaves a full-screen, fully transparent, backdrop-filtered layer
     sitting live over the site. It should be incapable of receiving a touch
     whenever it is not open, regardless of what happened to the timer. */
  .sdraw{display:block;position:fixed;inset:0;z-index:140;pointer-events:none;
    background:rgba(20,26,60,.42);-webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
    opacity:0;transition:opacity .34s}
  .sdraw.is-open{opacity:1;pointer-events:auto}

  /* The panel is taller than the screen on purpose: the arc has to run off
     both ends rather than terminate in a visible point, or it stops reading
     as a circle passing through the page and starts reading as a leaf.

     `92% … / 50% …` is two quarter-ellipses that meet at the panel's middle,
     which is the only pair of vertical radii that leaves no straight segment
     down the left edge. sidenav.js solves the same ellipse to place the rules
     between the rows on it. */
  .sdraw__panel{position:absolute;right:0;top:-7vh;height:114vh;
    width:min(87%,430px);overflow:hidden;
    background:var(--card);
    border-radius:92% 0 0 92% / 50% 0 0 50%;
    box-shadow:-34px 0 80px -30px rgba(20,26,60,.55);
    transform:translateX(101%);
    transition:transform .58s cubic-bezier(.16,1,.3,1)}
  .sdraw.is-open .sdraw__panel{transform:none}

  /* The wordmark rides the widest part of the curve, not the corner, where
     the panel is 13px across. */
  /* +13px is half the wordmark's height against +26px for half the button's,
     so the two centres land together and stay together on a notched phone. */
  .sdraw__head{position:absolute;
    top:calc(7vh + max(12px,env(safe-area-inset-top)) + 13px);
    right:64px;z-index:2;display:flex;align-items:center;gap:9px;
    opacity:0;transform:translateX(14px);
    transition:opacity .3s .18s,transform .5s cubic-bezier(.16,1,.3,1) .18s}
  .sdraw.is-open .sdraw__head{opacity:1;transform:none}
  .sdraw__head img{width:26px;height:26px;border-radius:8px}
  .sdraw__head b{font-size:18px;font-weight:800;letter-spacing:-.03em}

  /* The list scrolls under a fixed arc, so a row entering the tight end of
     the curve is clipped by it. That is the shape doing its job. The padding
     top and bottom is the room the curve needs before a row is readable. */
  /* `overflow-x:hidden` is not tidiness. A box with one axis `auto` and the
     other left at `visible` computes the visible one to `auto` as well — so
     the labels that deliberately overhang the arc turned the panel into a
     horizontal scroller and the whole menu could be dragged sideways. The
     overhang is meant to be cut by the curve, not chased. */
  .sdraw__scroll{position:absolute;inset:0;
    overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;touch-action:pan-y;
    padding:calc(7vh + 104px) 0 calc(7vh + 40px);
    scrollbar-width:none;
    /* The wordmark and the X do not scroll, so without this a row arriving at
       the top of the list simply parked behind them and two pieces of text
       sat in the same place, both legible. The mask makes the list dissolve
       before it gets there. The offsets are panel-local — the panel starts
       7vh above the viewport — so this is transparent to y=60 and solid from
       y=100, and the padding above starts the first row below that. */
    -webkit-mask-image:linear-gradient(to bottom,transparent calc(7vh + 60px),#000 calc(7vh + 100px));
    mask-image:linear-gradient(to bottom,transparent calc(7vh + 60px),#000 calc(7vh + 100px))}
  .sdraw__scroll::-webkit-scrollbar{display:none}

  /* `--arc` is set per row by script: the distance from the panel's left box
     edge to the curve at that row's height. It moves the text box and the
     rule above it together, so neither ever crosses the arc. */
  .sdraw__l{position:relative;display:flex;align-items:center;justify-content:flex-end;gap:14px;
    padding:15px 20px 15px calc(var(--arc,40px) + 14px);color:var(--ink);
    opacity:0;transform:translateX(26px);
    transition:opacity .34s,transform .52s cubic-bezier(.16,1,.3,1),background .2s}
  .sdraw.is-open .sdraw__l{opacity:1;transform:none}
  .sdraw__l::before{content:"";position:absolute;top:0;right:20px;
    left:calc(var(--arc,40px) + 14px);height:1px;background:var(--line)}
  .sdraw__l:first-child::before{display:none}

  /* The row's box runs from the panel's straight left edge, well outside the
     curve, so anything painted on the box itself is a rectangle sticking out
     of the arc. Safari's default tap highlight is exactly that, and it is
     drawn as an overlay that ancestor clipping does not touch — which is the
     grey slab that appeared across the blurred page on every tap. Kill it and
     paint our own, inset to the arc, so the pressed state is a pill that
     stays inside the shape. */
  .sdraw__l{-webkit-tap-highlight-color:transparent}
  .sdraw__l::after{content:"";position:absolute;
    top:4px;bottom:4px;right:12px;left:calc(var(--arc,40px) + 8px);
    border-radius:20px;background:var(--card-2);opacity:0;z-index:0;
    pointer-events:none;transition:opacity .18s}
  .sdraw__l:active::after{opacity:1}
  .sdraw__txt,.sdraw__i{position:relative;z-index:1}

  /* Never shrinks and never wraps. A row passing through the pinched end of
     the curve runs out of width, and the right answer there is the one the
     shape already gives: the label slides under the arc and the arc cuts it,
     the way the top row is cut. A wrapped two-line "Portfolio" would be the
     layout apologising for the curve. */
  .sdraw__txt{display:flex;flex-direction:column;align-items:flex-end;gap:1px;
    flex:none;white-space:nowrap}
  .sdraw__txt b{font-size:20px;font-weight:800;letter-spacing:-.032em;line-height:1.2}
  .sdraw__txt i{font-style:normal;font-family:"Mono",ui-monospace,monospace;
    font-size:10.5px;font-weight:500;letter-spacing:.055em;text-transform:uppercase;
    color:var(--ink-3);white-space:nowrap}

  /* The round plate is what the reference is really made of — every row is a
     word and a coin. */
  .sdraw__i{flex:none;display:flex;align-items:center;justify-content:center;
    width:52px;height:52px;border-radius:50%;background:var(--card);
    box-shadow:0 6px 18px -6px rgba(20,26,60,.28),0 0 0 1px var(--line) inset;
    color:var(--ink);
    transition:transform .42s cubic-bezier(.34,1.5,.5,1),box-shadow .3s}
  .sdraw__i svg{width:23px;height:23px}
  .sdraw__l:active .sdraw__i{transform:scale(.93)}
  .sdraw__l.is-cta .sdraw__i{background:var(--hot);color:#fff;
    box-shadow:0 10px 22px -8px rgba(245,130,42,.7)}
  .sdraw__l:focus-visible{outline:2px solid var(--brand);outline-offset:-4px;border-radius:18px}
}

@media (prefers-reduced-motion:reduce){
  .srail{transition:none;transform:none}
  .srail__bars i,
  .sdraw,.sdraw__panel,.sdraw__head,.sdraw__l,.sdraw__i{transition:none}
}

/* ═══════════════════════════════════════════════════ 05 · manifesto ══ */
/* One statement, revealed at the speed you scroll it. The words start faint
   and are brought up by scrub — see initManifesto() in site.js, which splits
   the paragraph into spans. With motion off they are simply all on. */
.manifesto{padding:clamp(78px,11vw,150px) 0}
.manifesto__t{margin:26px 0 0;max-width:22ch;font-weight:800;
  font-size:clamp(28px,5.4vw,62px);line-height:1.14;letter-spacing:-.04em;text-wrap:balance}
.manifesto .mw{display:inline-block;opacity:.13;transition:opacity .1s linear}
.manifesto .mw--b{color:var(--brand)}

/* ══════════════════════════════════════════════════ 06 · the receipt ══ */
/* Two real pages, one handle. Fixed aspect so the two scenes cannot
   disagree about their own height and jump as the handle passes. */
.vs{padding:clamp(70px,10vw,130px) 0}
.vs__stage{position:relative;margin-top:38px;border-radius:var(--r-lg);overflow:hidden;
  background:var(--card);box-shadow:var(--sh);border:2px solid var(--line);
  /* Matched to the proportion the two scenes actually want. Their root font
   size does not scale with the box, so a taller stage just adds dead
   background under them. Measured: at 1150px wide the scenes come out
   481px tall, which is this ratio. Change the scenes and re-measure. */
  aspect-ratio:16/6.7;touch-action:pan-y;cursor:ew-resize;isolation:isolate}
.vs__side{position:absolute;inset:0}
/* The AI half is the one that gets clipped away, so the finished build is
   what the handle reveals rather than what it buries. */
.vs__side--ai{z-index:2;clip-path:inset(0 50% 0 0)}
.vs__side iframe{width:100%;height:100%;border:0;display:block;pointer-events:none;
  background:var(--card)}

.vs__tag{position:absolute;top:14px;z-index:3;display:inline-flex;align-items:center;gap:7px;
  padding:8px 14px;border-radius:999px;font-family:"Mono",ui-monospace,monospace;
  font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  box-shadow:var(--sh-sm);white-space:nowrap}
.vs__tag--bad{left:14px;background:var(--ink);color:#fff}
.vs__tag--good{right:14px;background:var(--brand);color:#fff}
.vs__tag svg{width:13px;height:13px}

.vs__handle{position:absolute;top:0;bottom:0;left:50%;z-index:4;width:3px;margin-left:-1.5px;
  background:#fff;box-shadow:0 0 0 1px rgba(20,26,60,.16);pointer-events:none}
.vs__grip{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:46px;height:46px;border-radius:999px;background:#fff;color:var(--ink);
  display:flex;align-items:center;justify-content:center;box-shadow:0 10px 26px -8px rgba(20,26,60,.5)}
.vs__grip svg{width:20px;height:20px}
/* The native range is the keyboard and screen-reader path to the same
   control: a bare pointer-drag would leave it unusable without a mouse. It
   sits invisibly over the stage rather than being hidden, which would take
   it off the focus order. */
.vs__range{position:absolute;inset:auto 0 0;z-index:5;width:100%;margin:0;
  opacity:0;height:44px;cursor:ew-resize;
  /* The stage says `pan-y`; this sits on top of it and did not, so the bottom
     44px of the comparison was a band where a scroll gesture went into the
     range instead of the page. */
  touch-action:pan-y}
.vs__range:focus-visible{opacity:1;outline:3px solid var(--brand);outline-offset:2px}

.vs__diffs{list-style:none;margin:26px 0 0;padding:0;display:grid;gap:10px;
  grid-template-columns:repeat(2,1fr)}
.vsd{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:stretch}
.vsd__b,.vsd__g{display:flex;gap:9px;align-items:flex-start;padding:13px 15px;
  border-radius:16px;font-size:14.5px;font-weight:600;line-height:1.4}
.vsd__b{background:var(--card-2);color:var(--ink-3)}
.vsd__g{background:var(--lav);color:var(--brand-2)}
.vsd i{font-style:normal;font-weight:900;flex-shrink:0}
.vsd__b i{color:var(--ink-3)} .vsd__g i{color:var(--brand)}

@media (max-width:900px){
  .vs__diffs{grid-template-columns:1fr}
}
@media (max-width:640px){
  /* Two live pages side by side inside 360px is not a comparison, it is two
     unreadable thumbnails. The stage gets taller so each half still shows a
     recognisable page, and the receipt below carries the detail. */
  /* Taller. Two live pages side by side is a hard thing to fit on a phone at
     all, and every pixel of height is a pixel of each page you can actually
     recognise. */
  /* Two live pages side by side inside 338px gives each of them 169px, and a
     web page at 169px is a swatch, not a comparison — you cannot read a word
     of either, which is the one thing this section exists to let you do. So on
     a phone they stop sharing the width and take turns: one at a time, full
     width, switched by the pair of tabs above. The handle and its rail go,
     and the heading says "Tap to compare" instead of "Drag the handle". */
  .vs__stage{aspect-ratio:3/4;margin-top:14px}
  .vs{padding:clamp(52px,8vw,90px) 0}
  .vs__stage.is-tabs{cursor:auto}
  .vs__stage.is-tabs .vs__handle,.vs__stage.is-tabs .vs__range,
  .vs__stage.is-tabs .vs__tag{display:none}
  .vs__stage.is-tabs .vs__side{transition:opacity .34s}

  .vstabs{display:flex;gap:6px;margin-top:24px;padding:5px;
    background:var(--card-2);border-radius:999px}
  .vstabs button{flex:1 1 0;min-width:0;border:0;cursor:pointer;font:inherit;
    padding:11px 8px;border-radius:999px;background:none;color:var(--ink-2);
    font-family:"Mono",ui-monospace,monospace;font-size:10.5px;font-weight:700;
    letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
    -webkit-tap-highlight-color:transparent;
    transition:background .3s,color .3s,box-shadow .3s}
  .vstabs button[aria-selected="true"]{background:var(--ink);color:#fff;
    box-shadow:var(--sh-sm)}
  .vstabs button:nth-child(2)[aria-selected="true"]{background:var(--brand)}

  .vsd__b,.vsd__g{font-size:13.5px;padding:10px 13px;border-radius:14px}
  .vs__diffs{gap:7px;margin-top:20px}
  .vs__tag{font-size:8.5px;padding:6px 10px;top:10px}
  .vs__tag--bad{left:10px} .vs__tag--good{right:10px}
  .vs__grip{width:38px;height:38px}
  .vsd{grid-template-columns:1fr;gap:6px}
  .vsd__b,.vsd__g{font-size:13.5px;padding:11px 13px}
  .manifesto__t{max-width:none}
}

/* ═══════════════════════════════════════════════ cookie consent ══ */
/* The banner sits bottom-left, out of the way of the phone's tab bar and of
   the reading column. It arrives 300ms after load — see the reason in
   consent.js, it is a measured one and not a taste. */
/* Bottom-right, not bottom-left. The reading column on every page here is
   left-aligned, so a card in that corner sat on top of the FAQ accordion and
   the portfolio's filter buttons and swallowed the taps — which is what "it
   won't let me press" turned out to be. */
/* While the notice is up the page keeps room underneath it, so anything it
   would otherwise sit on top of can be scrolled out from under it. */
body.has-cc{padding-bottom:var(--cc-h,0px)}
.cc{position:fixed;inset-inline-end:20px;bottom:20px;z-index:60;
  width:min(400px,calc(100vw - 32px));background:rgba(252,251,254,.92);
  backdrop-filter:blur(18px);border:1.5px solid var(--line);border-radius:24px;
  padding:18px;box-shadow:0 34px 70px -26px rgba(20,26,60,.55);
  opacity:0;transform:translateY(18px) scale(.97);
  transition:opacity .3s,transform .45s cubic-bezier(.32,.72,0,1)}
.cc.is-in{opacity:1;transform:none}
.cc__top{display:flex;gap:12px;align-items:flex-start;padding-inline-end:26px}
/* The real component has this and it matters: a notice you can only answer is
   a notice that holds the page hostage. Dismissing means necessary only. */
.cc__x{position:absolute;top:14px;inset-inline-end:14px;width:26px;height:26px;
  border:0;border-radius:9px;background:none;color:var(--ink-3);cursor:pointer;
  display:flex;align-items:center;justify-content:center;font-size:17px;line-height:1;
  transition:background .25s,color .25s}
.cc__x:hover{background:var(--card-2);color:var(--ink)}
.cc__ic{width:36px;height:36px;border-radius:12px;flex-shrink:0;background:var(--lav);
  color:var(--brand);display:flex;align-items:center;justify-content:center}
.cc__ic svg{width:18px;height:18px}
.cc__top b{display:block;font-weight:800;font-size:15px;letter-spacing:-.025em}
.cc__top p{margin:5px 0 0;font-size:13px;line-height:1.55;color:var(--ink-2)}
.cc__top a{color:var(--brand);font-weight:700}
.cc__act{display:flex;align-items:center;gap:8px;margin-top:15px;flex-wrap:wrap}
.cc__act .btn{flex:1;justify-content:center;padding:10px 14px;font-size:14px;border-radius:13px}
.cc__choose{display:inline-flex;align-items:center;gap:7px;border:0;background:none;
  font:inherit;font-size:13px;font-weight:700;color:var(--ink-2);cursor:pointer;
  padding:8px 4px;transition:color .25s}
.cc__choose:hover{color:var(--brand)}
.cc__choose svg{width:15px;height:15px}
.cc__panel{max-height:min(48vh,360px);overflow-y:auto;margin-top:14px;
  border-top:1px solid var(--line);padding-top:4px}
/* With the panel open the primary takes the full width: "Save my choice" was
   wrapping to two lines inside a shared half. */
.cc.is-open .cc__act [data-yes]{flex:1 1 100%}

/* one switch list, the banner's compact form and the page's full one */
.cc__cat{display:flex;align-items:flex-start;gap:14px;padding:14px 0;
  border-bottom:1px solid var(--line)}
.cc__cat:last-child{border-bottom:0}
.cc__catb{flex:1;min-width:0}
.cc__catb b{display:block;font-weight:800;font-size:14.5px;letter-spacing:-.02em}
.cc__catb b em{font-style:normal;font-family:"Mono",ui-monospace,monospace;font-size:9px;
  font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
  margin-inline-start:7px;vertical-align:1px}
.cc__catb p{margin:4px 0 0;font-size:13px;line-height:1.55;color:var(--ink-2)}
.cc__sw{position:relative;flex-shrink:0;width:44px;height:25px;border:0;padding:0;
  cursor:pointer;border-radius:999px;background:var(--line);transition:background .3s}
.cc__sw.on{background:var(--brand)}
.cc__sw[disabled]{cursor:default;background:var(--sage)}
.cc__sw i{position:absolute;top:3px;inset-inline-start:3px;width:19px;height:19px;
  border-radius:99px;background:#fff;box-shadow:0 2px 6px rgba(20,26,60,.28);
  transition:transform .4s cubic-bezier(.32,.72,0,1)}
.cc__sw.on i,.cc__sw[disabled] i{transform:translateX(19px)}
.cc__sw:focus-visible{outline:3px solid var(--brand);outline-offset:3px}

/* the page */
.cc__tbl{width:100%;border-collapse:collapse;margin-top:12px;font-size:12.5px}
.cc__tbl th{text-align:start;font-family:"Mono",ui-monospace,monospace;font-size:9px;
  font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
  padding:0 12px 7px 0}
.cc__tbl td{padding:7px 12px 7px 0;border-top:1px solid var(--line);color:var(--ink-2)}
.cc__tbl td:first-child{font-family:"Mono",ui-monospace,monospace;color:var(--ink)}
.cc__pageact{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin-top:clamp(22px,3vw,32px)}
.cc__saved{display:flex;align-items:center;gap:9px;margin:0;font-size:13.5px;
  font-weight:700;color:var(--mint)}
.cc__saved svg{width:16px;height:16px;flex-shrink:0}
.foot__ck{margin-inline-start:auto;color:var(--ink-2);font-weight:700;font-size:13.5px}
.foot__ck:hover{color:var(--brand)}

@media (max-width:640px){
  /* On a phone the card was 340px of a 844px screen and it sat on top of
     whatever you were reading until you answered — which is most of why it
     felt like the page would not let you press anything. Closed, it is a
     compact bar: the notice still says what it is for, in two lines, and
     Choose opens it to full size when somebody actually wants to choose. */
  .cc{inset-inline:12px;bottom:max(12px,env(safe-area-inset-bottom));width:auto;padding:14px;border-radius:20px}
  .cc__x{top:11px;inset-inline-end:11px}
  .cc:not(.is-open) .cc__ic{width:30px;height:30px}
  .cc:not(.is-open) .cc__ic svg{width:15px;height:15px}
  .cc__act{margin-top:12px;gap:7px}
  .cc__act .btn{flex:1 1 0;min-width:0;padding:11px 10px;font-size:13.5px}
  .cc__choose{flex:1 1 100%;justify-content:center;padding:6px 4px}
  .cc.is-open .cc__act .btn{flex:1 1 100%}
  .foot__ck{margin-inline-start:0}
}
/* .wrap centres a 1180 column, so capping the page at 760 re-centred it and
   the switches stopped lining up with the heading above them. The measure
   belongs on the content, not on the container that does the centring. */
.ckpage{padding-bottom:clamp(60px,8vw,110px)}
.ckpage .cc__list,.ckpage .cc__pageact{max-width:760px}

/* ═══════════════════════════════════════════════ printable receipt ══ */
.rc{background:var(--card-2);display:flex;align-items:flex-start;justify-content:center;
  padding:clamp(16px,4vw,56px) clamp(12px,3vw,24px)}
.rcp{width:min(760px,100%);background:var(--card);border-radius:26px;
  box-shadow:var(--sh);padding:clamp(24px,4vw,48px)}
.rcp__h{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;
  flex-wrap:wrap;padding-bottom:clamp(18px,2.5vw,26px);border-bottom:1px solid var(--line)}
.rcp__mk{display:flex;align-items:center;gap:12px}
.rcp__mk img{border-radius:11px}
.rcp__mk b{display:block;font-weight:900;font-size:19px;letter-spacing:-.035em}
.rcp__mk span{display:block;font-size:12.5px;color:var(--ink-3)}
.rcp__no{text-align:end}
.rcp__no span{display:block;font-family:"Mono",ui-monospace,monospace;font-size:9.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.rcp__no b{display:block;margin-top:3px;font-family:"Mono",ui-monospace,monospace;
  font-size:14px;font-weight:700}
.rcp__who{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  gap:18px;padding:clamp(18px,2.5vw,26px) 0}
.rcp__who span{display:block;font-family:"Mono",ui-monospace,monospace;font-size:9.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.rcp__who b{display:block;margin-top:5px;font-weight:800;font-size:15.5px;letter-spacing:-.025em}
.rcp__who p{margin:2px 0 0;font-size:13.5px;color:var(--ink-2)}
.rcp__t{width:100%;border-collapse:collapse;margin-top:6px}
.rcp__t th{text-align:start;font-family:"Mono",ui-monospace,monospace;font-size:9.5px;
  font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);
  padding-bottom:10px;border-bottom:1px solid var(--line)}
.rcp__t th:last-child,.rcp__t .num{text-align:end}
.rcp__t td{padding:16px 0;border-bottom:1px solid var(--line);vertical-align:top}
.rcp__t tbody b{display:block;font-weight:800;font-size:16px;letter-spacing:-.025em}
.rcp__t tbody span{display:block;margin-top:3px;font-size:13.5px;color:var(--ink-2)}
.rcp__t .num{font-variant-numeric:tabular-nums;font-weight:700}
.rcp__t tfoot td{border-bottom:0;padding-top:18px;font-weight:900;font-size:20px;
  letter-spacing:-.035em}
.rcp__note{margin:clamp(14px,2vw,20px) 0 0;font-size:13.5px;line-height:1.6;color:var(--ink-2)}
.rcp__note a{color:var(--brand);font-weight:700}
.rcp__act{display:flex;gap:10px;flex-wrap:wrap;margin-top:clamp(20px,3vw,30px)}

/* What comes out of the printer is the receipt, not the page around it. */
@media print{
  .rc{background:#fff;padding:0}
  .rcp{box-shadow:none;border-radius:0;width:100%;padding:0}
  .rcp__act{display:none}
  /* Every fixed overlay, not a list of the ones that existed when this was
     written. The chat panel was added later, kept its dark ground, and
     printed as a black rectangle across the bottom of the receipt — which is
     what a receipt with an un-hidden fixed element looks like. */
  .nav,.srail,.sdraw,.cc,.foot,.gfab,.gchat,.cvov,.st__tape{display:none!important}
  body{padding:0!important;background:#fff!important}
  /* The sheet, not the screen. Without this the printed layout inherits
     whatever width the browser happened to be, and the amount column ends up
     off the right edge of the paper. */
  @page{margin:14mm}
  html,body{width:auto!important;min-width:0!important;margin:0!important}
  /* Every decorative ground off. The page's radial gradients printed as a
     large tinted block down the sheet the moment colour-adjust was forced on
     — a receipt is text on white, and the only thing print should carry from
     the screen is the text. */
  html,body,.rc,.rcp,.rcp__h,.rcp__who,.rcp__t{
    background:#fff!important;background-image:none!important}
  .rc,.rcp{max-width:100%!important;width:auto!important;margin:0!important}
  .rcp__h,.rcp__who,.rcp__t tr{page-break-inside:avoid}
  /* The receipt number is the one string that must never be shortened. */
  .rcp__no{flex:none;white-space:nowrap}
  .rcp__no b{font-size:13px}
}

/* ═══════════════════════════════════════════════ the public chat ══ */
/* A visitor with no account. The bubble sits opposite the cookie notice so the
   two never argue over the same corner — true on desktop, where they are in
   different corners at the same time. On a phone it isn't: see this file's
   mobile block for why the button moves there instead. */
.gfab{position:fixed;inset-inline-start:20px;bottom:20px;z-index:55;width:54px;height:54px;
  border-radius:999px;border:0;cursor:pointer;display:flex;align-items:center;
  justify-content:center;color:#fff;background:linear-gradient(180deg,#7472FF,var(--brand));
  /* A neutral shadow. This was purple at .9 alpha and 34px of blur, which is
     not a shadow — it is a glow, and it hung around the button as a visible
     lilac cloud on a pale page. The button is already the only violet circle
     on the site; it does not need announcing twice. */
  /* Measured: with the old glow the button painted a 207x197px footprint for
     a 48px button. Neutralising the colour brought that to 69x65, and what is
     left of the ring is simply the shadow — so the shadow goes tight too. A
     contact shadow, not an aura. */
  box-shadow:0 4px 14px -6px rgba(20,26,60,.34);
  -webkit-tap-highlight-color:transparent;
  transition:transform .4s cubic-bezier(.32,.72,0,1),box-shadow .4s}
.gfab:hover{transform:translateY(-2px);box-shadow:0 8px 20px -8px rgba(20,26,60,.42)}
.gfab:active{transform:scale(.95)}
.gfab svg{width:23px;height:23px}
.gfab__dot{position:absolute;top:10px;inset-inline-end:11px;width:11px;height:11px;
  border-radius:99px;background:var(--hot);border:2.5px solid #6260FF}

.gchat{position:fixed;inset-inline-start:20px;bottom:86px;z-index:56;
  width:min(370px,calc(100vw - 32px));max-height:min(560px,72vh);
  background:var(--card);border:1.5px solid var(--line);border-radius:24px;
  box-shadow:0 40px 80px -30px rgba(20,26,60,.55);display:flex;flex-direction:column;
  overflow:hidden;opacity:0;transform:translateY(14px) scale(.97);transform-origin:bottom left;
  transition:opacity .26s,transform .38s cubic-bezier(.32,.72,0,1)}
.gchat.is-in{opacity:1;transform:none}
.gchat__h{display:flex;align-items:center;gap:11px;padding:13px 14px;
  border-bottom:1px solid var(--line);flex:0 0 auto}
.gchat__h > div{flex:1;min-width:0}
.gchat__h b{display:block;font-weight:800;font-size:15px;letter-spacing:-.025em}
.gchat__h span{display:block;font-size:11.5px;color:var(--ink-3)}
.gchat__av{width:32px;height:32px;border-radius:99px;flex-shrink:0;display:flex;
  align-items:center;justify-content:center;font-size:13px;font-weight:900;color:#fff;
  background:linear-gradient(180deg,#7472FF,var(--brand))}
.gchat__b{width:30px;height:30px;border-radius:10px;border:0;background:none;cursor:pointer;
  color:var(--ink-3);display:flex;align-items:center;justify-content:center;font-size:19px;
  line-height:1;flex-shrink:0;transition:background .2s,color .2s}
.gchat__b:hover{background:var(--card-2);color:var(--ink)}
.gchat__b svg{width:15px;height:15px}

.gchat__b0{padding:16px 14px;overflow-y:auto}
.gchat__q{margin:0 0 12px;font-weight:800;font-size:16px;letter-spacing:-.03em}
.gopt{display:flex;align-items:center;gap:11px;width:100%;text-align:start;cursor:pointer;
  font:inherit;font-size:14.5px;font-weight:700;color:var(--ink);background:var(--card-2);
  border:1.5px solid transparent;border-radius:15px;padding:12px 14px;margin-bottom:8px;
  transition:border-color .3s,background .3s,transform .3s cubic-bezier(.32,.72,0,1)}
.gopt:hover{border-color:var(--brand);background:var(--lav);transform:translateX(2px)}
.gopt__ic{width:30px;height:30px;border-radius:10px;flex-shrink:0;background:var(--card);
  color:var(--brand);display:flex;align-items:center;justify-content:center}
.gopt__ic svg{width:15px;height:15px}
.gopt--plain{justify-content:center}
.gchat__n{margin:12px 0 0;font-size:11.5px;line-height:1.55;color:var(--ink-3)}
.gchat__err{margin:8px 0 0;font-size:12.5px;font-weight:700;color:#B3261E}
.gchat [data-intro] input,.gchat [data-intro] textarea,.gchat__new input{
  width:100%;font:inherit;font-size:15px;font-weight:500;color:var(--ink);
  background:var(--card-2);border:1.5px solid var(--line);border-radius:14px;
  padding:11px 13px;margin-bottom:9px;resize:vertical}
.gchat [data-intro] input:focus,.gchat [data-intro] textarea:focus,.gchat__new input:focus{
  outline:none;border-color:var(--brand);background:var(--card)}
.gsend{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  border:0;cursor:pointer;font:inherit;font-size:14.5px;font-weight:800;color:#fff;
  background:linear-gradient(180deg,#7472FF,var(--brand));border-radius:14px;padding:12px;
  box-shadow:0 10px 22px -12px rgba(98,96,255,.9)}
.gsend svg{width:15px;height:15px}
.gsend--sm{width:40px;height:40px;flex-shrink:0;padding:0;border-radius:13px;margin-bottom:9px}

.gchat__log{flex:1;min-height:0;overflow-y:auto;padding:14px;display:flex;
  flex-direction:column;gap:9px}
.gbub{max-width:88%;border-radius:16px;padding:10px 13px}
.gbub p{margin:0;font-size:14px;line-height:1.5}
.gbub--them{background:var(--card-2);align-self:flex-start;border-bottom-left-radius:6px}
.gbub--us{background:linear-gradient(180deg,#7472FF,var(--brand));color:#fff;
  align-self:flex-end;border-bottom-right-radius:6px}
.gchat__new{display:flex;gap:8px;align-items:flex-start;padding:11px 11px 2px;
  border-top:1px solid var(--line);flex:0 0 auto}

@media (max-width:640px){
  /* These were pushed up to clear the bottom tab bar, and once the bar became
     a rail at the top they were left hanging in the middle of the screen with
     nothing under them. Back on the floor. */
  /* 31 Aug, mobile bug pass: switched from inset-inline-start to -end here
     only, not in the desktop rule above. On a phone this button sat on top
     of real content at rest, not just in transit — the hero's third stat
     tile ("24h") measured fully behind it on load, then "We don't ship
     templates." and a numbered step further down, on a real device. Same
     failure .cc was moved off of once already (see that rule's own comment:
     "the reading column on every page here is left-aligned, so a card in
     that corner sat on top of ... and swallowed the taps") — the corner
     freed up when .cc moved right was never re-checked before this button
     took it. .cc itself is no obstacle here: body.has-cc already hides this
     button below while the notice is up, on both sides, so there is nothing
     left in the bottom-right for it to collide with on a phone. Left alone
     on desktop, where the two sit in different corners at the same time and
     the reading column has more room before it reaches either one. */
  .gfab{inset-inline-start:auto;inset-inline-end:14px;bottom:max(16px,env(safe-area-inset-bottom));
    width:48px;height:48px}
  /* The button is 48px here, not 54, so the unread dot has to come in with it
     or it hangs off the rim. */
  .gfab__dot{top:7px;inset-inline-end:8px;width:10px;height:10px}
  /* `--kb` is the on-screen keyboard's height, published by chat.js from
     visualViewport. A fixed element is pinned to the *layout* viewport, which
     the keyboard does not shrink — so the moment you tapped the input, the
     panel you were typing into sat behind the keyboard. Lifting by --kb, and
     capping the height against what is actually left on screen, keeps the
     whole panel in view while typing. */
  .gchat{inset-inline:14px;
    bottom:calc(max(16px,env(safe-area-inset-bottom)) + 58px + var(--kb,0px));
    width:auto;
    max-height:calc(var(--vvh,100vh) - var(--kb,0px) - 96px);
    transition:opacity .26s,transform .38s cubic-bezier(.32,.72,0,1),bottom .22s}
  /* With the keyboard up the bubble is under it and pointless. */
  body.kb-up .gfab{opacity:0;pointer-events:none}
  /* The notice is a full-width bar down here, not a card in the far corner,
     so there is no corner left to move the bubble to — lifting it clear put
     it on top of the Apply button in the middle of the hero, which is worse
     than what it was avoiding. It waits instead. The notice is answered once
     and never comes back, and a chat bubble is not what you need in the two
     seconds you are being asked about cookies. */
  body.has-cc .gfab{opacity:0;transform:translateY(10px);pointer-events:none}
  .gfab{transition:transform .4s cubic-bezier(.32,.72,0,1),box-shadow .4s,opacity .3s}
}

/* ═══════════════════════════════════════════════ 02 · the work ══
   Three projects, full screen, one at a time, driven by the scroll.

   Elad, 2026-08-28, third pass, with shiruziel.com as the reference: on a
   desktop this has to take the whole screen rather than a slice of it, it has
   to be one screen and not two, and the scroll has to be worth watching.

   So the section is a pinned stage. The page scroll no longer moves it — it
   *plays* it: which product is on stage, the tilt of the panel it sits in, and
   the beat the app is on are all functions of one number, how far through this
   section you are. Scrolling types the item into Aisle, swipes Matala's card,
   and counts PickMeUp's kilometres up. Scroll back and it all runs backwards,
   because nothing here is on a timer.

   Dark, because the three apps are light. On this site's own pale surface the
   screens had nothing to sit against; on ink they read as lit.

   Below 900px nothing is pinned — the three simply stack, each a screenful,
   and the beats run on a timer while a project is in view. A pinned stage on
   a phone is how this section once presented as empty. */

.stage{position:relative;color:#EDEEF9;border-radius:var(--r-card);overflow:clip;
  background:linear-gradient(168deg,#191348 0%,#141039 46%,#171243 100%);
  margin-top:clamp(50px,7vw,90px)}
/* the section's own words, before the stage takes over the screen */
.stage__head{position:relative;z-index:3;max-width:900px;
  padding:clamp(56px,7vw,104px) var(--pad) clamp(30px,4vw,48px)}
.stage__head .h2{color:#fff}
.stage__head .h2 em{color:var(--brand)}
/* 31 Aug: this only overrode the text, not the pill's own light background
   (var(--lav), meant for the light theme everywhere else) — near-white text
   on a near-white pill, unreadable. Same dark tint the nav bar already uses
   for a pill sitting directly on this section's own dark background. */
.stage__head .eyebrow{color:rgba(237,238,249,.92);background:rgba(255,255,255,.12)}
.stage__head .lead{color:rgba(237,238,249,.62)}

/* the scroll room the pinned stage is played across, once the driver has
   said it is taking over */
.stage__track{position:relative;height:auto}
.stage__pin{position:relative;height:auto}
.stage.is-pinned .stage__track{height:calc(3 * 150svh)}
.stage.is-pinned .stage__pin{position:sticky;top:0;height:100svh;overflow:hidden}

/* the colour the product brings with it, crossfading between projects */
.stage__glow{position:absolute;inset:0;z-index:0;pointer-events:none;
  transition:background .8s cubic-bezier(.32,.72,0,1)}

/* which of the three you are on */
.stage__rail{display:none}
.stage.is-pinned .stage__rail{position:absolute;z-index:5;inset-inline-start:clamp(16px,2.4vw,38px);
  top:50%;transform:translateY(-50%);list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:16px}
.stage__rail li{display:flex;align-items:center;gap:11px;
  font-family:"Mono",ui-monospace,monospace;font-size:11px;font-weight:700;
  letter-spacing:.14em;color:rgba(237,238,249,.34);transition:color .45s}
.stage__rail li::before{content:"";width:2px;height:26px;border-radius:2px;
  background:rgba(237,238,249,.22);transition:background .45s,height .45s}
.stage__rail li.on{color:#fff}
.stage__rail li.on::before{background:var(--ac);height:40px}

/* ── one project ───────────────────────────────────────────────────── */
.proj{position:relative;z-index:2;display:block;
  padding:clamp(26px,6vw,44px) clamp(20px,5vw,34px) clamp(40px,8vw,64px)}
.stage.is-pinned .proj{position:absolute;inset:0;
  display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
  align-items:center;gap:clamp(20px,3.4vw,60px);
  padding:0 clamp(30px,5vw,88px) 0 clamp(120px,11vw,186px);
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .6s cubic-bezier(.32,.72,0,1),visibility .6s}
.stage.is-pinned .proj.on{opacity:1;visibility:visible;pointer-events:auto}

/* ── the panel the app plays in ────────────────────────────────────── */
.proj__frame{position:relative;justify-self:center;width:100%;
  padding:clamp(18px,4vw,26px) 0;margin-bottom:clamp(26px,5vw,36px);
  border-radius:34px;background:var(--field);overflow:hidden;
  box-shadow:0 60px 120px -50px rgba(0,0,0,.85),0 0 0 1px rgba(255,255,255,.09)}
.stage.is-pinned .proj__frame{width:var(--fw,460px);max-width:100%;
  height:var(--fh,760px);padding:0;margin-bottom:0;
  transform:perspective(2000px) rotateY(var(--ry,0deg)) translateY(var(--ty,0px));
  transform-origin:center;transition:transform .12s linear}
/* the product's own colour, softly, behind its screen */
.proj__frame::before{content:"";position:absolute;inset:0;
  background:radial-gradient(72% 46% at 50% 0%, color-mix(in srgb, var(--p) 26%, transparent), transparent 70%),
             radial-gradient(64% 44% at 50% 104%, color-mix(in srgb, var(--p2) 22%, transparent), transparent 70%)}
.proj__screen{position:relative;margin:0 auto}
.stage.is-pinned .proj__screen{position:absolute;inset:auto;
  top:50%;left:50%;transform:translate(-50%,-50%)}
.scr{transform-origin:top left}
.stage.is-pinned .scr{position:absolute;top:0;left:0}

/* A surface, not a device — Elad, 2026-08-21, and still true. The screen is a
   fixed 330×626 and is scaled from JS to whatever the panel measures, so the
   app's own proportions are never re-drawn to fit a mock. */
.scr{flex:none;width:330px;height:626px;position:absolute;top:0;left:0;overflow:hidden;
  border-radius:30px;background:#fff;transform:scale(var(--k,1));
  box-shadow:0 40px 80px -36px rgba(0,0,0,.6);
  font-family:"Fig",system-ui,sans-serif;font-size:15px;line-height:1.45}
.scr *{box-sizing:border-box}

/* ── the words beside it ───────────────────────────────────────────── */
.proj__copy{position:relative;z-index:2;max-width:none;padding-top:0}
.stage.is-pinned .proj__copy{max-width:560px;padding-top:clamp(60px,8vw,96px)}
/* the name, once as a wall and once to read */
.proj__ghost{display:none}
.stage.is-pinned .proj__ghost{display:block;position:absolute;z-index:-1;inset-inline-start:-2px;top:0;
  font-weight:900;letter-spacing:-.06em;line-height:.8;white-space:nowrap;
  font-size:clamp(66px,8.6vw,148px);color:rgba(255,255,255,.055);
  transform:translate3d(var(--gx,0px),-14%,0);pointer-events:none;
  transition:transform .12s linear}
.proj__tag{display:inline-flex;align-items:center;gap:9px;margin:0 0 18px;
  font-family:"Mono",ui-monospace,monospace;font-size:10.5px;font-weight:700;
  letter-spacing:.18em;text-transform:uppercase;color:var(--ac);
  background:color-mix(in srgb, var(--ac) 22%, transparent);
  border:1px solid color-mix(in srgb, var(--ac) 46%, transparent);
  border-radius:999px;padding:7px 15px}
.proj__name{margin:0;font-weight:900;letter-spacing:-.055em;line-height:.9;
  font-size:clamp(40px,4.4vw,66px);color:#fff}
.proj__one{margin:14px 0 0;font-size:clamp(19px,1.7vw,25px);line-height:1.24;
  font-weight:800;letter-spacing:-.03em;color:var(--ac);max-width:20ch}
.proj__brief{margin:14px 0 0;font-size:clamp(15.5px,1.05vw,16.5px);line-height:1.6;
  color:rgba(237,238,249,.7);max-width:44ch}
.proj__build{list-style:none;margin:clamp(16px,1.8vw,24px) 0 0;padding:0;max-width:44ch}
.proj__build li{position:relative;padding:10px 0 10px 24px;font-size:14px;
  font-weight:600;color:rgba(237,238,249,.82);
  border-top:1px solid rgba(255,255,255,.11)}
.proj__build li:last-child{border-bottom:1px solid rgba(255,255,255,.11)}
.proj__build li::before{content:"";position:absolute;inset-inline-start:2px;top:17px;
  width:7px;height:7px;border-radius:99px;background:var(--ac)}

.proj__foot{display:flex;flex-wrap:wrap;align-items:center;gap:14px;
  margin-top:clamp(20px,2.4vw,30px)}
.proj__open{display:inline-flex;align-items:center;gap:10px;min-height:52px;
  padding-inline:24px;border-radius:999px;font-size:15px;font-weight:800;
  background:linear-gradient(150deg,var(--ac),var(--ac2));
  box-shadow:0 18px 38px -16px color-mix(in srgb, var(--ac) 70%, transparent);
  color:#131038
  transition:transform .3s cubic-bezier(.32,.72,0,1),box-shadow .3s}
.proj__open:hover{transform:translateY(-2px)}
.proj__open i{width:17px;height:17px}
.proj__open i svg{width:100%;height:100%}
.proj__host{font-family:"Mono",ui-monospace,monospace;font-size:12px;font-weight:700;
  color:rgba(237,238,249,.42)}

/* the line that says what the app is doing right now */
.proj__cap{display:flex;align-items:center;gap:11px;margin:18px 0 0;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12);
  border-radius:999px;padding:10px 20px 10px 13px;min-height:44px;
  width:fit-content;max-width:100%;
  font-size:14.5px;font-weight:700;letter-spacing:-.015em;color:#fff}
.proj__cap i{width:9px;height:9px;border-radius:99px;background:var(--ac);flex:none;
  animation:capPulse 2s ease-in-out infinite}
@keyframes capPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}
.proj__cap span{transition:opacity .2s}

/* ══════════════════════════════════════════════════════════════════════
   THE APPS. Everything below is the products' own design language rather
   than this site's — colours, radii, shadows and glyphs were read off the
   running apps, so what is on stage is what opens when the button is
   pressed.

   Every row in every screen has a fixed height and every list is sized to
   fit the 626px screen exactly. Elad, 2026-08-28: rows were being cut and
   were not the same size as each other. Both came from letting content
   decide the height inside a box that could not grow.
   ══════════════════════════════════════════════════════════════════════ */

/* Every round or square icon plate on this stage centres its glyph, stated
   once and with enough specificity that a bar's text rule cannot win against
   it. This is the rule that was missing three times over. */
.scr :is(.ai-mark,.ai-rb,.ai-zi,.ai-ck,.ai-plus,.ai-fab,.ai-badge,
         .mt-mark,.mt-ci,.mt-av,.mt-acts i,.mt-misery > span,
         .pm-fl,.pm-sr i){display:grid;place-items:center}
.scr :is(.ai-mark,.ai-rb,.ai-zi,.ai-ck,.ai-plus,.ai-fab,
         .mt-mark,.mt-ci,.mt-acts i,.mt-misery > span,
         .pm-fl,.pm-sr i) > svg{display:block;grid-area:1/1;place-self:center}

/* ── Aisle — light boutique. Navy on cool grey, 15px cards. ─────────── */
.ai{--a:#22405e;--a2:#35618c;--sf:#fff;--ik:#1e2733;--ik2:#5a6b80;--ik3:#94a2b5;
  position:relative;height:100%;background:linear-gradient(168deg,#eef1f6,#e6ecf4 60%,#f3eef0);
  color:var(--ik);display:flex;flex-direction:column;padding:16px 14px 0}
.ai-top{display:flex;align-items:center;gap:10px;height:38px;margin-bottom:14px;flex:none}
.ai-mark{width:38px;height:38px;border-radius:11px;background:var(--a);flex:none;
  display:grid;place-items:center;color:#fff}
.ai-mark svg{width:22px;height:22px;display:block}
.ai-tt{flex:1;min-width:0;line-height:1.14}
.ai-tt b{display:block;font-size:18px;font-weight:800;letter-spacing:-.03em}
.ai-tt span{display:block;font-size:10.5px;font-weight:700;color:var(--ik2)}
.ai-rb{width:32px;height:32px;border-radius:11px;background:var(--sf);flex:none;
  display:grid;place-items:center;color:var(--a);box-shadow:0 3px 12px rgba(44,62,80,.07)}
.ai-rb svg{width:15px;height:15px;display:block}
.ai-code{display:inline-flex;align-items:center;justify-content:center;gap:5px;
  height:32px;padding:0 11px;border-radius:999px;background:#d7dfea;color:var(--a);
  font-size:11.5px;font-weight:800;letter-spacing:.04em;flex:none}
.ai-code svg{width:13px;height:13px;display:block}

.ai-addrow{display:flex;gap:8px;height:44px;margin-bottom:9px;flex:none}
.ai-add{flex:1;min-width:0;border-radius:14px;background:var(--sf);
  display:flex;align-items:center;padding:0 13px;font-size:13.5px;color:var(--ik3);
  box-shadow:0 3px 12px rgba(44,62,80,.06);overflow:hidden;white-space:nowrap}
.ai-add b{font-weight:600;color:var(--ik)}
.ai-caret{display:inline-block;width:1.5px;height:16px;background:var(--a);
  margin-inline-start:2px;flex:none;opacity:0}
.is-type .ai-caret{animation:aiCaret .9s steps(1) infinite}
@keyframes aiCaret{0%,49%{opacity:1}50%,100%{opacity:0}}
.ai-plus{width:44px;border-radius:14px;background:var(--a);color:#fff;flex:none;
  display:grid;place-items:center;box-shadow:0 6px 16px -6px rgba(34,64,94,.6)}
.ai-plus svg{width:19px;height:19px;display:block}
.is-file .ai-plus{animation:aiPress .5s cubic-bezier(.32,.72,0,1)}
@keyframes aiPress{40%{transform:scale(.88)}100%{transform:scale(1)}}

.ai-tools{display:flex;gap:8px;height:38px;margin-bottom:14px;flex:none}
.ai-tools span{flex:1;border-radius:13px;background:var(--sf);
  display:flex;align-items:center;justify-content:center;gap:7px;
  font-size:12.5px;font-weight:800;color:var(--ik);box-shadow:0 3px 12px rgba(44,62,80,.06)}
.ai-tools svg{width:14px;height:14px;display:block;color:var(--a);flex:none}
.ai-tools i{font-style:normal}

/* The list is sized to the space it has, so nothing is ever half a row. */
.ai-list{flex:1;min-height:0;display:flex;flex-direction:column;gap:6px;
  align-content:flex-start;overflow:hidden}
.ai-zone{display:flex;align-items:center;gap:11px;height:40px;flex:none}
.ai-newz{height:0;opacity:0;overflow:hidden;
  transition:height .5s cubic-bezier(.32,.72,0,1),opacity .4s}
.is-file .ai-newz{height:40px;opacity:1}
.ai-zi{width:38px;height:38px;border-radius:13px;flex:none;display:grid;place-items:center}
.ai-zi svg{width:19px;height:19px;display:block}
.ai-zone h4{flex:1;min-width:0;margin:0;font-size:15px;font-weight:600;letter-spacing:-.02em}
.ai-zone em{font-style:normal;font-size:12px;font-weight:800;color:var(--ik3);flex:none}
.z-veg{background:#e8f2e8;color:#5a9e5a} .z-bak{background:#f8f0de;color:#c79a4a}
.z-dai{background:#e4eef8;color:#4a90c4}

.ai-it{display:flex;align-items:center;gap:11px;background:var(--sf);border-radius:15px;
  height:54px;padding:0 13px;flex:none;box-shadow:0 3px 12px rgba(44,62,80,.06)}
.ai-ck{width:25px;height:25px;border-radius:9px;border:2px solid #dbe2ec;flex:none;
  display:grid;place-items:center;color:#fff;transition:background .3s,border-color .3s}
.ai-ck svg{width:13px;height:13px;display:block;opacity:0;transition:opacity .25s}
.ai-it > div{flex:1;min-width:0;line-height:1.15}
.ai-it b{display:block;font-size:14.5px;font-weight:800;letter-spacing:-.02em}
.ai-it small{display:flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;
  color:var(--ik2);margin-top:2px}
.ai-it small svg{width:11px;height:11px;display:block;flex:none}
.ai-x{color:var(--ik3);flex:none;display:grid;place-items:center}
.ai-x svg{width:15px;height:15px;display:block}
/* the row that arrives: height, not max-height, so it can never be cut */
.ai-new{height:0;opacity:0;transform:translateY(-8px);overflow:hidden;
  transition:height .5s cubic-bezier(.32,.72,0,1),opacity .4s,transform .45s cubic-bezier(.32,.72,0,1)}
.is-file .ai-new{height:54px;opacity:1;transform:none}
/* the tick lands on the item that was ticked — and nowhere else */
.is-tick .ai-new .ai-ck{background:var(--a);border-color:var(--a)}
.is-tick .ai-new .ai-ck svg{opacity:1}
.is-tick .ai-new b{text-decoration:line-through;color:var(--ik3)}

.ai-toast{position:absolute;left:14px;right:14px;bottom:86px;z-index:4;
  display:flex;align-items:center;gap:9px;background:#2c3e50;color:#fff;
  border-radius:14px;padding:11px 13px;font-size:12.5px;font-weight:700;
  box-shadow:0 12px 28px -12px rgba(44,62,80,.75);
  opacity:0;transform:translateY(12px);
  transition:opacity .4s,transform .45s cubic-bezier(.32,.72,0,1)}
.ai-toast svg{width:15px;height:15px;display:block;flex:none;color:#9fd7c9}
.is-sync .ai-toast{opacity:1;transform:none}
.is-tick .ai-toast{opacity:1;transform:none}
.ai-nav{margin:8px -14px 0;height:68px;flex:none;background:rgba(255,255,255,.94);
  border-radius:24px 24px 0 0;display:flex;align-items:center;justify-content:space-around;
  padding:0 22px;box-shadow:0 -6px 24px -14px rgba(44,62,80,.3)}
/* `:not(.ai-fab)` is the point: the cart button is a span in this bar too,
   and this rule was turning it into an icon-over-label column. */
.ai-nav > span:not(.ai-fab){display:flex;flex-direction:column;align-items:center;
  gap:3px;font-size:10.5px;font-weight:700;color:var(--ik3)}
.ai-nav > span:not(.ai-fab) svg{width:20px;height:20px;display:block}
.ai-fab{position:relative;width:54px;height:54px;border-radius:19px;background:var(--a);
  color:#fff;display:grid;place-items:center;margin-top:-13px;
  box-shadow:0 12px 26px -10px rgba(34,64,94,.7),0 0 0 5px #eef1f6}
.ai-fab svg{width:23px;height:23px;display:block}
.ai-badge{position:absolute;top:-7px;inset-inline-end:-9px;min-width:23px;height:23px;
  padding:0 6px;border-radius:999px;background:#fff;color:var(--a);font-size:11.5px;
  font-weight:900;display:grid;place-items:center;box-shadow:0 3px 10px rgba(44,62,80,.22)}
.is-file .ai-badge{animation:aiBump .55s cubic-bezier(.32,.72,0,1)}
@keyframes aiBump{40%{transform:scale(1.3)}100%{transform:scale(1)}}

/* ── Matala — claymorphism. Violet + mint, 26px corners, no borders. ─ */
.mt{--p:#7A6AF0;--p2:#6656e0;--s:#6FE0C4;--s2:#EFEBFE;--s3:#F3EFFC;
  --tx:#2C2749;--mut:#7B7599;--warn:#FF7E7E;--ok:#4FD3A5;
  --clay:0 16px 28px -12px rgba(70,55,140,.3),0 5px 10px -6px rgba(70,55,140,.18),
         inset 0 -7px 11px -5px rgba(70,55,140,.16),inset 0 9px 13px -7px rgba(255,255,255,.95);
  height:100%;background:var(--s3);color:var(--tx);display:flex;flex-direction:column}
.mt-hd{background:linear-gradient(150deg,#9184FF,#6A59DE);border-radius:0 0 28px 28px;
  padding:18px;height:82px;display:flex;align-items:center;gap:12px;flex:none;
  box-shadow:0 14px 26px -16px rgba(70,55,140,.7)}
.mt-mark{width:44px;height:44px;border-radius:15px;flex:none;background:rgba(255,255,255,.22);
  display:grid;place-items:center;color:#D9FBF0;box-shadow:inset 0 2px 0 rgba(255,255,255,.4)}
.mt-mark svg{width:26px;height:26px;display:block}
.mt-hd div{flex:1;min-width:0;line-height:1.2}
.mt-hd b{display:block;font-size:18px;font-weight:800;color:#fff;letter-spacing:-.02em}
/* `.mt-hd > div > span`, not `.mt-hd span` — the logo tile is a span in this
   header as well, and the flat rule was blocking its centring. */
.mt-hd > div > span{display:block;font-size:12px;font-weight:700;color:var(--s)}
.mt-body{flex:1;min-height:0;position:relative}

/* the deck */
.mt-deck{position:absolute;inset:14px 18px 0;display:flex;flex-direction:column;
  transition:opacity .5s,transform .5s cubic-bezier(.32,.72,0,1)}
.is-split .mt-deck,.is-who .mt-deck{opacity:0;transform:scale(.94) translateY(-14px)}
.mt-prog{display:flex;align-items:center;gap:12px;height:20px;margin-bottom:14px;flex:none}
.mt-prog b{font-size:12.5px;font-weight:800;color:var(--mut);white-space:nowrap}
.mt-bar{flex:1;height:10px;border-radius:99px;background:#E6E0F7;overflow:hidden;
  box-shadow:inset 0 3px 6px -3px rgba(70,55,140,.3)}
.mt-bar i{display:block;height:100%;width:12.5%;border-radius:99px;background:var(--s);
  transition:width .55s cubic-bezier(.32,.72,0,1)}
.is-count .mt-bar i{width:37.5%}
.mt-cards{position:relative;flex:1;min-height:0}
.mt-card{position:absolute;inset:0;background:#fff;border-radius:26px;box-shadow:var(--clay);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
  padding:20px;text-align:center}
.mt-card--back{transform:scale(.93) translateY(-12px);opacity:.75;z-index:0}
.mt-card--top{z-index:1;transition:transform .6s cubic-bezier(.5,0,.75,0),opacity .6s}
.is-count .mt-card--top,.is-split .mt-card--top,.is-who .mt-card--top{
  transform:translateX(-118%) rotate(-17deg);opacity:0}
.mt-ci{width:64px;height:64px;border-radius:22px;background:var(--s2);color:var(--p);
  display:grid;place-items:center;margin-bottom:2px;flex:none}
.mt-ci svg{width:30px;height:30px;display:block}
.mt-card b{font-size:20px;font-weight:800;letter-spacing:-.03em}
.mt-card small{font-size:12.5px;font-weight:700;color:var(--mut)}
.mt-card em{font-style:normal;font-size:12px;font-weight:800;color:var(--p);
  background:var(--s2);border-radius:999px;padding:6px 14px;margin-top:3px}
.mt-stamp{position:absolute;top:16px;inset-inline-start:16px;display:inline-flex;
  align-items:center;gap:5px;font-size:11px;font-weight:800;color:var(--warn);
  border:2px solid var(--warn);border-radius:999px;padding:5px 11px;
  opacity:0;transform:rotate(-12deg) scale(1.3);transition:opacity .3s,transform .3s}
.mt-stamp svg{width:13px;height:13px;display:block}
.is-count .mt-stamp{opacity:1;transform:rotate(-12deg) scale(1)}
.mt-acts{display:flex;justify-content:center;align-items:center;gap:18px;
  height:76px;flex:none}
.mt-acts i{width:54px;height:54px;border-radius:999px;display:grid;place-items:center;
  color:#fff;box-shadow:var(--clay);flex:none}
.mt-acts i svg{width:23px;height:23px;display:block}
.mt-acts .b{background:var(--warn)}
.mt-acts .m{background:#fff;color:var(--p);width:46px;height:46px}
.mt-acts .m svg{width:19px;height:19px}
.mt-acts .g{background:var(--ok)}
.is-count .mt-acts .b{animation:mtTap .5s cubic-bezier(.32,.72,0,1)}
@keyframes mtTap{40%{transform:scale(.84)}100%{transform:scale(1)}}
.mt-hint{margin:0;text-align:center;font-size:11.5px;font-weight:600;color:var(--mut);flex:none}

/* the board */
.mt-board{position:absolute;inset:14px 18px 0;display:flex;flex-direction:column;gap:10px;
  opacity:0;transform:translateY(18px);
  transition:opacity .5s,transform .55s cubic-bezier(.32,.72,0,1)}
.is-split .mt-board,.is-who .mt-board{opacity:1;transform:none}
.mt-lab{margin:0;font-size:10.5px;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mut);flex:none}
.mt-two{display:flex;gap:10px;flex:none}
.mt-stat{flex:1;background:#fff;border-radius:22px;padding:13px 13px 15px;box-shadow:var(--clay)}
.mt-stat b{display:block;font-size:25px;font-weight:900;color:var(--p);letter-spacing:-.04em;
  line-height:1}
.mt-stat span{display:block;font-size:11px;font-weight:700;color:var(--tx);margin:5px 0 9px}
.mt-stat i{display:block;height:9px;border-radius:99px;background:#EFEBFE;overflow:hidden;
  box-shadow:inset 0 3px 5px -3px rgba(70,55,140,.28)}
.mt-stat i::after{content:"";display:block;height:100%;width:0;border-radius:99px;
  background:var(--p);transition:width .9s cubic-bezier(.32,.72,0,1) .15s}
.is-split .mt-stat--a i::after,.is-who .mt-stat--a i::after{width:71%}
.is-split .mt-stat--b i::after,.is-who .mt-stat--b i::after{width:100%}
.mt-misery{display:flex;align-items:center;gap:12px;background:#fff;border-radius:22px;
  padding:13px 14px;flex:none;box-shadow:var(--clay)}
.mt-misery > span{width:42px;height:42px;border-radius:15px;background:var(--s2);
  color:var(--p);display:grid;place-items:center;flex:none}
.mt-misery > span svg{width:21px;height:21px;display:block}
.mt-misery div{min-width:0;line-height:1.3}
.mt-misery b{display:block;font-size:13.5px;font-weight:800;letter-spacing:-.02em}
.mt-misery small{display:block;font-size:11.5px;color:var(--mut)}
.mt-whowrap{flex:1;min-height:0;display:flex;flex-direction:column;gap:10px;
  opacity:0;transform:translateY(12px);
  transition:opacity .45s,transform .5s cubic-bezier(.32,.72,0,1)}
.is-who .mt-whowrap{opacity:1;transform:none}
.mt-who{background:#fff;border-radius:22px;padding:11px 14px 6px;box-shadow:var(--clay);
  flex:1;min-height:0;overflow:hidden}
.mt-p{display:flex;align-items:center;gap:9px;height:34px;margin-bottom:5px}
.mt-av{width:30px;height:30px;border-radius:999px;background:var(--p);color:#fff;
  display:grid;place-items:center;font-size:13px;font-weight:900;flex:none}
.mt-p b{font-size:14px;font-weight:800}
.mt-p em{font-style:normal;font-size:10.5px;font-weight:800;color:var(--p);
  background:var(--s2);border-radius:999px;padding:4px 9px}
.mt-r{display:flex;align-items:center;gap:10px;height:38px;
  border-top:1px solid #F0ECFA;font-size:13px;font-weight:700;
  opacity:0;transform:translateX(-14px);
  transition:opacity .4s cubic-bezier(.32,.72,0,1),transform .4s cubic-bezier(.32,.72,0,1)}
.is-who .mt-r{opacity:1;transform:none}
.is-who .mt-r:nth-of-type(2){transition-delay:.07s}
.is-who .mt-r:nth-of-type(3){transition-delay:.15s}
.mt-r > svg{width:17px;height:17px;display:block;color:var(--p);flex:none}
.mt-r span{flex:1;min-width:0;font-size:13px;font-weight:800;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mt-r em{font-style:normal;font-size:11.5px;font-weight:700;color:var(--mut);flex:none}
.mt-r > b{font-size:13.5px;font-weight:900;color:var(--tx);flex:none;
  min-width:26px;text-align:end}
.mt-nav{height:64px;flex:none;background:#fff;border-radius:24px;margin:10px 16px 14px;
  display:flex;align-items:center;justify-content:space-around;box-shadow:var(--clay)}
.mt-nav i{position:relative;z-index:0;display:flex;flex-direction:column;align-items:center;
  gap:3px;font-style:normal;font-size:10px;font-weight:700;color:var(--mut)}
.mt-nav i svg{width:19px;height:19px;display:block}
.mt-nav i.on{color:#fff}
.mt-nav i.on::before{content:"";position:absolute;left:50%;top:50%;
  width:52px;height:52px;margin:-26px 0 0 -26px;border-radius:999px;
  background:var(--ok);z-index:-1}

/* ── PickMeUp — lavender and purple, shown in its English state. ────── */
.pm{--a:#8b5fbf;--a2:#61398f;--bg:#f5f3f7;--ik:#4a4a4a;--ik2:#6f6880;--ik3:#aaa2b8;
  height:100%;background:var(--bg);color:var(--ik);
  display:flex;flex-direction:column;position:relative;overflow:hidden}
/* the map is drawn here: this page's policy allows images from nowhere but
   itself, and a tile server is somewhere else */
.pm-map{position:absolute;inset:0}
.pm-map::before{content:"";position:absolute;inset:-24%;
  background:
    linear-gradient(90deg,transparent 0 46px,#fff 46px 55px,transparent 55px) 0 0/126px 100%,
    linear-gradient(0deg,transparent 0 58px,#fff 58px 66px,transparent 66px) 0 0/100% 150px,
    linear-gradient(90deg,transparent 0 18px,#faf8f4 18px 23px,transparent 23px) 0 0/44px 100%,
    linear-gradient(0deg,transparent 0 22px,#faf8f4 22px 26px,transparent 26px) 0 0/100% 50px,
    #ece7de;
  transform:rotate(-11deg)}
.pm-map::after{content:"";position:absolute;inset:0;
  background:radial-gradient(56% 40% at 24% 20%,#dfe9dc,transparent 70%),
             radial-gradient(46% 32% at 84% 72%,#dce7ea,transparent 70%)}
.pm-route{position:absolute;inset:0;z-index:1}
.pm-route path{fill:none;stroke:#8b5fbf;stroke-width:7;stroke-linecap:round;
  stroke-linejoin:round;stroke-dasharray:640;stroke-dashoffset:640;
  filter:drop-shadow(0 3px 8px rgba(97,57,143,.4))}
/* stroke-dashoffset on both of these is set from the scroll driver, so no
   transition is declared here — one would fight the scrub. */
.pm-dot{position:absolute;z-index:2;left:77%;top:27%;width:18px;height:18px;
  border-radius:999px;background:#8b5fbf;border:4px solid #fff;
  box-shadow:0 3px 10px rgba(97,57,143,.5)}
.pm-dot::after{content:"";position:absolute;inset:-6px;border-radius:999px;
  border:2px solid rgba(139,95,191,.5);animation:pmPing 2.2s ease-out infinite}
@keyframes pmPing{0%{transform:scale(.7);opacity:.9}100%{transform:scale(2.4);opacity:0}}

/* the three floating controls, clear of the panel below them */
.pm-fl{position:absolute;z-index:3;width:42px;height:42px;border-radius:15px;background:#fff;
  display:grid;place-items:center;color:var(--a);box-shadow:0 3px 12px rgba(97,57,143,.16)}
.pm-fl svg{width:19px;height:19px;display:block}
.pm-fl--a{top:16px;left:16px} .pm-fl--b{top:16px;right:16px}
.pm-fl--c{top:66px;left:16px;background:var(--a);color:#fff}

.pm-hud{position:relative;z-index:4;margin:124px 16px 0;background:#fff;border-radius:22px;
  height:74px;display:flex;align-items:center;box-shadow:0 8px 26px rgba(97,57,143,.14)}
.pm-hud div{flex:1;text-align:center;position:relative}
.pm-hud div + div::before{content:"";position:absolute;left:0;top:12%;
  height:76%;width:1px;background:#eee3f3}
.pm-hud b{display:block;font-size:20px;font-weight:900;letter-spacing:-.03em;color:var(--ik)}
.pm-hud .cost b{color:var(--a2)}
.pm-hud span{display:block;font-size:10.5px;font-weight:700;color:var(--ik3);margin-top:2px}

.pm-speedo{position:relative;z-index:4;width:146px;height:146px;margin:auto;
  display:grid;place-items:center;border-radius:999px;background:rgba(255,255,255,.94);
  box-shadow:0 14px 34px -12px rgba(97,57,143,.4)}
.pm-speedo svg{position:absolute;inset:0;width:100%;height:100%;transform:rotate(135deg)}
.pm-speedo .tr{fill:none;stroke:#ece3f4;stroke-width:9;stroke-linecap:round;
  stroke-dasharray:198 264}
.pm-speedo .fl{fill:none;stroke:#8b5fbf;stroke-width:9;stroke-linecap:round;
  stroke-dasharray:198 264;stroke-dashoffset:198}
.pm-sv{text-align:center;line-height:1}
.pm-sv b{display:block;font-size:38px;font-weight:900;letter-spacing:-.05em;color:var(--a2)}
.pm-sv span{display:block;font-size:11px;font-weight:700;color:var(--ik2);margin-top:4px}

.pm-btm{position:relative;z-index:4;padding:0 16px 18px;margin-top:auto}
.pm-end{height:56px;border-radius:22px;background:linear-gradient(150deg,#9b6fc9,#61398f);
  color:#fff;display:flex;align-items:center;justify-content:center;gap:10px;
  font-size:16.5px;font-weight:800;box-shadow:0 12px 28px -10px rgba(97,57,143,.7)}
.pm-end svg{width:20px;height:20px;display:block}
.is-done .pm-end{opacity:.4}

/* the ledger the trip ends on */
.pm-sum{position:absolute;z-index:5;inset:0;background:linear-gradient(178deg,#faf7fc,#f2ecf7);
  padding:26px 18px;display:flex;flex-direction:column;align-items:center;text-align:center;
  opacity:0;transform:translateY(26px);pointer-events:none;
  transition:opacity .5s,transform .55s cubic-bezier(.32,.72,0,1)}
.is-done .pm-sum{opacity:1;transform:none}
.pm-sum em{font-style:normal;display:inline-flex;align-items:center;gap:6px;flex:none;
  font-size:11.5px;font-weight:800;letter-spacing:.06em;color:var(--a2);
  background:rgba(139,95,191,.11);border-radius:999px;padding:7px 14px}
.pm-sum em svg{width:14px;height:14px;display:block}
.pm-total{font-size:60px;font-weight:900;letter-spacing:-.05em;color:var(--a2);
  line-height:1.05;margin-top:14px;flex:none}
.pm-sub{font-size:13px;font-weight:700;color:var(--ik2);margin-top:2px;flex:none}
.pm-row{display:flex;width:100%;background:#fff;border-radius:22px;height:78px;
  align-items:center;margin-top:18px;flex:none;box-shadow:0 8px 26px rgba(97,57,143,.12)}
.pm-row div{flex:1;position:relative}
.pm-row div + div::before{content:"";position:absolute;left:0;top:12%;
  height:76%;width:1px;background:#f0e8f6}
.pm-row b{display:block;font-size:22px;font-weight:900;letter-spacing:-.03em;color:var(--ik)}
.pm-row span{display:block;font-size:11px;font-weight:700;color:var(--ik3);margin-top:3px}
.pm-chart{width:100%;background:#fff;border-radius:22px;padding:13px 12px 9px;margin-top:12px;
  flex:none;box-shadow:0 8px 26px rgba(97,57,143,.12);text-align:start}
.pm-chart h5{margin:0 0 7px;font-size:11.5px;font-weight:800;color:var(--ik2)}
.pm-chart svg{display:block;width:100%;height:70px}
.pm-chart .fill{fill:url(#pmg)}
.pm-chart .line{fill:none;stroke:#8b5fbf;stroke-width:2.6;stroke-linejoin:round;
  stroke-linecap:round}
.pm-chart p{margin:5px 0 0;font-size:11px;font-weight:700;color:var(--ik3)}
.pm-chart p b{color:var(--a2)}
.pm-split{width:100%;background:#fff;border-radius:22px;padding:13px 14px;margin-top:12px;
  flex:none;box-shadow:0 8px 26px rgba(97,57,143,.12);text-align:start}
.pm-split h5{margin:0 0 8px;font-size:11.5px;font-weight:800;color:var(--ik2)}
.pm-sr{display:flex;align-items:center;gap:9px;height:38px;font-size:13px;font-weight:700}
.pm-sr + .pm-sr{border-top:1px solid #f4eef8}
.pm-sr i{width:27px;height:27px;border-radius:999px;background:rgba(139,95,191,.12);
  color:var(--a);display:grid;place-items:center;flex:none}
.pm-sr i svg{width:15px;height:15px;display:block}
.pm-sr span{flex:1;min-width:0}
.pm-sr b{font-weight:900;color:var(--a2);flex:none}

/* ═══════════════════════════════════════════════════════════════════════
   Below 900px nothing is pinned and nothing overlaps. The three projects
   simply stack, each a screenful of its own, with the app at the top at a
   size you can read and the words under it on solid ground. A pinned
   stage on a phone is how this section once presented as empty, and a
   paragraph set over a running interface on a 390px screen is not
   readable — readable wins.
   ═══════════════════════════════════════════════════════════════════════ */
/* Narrow desktops only. This has to be scoped to the pinned layout: the
   left padding exists to clear the rail, and unscoped it also applied on a
   phone — where there is no rail — and squashed the panel to three quarters
   of the card and shoved it against the right-hand edge. That is the
   off-centre, clipped screen in Elad's phone screenshot. */
@media (max-width:1180px){
  .stage.is-pinned .proj{padding:0 clamp(24px,4vw,44px) 0 clamp(78px,8vw,104px);
    gap:clamp(16px,2.6vw,34px)}
  .stage.is-pinned .proj__brief{display:none}
  /* no room for the names beside the numbers before the panel starts */
  .stage__rail li{font-size:0}
  .stage__rail li::after{content:attr(data-n);font-size:11px;letter-spacing:.14em}
}
@media (max-width:900px){
  .stage{border-radius:var(--r-lg)}
  .proj__brief{display:block;max-width:none}
  .proj__build{max-width:none}
  .proj__one{max-width:none;font-size:clamp(20px,5.4vw,26px)}
  .proj__name{font-size:clamp(38px,10vw,56px)}
}

/* Reduced motion: no drift, no pulse, and the scene holds on its last beat
   instead of running. The section is a picture of three finished products
   either way. */
@media (prefers-reduced-motion:reduce){
  .proj__frame,.proj__ghost{transition:none}
  .pm-dot::after{animation:none}
  .proj__cap i{animation:none}
  .is-type .ai-caret{animation:none;opacity:1}
}


/* ══════════════════════════════════════════ G1 · the button rungs ══
   Lives here rather than in ui.css because five of the twenty-five pages
   load ui.css and all of them load this — and `.btn` is this file's own
   class. ui.css maps the studio's and the shop's own families onto the
   same rungs; the numbers are written once, here.

   Measured before writing it: ten button heights between 31 and 66px
   across thirteen routes, seven type sizes, three weights, four radii —
   with `.btn` alone rendering at 66, 59 and 48 depending on the page and
   on whether it happened to carry an icon. */
:root{
  --btn-lg-h:48px;  --btn-lg-fs:15px;   --btn-lg-px:22px;
  --btn-md-h:40px;  --btn-md-fs:14px;   --btn-md-px:16px;
  --btn-sm-h:30px;  --btn-sm-fs:12.5px; --btn-sm-px:12px;
  --btn-ico:34px;
  --btn-fw:700;
}

/* lg — `.btn`, everywhere. It was three sizes under one name: 66px on the
   homepage, 59px on a form, 48px in the app. The 66/59 split inside a single
   page was not even a decision — the ones with an icon were taller, because
   the glyph outgrew the line box and pushed the padding out.
   One rung, and an icon can no longer change the height. */
.btn{
  min-height:var(--btn-lg-h);
  align-items:center;
  padding-block:0;
  padding-inline:var(--btn-lg-px);
  font-size:var(--btn-lg-fs);
  font-weight:800;
  border-radius:999px;
  line-height:1;
}
.btn>i[data-cvicon],.btn>i[data-icon]{flex:none}
/* The one place a bigger target is the point: the two calls to action a
   visitor meets on the homepage. Deliberate, named, and only there. */
.btn--big{
  min-height:60px;
  padding-inline:30px;
  font-size:16.5px;
}


@media (max-width:760px){
  :root{--btn-lg-h:46px}
  .btn--big{min-height:52px;padding-inline:24px;font-size:15.5px}
}

/* The footer language row. The site is English by design; /he, /fr, /de and
   /es are real localized landing pages that are not in the nav, so this one
   discreet row is the only place a human can walk to them — and hreflang is
   trusted far more when the alternates are actually reachable. */
.foot__langs{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center}
.foot__langs a{color:var(--ink-3);text-decoration:none;font-size:14px;font-weight:600}
.foot__langs a:hover{color:var(--brand)}
