:root{
  --paper:#FFFDFB; --panel:#F7F5F1; --sunk:#F1EEE9;
  --ink:#0C0F14; --ink2:#39424E; --muted:#59616D; --rule:#E7E3DC;
  --flame1:#FF9040; --flame2:#FF5A1E; --flame3:#E5206B;
  --accent:#C2410C; --live:#16A34A;
  /* Named because a theme has to redefine them. --on-ink is the text that sits
     on --ink or on the flame, and it is the one that silently breaks in dark:
     white on a light button reads as nothing at all. --chrome is the sticky
     bars' own translucent ground, --warm the card's hover edge, --story-ink the
     chapter drawing behind the page. */
  --on-ink:#FFFFFF;
  --chrome:rgba(255,255,255,.92);
  --warm:#F0DCCB; --warm2:#F7E6DA; --warm3:#EFE3D8;
  --story-ink:#0C0F14;
  --shadow:12,15,20;
  --flame:linear-gradient(115deg,var(--flame1),var(--flame2) 46%,var(--flame3));
  /* The flame is decoration. Anything that carries text uses these instead:
     --flame-deep under white text (5.2:1 at its lightest stop), --flame-ink as
     gradient text on the page ground (5.1:1 on paper). Dark swaps --flame-ink
     back to the bright flame, which is what reads on a dark ground. */
  --flame-deep:linear-gradient(115deg,#C2410C,#BE185D);
  --flame-ink:linear-gradient(115deg,#C2410C,#BE185D);
  /* the italic turn in a heading: the original orange-to-pink, one step deeper
     so it holds 3.4:1 or better at heading size on paper and on the tint */
  --turn:linear-gradient(115deg,#E4571B,#DB2777);
  --rail:250px; --gut:clamp(20px,3.4vw,52px);
  --f:"Manrope",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --m:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  /* Instrument Serif carries the one classic voice on the site — the quoted
     line, and nothing else. Caveat is the margin hand: annotations that read as
     somebody's note on the page rather than another styled component. Both are
     SIL Open Font Licence, like Sora and the mono. */
  --s:"Instrument Serif",Georgia,"Times New Roman",serif;
  --h:"Caveat","Segoe Script","Bradley Hand",cursive;
}

/* ---------- dark ----------
   Opt-in only: light is the default and prefers-color-scheme is deliberately
   not consulted, because the toggle is the thing that decides. The stamp lands
   on <html> before first paint, from the inline script in every page's head. */
:root[data-theme="dark"]{
  --paper:#0F0D14; --panel:#17141C; --sunk:#1C1826;
  --ink:#FFFFFF; --ink2:#C9C4D2; --muted:#9A93A8; --rule:#2A2434;
  --accent:#FF8A4C; --live:#4ADE80;
  --on-ink:#0F0D14;
  --chrome:rgba(15,13,20,.86);
  --warm:#45302A; --warm2:#5A3A2A; --warm3:#3A2A24;
  --story-ink:#FFFFFF;
  --shadow:0,0,0;
  --flame-ink:var(--flame);
  --turn:var(--flame);
}
/* The chapter drawing is inline SVG with its ink baked into stroke/fill
   attributes. CSS beats a presentation attribute, so the neutral strokes
   retheme and the flame accent is left alone. */
:root[data-theme="dark"] .story [stroke="#0C0F14"]{stroke:var(--story-ink)}
:root[data-theme="dark"] .story [fill="#0C0F14"]{fill:var(--story-ink)}
/* Posters and letters are light artwork; on a dark ground they glare. */
:root[data-theme="dark"] .wall img,
:root[data-theme="dark"] .lpreview img{filter:brightness(.88) contrast(1.02)}

*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--f);
  font-weight:500;font-size:16.5px;line-height:1.72;-webkit-font-smoothing:antialiased}
svg,img{max-width:100%;display:block}
a{color:inherit}
button{font:inherit;color:inherit}
:focus-visible{outline:2.5px solid var(--accent);outline-offset:3px;border-radius:6px}
.skip{position:absolute;left:-9999px;background:var(--ink);color:var(--on-ink);padding:12px 18px;
  z-index:99}
.skip:focus{left:8px;top:8px}
.mono{font-family:var(--m)}
.tiny{font-size:12px;letter-spacing:.02em;color:var(--muted)}

/* ---------- the shell ---------- */
.shell{display:grid;grid-template-columns:var(--rail) minmax(0,1fr);min-height:100vh}
.rail{position:sticky;top:0;height:100vh;background:var(--panel);
  border-right:1px solid var(--rule);display:flex;flex-direction:column;
  padding:18px 14px;gap:22px}
.rail .brand{display:flex;align-items:center;gap:9px;text-decoration:none;
  font-weight:800;letter-spacing:-.022em;font-size:16.5px;padding:6px 10px}
.rail .brand .mk{height:17px;width:auto;color:var(--flame2)}
.rail .brand i{font-style:normal;font-weight:500;color:var(--muted)}
.rail nav{display:flex;flex-direction:column;gap:2px}
.rail .grp{margin:14px 0 5px;padding:0 11px;font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted)}
.rail .grp:first-child{margin-top:0}
.rail nav a{display:flex;align-items:center;justify-content:space-between;gap:10px;
  text-decoration:none;font-size:14.5px;color:var(--ink2);padding:9px 11px;
  border-radius:8px;transition:transform .16s,background .16s}
.rail nav a:hover{background:var(--sunk);transform:translateX(3px)}
.rail nav a.on{background:var(--paper);color:var(--ink);font-weight:600;
  box-shadow:0 1px 2px rgba(var(--shadow),.06),0 0 0 1px var(--rule)}
.rail kbd{font-family:var(--m);font-size:10.5px;color:var(--muted);
  border:1px solid var(--rule);border-radius:5px;padding:1px 5px;background:var(--paper)}
.railfoot{margin-top:auto;padding:10px 11px;display:grid;gap:5px}
.stat{margin:0;font-family:var(--m);font-size:11.5px;color:var(--muted);
  display:flex;align-items:center;gap:7px}
.pulse{width:7px;height:7px;border-radius:50%;background:var(--live);flex:none;
  box-shadow:0 0 0 0 rgba(22,163,74,.5);animation:ping 2.6s ease-out infinite}
@keyframes ping{70%{box-shadow:0 0 0 8px rgba(22,163,74,0)}
  100%{box-shadow:0 0 0 0 rgba(22,163,74,0)}}

.panehost{min-width:0;display:flex;flex-direction:column}
.topbar{position:sticky;top:0;z-index:30;display:flex;align-items:center;gap:14px;
  padding:11px var(--gut);background:var(--chrome);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--rule)}
.crumb{margin:0;font-size:14px;color:var(--ink2)}
.crumb .mono{color:var(--muted);font-size:12.5px}
.cmdk{margin-left:auto;display:flex;align-items:center;gap:12px;background:var(--panel);
  border:1px solid var(--rule);border-radius:9px;padding:7px 11px;font-size:13.5px;
  color:var(--muted);cursor:pointer;transition:border-color .16s}
.cmdk:hover{border-color:var(--muted)}
.cmdk kbd{font-family:var(--m);font-size:11px;border:1px solid var(--rule);
  border-radius:5px;padding:1px 5px;background:var(--paper)}
.btn{display:inline-flex;align-items:center;text-decoration:none;font-weight:600;
  font-size:14.5px;padding:9px 17px;border-radius:999px;background:var(--ink);
  color:var(--on-ink);flex:none;transition:transform .16s}
.btn:hover{transform:translateY(-1.5px)}
/* the gradient is the same in both themes, so its text is too */
/* The primary button is the site's original quiet pill: ink on paper, paper on
   ink in dark. The flame stays in the mark and the headings, not under a label. */
.btn.flame{background:var(--ink);color:var(--on-ink)}
button.btn{border:0;cursor:pointer;font-family:var(--f)}
.btn.line{background:none;color:var(--ink);border:1px solid var(--rule)}

.pane{flex:1;padding:0 var(--gut) 0;animation:settle .34s ease-out}
@keyframes settle{from{opacity:.4;transform:translateY(6px)}}
.pane > section{max-width:920px;padding-block:clamp(40px,5.4vw,76px);
  border-top:1px solid var(--rule)}
.pane.wide > section{max-width:none}
.pane > section:first-of-type{border-top:0}
.pane footer{max-width:920px;border-top:1px solid var(--rule);padding-block:26px 46px;
  display:grid;gap:9px}
/* Every view reachable from every view. The column count comes from the width
   the footer has rather than a breakpoint, so it thins to two and then one
   without anything being told to. */
.fgrid{display:grid;gap:26px 30px;padding-bottom:26px;margin-bottom:22px;
  border-bottom:1px solid var(--rule);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,158px),1fr))}
.fcol{display:grid;gap:9px;align-content:start;min-width:0}
.fcol h2{font-family:var(--m);font-size:10.5px;font-weight:500;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);margin:0}
.fcol nav{display:grid;gap:7px}
.fcol a{font-size:14px;color:var(--ink2);text-decoration:none;
  transition:color .16s,transform .16s}
.fcol a:hover{color:var(--accent);transform:translateX(2px)}
.fbase{display:grid;gap:9px}

/* A fact only the company holds. Marked rather than guessed: a policy that
   states a retention period nobody chose is worse than one that admits the gap,
   and this has to be impossible to ship by accident. */
.fill{background:rgba(255,144,64,.16);color:var(--accent);
  border:1px dashed var(--accent);border-radius:5px;padding:1px 7px;
  font-family:var(--m);font-size:12.5px;font-style:normal;line-height:1.5;
  display:inline;box-decoration-break:clone;-webkit-box-decoration-break:clone}
.fill::before{content:"to complete: ";opacity:.72;letter-spacing:.06em;
  text-transform:uppercase;font-size:9.5px}

.footlinks{display:flex;flex-wrap:wrap;gap:6px 20px;margin-bottom:5px}
.footlinks a{font-family:var(--m);font-size:12.5px;color:var(--muted);
  text-decoration:none}
.footlinks a:hover{color:var(--ink)}
/* the one line on the page written by a hand rather than set by a system */
.fsig{font-family:var(--h);font-weight:500;font-size:21px;color:var(--muted);
  margin-top:6px;transform:rotate(-1.2deg);transform-origin:left center}

/* ---------- the phone build ----------
   Under 900px the desktop chrome is not squeezed, it is replaced: a sticky app
   bar at the top, a fixed tab bar at the bottom, and the views reachable from a
   sheet rather than from a rail that has been turned on its side. Every fixed
   edge pads itself out of the safe area, so the bar clears a home indicator and
   the app bar clears a notch. */
.appbar{display:none;position:sticky;top:0;z-index:40;align-items:center;gap:12px;
  padding:calc(9px + env(safe-area-inset-top)) 16px 9px;
  background:var(--chrome);backdrop-filter:saturate(180%) blur(14px);
  border-bottom:1px solid var(--rule)}
.appbar .brand{display:flex;align-items:center;gap:8px;text-decoration:none;
  font-weight:800;letter-spacing:-.022em;font-size:16.5px}
.appbar .brand .mk{height:16px;width:auto;color:var(--flame2)}
.appbar .brand i{font-style:normal;font-weight:500;color:var(--muted)}
/* ---------- the signature line ----------
   Rides the eyebrow after a hairline dot: the label stays mono and shouting,
   the line answers it in the classic italic the site keeps for its one quoted
   voice. It is a kicker, not a second headline — if it ever reads as loud as
   the h1 it has failed. */
.sigline{font-family:var(--s);font-style:italic;font-weight:400;
  font-size:15.5px;letter-spacing:.004em;text-transform:none;color:var(--ink2);
  margin-left:12px;padding-left:13px;position:relative;white-space:nowrap}
.sigline::before{content:"";position:absolute;left:0;top:50%;width:5px;height:5px;
  margin-top:-2.5px;border-radius:50%;background:var(--flame);opacity:.8}
@media(max-width:640px){
  /* on a phone it drops under the label rather than squeezing it */
  .sigline{display:block;margin:7px 0 0;padding-left:0;font-size:15px;
    white-space:normal}
  .sigline::before{display:none}
}

/* ---------- the hero mark ----------
   One drawing per view, sitting in the hero at a few per cent ink. It is a
   watermark: it never competes with the headline, it is inert to the pointer,
   and it is hidden from screen readers. Ink comes from --ink so it follows the
   theme without a second palette, and --mark-turn / --mark-lean are set once on
   <html> from the hour, so a page opened at night leans differently from the
   same page at noon. */
.mark{position:absolute;right:clamp(-30px,-1vw,8px);top:50%;
  width:clamp(200px,26vw,380px);aspect-ratio:1;translate:0 -50%;
  color:var(--ink);opacity:var(--mark-ink,.07);pointer-events:none;
  z-index:0;user-select:none;
  /* Feathered at its own edges so it reads as part of the page rather than a
     drawing placed on top of it — the difference between a watermark and a
     graphic. */
  -webkit-mask-image:radial-gradient(closest-side,#000 52%,transparent 92%);
  mask-image:radial-gradient(closest-side,#000 52%,transparent 92%)}
.mark svg{width:100%;height:100%;display:block;overflow:visible;
  rotate:var(--mark-turn,0deg);
  transition:rotate .9s cubic-bezier(.2,.8,.25,1),opacity .5s}
/* the hero holds it: everything else in the section stays above */
.pane > section:first-of-type{position:relative;overflow:clip}
.pane > section:first-of-type > .wrap{position:relative;z-index:1}
/* Dark ground takes more ink before a line reads at all. */
:root[data-theme="dark"] .mark{opacity:var(--mark-ink-dark,.085)}
/* The scroll parallax is a transform on the wrapper, so the rotate above is
   free to be its own property and the two never fight. */
.mark{will-change:transform}
@media(max-width:900px){
  /* On a phone the hero is the whole first screen, so the mark moves behind
     the text rather than beside it, and loses a little more ink. */
  .mark{right:auto;left:50%;translate:-50% -50%;width:min(78vw,340px);
    opacity:var(--mark-ink-sm,.04)}
  :root[data-theme="dark"] .mark{opacity:.06}
}
@media(prefers-reduced-motion:reduce){
  .mark svg{transition:none}
  .mark{transform:none!important}
}

/* ---------- theme toggle ----------
   One circle and eight rays. Light: a full disc with its rays out. Dark: the
   rays retract, a second disc slides in from the corner and bites a crescent
   out of the first, and the whole thing turns a few degrees. The bite is a
   mask rather than a second drawn shape, so the crescent keeps the flame
   gradient instead of flattening to a silhouette. */
.themed{flex:none;width:34px;height:34px;display:grid;place-items:center;
  border:1px solid var(--rule);border-radius:50%;background:var(--panel);
  cursor:pointer;padding:0;color:var(--accent);
  transition:border-color .2s,background .2s,transform .2s}
.themed:hover{border-color:var(--accent);background:var(--sunk)}
.themed:active{transform:scale(.92)}
.themed svg{width:17px;height:17px;display:block;overflow:visible;
  transition:transform .5s cubic-bezier(.4,1.4,.5,1)}
:root[data-theme="dark"] .themed svg{transform:rotate(-38deg)}
.themed .disc{transition:transform .45s cubic-bezier(.4,1.4,.5,1)}
.themed .rays line{stroke:currentColor;stroke-width:2;stroke-linecap:round;
  transform-origin:12px 12px;
  transition:transform .4s cubic-bezier(.4,1.5,.5,1),opacity .28s}
/* the mask disc parks outside the frame in light, and slides over in dark */
.themed .bite{transform:translate(9px,-9px);
  transition:transform .45s cubic-bezier(.4,1.4,.5,1)}
:root[data-theme="dark"] .themed .bite{transform:translate(4.5px,-4.5px)}
:root[data-theme="dark"] .themed .disc{transform:scale(1.16);transform-origin:12px 12px}
:root[data-theme="dark"] .themed .rays line{transform:scale(.15);opacity:0}
.themed .rays line:nth-child(2){transition-delay:.02s}
.themed .rays line:nth-child(3){transition-delay:.04s}
.themed .rays line:nth-child(4){transition-delay:.06s}
.themed .rays line:nth-child(5){transition-delay:.08s}
.themed .rays line:nth-child(6){transition-delay:.10s}
.themed .rays line:nth-child(7){transition-delay:.12s}
.themed .rays line:nth-child(8){transition-delay:.14s}
@media(prefers-reduced-motion:reduce){
  .themed svg,.themed .disc,.themed .bite,.themed .rays line{transition:none}
}

/* ---------- sign in ----------
   On the phone bar it sits after the search button, which already claims
   margin-left:auto — so this one does not, or the two fight over the gap. */
.appbar .signin{flex:none;text-decoration:none;font-weight:600;font-size:14px;
  letter-spacing:-.01em;color:var(--ink);border:1px solid var(--rule);
  border-radius:999px;padding:8px 14px;min-height:38px;display:inline-flex;
  align-items:center;background:var(--paper)}
.appbar .signin:active{transform:scale(.97)}
/* A keyboard key named in running text — the rail and command bar style their
   own; this is the one for prose. */
.pane p kbd,.pane li kbd{font-family:var(--m);font-size:11.5px;line-height:1;
  color:var(--ink2);border:1px solid var(--rule);border-bottom-width:2px;
  border-radius:5px;padding:2px 5px;background:var(--panel);
  display:inline-block;vertical-align:baseline;margin-inline:1px}

.iconbtn{margin-left:auto;display:grid;place-items:center;width:44px;height:44px;
  border:1px solid var(--rule);border-radius:12px;background:var(--paper);
  color:var(--ink2);cursor:pointer}
.iconbtn .ic{width:21px;height:21px}
.iconbtn:active{background:var(--sunk)}

.tabbar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:60;
  grid-template-columns:repeat(5,1fr);gap:2px;
  padding:5px 4px calc(5px + env(safe-area-inset-bottom));
  background:var(--chrome);backdrop-filter:saturate(180%) blur(16px);
  border-top:1px solid var(--rule)}
.tab{display:grid;justify-items:center;gap:3px;padding:7px 2px 6px;border:0;
  border-radius:12px;background:none;text-decoration:none;cursor:pointer;
  font-size:10.5px;letter-spacing:.01em;color:var(--muted);min-height:52px;
  transition:color .14s,background .14s}
.tab .ic{width:22px;height:22px}
.tab.on{color:var(--accent)}
.tab:active{background:var(--sunk)}

/* The sheet: one panel, three groups, whichever the tab asked for. */
.sheetwrap{position:fixed;inset:0;z-index:70;display:flex;align-items:flex-end;
  background:rgba(var(--shadow),.38);backdrop-filter:blur(2px);animation:fade .18s ease}
@keyframes fade{from{opacity:0}}
.sheet{width:100%;max-height:78dvh;display:flex;flex-direction:column;
  background:var(--paper);border-radius:20px 20px 0 0;
  box-shadow:0 -20px 60px -30px rgba(var(--shadow),.6);
  padding:8px 14px calc(16px + env(safe-area-inset-bottom));
  animation:rise .22s cubic-bezier(.2,.8,.25,1)}
@keyframes rise{from{transform:translateY(100%)}}
.grab{width:40px;height:4px;border-radius:2px;background:var(--rule);
  margin:2px auto 10px;flex:none}
.sheetbody{overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.sheetg h2{font-size:13px;letter-spacing:.16em;text-transform:uppercase;
  font-family:var(--m);font-weight:500;color:var(--muted);margin:2px 6px 8px}
.srow{display:flex;align-items:center;justify-content:space-between;gap:14px;
  text-decoration:none;padding:12px 12px;border-radius:13px;min-height:56px}
.srow:active{background:var(--sunk)}
.srow[aria-current="page"]{background:var(--panel)}
.sw{display:grid;gap:2px;min-width:0}
.sw b{font-size:15.5px;font-weight:600;letter-spacing:-.012em}
.sw span{font-family:var(--m);font-size:11.5px;color:var(--muted)}
.sgo{color:var(--muted);flex:none}

/* Touch standards, applied once rather than per component: no 300ms delay, no
   grey flash on tap, and a press state on everything that is pressable. */
html{-webkit-text-size-adjust:100%}
a,button,input,select,label{-webkit-tap-highlight-color:transparent;
  touch-action:manipulation}
@media(hover:none){
  .btn:active,.card:active,.ext:active,.dept:active,.tile:active,.dl:active{
    transform:scale(.985)}
  .btn:hover,.ext:hover,.tile:hover{transform:none}
}
[hidden]{display:none!important}

@media(max-width:900px){
  .shell{grid-template-columns:1fr}
  .rail,.topbar{display:none}
  .appbar{display:flex}
  .tabbar{display:grid}
  .pane{padding-bottom:calc(74px + env(safe-area-inset-bottom))}
  .pane > section{padding-block:34px}
}

/* ---------- content ---------- */
/* Page and section headings are written in the margin hand — the same Caveat
   the notes use ("pick one. the honest version") — set straight rather than
   tilted, so they read as a person's sentence and still scan as headings. Lines
   fall where balance puts them. Caveat is small on its body, so it is sized up
   against the sans. Card-level h3s stay in the sans, so the two never compete. */
h1,h2,h3{margin:0;text-wrap:balance}
h1,h2{font-family:var(--h);font-weight:600;letter-spacing:0;line-height:1.02;
  color:var(--ink)}
h1{font-size:clamp(48px,6.4vw,80px)}
h2{font-size:clamp(36px,4.5vw,56px);line-height:1.05}
h3{font-weight:700;font-size:clamp(18px,1.9vw,21px);letter-spacing:-.018em;line-height:1.28}
/* the turn inside a heading keeps its flame colour but stays in the same hand:
   Caveat has no italic, and a synthesised slant would smear it */
h1 .ser,h2 .ser{font-family:inherit;font-style:normal;font-weight:inherit;
  font-size:1em;line-height:inherit;letter-spacing:0}
p{margin:0;max-width:64ch;color:var(--ink2)}
.lede{font-size:clamp(17px,1.8vw,20px);line-height:1.62;color:var(--ink2);
  max-width:62ch}
.eyebrow{font-family:var(--m);font-size:11.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);margin:0 0 16px}
.stack{display:flex;flex-direction:column;align-items:flex-start;gap:22px}
.grad{background:var(--turn);-webkit-background-clip:text;background-clip:text;
  color:transparent}
.cta{display:flex;flex-wrap:wrap;gap:10px}
.tint{background:color-mix(in srgb,var(--panel) 82%,transparent);
  margin-inline:calc(var(--gut)*-1);
  padding-inline:var(--gut)!important;max-width:none!important}
.tint > *{max-width:920px}

.grid{display:grid;gap:clamp(13px,1.7vw,20px);width:100%;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,238px),1fr))}
.grid.two{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}
.card{border:1px solid var(--rule);background:var(--paper)}
.card p{color:var(--muted)}
.num{font-family:var(--m);font-size:11px;letter-spacing:.18em;color:var(--muted);
  display:block;margin-bottom:12px}

/* ---------- the cards ----------
   Every .grid on the site is these, so the treatment is here rather than on one
   page's own class. Columns come from the width the content actually has —
   min(100%,…) so a narrow pane is never asked for more than it has — and the two
   rules below catch the one case auto-fit cannot see: a third card left alone on
   a second row. Everything past that is decoration, and the cards are complete
   without it: the reveal is gated on .js, so with no script they are simply
   there. Below 640px none of it applies — the deck takes over. */
/* Two columns, three cards. The rail's presence decides the pane's width, so
   the ranges are the viewport's — with rail, then without, and never inside the
   swipe deck, where a card spanning the row would break the snap. */
@media(min-width:900px) and (max-width:1129px){
  .grid > .card:nth-child(3):last-child{grid-column:1/-1}}
@media(min-width:641px) and (max-width:899px){
  .grid > .card:nth-child(3):last-child{grid-column:1/-1}}

.card{position:relative;overflow:hidden;isolation:isolate;border-radius:14px;
  padding:clamp(18px,2.1vw,26px);
  transition:translate .3s cubic-bezier(.2,.8,.25,1),box-shadow .3s,border-color .3s}
/* The lift is `translate`, not `transform`: the reveal below animates transform,
   and an animation with a fill wins the cascade over a hover that names the same
   property — which is how the lift quietly stops working once a card has
   arrived. The two compose instead. */
.card:hover{translate:0 -4px;border-color:var(--warm);
  box-shadow:0 22px 38px -28px rgba(197,74,20,.62)}
.card:active{scale:.988}

/* the rule across the top, drawn when the card arrives */
.card::before{content:"";position:absolute;inset:0 0 auto;height:2px;
  background:var(--flame);transform-origin:left;
  transition:transform .62s cubic-bezier(.2,.8,.25,1)}
.js .grid.anim .card::before{transform:scaleX(0)}
.js .grid.anim.in .card::before{transform:scaleX(1)}
.js .grid.anim.in .card:nth-child(2)::before{transition-delay:.11s}
.js .grid.anim.in .card:nth-child(3)::before{transition-delay:.22s}
.js .grid.anim.in .card:nth-child(4)::before{transition-delay:.33s}

/* warmth under the pointer, behind the words and above the card's own ground */
.card::after{content:"";position:absolute;inset:0;z-index:-1;opacity:0;
  background:radial-gradient(120% 92% at 14% 0,rgba(255,90,30,.11),transparent 64%);
  transition:opacity .3s}
.card:hover::after{opacity:1}

/* the numeral twice: once to read, once oversized as the card's decoration */
.ghost{position:absolute;right:-4px;top:-18px;z-index:-1;
  font-family:var(--m);font-weight:500;font-size:clamp(72px,7.4vw,104px);
  line-height:1;letter-spacing:-.05em;color:var(--sunk);
  transition:color .32s,translate .45s cubic-bezier(.2,.8,.25,1)}
.card:hover .ghost{color:var(--warm2);translate:0 4px}
.card .num{display:inline-block;margin:0;font-size:12px;letter-spacing:.2em;
  font-weight:600;background:var(--flame-ink);-webkit-background-clip:text;
  background-clip:text;color:transparent}
.kick{display:block;margin:3px 0 12px;font-family:var(--m);font-size:10.5px;
  letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.card h3{margin-bottom:9px}
/* Stretched link: the heading's anchor claims the whole card as its hit area,
   so a thumb can land anywhere on it. The card is already position:relative,
   and the pseudo-element sits under the text rather than over it, so selecting
   the copy still works. */
.card h3 a{text-decoration:none;color:inherit;
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:color-mix(in srgb,var(--accent) 45%,transparent)}
.card h3 a::after{content:"";position:absolute;inset:0;z-index:1}
.card:hover h3 a{color:var(--accent)}
.card h3 a:focus-visible{outline-offset:6px}
.card p{font-size:15px;max-width:44ch}

/* the reveal itself: the .in the diagrams already use, one card behind the next */
.js .grid.anim .card{opacity:0;transform:translateY(15px)}
.js .grid.anim.in .card{animation:cardIn .62s cubic-bezier(.2,.8,.25,1) both}
.js .grid.anim.in .card:nth-child(2){animation-delay:.09s}
.js .grid.anim.in .card:nth-child(3){animation-delay:.18s}
.js .grid.anim.in .card:nth-child(4){animation-delay:.27s}
@keyframes cardIn{to{opacity:1;transform:none}}

.rows{list-style:none;margin:0;padding:0;width:100%}
.rows li{display:grid;gap:6px 28px;grid-template-columns:236px minmax(0,1fr);
  padding:20px 0;border-top:1px solid var(--rule);align-items:baseline}
.rows li:first-child{border-top:0}
.rows .k{font-family:var(--m);font-size:12.5px;letter-spacing:.04em;color:var(--muted);
  min-width:0}
.rows .k b{display:block;font-family:var(--f);font-size:16.5px;letter-spacing:-.012em;
  color:var(--ink);font-weight:600;margin-bottom:3px;overflow-wrap:anywhere}
.rows .k .chip{margin-top:6px}
.rows p{font-size:15px;color:var(--ink2)}
.rows li.on{background:linear-gradient(90deg,rgba(255,90,30,.07),transparent 62%);
  border-radius:10px;padding-inline:13px;margin-inline:-13px}
.rows li.on .k b{color:var(--accent)}
@media(max-width:640px){.rows li{grid-template-columns:1fr}}

.dl{display:inline-flex;align-items:center;gap:9px;margin-top:11px;
  font-size:14.5px;font-weight:600;letter-spacing:-.01em;color:var(--ink);
  text-decoration:none;border-bottom:2px solid var(--flame2);padding-bottom:2px;
  transition:gap .16s}
.dl:hover{gap:13px}
.dl .mono{font-weight:400;font-size:11px;letter-spacing:.1em;color:var(--muted);
  border:0}

.chip{display:inline-block;font-family:var(--m);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;border:1px solid var(--rule);border-radius:999px;
  padding:3px 10px;color:var(--muted);background:var(--paper);white-space:nowrap}
.chip.live{border-color:color-mix(in srgb,var(--accent) 34%,transparent);
  background:color-mix(in srgb,var(--accent) 9%,var(--paper));color:var(--accent)}
.addr{font-family:var(--m);font-size:clamp(15px,2vw,23px);display:flex;
  align-items:center;gap:11px;flex-wrap:wrap;border:1px solid var(--rule);
  border-radius:11px;padding:15px 19px;background:var(--paper)}
.addr .you{color:var(--accent)}
/* The quoted line is in the same hand as the headings, sized up because Caveat
   runs small, and kept straight so it reads as a statement rather than a note. */
.quote{border-left:3px solid transparent;border-image:var(--flame) 1;padding-left:22px;
  font-family:var(--h);font-weight:600;font-size:clamp(32px,4.3vw,52px);
  letter-spacing:0;line-height:1.08;color:var(--ink);max-width:26ch;margin:0;
  text-wrap:balance}
.quote em{font-style:normal;background:var(--turn);-webkit-background-clip:text;
  background-clip:text;color:transparent}

/* The turn of a headline, set in the serif italic. Two voices in one sentence:
   the geometric sans states, the serif turns. Sized up because a serif at the
   same pixel height reads noticeably smaller beside a heavy grotesque. */
.ser{font-family:var(--s);font-style:italic;font-weight:400;font-size:1.09em;
  letter-spacing:-.008em;line-height:.98}

/* A signature, not a name badge. */
.sig{font-family:var(--h);font-weight:600;font-size:clamp(28px,3.4vw,40px);color:var(--ink);
  margin:22px 0 0;transform:rotate(-2.2deg);transform-origin:left center}
.sig small{display:block;font-family:var(--m);font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);transform:rotate(2.2deg);margin-top:8px}

/* A margin note, in the hand. Slight rotation and an arrow, because a note
   written straight and centred is just another component. */
/* Caveat is a handwriting face with narrow glyph coverage — an arrow character
   in ::before rendered as tofu. The mark is drawn instead, as a short pen
   stroke, which is also more in keeping than a typographic arrow would be. */
.note{font-family:var(--h);font-weight:500;font-size:clamp(20px,2.2vw,25px);line-height:1.28;
  color:var(--accent);max-width:24ch;transform:rotate(-1.4deg);
  transform-origin:left center;margin-block:14px 4px;padding-left:34px;
  position:relative}
.note::before{content:"";position:absolute;left:2px;top:.44em;width:22px;height:11px;
  border-left:2.5px solid currentColor;border-bottom:2.5px solid currentColor;
  border-bottom-left-radius:7px;opacity:.55}

/* Hand-drawn underline. Drawn on entry, never hiding the text underneath — if
   the observer never fires, the sentence still reads. */
.ul{position:relative;white-space:nowrap}
.ul svg{position:absolute;left:-2%;bottom:-.34em;width:104%;height:.42em;
  overflow:visible;pointer-events:none}
.ul path{fill:none;stroke:var(--flame2);stroke-width:6;stroke-linecap:round;
  stroke-dasharray:340;stroke-dashoffset:340}
.ul.drawn path{animation:draw .82s cubic-bezier(.3,.75,.25,1) forwards}
@keyframes draw{to{stroke-dashoffset:0}}
.strike{text-decoration:line-through;text-decoration-thickness:2px;color:var(--muted)}

/* ---------- the board ---------- */
.filters{display:flex;flex-wrap:wrap;gap:8px;margin:4px 0 26px}
.filters button{font-family:var(--m);font-size:12px;letter-spacing:.06em;
  border:1px solid var(--rule);background:var(--paper);border-radius:999px;
  padding:7px 14px;color:var(--muted);cursor:pointer;transition:all .16s}
.filters button:hover{border-color:var(--muted);color:var(--ink)}
.filters button[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);
  color:var(--on-ink)}
/* A real masonry: the grid rows are 8px tall and each pin spans as many of
   them as its own height needs, measured after the image has loaded. The wide
   ones span two columns — same picture, bigger pin — which is what gives the
   wall its rhythm when every asset happens to be the same shape. */
/* width:100% is what stops auto-fill counting columns against max-content: the
   wall sits in a flex column with align-items:flex-start, so without a width it
   shrink-to-fits — and a masonry's max-content width is every pin in one row,
   which is how a phone ended up laying the page out at 810px. */
.wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(208px,1fr));
  grid-auto-rows:8px;column-gap:14px;width:100%;max-width:none}
/* align-self:start is load-bearing: a stretched grid item reports the height
   of the area it was given, so measuring it to decide how many rows it needs is
   circular and every pin comes out the same height. */
/* min-width:0 is not decoration. A grid item defaults to min-width:auto, so
   the nowrap caption inside made every column at least as wide as the longest
   caption — which widened the grid, which widened the page, which widened the
   layout viewport until a phone was laying the site out at 810px. */
.tile{grid-row-end:span 40;align-self:start;min-width:0;margin-bottom:14px;
  border-radius:16px;background:transparent;text-decoration:none;display:block;
  transition:transform .2s cubic-bezier(.2,.8,.25,1)}
.tile figcaption{min-width:0}
.tile.big{grid-column:span 2}
.tile .shot{display:block;position:relative;overflow:hidden;border-radius:16px;
  background:var(--sunk);box-shadow:0 1px 2px rgba(var(--shadow),.05),
  0 0 0 1px var(--rule)}
.tile img{width:100%;height:auto;display:block;
  transition:transform .35s cubic-bezier(.2,.8,.25,1)}
/* top-right, out of the way of the card's own footer line */
.tile .open{position:absolute;right:12px;top:12px;font-family:var(--m);
  font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:#fff;
  background:rgba(0,0,0,.62);backdrop-filter:blur(6px);border-radius:999px;
  padding:6px 13px;opacity:0;transform:translateY(6px);
  transition:opacity .2s,transform .2s}
.tile:hover{transform:translateY(-3px)}
.tile:hover .shot{box-shadow:0 18px 40px -22px rgba(197,74,20,.5),
  0 0 0 1px var(--rule)}
.tile:hover img{transform:scale(1.035)}
.tile:hover .open{opacity:1;transform:none}
.tile figcaption{padding:9px 4px 0;display:flex;gap:9px;align-items:baseline;
  justify-content:space-between}
.tile .cap{font-size:13px;font-weight:600;letter-spacing:-.01em;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tile .set{font-family:var(--m);font-size:10px;color:var(--muted);flex:none}
.tile.hide{display:none}
.tile.gif .shot{box-shadow:0 0 0 1px var(--rule),0 0 0 3px rgba(255,90,30,.14)}
@media(hover:none){.tile .open{opacity:1;transform:none}}
@media(max-width:560px){
  .wall{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));column-gap:10px}
  .tile{margin-bottom:10px}
  .tile .cap{font-size:12px}
}

/* ---------- the board's viewer ----------
   A tile used to open the raw file in a new tab, which is a directory listing
   with better manners. This is the pattern a phone already taught everyone:
   full-bleed, caption underneath, swipe or arrows for the next one, and "next"
   means the next one in whatever is currently filtered. */
.viewer{position:fixed;inset:0;z-index:90;background:rgba(10,11,14,.96);
  backdrop-filter:blur(6px);
  display:flex;align-items:center;justify-content:center;
  padding:calc(14px + env(safe-area-inset-top)) 14px
          calc(14px + env(safe-area-inset-bottom));
  animation:fade .16s ease}
.vstage{position:relative;display:flex;flex-direction:column;align-items:center;
  gap:12px;max-width:min(1000px,100%);max-height:100%}
.vstage img{max-width:100%;max-height:calc(100dvh - 150px);width:auto;height:auto;
  border-radius:14px;background:#14161b;animation:pop .2s ease-out}
.vbar{display:flex;align-items:baseline;justify-content:space-between;gap:18px;
  width:100%;color:#E7E3DC}
.vcap{margin:0;font-size:14.5px;color:#F3F0EB;max-width:none}
.vcount{margin:0;font-size:11.5px;color:#9AA0A8;flex:none}
.vclose,.vnav{position:absolute;z-index:2;display:grid;place-items:center;
  border:0;border-radius:999px;background:rgba(255,255,255,.12);color:#fff;
  cursor:pointer;backdrop-filter:blur(6px);transition:background .15s}
.vclose:hover,.vnav:hover{background:rgba(255,255,255,.22)}
.vclose{top:-6px;right:-6px;width:44px;height:44px;font-size:16px}
.vnav{top:50%;transform:translateY(-50%);width:48px;height:48px;font-size:26px;
  line-height:1}
.vnav.prev{left:-8px}
.vnav.next{right:-8px}
@media(max-width:760px){
  .vclose{top:-2px;right:-2px}
  .vnav{width:44px;height:44px;font-size:22px}
  .vnav.prev{left:-4px}
  .vnav.next{right:-4px}
  .vstage img{max-height:calc(100dvh - 190px)}
  .vcap{font-size:13.5px}
}

/* ---------- command bar ---------- */
.cmdwrap{position:fixed;inset:0;z-index:80;background:rgba(var(--shadow),.34);
  display:flex;align-items:flex-start;justify-content:center;padding:12vh 16px 16px;
  backdrop-filter:blur(3px)}
.cmdwrap[hidden]{display:none}
.cmdbox{width:min(520px,100%);background:var(--paper);border:1px solid var(--rule);
  border-radius:14px;box-shadow:0 30px 70px -24px rgba(var(--shadow),.5);overflow:hidden;
  animation:pop .17s ease-out}
@keyframes pop{from{opacity:0;transform:scale(.97) translateY(-6px)}}
#cmdq{width:100%;border:0;border-bottom:1px solid var(--rule);padding:16px 18px;
  font-size:16px;font-family:var(--f);outline:none;background:var(--paper);color:var(--ink)}
.cmdlist{list-style:none;margin:0;padding:6px;max-height:46vh;overflow:auto}
.cmdlist a{display:flex;justify-content:space-between;gap:12px;align-items:center;
  text-decoration:none;padding:10px 12px;border-radius:8px;font-size:14.5px}
.cmdlist li.sel a,.cmdlist a:hover{background:var(--sunk)}
.cmdlist .sub{font-family:var(--m);font-size:11px;color:var(--muted)}
.cmdhint{margin:0;padding:9px 14px;border-top:1px solid var(--rule);font-size:11px;
  color:var(--muted);background:var(--panel)}

/* ---------- experience ---------- */
.claim{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));
  align-items:end;width:100%;max-width:820px}
.claim label{display:grid;gap:6px;font-size:13px;color:var(--muted);
  font-family:var(--m);letter-spacing:.04em}
.claim input,.claim select{font:inherit;font-size:15.5px;font-family:var(--f);
  color:var(--ink);background:var(--paper);border:1px solid var(--rule);
  border-radius:9px;padding:11px 13px;width:100%}
.claim input:focus,.claim select:focus{outline:none;border-color:var(--accent)}
.claim .btn{justify-content:center;padding:13px 20px}

.depts{display:flex;flex-wrap:wrap;gap:8px;width:100%}
.dept{display:grid;gap:1px;text-align:left;border:1px solid var(--rule);
  background:var(--paper);border-radius:10px;padding:10px 14px;cursor:pointer;
  transition:all .16s}
.dept b{font-size:14.5px;font-weight:600;letter-spacing:-.01em}
.dept span{font-family:var(--m);font-size:10.5px;color:var(--muted)}
.dept:hover{border-color:var(--muted)}
.dept[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--on-ink)}
.dept[aria-pressed="true"] span{color:color-mix(in srgb,var(--on-ink) 66%,transparent)}

.board-panel{width:100%;max-width:820px;border:1px solid var(--rule);
  border-radius:12px;overflow:hidden;background:var(--paper)}
.bp-head{display:flex;align-items:center;justify-content:space-between;
  padding:12px 16px;border-bottom:1px solid var(--rule);background:var(--panel);
  font-size:13px;letter-spacing:.06em}
.board-panel .rows{padding:4px 16px 10px}
.board-panel .rows li{grid-template-columns:1fr auto;padding:13px 0;gap:4px 18px}
.board-panel .rows .k b{margin:0}
.board-panel .rows .when{font-family:var(--m);font-size:11.5px;color:var(--muted);
  white-space:nowrap}

.code{position:relative;width:100%;max-width:820px;background:#0C0F14;
  border-radius:12px;overflow:hidden}
.code pre{margin:0;padding:18px 20px;overflow-x:auto;font-family:var(--m);
  font-size:13px;line-height:1.75;color:#D7DCE4}
.copy{position:absolute;top:10px;right:10px;font-family:var(--m);font-size:11px;
  letter-spacing:.08em;background:rgba(255,255,255,.09);color:#D7DCE4;border:0;
  border-radius:7px;padding:6px 11px;cursor:pointer}
.copy:hover{background:rgba(255,255,255,.16)}

.report{display:grid;gap:14px;width:100%;max-width:820px}
.met{display:grid;gap:7px;border:1px solid var(--rule);border-radius:11px;padding:16px 18px}
.met .top{display:flex;justify-content:space-between;align-items:baseline;gap:14px}
.met .nm{font-size:14.5px;font-weight:600;letter-spacing:-.01em}
.met .vl{font-family:var(--m);font-size:13px;color:var(--muted);
  font-variant-numeric:tabular-nums}
.met .track{height:7px;border-radius:4px;background:var(--sunk);overflow:hidden}
.met .fill{height:100%;border-radius:4px;background:var(--flame);width:0;
  transition:width .9s cubic-bezier(.2,.7,.2,1)}
.met .note{font-family:var(--m);font-size:11px;color:var(--muted)}

/* ---------- elsewhere ---------- */
.elsewhere{display:grid;gap:10px;width:100%;max-width:660px}
.ext{display:flex;align-items:center;justify-content:space-between;gap:16px;
  text-decoration:none;border:1px solid var(--rule);border-radius:11px;
  padding:15px 18px;background:var(--paper);transition:border-color .16s,transform .16s}
.ext:hover{border-color:var(--muted);transform:translateX(3px)}
.ext .who{display:grid;gap:2px;min-width:0}
.ext .who b{font-size:15.5px;font-weight:600;letter-spacing:-.01em}
.ext .who span{font-family:var(--m);font-size:11.5px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis}
.ext .go{font-family:var(--m);font-size:12px;color:var(--muted);flex:none}

/* ---------- the story behind the page ----------
   One chapter per view, drawn in tools/story_bg.py, sitting under the content
   at a few per cent ink. It is inert: no pointer events, hidden from screen
   readers, and never selectable. The bands translate on scroll — transform
   only, one shared listener — and hold still under reduced motion. */
.story{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  user-select:none}
/* Paper, at part opacity, between the chapter and the text. Every view loses
   the same small amount of contrast this way, instead of each one losing a
   different amount wherever its own drawing happened to be busiest — which is
   what tools/check_contrast.py was measuring when it found headlines paying
   five points for a background nobody had asked to read. */
.veil{position:absolute;inset:0;background:var(--paper);opacity:.30}
.storysvg{width:100%;height:100%;display:block}
.bnd{will-change:transform}
/* Only the pane needs a position to sit above the layer — the rail, app bar
   and top bar are already sticky and the tab bar is fixed, and restating
   position here is how a sticky rail quietly stops sticking. */
.pane{position:relative;z-index:1}
/* The rail only needs to clear the chapter. The app bar and top bar keep the
   z-index their own rules give them — restating them here is what put the phone
   app bar on layer 1 and let positioned page components slide over it. */
.rail{z-index:20}
@media(prefers-reduced-motion:reduce){.bnd{transform:none!important}}
/* A phone paints the two nearest bands only: the far ones are the expensive
   ones and the least visible. */
@media(max-width:640px){.story .bnd:nth-child(n+3):not(:last-child){display:none}}

/* ---------- diagrams ----------
   Flow and timeline are HTML, not pictures of HTML: they reflow to one column on
   a phone instead of scaling a wide drawing down to nothing. Only the mesh is
   genuinely graphical, and that one is SVG. */
.dg{margin:0;width:100%;max-width:860px;border:1px solid var(--rule);
  border-radius:15px;background:var(--paper);padding:22px 20px 14px}
.dg figcaption{margin-top:14px;padding-top:12px;border-top:1px solid var(--rule);
  font-family:var(--m);font-size:11.5px;line-height:1.6;color:var(--muted)}
.dgtwo{display:grid;gap:18px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.dghalf{display:grid;gap:9px}
.dghalf h3{margin:0;font-size:13px;font-weight:600;letter-spacing:-.01em;
  line-height:1.35}
.dghalf p{font-family:var(--m);font-size:11px;color:var(--muted)}
.dg svg{width:100%;height:auto;overflow:visible}
.dg .mesh{stroke:var(--rule);stroke-width:1.4;fill:none}
.dg .hub{stroke:var(--flame2);stroke-width:1.7;fill:none;opacity:.85}
.dg .nd{fill:var(--panel);stroke:var(--rule);stroke-width:1.4}
.dg .nd.hot{fill:var(--flame2);stroke:none}
.dg .ndt{font-family:var(--m);font-size:9px;fill:var(--muted)}
/* the middle label sits on top of the drawing, so it carries its own ground */
.dg .ndt.mid{fill:var(--ink);paint-order:stroke;stroke:var(--paper);stroke-width:3.5px;
  stroke-linejoin:round}
.dg.in .mesh,.dg.in .hub{stroke-dasharray:var(--l,300);stroke-dashoffset:var(--l,300);
  animation:draw 1.05s ease forwards}

.flow{list-style:none;margin:0;padding:0;width:100%;display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.flow li{position:relative;border:1px solid var(--rule);border-radius:13px;
  padding:16px 17px;background:var(--paper);display:grid;gap:6px;
  opacity:1;transform:none}
.flow li .st{font-family:var(--m);font-size:10.5px;letter-spacing:.16em;
  color:var(--accent)}
.flow li b{font-size:15.5px;font-weight:600;letter-spacing:-.014em}
.flow li p{font-size:13.5px;color:var(--muted);line-height:1.5}
.js .flow.anim li{opacity:0;transform:translateY(9px)}
.js .flow.anim.in li{animation:rise2 .5s cubic-bezier(.2,.8,.25,1) forwards}
@keyframes rise2{to{opacity:1;transform:none}}
.flow li:nth-child(2){animation-delay:.08s}
.flow li:nth-child(3){animation-delay:.16s}
.flow li:nth-child(4){animation-delay:.24s}
.flow li:nth-child(5){animation-delay:.32s}

.tl{list-style:none;margin:0;padding:0 0 0 30px;width:100%;max-width:760px;
  position:relative}
.tl::before{content:"";position:absolute;left:8px;top:9px;bottom:9px;width:2px;
  background:linear-gradient(var(--flame2),var(--rule))}
.tl li{position:relative;padding:0 0 26px}
.tl li:last-child{padding-bottom:0}
.tl li::before{content:"";position:absolute;left:-27px;top:6px;width:11px;height:11px;
  border-radius:50%;background:var(--paper);border:2.5px solid var(--flame2)}
.tl .st{font-family:var(--m);font-size:10.5px;letter-spacing:.16em;color:var(--muted)}
.tl b{display:block;font-size:17px;font-weight:600;letter-spacing:-.016em;
  margin:2px 0 5px}
.tl p{font-size:15px}

/* ---------- why now: the era band and the calm sections ---------- */
.eras{list-style:none;margin:0;padding:0;width:100%;display:grid;gap:2px;
  counter-reset:era}
.eras li{position:relative;display:grid;gap:9px;padding:28px 0 30px 0;
  border-top:1px solid var(--rule)}
.eras li:first-child{border-top:0}
.eras .when{font-family:var(--m);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent)}
.eras b{font-size:clamp(22px,3vw,31px);font-weight:800;letter-spacing:-.026em;
  line-height:1.1}
.eras p{font-size:15.5px}
.eras .then{color:var(--muted);border-left:2px solid var(--rule);padding-left:15px;
  font-size:14.5px}
.eras li:last-child .then{border-left-color:var(--flame2);color:var(--ink2)}

/* The calmest register on the site: more air above and below, nothing tinted,
   and the page allowed to breathe between two ideas. */
.calm{padding-block:clamp(56px,8vw,120px)!important}
.calm .lede{max-width:58ch}

/* ---------- the letter, and the gate in front of it ---------- */
.letterbox{display:grid;gap:26px;grid-template-columns:minmax(0,320px) minmax(0,1fr);
  align-items:start;width:100%}
.lprev{margin:0;border:1px solid var(--rule);border-radius:16px;overflow:hidden;
  background:var(--paper);box-shadow:0 24px 48px -34px rgba(var(--shadow),.45)}
.lprev img{width:100%;height:auto}
.lprev figcaption{padding:10px 13px;border-top:1px solid var(--rule);font-size:11px;
  letter-spacing:.1em;color:var(--muted);text-transform:uppercase}
.gate{display:grid;gap:16px;min-width:0}
.fb{display:grid;gap:13px}
.fb h3{font-size:clamp(19px,2.4vw,23px);letter-spacing:-.02em}
.fb p{font-size:14.5px}
.fb label{display:grid;gap:7px;font-family:var(--m);font-size:12px;
  letter-spacing:.04em;color:var(--muted)}
.fb .opt{font-family:var(--m);font-size:10.5px;color:var(--muted);opacity:.8}
.fb textarea,.fb input{font-family:var(--f);font-size:16px;color:var(--ink);
  background:var(--paper);border:1px solid var(--rule);border-radius:11px;
  padding:12px 14px;width:100%;resize:vertical;line-height:1.55}
.fb textarea:focus,.fb input:focus{outline:none;border-color:var(--accent)}
.fb button{justify-self:start;min-height:48px}
.gateout{display:grid;gap:13px;animation:settle .3s ease-out}
.gstat{font-size:12.5px;color:var(--ink2);border-left:2.5px solid var(--flame2);
  padding-left:12px}
.dls{display:flex;flex-wrap:wrap;gap:9px}
.dls .btn{font-size:13.5px;padding:10px 15px;gap:8px}
.dls .mono{font-size:10.5px;letter-spacing:.1em;color:var(--muted)}
.onfnd{font-family:var(--m);font-size:11px;letter-spacing:.04em;color:var(--muted)}
.waiting{display:inline-block;margin-top:11px;font-size:11.5px;letter-spacing:.08em;
  color:var(--muted);border-bottom:1.5px dashed var(--rule);padding-bottom:3px}
@media(max-width:760px){
  .letterbox{grid-template-columns:1fr}
  .lprev{max-width:340px}
}

/* ---------- the six situations ---------- */
.ring{width:100%;max-width:600px;margin:2px auto 0;color:var(--flame2);
  overflow:visible}
.ring .rr{fill:none;stroke:var(--rule);stroke-width:1.4}
.ring .spoke{stroke:var(--rule);stroke-width:1.4}
.ring .ndot{fill:var(--paper);stroke:var(--muted);stroke-width:1.6;
  transition:fill .18s,stroke .18s,r .18s}
.ring .nhit{fill:transparent;cursor:pointer}
.ring .rlab{font-family:var(--m);font-size:12px;fill:var(--muted)}
.ring .rmk{color:var(--flame2);opacity:.9}
.ring .pnode:hover .ndot{stroke:var(--accent)}
.ring .pnode.on .ndot{fill:var(--flame2);stroke:var(--flame2);r:19}
.ring .pnode.on ~ .rlab{fill:var(--ink)}
.ring .pnode:focus-visible .ndot{stroke:var(--accent);stroke-width:3}
.ring .pnode{outline:none}

.sitwrap{width:100%}
.sit[hidden]{display:none}
.sit{display:grid;gap:16px;animation:settle .3s ease-out}
.sit h2{font-size:clamp(28px,3.4vw,36px);letter-spacing:0;
  line-height:1.1}
.sitgrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.sitcell{border:1px solid var(--rule);border-radius:13px;padding:16px 18px;
  background:var(--paper);display:grid;gap:7px;align-content:start}
.sitcell .lab{font-family:var(--m);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.sitcell p{font-size:14.5px;line-height:1.6}
.sitcell.then{background:linear-gradient(150deg,rgba(255,144,64,.11),
  rgba(229,32,107,.05));border-color:transparent}
.sitcell.then .lab{color:var(--accent)}
.fnd{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;font-size:14px;
  color:var(--ink2);border-top:1px solid var(--rule);padding-top:13px;margin:0}
.fnd span{font-family:var(--m);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.rows.lay li{padding:15px 0}
@media(max-width:640px){
  .ring{max-width:420px}
  .ring .rlab{display:none}
  .sitgrid{grid-template-columns:1fr}
}

/* ---------- scenario tabs and the thread ---------- */
.tabs{display:flex;gap:8px;width:100%;overflow-x:auto;scrollbar-width:none;
  padding-bottom:2px}
.tabs::-webkit-scrollbar{display:none}
.tabs button{flex:none;font-family:var(--m);font-size:12px;letter-spacing:.06em;
  border:1px solid var(--rule);background:var(--paper);border-radius:999px;
  padding:9px 15px;color:var(--muted);cursor:pointer;min-height:40px;
  transition:all .16s}
.tabs button[aria-selected="true"]{background:var(--ink);border-color:var(--ink);
  color:var(--on-ink)}
/* Grid items default to min-width:auto, so one long unbreakable token — a
   config path, an endpoint — sets a min-content width wider than the column and
   pushes the phone layout sideways. Both halves of that are fixed here: the
   track may shrink, and the token may break. */
.panel > *{min-width:0}
.pane code{font-family:var(--m);font-size:.92em;overflow-wrap:anywhere;
  background:var(--sunk);border-radius:4px;padding:1px 5px;color:var(--ink)}
.code code,.pane pre code{background:none;padding:0}

.panel[hidden]{display:none}
.panel{display:grid;gap:22px;width:100%;animation:settle .28s ease-out}

.thread{display:grid;gap:9px;width:100%;max-width:720px}
.bub{border:1px solid var(--rule);border-radius:16px;padding:12px 16px;font-size:15px;
  line-height:1.5;max-width:90%;color:var(--ink2)}
.bub.me{background:var(--ink);color:var(--on-ink);border-color:transparent;justify-self:end;
  border-bottom-right-radius:6px}
.bub.it{background:var(--panel);border-bottom-left-radius:6px}
.bub .who{display:block;font-family:var(--m);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;opacity:.6;margin-bottom:4px}

/* ---------- the sum, and the fit check ---------- */
.calc{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  width:100%;max-width:820px}
.calc label{display:grid;gap:6px;font-family:var(--m);font-size:12px;
  letter-spacing:.04em;color:var(--muted)}
.calc input{font-family:var(--f);font-size:16px;font-weight:600;color:var(--ink);
  background:var(--paper);border:1px solid var(--rule);border-radius:10px;
  padding:12px 14px;width:100%;min-height:48px}
.calc input:focus{outline:none;border-color:var(--accent)}
.outs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
  width:100%;max-width:820px}
.out{border:1px solid var(--rule);border-radius:13px;padding:17px 18px;display:grid;
  gap:4px;background:var(--paper)}
.out .big{font-size:clamp(27px,4.4vw,38px);font-weight:800;letter-spacing:-.03em;
  line-height:1;font-variant-numeric:tabular-nums}
.out .cap{font-size:13px;color:var(--muted);line-height:1.45}
.out.lit{background:linear-gradient(140deg,rgba(255,144,64,.13),rgba(229,32,107,.07));
  border-color:transparent}

.check{list-style:none;margin:0;padding:0;width:100%;max-width:760px;display:grid;
  gap:2px}
.check li{border-top:1px solid var(--rule)}
.check li:first-child{border-top:0}
.check label{display:flex;gap:14px;align-items:flex-start;padding:15px 4px;
  cursor:pointer;min-height:56px}
.check input{appearance:none;-webkit-appearance:none;flex:none;width:24px;height:24px;
  margin-top:1px;border:1.8px solid var(--rule);border-radius:7px;background:var(--paper);
  cursor:pointer;transition:all .14s}
.check input:checked{background:var(--flame);border-color:transparent}
.check input:checked::after{content:"";display:block;width:6px;height:11px;
  margin:3px auto 0;border:2.4px solid #fff;border-top:0;border-left:0;
  transform:rotate(42deg)}
.check .q{display:grid;gap:3px}
.check .q b{font-size:15.5px;font-weight:600;letter-spacing:-.012em}
.check .q span{font-size:13.5px;color:var(--muted);line-height:1.5}
.verdict{width:100%;max-width:760px;border:1px solid var(--rule);border-radius:14px;
  padding:20px 22px;display:grid;gap:8px;background:var(--panel)}
.verdict .score{font-family:var(--m);font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.verdict b{font-size:clamp(19px,2.6vw,25px);letter-spacing:-.02em;font-weight:800}
.verdict p{font-size:15px}

/* ---------- responsive ---------- */
/* Card rows become a swipe deck on a phone, snapping like a native carousel
   rather than stacking into a column the length of a receipt. The track scrolls,
   never the page. */
@media(max-width:640px){
  /* A fixed track, not minmax(0,82%): with a floor of zero the tracks simply
     shrink to share the pane, the row never overflows, and what was meant to be
     a deck arrives as three squeezed columns instead. The card has to be wider
     than its share for there to be anything to swipe. */
  .grid,.outs{grid-template-columns:none;grid-auto-flow:column;
    grid-auto-columns:82%;overflow-x:auto;scroll-snap-type:x mandatory;
    scroll-padding-left:0;padding-bottom:6px;scrollbar-width:none;
    overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
  .grid::-webkit-scrollbar,.outs::-webkit-scrollbar{display:none}
  .grid > *,.outs > *{scroll-snap-align:start}
  .flow{grid-template-columns:1fr}
  .calc{grid-template-columns:1fr 1fr}
}
@media(max-width:560px){
  h1{font-size:clamp(42px,11.4vw,54px)}
  h2{font-size:clamp(34px,9vw,42px)}
  .pane > section{padding-block:38px}
  /* gap only — restating grid-template-columns here would undo the deck */
  .grid{gap:14px}
  .grid,.outs{grid-auto-columns:86%}
  .card{padding:19px}
  .wall{columns:1}
  .claim{grid-template-columns:1fr}
  .board-panel .rows li{grid-template-columns:1fr}
  .ext{flex-wrap:wrap}
  .filters button{font-size:11px;padding:6px 11px}
  .addr{font-size:15px;padding:13px 15px}
  .note{max-width:none;transform:none}
  .code pre{font-size:11.5px;padding:15px 14px}
  .dg{padding:17px 15px 12px}
  .bub{max-width:96%;font-size:14.5px}
  .tl{padding-left:26px}
  .claim input,.claim select{font-size:16px;min-height:48px}
  .btn{min-height:46px;padding-inline:20px}
  .verdict{padding:17px 18px}
}
@media(min-width:561px) and (max-width:900px){.wall{columns:2}}

/* ---------- touch ----------
   A finger cannot aim the way a mouse can. These grow the target without
   growing the control: the visible size is unchanged, the hit area is not.
   Scoped to a coarse pointer, so desktop density is untouched — and matched to
   the 44px floor Apple's guidance and WCAG 2.5.5 both use. */
@media(pointer:coarse){
  .themed{width:44px;height:44px}
  .themed svg{width:19px;height:19px}
  .appbar .brand{min-height:44px;display:inline-flex;align-items:center}
  .appbar .signin{min-height:44px}
  .copy{min-height:40px;padding:9px 15px;font-size:12px}
  .fcol a,.footlinks a{min-height:40px;display:inline-flex;align-items:center}
  .tabs button{min-height:42px}
  .filters button{min-height:40px}
  .srow{min-height:56px}
  .dl,.ext{min-height:44px}
  .dept{min-height:44px}
  /* a tap should never leave a stuck hover state */
  .fcol a:hover{transform:none}
}

/* ---------- the phone's own type scale ----------
   Ten-point type is a label on a desktop and a squint on a phone. The floor
   here is 11.5px for anything that is genuinely a label, and 12.5px for
   anything that is read as text. Nothing above the floor is touched, so the
   hierarchy the page was designed with survives. */
@media(max-width:640px){
  .grp,.kick,.st,.chip,.fcol h2,.tl .st,.flow li .st,.lab,.sitcell .lab,.onfnd{font-size:11.5px}
  .eyebrow,.copy,.cmdhint,.vcount{font-size:12px}
  .tiny,.code pre,.pane p kbd,.pane li kbd{font-size:12.5px}
  .rows .k{font-size:13px}
  .dghalf p{font-size:12px}
}

/* ---------- the hero, on a phone ----------
   Sized in svh rather than vh: on a phone vh is the viewport with the browser
   chrome retracted, so a hero measured in it is taller than the screen the
   moment the address bar is showing, and the first thing under the fold is the
   thing you most wanted read. svh is the small viewport — chrome visible — so
   the hero fits on arrival rather than after a scroll. */
@media(max-width:640px){
  .pane > section:first-of-type{
    min-height:min(86svh,700px);
    display:flex;flex-direction:column;justify-content:center;
    padding-block:clamp(26px,7vw,42px) clamp(34px,9vw,52px)}
  .pane > section:first-of-type h1{font-size:clamp(44px,12.2vw,58px);line-height:1.02}
  .pane > section:first-of-type .lede{font-size:clamp(16.5px,4.3vw,19px)}
  .pane > section:first-of-type .cta{width:100%;gap:9px}
  .pane > section:first-of-type .cta .btn{flex:1 1 auto;justify-content:center;
    min-height:50px;font-size:15.5px}
}
/* Landscape on a phone is short, so the hero stops reserving a screen it
   cannot fill and goes back to being a section. */
@media(max-height:520px) and (orientation:landscape){
  .pane > section:first-of-type{min-height:0;display:block;padding-block:26px}
}

/* Very small — 320px is still a live width on older Android and the SE. */
@media(max-width:360px){
  :root{--gut:16px}
  .pane > section:first-of-type h1{font-size:clamp(38px,11.4vw,44px)}
  .addr{font-size:13.5px;padding:11px 13px}
  .tabs{gap:6px}
  .tabs button{padding:7px 11px;font-size:11.5px}
}

@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .ul path{stroke-dashoffset:0}
  /* the stagger is an animation; without it the cards must still be visible */
  .js .flow.anim li{opacity:1;transform:none}
  /* same for the cards, and the top rule is drawn rather than left undrawn */
  .js .grid.anim .card{opacity:1;transform:none}
  .js .grid.anim .card::before{transform:scaleX(1)}
  .dg.in .mesh,.dg.in .hub{stroke-dashoffset:0}
}

/* ---------- conversion, the hero demo, and contact ---------- */

/* The address is one flex item. As two (a span and a bare text node) the row's
   gap landed inside the domain and it read "yourcompany .wayworks.space". */
.addr .host{min-width:0;overflow-wrap:anywhere}

/* The phone app bar carries the one action that matters; the theme control
   lives in every footer instead. */
.appbar .themed{display:none}
.appbar .signin{background:var(--ink);color:var(--on-ink);border-color:var(--ink)}
/* Sign in rides beside the primary pill as plain text, so the bar keeps one
   filled button and still fits a 360px phone. */
.appbar .appsignin{flex:none;display:inline-flex;align-items:center;min-height:44px;
  padding:0 4px;text-decoration:none;font-weight:600;font-size:14px;letter-spacing:-.01em;
  color:var(--ink2)}
.appbar .appsignin:active{color:var(--ink)}
/* The mark never gives up its width. As the phone narrows, the bar sheds the
   least-needed piece first: ".space", then search (the tab bar already
   navigates), then the Sign in text, which stays in every footer. */
.appbar .brand .mk{flex:none}
@media(max-width:419px){.appbar{gap:10px}.appbar .brand i{display:none}}
@media(max-width:379px){.appbar .iconbtn{display:none}.appbar .appsignin{margin-left:auto}}
@media(max-width:339px){.appbar .appsignin{display:none}.appbar .signin{margin-left:auto}}
.fprefs{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.fine{font-size:13px;line-height:1.6;color:var(--muted);max-width:60ch}
.fine a{color:var(--ink2)}

/* The overview hero shows the product: copy on the left, an example
   conversation on the right once the pane is wide enough, stacked below that. */
.pane > section.split{max-width:1180px}
.split h1{font-size:clamp(48px,5.4vw,76px)}
.herogrid{display:grid;gap:clamp(28px,4vw,48px);align-items:center;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:1260px){
  .herogrid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}}
.convo{margin:0;width:100%;max-width:520px;display:grid;gap:14px;
  border:1px solid var(--rule);border-radius:18px;background:var(--paper);
  padding:14px 16px;box-shadow:0 30px 60px -40px rgba(var(--shadow),.45)}
.convo-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:2px 2px 12px;border-bottom:1px solid var(--rule);font-size:12px;color:var(--muted)}
.convo-head .mono{min-width:0;overflow-wrap:anywhere}
.convo-head .you{color:var(--accent)}
.convo .thread{max-width:none}
.convo .bub{font-size:14.5px}
.convo-rec{display:flex;align-items:center;gap:9px;margin:0;padding:11px 2px 1px;
  border-top:1px solid var(--rule);font-size:11.5px;line-height:1.5;color:var(--muted)}

/* the page ends on the action, not on a link to more reading */
.pane > section.closer{border-top:0;padding-top:0}
.closer > .wrap{width:100%;border:1px solid var(--warm);border-radius:20px;
  padding:clamp(24px,4.4vw,48px);
  background:linear-gradient(140deg,rgba(255,144,64,.10),rgba(229,32,107,.05)),var(--paper)}

/* the early-access form, built on the letter page's form styles */
.access{width:100%;max-width:640px}
.access .arow{display:grid;gap:13px;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.fb select{font-family:var(--f);font-size:16px;color:var(--ink);background:var(--paper);
  border:1px solid var(--rule);border-radius:11px;padding:12px 14px;width:100%;min-height:48px}
.fb select:focus{outline:none;border-color:var(--accent)}

/* A phone crops the DebugInit wordmark in the background drawing to a stray
   "ugInit". The band rule above spares the last band, which is the one holding it,
   so the wordmark itself is hidden. */
@media(max-width:640px){.story [d^="M14.4 78.4V63.1"]{display:none}}

/* Swipe decks run to the screen edge, so the next card peeks in rather than
   being cut at the gutter, and say where you are in them. */
.deckcount{display:none}
@media(max-width:640px){
  .stack > .grid,.stack > .outs{width:calc(100% + var(--gut)*2);max-width:none;
    margin-inline:calc(var(--gut)*-1);padding-inline:var(--gut);
    scroll-padding-inline:var(--gut)}
  .deckcount{display:block;margin:-12px 0 0;font-size:12px;color:var(--muted);
    font-variant-numeric:tabular-nums}
}

/* ---------- the time, as a watermark ----------
   The visitor's local HH:MM in the background layer, bottom right, at a few
   per cent ink like the hero drawing. Each digit sits in its own clipped
   window, so a falling digit leaves through the bottom edge and the next one
   enters from the top. Fixed widths keep the digits from shifting as they
   change. It follows the theme through --story-ink. */
.clockmark{position:absolute;right:var(--gut);bottom:clamp(14px,3.5vh,40px);
  display:flex;align-items:center;pointer-events:none;user-select:none;
  font-family:var(--f);font-weight:800;font-size:clamp(120px,17vw,280px);
  line-height:1;letter-spacing:-.04em;font-variant-numeric:tabular-nums;
  color:var(--story-ink);opacity:.055}
.clockmark .cd{position:relative;display:block;width:.64em;height:1.02em;overflow:hidden}
.clockmark .cv{position:absolute;inset:0;display:block;text-align:center;will-change:transform}
.clockmark .cs{display:block;width:.3em;text-align:center;transform:translateY(-.07em)}
:root[data-theme="dark"] .clockmark{opacity:.075}
@media(max-width:900px){
  /* clear of the tab bar, and a little lighter behind running text */
  .clockmark{font-size:clamp(88px,28vw,150px);right:16px;opacity:.045;
    bottom:calc(78px + env(safe-area-inset-bottom))}
  :root[data-theme="dark"] .clockmark{opacity:.065}
}
@media print{.clockmark{display:none}}
