@font-face{font-family:"Source Serif 4";src:url("assets/fonts/SourceSerif4-Variable-latin.woff2") format("woff2");font-weight:300 600;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Source Serif 4";src:url("assets/fonts/SourceSerif4-Variable-latin-ext.woff2") format("woff2");font-weight:300 600;font-style:normal;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Source Serif 4";src:url("assets/fonts/SourceSerif4-VariableItalic-latin.woff2") format("woff2");font-weight:300 500;font-style:italic;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Source Serif 4";src:url("assets/fonts/SourceSerif4-VariableItalic-latin-ext.woff2") format("woff2");font-weight:300 500;font-style:italic;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Geist Mono";src:url("assets/fonts/GeistMono-Regular.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Geist Mono";src:url("assets/fonts/GeistMono-Medium.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}

:root{
  --ink:#191712;--ink-soft:#3A342A;--paper:#F6F5F1;--paper-2:#EEEBE2;
  --rule:#CFC8B8;--rule-2:#B9B0A0;--muted:#6E675A;
  --signal:#00F800;--signal-hover:#00D000;--denied:#B3261E;
  --term-bg:#0A0A0A;--term-fg:#F6F5F1;--term-dim:#8F887A;
  --serif:"Source Serif 4","Iowan Old Style",Georgia,serif;
  --mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --h1-size:clamp(40px,6.6vw,92px);--h1-lh:1.0;
  --hero-size:clamp(46px,10.4vw,130px);--hero-lh:1.32;
  --h2-size:clamp(30px,4.4vw,60px);--h2-lh:1.04;
  --lead-size:clamp(19px,1.6vw,23px);--lead-lh:1.52;
  --body-size:19px;--body-lh:1.55;
  --section-gap:clamp(56px,8vw,132px);
  --gutter:clamp(20px,5vw,64px);
  --measure:70ch;
  --measure-prose:66ch;
  color-scheme:light}

*{box-sizing:border-box}
[hidden]{display:none !important}
html{scroll-padding-top:24px;-webkit-text-size-adjust:100%}
html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);font-family:var(--serif);font-weight:400;font-size:var(--body-size);line-height:var(--body-lh);font-optical-sizing:auto;-webkit-font-smoothing:antialiased;text-wrap:pretty}
h1,h2,h3,p,ul,ol,figure,table{margin:0}
ul{padding:0;list-style:none}
a{color:inherit;text-decoration:none}
a:hover{text-decoration:underline;text-decoration-color:var(--signal);text-decoration-thickness:2px;text-underline-offset:4px}
img,video,svg{max-width:100%}
::selection{background:var(--signal);color:#111110}
input::placeholder,textarea::placeholder{color:var(--muted)}

/* ---------- side nav ---------- */
.page-shell{display:flex;align-items:stretch}
.page-nav{flex:0 0 auto;display:flex;flex-direction:column;position:sticky;top:0;align-self:flex-start}
.nav-toggle,.nav-brand{display:none}
.page-body{flex:1 1 auto;min-width:0}
.side-nav{height:100vh;overflow-y:auto;width:170px;background:var(--paper);border-right:1px solid var(--rule);padding:28px 16px 28px 22px;z-index:80;display:block}
.side-logo{display:flex;align-items:center;flex:none;margin-bottom:28px}
.side-logo img{height:18px;width:auto;display:block}
.side-logo:hover{text-decoration:none}
.side-link,.side-group-label{position:relative;display:flex;align-items:baseline;gap:6px;font-family:var(--mono);font-size:13px;line-height:1.35;letter-spacing:.01em;color:var(--ink);padding:4px 0}
.side-group-label{font-weight:500;cursor:pointer}
.side-link{font-weight:500}
.side-group{margin-top:10px}
.side-link+.side-group,.side-group+.side-group,.side-group+.side-link{margin-top:10px}
.side-n{color:var(--muted);font-size:10px;flex:none;display:inline-block;min-width:18px}
.side-sub{margin-top:2px;padding-left:24px;border-left:1px solid var(--rule);display:flex;flex-direction:column}
.side-sub a{position:relative;display:block;font-family:var(--mono);font-size:12px;line-height:1.35;color:var(--muted);padding:4px 0}
.side-sub a:hover{color:var(--ink);text-decoration:none}
.side-sub a[aria-current="page"]{color:var(--ink)}
.side-link[aria-current="page"] .side-n,.side-group-label.side-active .side-n{display:none}
.side-link[aria-current="page"]::before,.side-group-label.side-active::before{content:"";position:absolute;left:-14px;top:50%;transform:translateY(-50%);width:6px;height:6px;background:var(--signal)}
.side-sub a[aria-current="page"]::before{content:"";position:absolute;left:-16px;top:50%;transform:translateY(-50%);width:6px;height:6px;background:var(--signal)}
.side-link:hover{text-decoration:none;color:var(--ink)}
.side-group-label:hover{text-decoration:none}

/* ---------- buttons ---------- */
.btn{display:inline-block;border-radius:0;padding:14px 20px;font-family:var(--mono);font-size:12px;font-weight:400;line-height:1.4;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;transition:background 120ms;border:1px solid var(--ink)}
.btn:hover{text-decoration:none}
.btn-fill{background:var(--signal);color:#111110;border-color:var(--signal)}
.btn-fill:hover{background:var(--signal-hover);border-color:var(--signal-hover)}
.btn-ghost{background:transparent;color:var(--ink)}
.btn-ghost:hover{background:var(--signal)}
.btn-sm{padding:8px 12px}
.btns{display:flex;flex-wrap:wrap;gap:12px}

/* ---------- page shell (the frame is retired) ---------- */
.shell{max-width:1560px;margin:0 auto;padding:0 clamp(16px,4vw,72px)}
.frame{position:relative;border:0;padding:0;margin:0}
.frame-label{display:none}

/* ---------- sections and type ---------- */
.sec{border-top:1px solid var(--rule);margin-top:var(--section-gap);padding:clamp(24px,3vw,44px) 0 0}
.sec--open{border-top:0;margin-top:0;padding-top:clamp(44px,8vw,120px)}
.sec--open-tight{padding-top:clamp(44px,6vw,88px)}
.sec--last{padding-bottom:var(--section-gap)}
main h1{font-family:var(--serif);font-size:var(--h1-size);line-height:var(--h1-lh);letter-spacing:-.03em;font-weight:300;max-width:20ch}
main h1.hero{font-size:var(--hero-size);line-height:var(--hero-lh);letter-spacing:-.035em;max-width:16ch}
@media (min-width:1200px){main h1.hero{max-width:20ch}}
main h1.mono{font-family:var(--mono);font-size:clamp(26px,3vw,40px);line-height:1.2;letter-spacing:-.01em;font-weight:400;word-break:break-word;max-width:none}
main h2{display:flex;align-items:center;gap:clamp(14px,1.6vw,22px);font-family:var(--serif);font-size:var(--h2-size);line-height:var(--h2-lh);letter-spacing:-.025em;font-weight:400}
main h2::before{content:"";width:14px;height:14px;background:var(--signal);flex:none}
main h2.sm{font-size:clamp(22px,2.2vw,28px);line-height:1.2;letter-spacing:-.015em;flex-wrap:wrap}
main h2.plain::before{display:none}
main h3{font-family:var(--serif);font-size:clamp(22px,2.2vw,27px);line-height:1.18;letter-spacing:-.02em;font-weight:400}
.col{max-width:var(--measure)}
.lead{font-size:var(--lead-size);line-height:var(--lead-lh);letter-spacing:-.005em}
.small{font-size:17px;line-height:1.5}
.muted{color:var(--muted)}
.u{text-decoration:underline;text-decoration-color:var(--rule-2);text-decoration-thickness:1px;text-underline-offset:3px}
.u:hover{text-decoration-color:var(--signal);text-decoration-thickness:2px;text-underline-offset:4px}
.mt8{margin-top:8px}.mt12{margin-top:14px}.mt16{margin-top:16px}.mt24{margin-top:24px}.mt32{margin-top:32px}.mt40{margin-top:clamp(32px,4vw,48px)}.mt48{margin-top:clamp(36px,5vw,64px)}
.label{display:block;font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.13em;color:var(--muted)}
.status{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.11em;background:transparent;color:var(--ink);border:0;box-shadow:inset 0 0 0 1px var(--ink);border-radius:0;padding:6px 9px}
.status::before{content:"";width:6px;height:6px;background:var(--signal);flex:none}
.status--dev::before{background:var(--rule-2)}
.status--dev{background:transparent;color:var(--muted)}
.mono{font-family:var(--mono)}
.mono-line{font-family:var(--mono);font-size:12px;line-height:1.6;letter-spacing:.09em;text-transform:uppercase}
code{font-family:var(--mono);font-size:.82em;background:rgba(25,23,18,.07);border-radius:0;padding:1px 4px}
.eyebrow{font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.14em;color:var(--muted)}

/* ---------- figures ---------- */
.fig{margin:28px 0;max-width:none}
.fig+.mono-line{margin-top:28px}
.fig svg{display:block;width:100%;height:auto}
.fig text{font-family:var(--mono);font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;fill:var(--muted)}
.fig .fig-hd{fill:var(--ink)}
/* Phones: scale the diagram to the column instead of scrolling it sideways.
   The label type is bumped in viewBox units so it survives the downscale. */
@media (max-width:640px){.fig{overflow-x:visible}.fig svg{min-width:0}.fig text{font-size:11px;letter-spacing:.06em}}

/* ---------- dimension lines ---------- */
.dim{margin:32px 0;max-width:640px}
.dim.wide{max-width:960px}
.dim figcaption,.dim .dim-cap{display:block;font-family:var(--mono);font-size:11px;line-height:1.4;letter-spacing:.13em;text-transform:uppercase;text-align:center;color:var(--muted);margin-bottom:8px}
.dim-line{position:relative;height:6px;border-left:1px solid var(--ink);border-right:1px solid var(--ink)}
.dim-line::before{content:"";position:absolute;left:0;right:0;top:2px;border-top:1px solid var(--ink)}

/* ---------- lists / rows ---------- */
.rows{border-top:1px solid var(--ink)}
.rows>li,.rows>.row{border-bottom:1px solid var(--rule);padding:20px 0}
.rows.pad>li{padding:24px 0}
.row-2{display:grid;grid-template-columns:minmax(0,280px) minmax(0,1fr);gap:8px clamp(24px,4vw,56px)}
.row-2.narrow{grid-template-columns:minmax(0,200px) minmax(0,1fr)}
.row-2.wide{grid-template-columns:minmax(0,330px) minmax(0,1fr)}
.row-2.num{grid-template-columns:minmax(0,48px) minmax(0,1fr)}
.row-3{display:grid;grid-template-columns:minmax(0,104px) minmax(0,300px) minmax(0,1fr);gap:6px clamp(20px,3vw,32px);align-items:baseline}
@media (max-width:900px){.row-3{grid-template-columns:minmax(0,104px) minmax(0,1fr)}.row-3>:last-child{grid-column:2}}
@media (max-width:640px){.row-2,.row-2.narrow,.row-2.wide{grid-template-columns:minmax(0,1fr)}.row-3{grid-template-columns:minmax(0,1fr)}.row-3>:last-child{grid-column:1}}
.row-key{font-family:var(--mono);font-size:12px;line-height:1.7;letter-spacing:.06em}
.row-key.up{font-size:11px;text-transform:uppercase;letter-spacing:.13em;color:var(--muted)}
.grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:clamp(28px,3vw,44px)}
.grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:clamp(28px,3vw,44px)}
.grid-3>div>.label,.grid-2>div>.label{padding-top:16px;border-top:1px solid var(--ink)}
.commit{border-top:1px solid var(--ink);display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.commit--4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:900px){.commit--4{grid-template-columns:repeat(2,minmax(0,1fr))}}
.commit li{border-bottom:1px solid var(--rule);padding:16px 0;font-family:var(--mono);font-size:12px;line-height:1.7;letter-spacing:.04em;padding-right:24px}

/* ---------- terminal / code ---------- */
.term{background:var(--term-bg);border-radius:0;padding:24px;font-family:var(--mono);font-size:14px;line-height:1.6;color:var(--term-fg);overflow-x:auto;display:grid;gap:4px}
.term .p{color:var(--signal)}
.term .ok{color:var(--term-fg)}
.term .cm{color:#8F887A}
.term .kw{color:#F2938C}
.term .st{color:#8FD69C}
.term .fn{color:#8AB4F8}
.term .mt{color:#C9A2E8}
.term .pr{color:#A7CFEA}
.term .nu{color:#F0B37E}
.term-copy{position:relative;padding-right:96px;display:block}
.copy{position:absolute;top:16px;right:16px;background:transparent;border:1px solid var(--term-dim);border-radius:0;color:var(--term-fg);font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.11em;padding:5px 8px;cursor:pointer;transition:background 120ms,color 120ms}
.copy:hover{background:var(--signal);color:#0A0A0A;border-color:var(--signal)}
pre.term{display:block;margin:0;white-space:pre}
/* inline code must never push the page wider than the viewport */
code{overflow-wrap:break-word}
/* A nowrap code line is a grid/flex item with min-width:auto, so it sizes its
   own track and widens the whole page. Contain the scroll inside the block at
   every width, not just on phones. */
.stack32>*,.frame>*,.hero-split>*{min-width:0}
pre.term{max-width:100%;overflow-x:auto}

/* ---------- agent file ---------- */
.agentfile{border:1px solid var(--rule);border-radius:0;padding:clamp(20px,3vw,32px);font-family:var(--mono);max-width:820px}
.agentfile .fence{font-size:12px;line-height:1.8;color:var(--muted)}
.agentfile .desc{font-size:13px;line-height:1.8;max-width:72ch}
.agentfile p{font-size:13px;line-height:1.8;max-width:72ch;margin-bottom:20px}
.agentfile p:last-child{margin-bottom:0}

/* ---------- cards, tables, forms ---------- */
.card{border:0;border-top:1px solid var(--ink);border-radius:0;padding:24px 0 0;max-width:820px;display:grid;gap:14px}
table{width:100%;border-collapse:collapse;text-align:left}
th,td{vertical-align:top}
thead th{border-bottom:1px solid var(--ink);padding:12px 24px 12px 0;font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.13em;font-weight:400;color:var(--muted)}
tbody th{border-bottom:1px solid var(--rule);padding:16px 24px 16px 0;font-family:var(--mono);font-size:12px;line-height:1.7;font-weight:400;letter-spacing:.04em;text-align:left}
tbody td{border-bottom:1px solid var(--rule);padding:16px 24px 16px 0;font-size:17px;line-height:1.5}
.scroll-x{overflow-x:auto}
form.apply{max-width:640px;display:grid;gap:26px}
.field{display:grid;gap:8px}
.field label,.field>span{font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.13em;font-weight:400}
input[type=text],input[type=email]{height:46px;background:transparent;color:var(--ink);border:0;border-bottom:1px solid var(--ink);border-radius:0;padding:0 2px;font-family:var(--serif);font-size:19px}
textarea{background:transparent;color:var(--ink);border:1px solid var(--ink);border-radius:0;padding:12px;font-family:var(--serif);font-size:19px;line-height:1.5;resize:vertical}
input:focus,textarea:focus{outline:2px solid var(--signal);outline-offset:2px}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{font-family:var(--mono);font-size:11px;line-height:1.4;letter-spacing:.11em;text-transform:uppercase;border:1px solid var(--rule-2);background:transparent;color:var(--ink);border-radius:0;padding:9px 12px;cursor:pointer}
.chip[aria-pressed="true"],.chip[aria-current="true"]{border-color:var(--ink);background:var(--signal);color:#0A0A0A}
.filter{height:46px;background:transparent;color:var(--ink);border:0;border-bottom:1px solid var(--ink);border-radius:0;padding:0 2px;font-family:var(--mono);font-size:13px;line-height:1.6;flex:1 1 auto}
.tab{font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.11em;border:1px solid var(--rule-2);border-radius:0;padding:9px 12px;cursor:pointer;background:transparent;color:var(--ink)}
.tab[aria-selected="true"]{border-color:var(--ink);background:var(--signal);color:#0A0A0A}
.note{border:0;border-left:1px solid var(--ink);border-radius:0;padding:2px 0 2px 18px;font-size:17px;line-height:1.5}
.note.mono-note{font-family:var(--mono);font-size:11px;line-height:1.8;text-transform:uppercase;letter-spacing:.11em}

/* ---------- prose (blog) ---------- */
.prose{max-width:var(--measure-prose)}
.prose p{margin-top:26px;font-size:20px;line-height:1.62}
.prose p:first-child{margin-top:0}
.prose a{text-decoration:underline;text-decoration-color:var(--rule-2);text-decoration-thickness:1px;text-underline-offset:3px}
.prose a:hover{text-decoration-color:var(--signal)}

/* ---------- diagrams ---------- */
.diagram{display:block;width:100%;height:auto;font-family:var(--mono)}

/* ---------- colophon ---------- */
.footer{background:var(--term-bg);color:var(--term-fg)}
.footer-in{max-width:1560px;margin:0 auto;padding:clamp(44px,6vw,88px) clamp(16px,4vw,72px) 36px;container-type:inline-size;border-top:1px solid var(--ink)}
.footer-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:32px clamp(14px,1.5vw,24px);padding-top:24px;max-width:840px}
.footer-col{display:flex;flex-direction:column;gap:9px;align-items:flex-start}
.footer-col a,.footer-col span.line{font-family:var(--mono);font-size:12px;line-height:1.5;letter-spacing:.04em}
.footer-col a{white-space:nowrap}
.footer-col .label{margin-bottom:4px}
.footer-col .st{font-family:var(--mono);font-size:11px;line-height:1.4;letter-spacing:.06em;color:var(--muted);white-space:nowrap}
.footer-row{display:flex;flex-direction:row;flex-wrap:wrap;gap:6px;align-items:baseline}
/* Tagline on its own line, CTA stacked flush left a clear line below it, at
   every width — not side-by-side on desktop. */
.footer-head{order:-1;display:flex;flex-direction:column;align-items:flex-start;gap:40px;margin:0 0 clamp(36px,5vw,72px)}
.footer-tag{margin:0;font-family:var(--serif);font-weight:300;font-size:clamp(26px,3.2vw,44px);line-height:0.94;letter-spacing:-.035em}
.footer-cta{display:flex;flex-direction:column;align-items:flex-start;gap:7px;text-align:left}
.footer-cta .eyebrow{color:var(--signal)}
.footer-cta a{font-family:var(--mono);font-size:12px;line-height:1.5;letter-spacing:.04em;text-decoration:underline;text-decoration-color:var(--term-dim);text-decoration-thickness:1px;text-underline-offset:4px}.footer-cta a:hover{color:var(--signal);text-decoration-color:var(--signal);text-decoration-thickness:2px}
.footer-wordmark{display:block;width:100%;height:auto;margin:clamp(48px,6vw,96px) 0 0;color:var(--term-fg);overflow:visible}
.footer-bottom{margin-top:clamp(22px,2.6vw,36px);padding-top:16px;border-top:1px solid var(--rule-2);display:flex;flex-wrap:wrap;gap:8px 32px;align-items:baseline;font-family:var(--mono);font-size:11px;line-height:1.5;letter-spacing:.11em;text-transform:uppercase;color:var(--muted)}
.footer-bottom>span:first-child{flex:1 1 auto}
.footer-bottom a{font-family:var(--mono);font-size:11px;line-height:1.5;letter-spacing:.11em;color:var(--muted)}
.footer-in{display:flex;flex-direction:column}

.chip:has(input:checked){border-color:var(--ink);background:var(--signal);color:#0A0A0A}
.chip{user-select:none}

/* ---------- skip link ---------- */
.skip{position:absolute;left:-9999px;top:0;z-index:100}
.skip:focus{left:8px;top:8px;background:var(--signal);color:#0A0A0A;border:1px solid var(--ink);border-radius:0;padding:10px 14px;font-family:var(--mono);font-size:11px;letter-spacing:.11em;text-transform:uppercase}

/* ---------- mobile navigation (no JavaScript) ---------- */
@media (max-width:720px){
  .page-shell{flex-direction:column}
  /* The bar stays with the reader for the whole scroll, not just at the top.
     Sticky is not enough: .footer is a sibling AFTER .page-shell, and a sticky
     element cannot leave its parent's box, so the bar used to scroll away just
     as the footer arrived. Fixed instead, with the bar's height given back to
     the shell as padding since it no longer occupies flow. */
  .page-nav{position:fixed;top:0;left:0;right:0;z-index:90;background:var(--paper);border-bottom:1px solid var(--rule)}
  .page-shell{padding-top:59px}
  /* anchor jumps must clear the sticky bar, not land under it */
  html{scroll-padding-top:78px}
  /* Full-width bar: logo left, toggle right, open panel on its own full row */
  .page-nav{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;width:100%}
  .nav-brand{display:flex;align-items:center;padding:18px 20px}
  .nav-brand img{height:22px;width:auto;display:block}
  .nav-brand:hover{text-decoration:none}
  .side-nav{display:none}
  /* whole bar is the menu control */
  .page-nav{cursor:pointer}
  /* Because the bar itself is clickable, iOS and Android paint their tap
     highlight over the whole of it — the opened panel included — so tapping
     one link flashes the entire menu. The property inherits, so this kills it
     for the bar and everything in it. */
  .page-nav{-webkit-tap-highlight-color:transparent}
  /* Feedback belongs to the tapped link instead: it takes the same signal mark
     the current page carries and holds it until the next page paints. Instant,
     never eased — this is the one thing the reader needs told, immediately. */
  .side-nav a:active{color:var(--ink);text-decoration:none}
  .side-link:active::before,.side-group-label:active::before{content:"";position:absolute;left:-14px;top:50%;transform:translateY(-50%);width:6px;height:6px;background:var(--signal)}
  .side-sub a:active::before{content:"";position:absolute;left:-16px;top:50%;transform:translateY(-50%);width:6px;height:6px;background:var(--signal)}
  .nav-toggle{display:block;background:none;border:none;padding:18px 20px;font-family:var(--mono);font-size:22px;line-height:1;color:var(--ink);cursor:pointer}
  .nav-toggle::after{content:"+"}
  .nav-toggle-input:checked~.nav-toggle::after{content:"\00AB"}
  .nav-toggle-input:checked~.side-nav{display:block;position:static;flex:1 0 100%;height:auto;max-height:calc(100vh - 64px);width:100%;border-right:0;border-top:1px solid var(--rule);border-bottom:0;padding:18px 20px 24px}
  /* the bar carries the logo on mobile, so the panel's own one is redundant */
  .nav-toggle-input:checked~.side-nav .side-logo{display:none}
  /* auto-fit lands on 3 + 1 orphan at this width; two even columns instead */
  .footer-cols{grid-template-columns:1fr 1fr}
}

/* ---------- demo fallback (no JavaScript / reduced motion) ---------- */
.demo-fallback{display:none;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;margin-top:16px}
html:not(.js) .demo-video{display:none}
html:not(.js) .demo-fallback{display:grid}
@media (prefers-reduced-motion:reduce){.demo-video{display:none}.demo-fallback{display:grid}}

/* ---------- layout utilities ---------- */
.lh24{line-height:1.6}
.lh27{line-height:1.6}
.fi{font-family:inherit}
.fi-sm{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--muted)}
.di{display:inline}
.db{display:block}
.m0{margin:0}
.mb8{margin-bottom:8px}
.mb12{margin-bottom:12px}
.mb20{margin-bottom:20px}
.mb24{margin-bottom:24px}
.bt{border-top:1px solid var(--rule)}
.pt48{padding-top:48px}
.ink{color:var(--ink)}
.nw{white-space:nowrap}
.t13{font-size:13px}
.t14{font-size:17px;line-height:1.5}
.t14b{font-size:12px;line-height:1.6;font-family:var(--mono);letter-spacing:.04em}
.t14w{font-size:13px;line-height:1.8;max-width:72ch}
.t22{font-size:clamp(20px,2vw,24px);line-height:1.3}
.code-lg{font-size:18px;padding:2px 5px}
.label-inline{font-family:var(--mono);font-size:11px;line-height:1.4;text-transform:uppercase;letter-spacing:.13em}
.label-xs{font-family:var(--mono);font-size:10px;line-height:1.4;text-transform:uppercase;letter-spacing:.14em}
.up-ls{text-transform:uppercase;letter-spacing:.11em}
.mw640{max-width:640px}
.mw680{max-width:680px}
.mw800{max-width:800px}
.mw820{max-width:820px}
.mw860{max-width:860px}
.mw1000{max-width:1000px}
.mw1072{max-width:1072px}
.mw34ch{max-width:34ch}
.mw68ch{max-width:var(--measure)}
.img-full{display:block;width:100%;height:auto;border-radius:0}
.video-full{display:block;width:100%;height:auto;border-radius:0;margin-top:16px}
.grid-img{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px}
.grid-260{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.grid-280{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:28px}
.grid-4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(28px,3vw,44px) 24px}
@media (max-width:960px){.grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.grid-4{grid-template-columns:minmax(0,1fr)}}
.stack32{display:grid;gap:clamp(28px,3vw,40px);max-width:820px}
.stack56{display:grid;gap:clamp(40px,5vw,64px);margin-top:clamp(40px,5vw,64px)}
.pad-stack{padding:clamp(24px,3vw,36px) 0;display:grid;gap:14px}
.mb20-stack{margin-bottom:20px;display:grid;gap:8px}
.row-between{display:flex;flex-wrap:wrap;gap:24px clamp(24px,4vw,56px);align-items:baseline;justify-content:space-between}
.row-wrap{display:flex;flex-wrap:wrap;gap:24px}
.row-center-16{display:flex;flex-wrap:wrap;gap:16px;align-items:center}
.row-baseline-24{display:flex;flex-wrap:wrap;gap:24px;align-items:baseline;margin-top:24px}
.row-baseline-32{display:flex;flex-wrap:wrap;gap:24px;align-items:baseline;justify-content:space-between;margin-top:32px}
.inline-wrap{display:flex;flex-wrap:wrap;gap:8px;align-items:baseline}
.split{display:flex;justify-content:space-between;gap:16px}
.split-wrap{display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;align-items:baseline}
.kv{display:flex;justify-content:space-between;gap:16px;padding-right:24px}
.gap8{display:flex;gap:8px}
.filter-wrap{display:flex;align-items:center;gap:12px;flex:1 1 260px;max-width:420px}
.meta-row{border-bottom:1px solid var(--rule);padding:24px 0;display:grid;grid-template-columns:minmax(0,220px) minmax(0,1fr);gap:16px clamp(24px,4vw,56px);align-items:baseline}
@media (max-width:640px){.meta-row{grid-template-columns:minmax(0,1fr)}}
.icon-inline{flex:none;display:inline-flex;align-items:center;color:var(--muted)}
.panel{margin-top:40px;max-width:720px;padding:24px 0 0;border:0;border-top:1px solid var(--ink);border-radius:0}
.postnav{padding:clamp(36px,5vw,64px) 0;display:flex;flex-wrap:wrap;gap:24px;justify-content:space-between;align-items:baseline;border-top:1px solid var(--rule)}
.postnav-a{display:flex;flex-direction:column;gap:6px;max-width:44%}
.postnav-b{display:flex;flex-direction:column;gap:6px;max-width:44%;text-align:right}
.h28{display:block;height:24px;width:auto}
.btn-submit{font-family:var(--mono);cursor:pointer}
.term--copy{position:relative;padding-right:96px}
.hidden{display:none}
#received{display:none}
#received:target{display:block}
@media (max-width:560px){.cap-mid{display:none}}

/* Grid and flex items default to min-width:auto, so a nowrap terminal line
   sizes its track instead of scrolling inside the .term. Two places did that
   at phone widths: the framework command blocks and the homepage install
   column. Keep the copy button clear of the text by moving it below the
   command rather than reserving padding for it. */
@media (max-width:640px){
  .stack32>*,.band .hero-meta,.hero-split>.hero-meta{min-width:0}
  .band .hero-meta{flex-basis:100%;max-width:100%}
  .band .kv,.kv{padding-right:0}
  /* The button holds the top-right corner at every width; the command wraps
     into the space left beside it instead of the button moving. */
  .term--copy,.band .term--copy{padding-right:84px}
  .term--copy>span,.band .term--copy>span{min-width:0;white-space:normal;overflow-wrap:anywhere}
  .band .term{overflow-x:visible}
}

/* ---------- print ---------- */
@media print{
  .side-nav,.page-nav,.footer-cols,.skip{display:none}
  .page-shell{display:block}
  html,body{background:#fff}
}

/* ---------- homepage: numbered sections, spot ink, index ---------- */
.sec-head{display:flex;flex-direction:column;gap:12px}
.secnum{flex:0 0 auto;display:block;font-family:var(--mono);font-size:11px;line-height:1.4;letter-spacing:.16em;color:var(--muted)}
.spot-wrap{white-space:nowrap}
.spot{position:relative;padding:0 .1em}
.spot::before{content:"";position:absolute;top:.2em;bottom:.04em;left:0;right:0;z-index:-1;background:var(--signal)}
.spot::selection{background:var(--signal)}
.hero{isolation:isolate}
.hero-meta{flex:0 1 300px;display:flex;flex-direction:column;gap:14px;font-family:var(--mono);font-size:11px;line-height:1.5;letter-spacing:.09em;text-transform:uppercase}
.hero-meta .kv{border-bottom:1px solid var(--rule);padding:0 0 10px}
.hero-split{border-top:1px solid var(--ink);padding-top:26px;display:flex;flex-wrap:wrap;gap:36px clamp(32px,5vw,80px)}
.hero-split>.lead{flex:1 1 380px;max-width:60ch}
.hero-split--muted-rule{border-top-color:#4A453A}
.sec--open .hero-split>.hero-meta{margin-left:auto;flex:1 1 340px}
.band{background:var(--term-bg);color:var(--term-fg);margin-top:var(--section-gap)}
.band-in{max-width:1560px;margin:0 auto;padding:clamp(48px,7vw,112px) clamp(16px,4vw,72px)}
main .band h2{color:var(--term-fg)}
.band p{color:var(--term-fg)}
.band .label,.band .figcap{color:var(--term-dim)}
.band .secnum{color:var(--term-dim)}
.band .kv{border-bottom:1px solid #4A453A;padding-bottom:12px}
.band .term{padding:18px 0;border-top:1px solid #4A453A;border-bottom:1px solid #4A453A}
.band img{border:1px solid #4A453A}
.figcap{margin-top:14px;display:flex;flex-wrap:wrap;gap:6px 24px;font-family:var(--mono);font-size:11px;line-height:1.5;letter-spacing:.11em;text-transform:uppercase}
.index{border-top:1px solid var(--ink)}
.index-row{border-bottom:1px solid var(--rule);padding:20px 0;display:grid;grid-template-columns:clamp(300px,44%,560px) minmax(24px,44px) minmax(0,1fr);gap:6px clamp(20px,2.6vw,40px);align-items:baseline}
@media (max-width:760px){.index-row{grid-template-columns:minmax(0,1fr)}.index-row .leader{display:none}}
.index-row>a{display:block;min-width:0}
.index-name{display:inline;font-size:clamp(24px,2.6vw,34px);line-height:1.15;letter-spacing:-.02em}
.index-count{display:inline;white-space:nowrap;padding-left:12px}
.index-count{font-family:var(--mono);font-size:11px;line-height:1.4;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.leader{flex:none;height:1px;border-bottom:1px dotted var(--rule-2);transform:translateY(-7px)}
.index-row>p{max-width:52ch;margin:0;font-size:17px;line-height:1.5;color:var(--ink-soft)}
.two-col{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:24px clamp(32px,4vw,64px)}
.two-col>p{margin:0}
.rule-both{border-top:1px solid var(--ink);border-bottom:1px solid var(--ink);padding:26px 0}

.band .term--copy{padding-right:104px}
.band .copy{top:12px;right:0}
.band .hero-meta .kv a:hover{text-decoration-color:var(--signal)}

/* install column: the command must never break inside the path */
.band .hero-meta{flex:1 1 420px;max-width:520px}
.band .term--copy{padding-right:88px}
.band .term>span{white-space:nowrap}
.band .term,.band .term>span{text-transform:none;letter-spacing:0}
.band .term{overflow-x:auto}

/* colophon on black */
.footer a{color:var(--term-fg)}
.footer a:hover{text-decoration-color:var(--signal)}
.footer-cols{border-top-color:#4A453A}
.footer-col .label{color:var(--term-dim)}
.footer-col .st{color:var(--term-dim)}
.footer-bottom{border-top-color:#4A453A;color:var(--term-dim)}
.footer-bottom a{color:var(--term-dim)}
.footer-tag{color:var(--term-fg)}

/* ---------- long-form post: headings, footnotes, references ---------- */
.prose h2{margin-top:clamp(44px,5vw,64px)}
.prose h3{margin-top:clamp(30px,3.4vw,42px)}
.prose h2+p,.prose h3+p{margin-top:20px}
.prose pre.term{margin:30px 0;font-size:13px;line-height:1.7}
.prose figure+p{margin-top:26px}
.fnr{font-family:var(--mono);font-size:10px;line-height:0;letter-spacing:.02em;vertical-align:super;color:var(--muted)}
.fnr a{text-decoration:none}
.fnr+.fnr{margin-left:2px}
.fnr a:hover{color:var(--ink);text-decoration:none}
.refs{max-width:var(--measure-prose);margin-top:24px;padding:0;list-style:none;border-top:1px solid var(--ink);counter-reset:ref}
.refs li{counter-increment:ref;position:relative;border-bottom:1px solid var(--rule);padding:14px 0 14px 38px;font-size:15px;line-height:1.6}
.refs li::before{content:counter(ref);position:absolute;left:0;top:18px;font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--muted)}
.refs li:target::before{color:var(--ink)}
.refs li:target{box-shadow:inset 3px 0 0 var(--signal)}
.refs a{text-decoration:underline;text-decoration-color:var(--rule-2);text-decoration-thickness:1px;text-underline-offset:3px}
.refs a:hover{text-decoration-color:var(--signal)}
.refs code{font-size:.78em;word-break:break-all}

/* ---------- action gate diagram ---------- */
.gate-fig{margin:36px 0;max-width:none}
.gate-fig figcaption{font-family:var(--mono);font-size:11px;line-height:1.5;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);margin-bottom:16px}
.gate-fig p.gate-edge{font-family:var(--mono);font-size:12px;line-height:1.6;letter-spacing:.05em;margin:0;padding:0 0 10px}
.gate-fig p.gate-edge.out{margin:0;padding:10px 0 0}
.gate{border:1px solid var(--ink);padding:14px clamp(14px,2vw,24px) 2px}
.gate>.label-xs{display:block;color:var(--muted)}
.gate .rows{border-top:0;margin-top:4px}
.gate .rows>li{display:grid;grid-template-columns:32px minmax(0,1fr) minmax(0,230px);gap:6px 20px;align-items:baseline;padding:14px 0}
.gate .rows>li:last-child{border-bottom:0}
.gate .step{font-size:17px;line-height:1.45}
.gate .row-key.up{color:var(--muted)}
@media (max-width:680px){.gate .rows>li{grid-template-columns:32px minmax(0,1fr)}.gate .rows>li>:last-child{grid-column:2}}

/* ---------- scroll reveal ---------- */
/* Visible by default; only html.js sets the hidden start state, so the page
   renders fully with JavaScript off. One pass, added then unobserved. */
/* Reveal animation cancelled: content is always visible, no fade or rise.
   boot.js and the .reveal/.is-in classes are left in place, inert. */
html.pre main .sec:not([data-hero])>*,html.pre main .band-in>*{opacity:1}
html.js .reveal,html.js .reveal.is-in{opacity:1;transform:none;transition:none}

/* ---------- canary (canary.js) ---------- */
/* One fixed 280px box, scaled by transform: the frame never changes size, so
   swapping poses cannot reflow or flicker. */
.cn{position:fixed;left:0;top:0;width:280px;height:280px;margin:-140px 0 0 -140px;z-index:70;pointer-events:none;opacity:0;will-change:transform,opacity}
/* The global img{max-width:100%} would collapse these inside a zero-size box */
.cn img{position:absolute;left:0;top:0;display:block;width:280px;height:280px;max-width:none;min-width:0;border:0}
/* The washes are translucent, so on the dark band and footer they need lifting. */
.cn--on-dark img{filter:brightness(1.5) saturate(1.1) drop-shadow(0 0 1px rgba(0,0,0,.3))}
/* At rest the head frames snap (no transition on the swap) and the box rocks
   ≤0.56° about the feet from canary.js; nothing here may ease or move it. */
.cn--rest img{transition:none}
@media (prefers-reduced-motion:reduce){.cn{display:none}}

/* The .band copy-button rules reset top/right at every width, so the phone
   placement has to be restated last or the button sits on the command. */
@media (max-width:640px){
  .band .term--copy{padding-right:84px}
  .band .copy{top:12px;right:0;bottom:auto;left:auto;width:max-content}
}

/* ---------- phones: code blocks and touch targets ---------- */
/* A 98-character command shrunk to fit a 358px column would be 4px type, so
   the blocks are shrunk one step and wrapped rather than scrolled sideways. */
@media (max-width:640px){
  pre.term,.prose pre.term{font-size:11px;line-height:1.7;white-space:pre-wrap;overflow-wrap:break-word;overflow-x:hidden}
}

