  @font-face{font-family:"Söhne";src:url(/fonts/soehne-buch.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
  @font-face{font-family:"Söhne";src:url(/fonts/soehne-kraftig.woff2) format("woff2");font-weight:500;font-style:normal;font-display:swap}
  @font-face{font-family:"Söhne";src:url(/fonts/soehne-dreiviertelfett.woff2) format("woff2");font-weight:600 700;font-style:normal;font-display:swap}   /* the display cut, the one Denote's site uses for its H1 (~640) */
  @font-face{font-family:"Söhne Mono";src:url(/fonts/soehne-mono-leicht.woff2) format("woff2");font-weight:300 500;font-style:normal;font-display:swap}   /* the label voice: one cut, Leicht, declared for every weight the labels ask (400 and 500) so nothing is synthesized */
  :root{
    /* day: the live site's theme tokens (background, highlight, base, faint, surface) */
    --paper:#ffffff; --ink:#1A1A1A; --text:#4A4A4A; --mute:#8C8C8C; --hair:#e8e8e8;   /* mute was the live site's #A4A4A4 (2.5:1); a notch darker at 3.4:1 (2026-09-05, Yaron: the dates were too faint by day; night's #797979 is 4:1 on its paper) */
    --sheet:#ffffff; --desk:#f5f5f5; --edge:#dddddd; --sheet-shadow:0 0 4px rgba(0,0,0,.08); --wire:#e3e3e3; --wireline:#cfcfcf;
    --card-edge:rgba(0,0,0,.09); --card-shadow:0 1px 2px rgba(0,0,0,.05),0 8px 24px rgba(0,0,0,.10); --card-shadow-up:0 -1px 2px rgba(0,0,0,.05),0 -8px 24px rgba(0,0,0,.10);   /* the note card: a 1px ring outside the box in black at 9% (the hair's grey on white, darker over darker things), and a modal's lift; the phone sheet's points up */
    /* the one accent, both themes */
    --accent:#00BEB1; --accent-hover:#00A99E; --on-accent:#FFFFFF;   /* text and icons on the teal fills, the Build button and the pins: white in both themes (2026-09-05, Yaron; was the ink, the contrast pick) */
    --red:#BE0003;                                           /* two uses only: the approved stamps and the scan line (and its parked form, the chip dash) */
    --accent-text:#00837B;                                   /* small spec text on white: same hue, 4.6:1. set to #00BEB1 for pure teal */
    --accent-soft:rgba(0,190,177,.55); --accent-edge:rgba(0,190,177,.30);
    --pen:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8 16L17 7' stroke='%2300BEB1' stroke-width='4' stroke-linecap='round'/%3E%3Cpath d='M4 20l1.6-4.8 3.2 3.2z' fill='%231A1A1A'/%3E%3C/svg%3E");
    --sans:"Söhne",system-ui,-apple-system,"Helvetica Neue",sans-serif;
    --mono:"Söhne Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
    --fs:16px; --lh:26px;                                    /* the one size for the sans. rank is color + weight, never size */
    --after-lit:#0A2C3E; --after-end:#020609; --page-edge:#dddddd; --moon-glow:rgba(231,197,99,.22);   /* the after-hours desk: a dark blue under the paper's edge (OKLCH .28 / .05 / 235: the teal accent is hue 186 and the painting's black is 219, so it sits between them; the same lightness as the #2C2C2C grey it replaced, 2026-09-05, Yaron: "a dark blue that is harmonious with the teal"), falling off to the painting's own ceiling (#020609, the mean of hooooper.png's top four rows; nighthawk's was #04090B), so the picture continues the ground with no fade; the page's cut edge is the day sheet edge, a token the band's night palette does not override */
  }
  body.night{--page-edge:#343434; --moon-glow:rgba(231,197,99,.18)}      /* the desk keeps its blue by night too (it used to start at the paper's own dark); the edge is the night sheet edge */
  body.night,body:not(.spec) #after{   /* the night palette; the after-hours band carries it in both themes while built, since its ground is dark in both; in the spec it is drawn on the theme's paper like every other section (2026-09-05, Yaron) */
    --paper:#1A1A1A; --ink:#ffffff; --text:#c5c5c5; --mute:#797979; --hair:#343434;
    --sheet:#222222; --desk:#161616; --edge:#343434; --wire:#3a3a3a; --wireline:#4d4d4d;
    --card-edge:rgba(255,255,255,.10); --card-shadow:0 1px 2px rgba(0,0,0,.5),0 8px 24px rgba(0,0,0,.5); --card-shadow-up:0 -1px 2px rgba(0,0,0,.5),0 -8px 24px rgba(0,0,0,.5);   /* the ring is white at 10% by night: black would vanish on the dark paper */
    --accent-text:#00BEB1;                                   /* teal reads on dark, 8:1 */
    --accent-soft:rgba(0,190,177,.40); --accent-edge:rgba(0,190,177,.22);
    --pen:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8 16L17 7' stroke='%2300BEB1' stroke-width='4' stroke-linecap='round'/%3E%3Cpath d='M4 20l1.6-4.8 3.2 3.2z' fill='%23ffffff'/%3E%3C/svg%3E");
  }
  *{box-sizing:border-box}
  html{margin:0}
  body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:var(--fs);line-height:var(--lh);-webkit-font-smoothing:antialiased;transition:background-color .5s,color .5s}   /* body only: the night tokens live on body.night, and the body background propagates to the canvas */
  .material-symbols-outlined{font-family:'Material Symbols Outlined';font-weight:normal;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:block;white-space:nowrap;word-wrap:normal;direction:ltr;overflow:hidden;-webkit-font-smoothing:antialiased;font-feature-settings:'liga';font-optical-sizing:auto;font-variation-settings:'FILL' 0,'wght' 400,'GRAD' 0,'opsz' 20}   /* the icon font (2026-09-17, Yaron: Material Symbols as a font, not inlined paths); each use sets its size and, for a solid glyph, FILL 1; the box is fixed so nothing moves while the font loads */
  a{color:inherit;text-decoration:underline;text-decoration-color:var(--hair);text-underline-offset:3px;transition:color .1s,text-decoration-color .1s,text-underline-offset .125s cubic-bezier(.2,.7,.2,1)}   /* hover is a small motion, not a switch (2026-09-05, Yaron): the ink and the underline fade to the accent and the underline drops 2px; halved the same day ("double as fast") */
  a:hover{color:var(--accent);text-decoration-color:var(--accent);text-underline-offset:5px}
  .ar{display:inline-block;margin-left:.25em;transition:transform .125s cubic-bezier(.2,.7,.2,1)}   /* a link's arrow: an inline block, so the underline stops at the word, and it nudges along its own direction on hover (Yaron: no underline under the icon, a slight animation) */
  a:hover .ar{transform:translateX(3px)}
  a:hover .ar.ne{transform:translate(2px,-2px)}
  body.spec .g a,body.spec .g a:hover{color:transparent}
  button{font-family:inherit;font-size:inherit;line-height:inherit;-webkit-appearance:none;appearance:none}   /* buttons take the one size too */
  button,a,[role=button],.ghint{cursor:pointer}
  button *,a *,.ghint *,.sign *{cursor:inherit}                       /* text inside a control keeps the control's cursor */
  button,.ghint,.sign,#chip{-webkit-user-select:none;user-select:none}  /* no I-beam over control text, no accidental selection while signing */
  :focus-visible{outline:2px solid var(--accent);outline-offset:3px}
  .label{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--mute)}
  /* the label voice keeps its own leading (1.3, what the mono had): the 26px line belongs to the text */
  .label,[data-tag]::before,.tb,#gate,#bar,#chip,.mh b,.mv b,.endrow .c{line-height:1.3}
  /* tabular figures stay declared: the mono is tabular by nature, the sans fallback is not */
  .label,.yr,.d,.tb span,.stb span,.mtick,.mlabel,#bar .meta,.endrow .c,#note .ne{font-variant-numeric:tabular-nums}
  /* the label voice is Söhne Mono Leicht (2026-09-04): labels, tags, notes, schemas, both strips, the controls and the stamps; the callout arrow and Skip stay in the sans */
  .label,[data-tag]::before,.mh b,.mv b,.tb b,.tb span,.tb .tstamp,.reach,.built .thumb b,.notes .d,.endrow .c,#bar .meta,#chip,.mlabel,.mtick,.stb b,.stb span,.sign .xline,.stamp,#note .ne{font-family:var(--mono)}

  /* ---------- the grid (spec only) ---------- */
  #grid{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:0;transition:opacity .5s;   /* the column edges only: the 26px baseline lines are gone (2026-09-05, Yaron: "get rid of the background lines"), and the --baseline token with them */
    background:
      linear-gradient(to right,
        transparent calc(50% - 321px), var(--accent-edge) calc(50% - 321px) calc(50% - 320px),
        transparent calc(50% - 320px) calc(50% + 320px),
        var(--accent-edge) calc(50% + 320px) calc(50% + 321px), transparent calc(50% + 321px))}
  body.spec #grid{opacity:1}

  /* ---------- the scan line ---------- */
  #scan{position:fixed;left:0;bottom:0;width:100%;height:2px;background:var(--red);z-index:100;pointer-events:none;opacity:0;border-radius:2px;transform-origin:0 0}   /* pinned to the screen's bottom edge like #lap and the chip, and moved by translateY from there: whatever a phone's browser does with elements fixed to the bottom while its URL bar slides, it does to all three alike, so the line always meets the chip (2026-09-05, the third Android round; was top:0 and animated in pixels from the top) */
  #lvh{position:fixed;top:0;left:0;width:0;height:100vh;height:100lvh;visibility:hidden;pointer-events:none}   /* a probe: the screen's height with a phone's URL bar gone; geo() reads it against the layout viewport to know how far past the layout's top the line must run on reopen */
  /* the lap: the same line as an SVG path once it reaches the chip's row, from the screen's left edge to the pill's left-middle and once around the pill; the visible dash window slides along it, then the ring dissolves into the chip's own border */
  #lap{position:fixed;left:0;bottom:0;width:100%;height:2px;z-index:100;pointer-events:none;opacity:0;overflow:visible}   /* pinned to the screen's bottom edge, 2px tall (a zero-height svg does not render), the path drawn above it: its origin rides the bottom as the chip does, so when a phone's URL bar collapses mid-ceremony and the viewport grows, the ring moves with the chip (2026-09-05, Yaron: on Android the line and the ring landed above the chip) */
  #lap path,#lap line{fill:none;stroke:var(--red);stroke-width:2}   /* the path: the run to the pill and the lap; the line: the overrun past the pill's edge to the screen's right edge */

  /* ---------- content column ---------- */
  main{position:relative;z-index:1;max-width:640px;margin:0 auto;padding:0}

  /* ---------- the top slot: the logo row when built, the title block when spec. both live in one grid cell, so the slot is as tall as the taller one and the intro never moves ---------- */
  #slot{position:relative;z-index:1;max-width:640px;margin:0 auto;display:grid}
  #slot > *{grid-area:1/1}
  #top{padding:56px 0 18vh;transition:opacity .4s var(--d,0s),visibility 0s linear calc(var(--d,0s) + .4s)}   /* the logo row, then the same gap the sections keep */
  body:not(.spec) #top{transition:opacity .4s var(--d,0s),visibility 0s linear var(--d,0s)}
  body.spec #top{opacity:0;visibility:hidden}
  #top .row{display:flex;align-items:center;justify-content:space-between}
  #top .logo{display:block;width:48px;height:48px}
  #top .logo svg{display:block;width:100%;height:100%;overflow:visible;fill:var(--accent)}
  #top .theme{background:none;border:0;padding:0;width:24px;height:24px;color:var(--ink);transition:color .1s}
  #top .theme svg{display:block;width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round}
  #top .theme:hover{color:var(--accent)}
  #top .theme .moon,body.night #top .theme .sun{display:none}
  body.night #top .theme .moon{display:block}
  /* on build the logo pops in as the line uncovers the intro, then the toggle: small to full size with one overshoot */
  @keyframes pop{from{transform:scale(.25)}to{transform:scale(1)}}
  #top.pop .logo,#top.pop .theme{transform-origin:center;animation:pop .55s cubic-bezier(.34,1.56,.64,1) var(--pd,0ms) both}
  #top.pop .theme{animation-delay:calc(var(--pd,0ms) + 160ms)}
  body:not(.spec) #top.pop{transition:none}                       /* the header is there at once; the pops are the entrance */
  /* on reopen the mirror: when the line climbs to the middle of the intro the toggle shrinks away, then the logo, each with a small anticipation; then the header hides */
  @keyframes unpop{from{transform:scale(1)}to{transform:scale(.25)}}
  #top.unpop .logo,#top.unpop .theme{transform-origin:center;animation:unpop .3s cubic-bezier(.36,0,.66,-.56) var(--pu,0ms) both}
  #top.unpop .logo{animation-delay:calc(var(--pu,0ms) + 100ms)}
  body.spec #top.unpop{transition:opacity 0s linear calc(var(--pu,0ms) + 400ms),visibility 0s linear calc(var(--pu,0ms) + 400ms)}   /* gone the moment the logo lands small */
  section,footer.sec{position:relative;margin-bottom:18vh}
  .reach{margin:0;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text)}   /* Email / LinkedIn under the intro (the alexalspaugh.com line): the label voice on the body's line */
  .reach a{text-decoration:none;color:inherit;transition:color .1s}
  .reach a:hover{color:var(--accent)}
  .reach span{margin:0 .7em;color:var(--mute)}
  #intro p.g{text-wrap:pretty}   /* the intro's paragraphs never end on a lone word where the browser can help it (2026-09-19, Yaron saw "Tower." alone on the desk; the copy was trimmed to two lines there, this covers the other widths; browsers without it wrap as before) */
  .endrow .reach{margin-left:auto}   /* the same line again at the end, on the right of the copyright */
  h1{font-size:32px;font-weight:700;letter-spacing:-.018em;line-height:1.15;margin:0 0 var(--lh);transition:opacity .4s var(--d,0s)}
  body.spec [data-tag] > h1{opacity:0}   /* a section's headline hides in the spec like every section title, and the SEC tag takes its first line (2026-09-05, Yaron); the intro's on the homepage, the page title on the other templates */   /* the one size exception: the intro, in the display cut */
  p{margin:0 0 var(--lh);color:var(--text)}
  h2{font-size:20px;font-weight:700;line-height:var(--lh);letter-spacing:-.012em;color:var(--ink);margin:0 0 20px;transition:opacity .4s var(--d,0s)}   /* section titles: the display cut at 20px, 1.6 under the 32px headline, on the same 26px line so the row keeps its height and the tag and the object pin stay centered on it (2026-09-05, Yaron: "a tad larger", "harmonious with the main title"; was the text size, the one-size rule bent on purpose); the tracking sits between the body's 0 and the headline's -.018em */
  body.spec h2{opacity:0}

  /* ---------- spec skin: outlines + tags ---------- */
  [data-tag]{outline:1px solid transparent;outline-offset:20px;transition:outline-color .4s var(--d,0s),opacity .5s ease var(--d,0s)}
  body.spec [data-tag]{outline-color:var(--accent-soft)}
  [data-tag]::before{content:attr(data-tag);position:absolute;top:-42px;left:0;font-weight:500;font-size:10px;letter-spacing:.1em;color:var(--accent-text);opacity:0;transition:opacity .4s var(--d,0s)}
  body.spec [data-tag]::before{opacity:1}
  [data-tag]:has(h2)::before{top:0;line-height:var(--lh)}   /* where a section has a title, the tag takes the title's row (the title hides in the spec), inside the box, instead of hanging above it (2026-09-05, Yaron); the line box is the title's, so the 10px tag centers on it. the intro (its h1 stays visible) and the footer (its row is the © line) keep theirs above */
  #after .col::before,[data-tag]:has(> h1)::before{top:0;line-height:calc(32px * 1.15)}   /* the band's title and a section's headline (the intro, a page's title) are the display cut */
  footer.sec::before{top:0;line-height:var(--lh)}   /* the footer has no title: the © hides in the spec and the tag takes its row (2026-09-05, Yaron) */
  body.spec .endrow .c{opacity:0}

  /* ---------- spec skin: greeked text ---------- */
  .g{position:relative;transition:color .4s var(--d,0s)}
  body.spec .g{color:transparent}
  body.spec .g a{text-decoration:none}
  .g::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .4s var(--d,0s);
    background:repeating-linear-gradient(to bottom, transparent 0 7px, var(--hair) 7px 19px, transparent 19px var(--lh))}
  body.spec .g::after{opacity:1}
  .gi{border-radius:3px}   /* the greeking transition lives on the next rule, not here (2026-09-17): on .gi itself it replaced every link's hover transition (the .4s made All posts fade slowly), and the row hover rule on .notes li>* replaced it back, so the blog titles greeked at the start of every ceremony instead of when the line passed */
  body.spec .gi{color:transparent!important;background-color:var(--hair);text-decoration:none}
  body.spec .gi,body.fx .gi{transition:color .4s var(--d,0s),background-color .4s var(--d,0s)}   /* the state change only: the reopen's after-change style is body.spec, the build's is body.fx, which buildFx holds for the length of the ceremony; outranks the hover rules, so between ceremonies every link hovers at the page's .1s */

  /* ---------- notes (spec only): the rules are comment pins now (2026-09-04). each note is data; its pin, a teal disc with a chat bubble, sits on the corner of the thing it is about (the year, the date, VISIT), lands with the pop as the line passes, and opens the note as a card beside it (hover previews, click keeps; a bottom sheet on phones) ---------- */
  .pin{position:absolute;width:28px;height:28px;z-index:5;opacity:0;pointer-events:none;transition:opacity .4s var(--d,0s),background-color .1s,box-shadow .1s}
  body.spec:not(.draft) .pin{opacity:1;pointer-events:auto}
  /* the disc: 28px teal with a paper ring and the sheets' shadow, the bubble white with the same shadow, so it sits on the drawing like a sticker (2026-09-04, Yaron) */
  .pn{display:grid;place-items:center;width:28px;height:28px;padding:0;border:2px solid var(--paper);border-radius:50%;background:var(--accent);color:var(--on-accent);box-shadow:var(--sheet-shadow);cursor:pointer;transform-origin:center;
    transition:background-color .2s,box-shadow .2s,border-color .5s}
  .pn .material-symbols-outlined{font-size:14px;width:14px;height:14px;font-variation-settings:'FILL' 1,'wght' 400,'GRAD' 0,'opsz' 20;filter:drop-shadow(var(--sheet-shadow))}   /* Material Symbols 'chat_bubble' (solid) and 'data_object', the font (2026-09-17; the prototype inlined the paths at the same 14px) */
  .pn:hover,.pin.open .pn{background:var(--accent-hover)}
  .pin.open .pn{box-shadow:var(--sheet-shadow),0 0 0 3px var(--accent-edge)}
  body.spec:not(.draft) .pn{animation:pop .55s cubic-bezier(.34,1.56,.64,1) var(--d,0s) both}
  /* the card is a modal, not a drawn box (2026-09-04, Yaron: "too flat"): 6px corners, a neutral hairline, a layered shadow, and it settles in from a hair smaller */
  #note{position:absolute;top:0;left:0;z-index:95;width:300px;padding:14px 40px 16px 16px;background:var(--paper);border:0;border-radius:6px;box-shadow:0 0 0 1px var(--card-edge),var(--card-shadow);
    opacity:0;visibility:hidden;transform:translateY(4px) scale(.98);transform-origin:top center;transition:opacity .18s,transform .18s,visibility 0s .18s,background-color .5s}
  #note.on{opacity:1;visibility:visible;transform:none;transition:opacity .18s,transform .18s,visibility 0s,background-color .5s}
  body.night #note{background:var(--sheet)}   /* a shade above the night paper, since a shadow alone does not lift there */
  #note .ne{display:block;font-weight:400;font-size:9px;line-height:1.3;letter-spacing:.12em;text-transform:uppercase;color:var(--accent-text);margin-bottom:6px}
  #note p{margin:0;color:var(--text)}
  #note.obj p{font-family:var(--mono);font-size:12px;line-height:20px;letter-spacing:.04em;color:var(--ink)}   /* an object's card is its schema, in the label voice; 12px so Product and Post are one line in the 244px card, Case study wraps at a comma */
  #note .nx{position:absolute;top:10px;right:10px;width:20px;height:20px;padding:0;border:0;background:none;color:var(--mute);display:grid;place-items:center;transition:color .1s}
  #note .nx .material-symbols-outlined{font-size:16px;width:16px;height:16px}
  #note .nx:hover{color:var(--ink)}

  /* ---------- ontology callouts (spec only) ---------- */
  /* the object schemas are pins now (2026-09-05, Yaron): see NOTES, kind Object */

  /* ---------- measures (spec only, desktop) ---------- */
  .mh{position:absolute;top:-64px;left:0;right:0;height:8px;border-left:1px solid var(--accent);border-right:1px solid var(--accent);opacity:0;transition:opacity .4s var(--d,0s)}
  .mh::before{content:"";position:absolute;left:0;right:0;top:4px;height:1px;background:var(--accent)}
  .mh b{position:absolute;left:50%;top:-3px;transform:translateX(-50%);background:var(--paper);padding:0 10px;font-weight:500;font-size:10px;letter-spacing:.1em;color:var(--accent-text)}
  .mv{position:absolute;left:calc(50% - 4px);top:calc(-18vh + 26px);height:calc(18vh - 52px);width:8px;border-top:1px solid var(--accent);border-bottom:1px solid var(--accent);opacity:0;transition:opacity .4s var(--d,0s)}
  .mv::before{content:"";position:absolute;top:0;bottom:0;left:4px;width:1px;background:var(--accent)}
  .mv b{position:absolute;top:50%;left:4px;transform:translate(-50%,-50%);background:var(--paper);padding:6px 10px;white-space:nowrap;font-weight:500;font-size:10px;letter-spacing:.1em;color:var(--accent-text)}
  body.spec .mh,body.spec .mv{opacity:1}
  @media (max-width:1024px){.mh,.mv{display:none}}

  /* ---------- title block (spec only) ---------- */
  .tb{position:relative;display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--accent-soft);align-self:start;margin:24px 0 48px;
    transition:opacity .4s var(--d,0s),border-color .4s var(--d,0s),visibility 0s linear calc(var(--d,0s) + .4s)}
  body.spec .tb{transition:opacity .4s var(--d,0s),border-color .4s var(--d,0s),visibility 0s linear var(--d,0s)}
  body:not(.spec) .tb{opacity:0;visibility:hidden;border-color:transparent}
  .tb div{padding:12px 16px;border-right:1px solid var(--accent-edge)}
  .tb div:nth-child(3n){border-right:0}
  .tb div:nth-child(-n+3){border-bottom:1px solid var(--accent-edge)}   /* two rows of three since the counts row went (2026-09-05) */
  .tb b{display:block;font-weight:400;font-size:9px;letter-spacing:.12em;color:var(--accent-text);text-transform:uppercase;margin-bottom:5px}
  .tb span{display:block;line-height:26px;font-size:11px;letter-spacing:.04em;color:var(--ink);text-transform:uppercase}   /* the value line is 26px, the height the signature mini also takes */
  @media (min-width:1025px){.tb span,.tb b{white-space:nowrap}}   /* where the block shares the slot with the logo row, a value (or a label, now that the labels carry the date and Sign again) that does not fit runs past its cell instead of wrapping and pushing the page down a line */
  .tb .c-appr{position:relative}
  /* the remembered sign-off (2026-09-17): once the visitor has signed or skipped, the two label lines carry it and no line is added anywhere (Yaron: no extra line; the stamp as the control was "too hidden"): the date joins the APPROVED BY label ("Approved by · 2026-09-17", "Approved · …" on phones like the names) and Sign again joins the STATUS label ("Status · Sign again"), a link in the label's size with a wider hit area for a thumb */
  .tb .sdate,.tb .sagain-w{display:none;font-style:normal}
  .tb.kept .sdate,.tb.kept .sagain-w{display:inline}
  .tb .sdate{letter-spacing:.06em}   /* the figures a touch tighter than the label's .12em */
  .tb .sdate::before,.tb .sagain-w::before{content:"·";margin:0 .5em;letter-spacing:0}   /* the middle dot as its own mark with margins, not typed spaces at the label's tracking: it can tighten on phones (below) so the two labels hold one line down to 360px wide */
  .tb .sagain{position:relative;font:inherit;letter-spacing:inherit;text-transform:inherit;line-height:inherit;background:none;border:0;padding:0;color:var(--accent-text);cursor:pointer;text-decoration:underline;text-decoration-color:var(--accent-edge);text-underline-offset:2px;transition:color .1s,text-decoration-color .1s}
  .tb .sagain::after{content:"";position:absolute;inset:-8px -6px}   /* the hit area, without touching the layout */
  .tb .sagain:hover{color:var(--accent);text-decoration-color:var(--accent)}
  body.remembered #chip{opacity:1;pointer-events:auto}   /* the chip is there from the first frame on a remembered visit (the script adds `on` too) */
  .tb .tstamp{position:absolute;right:12px;bottom:10px;display:none;line-height:normal;transform:rotate(-7deg);border:2px solid var(--red);border-radius:4px;padding:5px 8px 5px 11px;font-weight:500;font-size:10px;letter-spacing:.26em;text-transform:uppercase;color:var(--red);opacity:.9;pointer-events:none}

  /* ---------- lists ---------- */
  /* the row with a thumbnail: things I build and the case studies share it. the thumbnail is a placeholder box for now (real imagery is an open item); a crossed box means not built yet, and in the spec state every thumbnail is a crossed box, the wireframe's image */
  .built{list-style:none;padding:0;margin:0}   /* no rules between the rows (2026-09-05, Yaron): the thumbnails space the list, the 18px row padding is the gap */
  .built li{padding:18px 0;display:grid;grid-template-columns:1fr 1fr;grid-template-rows:auto auto 1fr;grid-template-areas:"thumb text" "thumb go" "thumb .";gap:8px 24px;align-items:start}   /* the third row takes the thumbnail's extra height, so the link stays 8px under the text */   /* half and half (Yaron): the thumbnail is one half of the row, the text the other, the link under the text */
  .built li>div{grid-area:text}
  .built h3{margin:0;font-size:inherit;font-weight:500}
  .built h3 a{color:inherit;text-decoration:none;transition:color .1s}
  .built h3 a:hover{color:var(--accent)}
  .built p{margin:0;color:var(--text)}
  .built .go{grid-area:go;justify-self:start;white-space:nowrap}   /* the regular link style (Yaron: not all caps mono), the arrows kept */
  .built .soon .go{color:var(--mute)}
  .built .thumb{grid-area:thumb;position:relative;display:block;aspect-ratio:4/3;border-radius:6px;background:var(--wire);overflow:hidden;color:var(--mute);text-decoration:none;transition:background-color .4s var(--d,0s),box-shadow .4s var(--d,0s),border-radius .4s var(--d,0s)}
  .built .thumb b{position:absolute;inset:0;display:grid;place-items:center;font-weight:500;font-size:9px;letter-spacing:.12em;text-transform:uppercase;transition:opacity .4s var(--d,0s)}
  .built .xb{position:absolute;inset:0;width:100%;height:100%;stroke:var(--wireline);stroke-width:1;opacity:0;transition:opacity .4s var(--d,0s)}
  .built .thumb img{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover;transition:opacity .4s var(--d,0s)}   /* a real thumbnail (2026-09-19, the D direction: the app at 2x cropped to its corner on the brand's color, a 4:3 WebP in src/img/things or img/work) fills the box; in the spec it fades out like the label and the crossed box takes over */
  body.spec .built .thumb img{opacity:0}
  /* the window thumbnail (2026-09-19, the fifth round, Yaron: "just move the screen image"; the live demo in the window, three rounds of it, is dropped, "too much work for the value"): the box's ground is the brand color from the data (`--ground`) and the app's window is its own image (`img.win`), rendered at the still's framing (a tenth in from the left, a fifth down, the app at 2.1x) with bleed of a twentieth past the right edge and a tenth past the bottom, where the box clips it. On a mouse hover the window slides up and left by 4% and 7.2% of the box (the third try's motion, 12.3 and 16.6px on the desk), leaving a strip of the ground at the top and the left, and its bleed covers the right and the bottom. The top corners and the shadow are the composition's, scaled. Never on touch, never in the spec */
  .built .thumb.ground{background:var(--ground,var(--wire))}
  body.spec .built .thumb.ground{background:transparent}
  .built .thumb img.win{inset:auto;left:10%;top:20%;width:95%;height:90%;object-fit:fill;border-radius:3px 3px 0 0;box-shadow:0 6px 16px rgba(0,0,0,.28);transition:opacity .4s var(--d,0s),transform .5s cubic-bezier(.2,.7,.2,1)}
  @media (hover:hover) and (pointer:fine){
    body:not(.spec) .built .thumb:hover img.win{transform:translate(-4.2105%,-8%)}   /* 4% and 7.2% of the box: the window is 95% and 90% of it */
  }
  /* the poster thumbnail (2026-09-19, Yaron, for Counts a-Lot: "make the image inside the thumbnail move slowly to become a bit larger"): the picture grows to 1.06 over 2.5s on a mouse hover, the box still and clipping it, and settles back at the same pace */
  .built .thumb img.phone{inset:auto;left:18%;bottom:14%;width:64%;aspect-ratio:683/817;height:auto;object-fit:fill;filter:drop-shadow(0 6px 10px rgba(0,0,0,.35));transition:opacity .4s var(--d,0s),transform .5s cubic-bezier(.2,.7,.2,1)}   /* the phone thumbnail (2026-09-21, the Compass Mobile App row, coming soon; first a drawn phone with an empty screen, then his own picture, "use this mobile phone": the lower part of a Pixel 6 Pro with the Compass app's map, `src/img/work/compass-mobile-phone.webp`, 683 by 817 with the corners' alpha, on the black ground with the deck's contour lines, the Agent Search row's): the phone stands in the box, 64% of it wide, its foot 14% above the box's, its head past the box's head, which hides the picture's cut edge; on a mouse hover it COMES DOWN 8% of its height (Yaron: "make the animation come down, so flip the order"; it rose at first), the head still past the box's top. the window for ServiceNow Arc (`servicenow-window.svg`, drawn: a generic LLM app, a sidebar like a chat app's with the three lights, a new chat button, greeked chat rows and an account row, the page with one sentence over an input field with a send button; the sentence in the system sans, an SVG in an img cannot reach the site's fonts) is a window like the others and needs no rule of its own */
  @media (hover:hover) and (pointer:fine){
    body:not(.spec) .built .thumb:hover img.phone{transform:translateY(8%)}
  }
  .built .thumb.dark img.win{box-shadow:0 0 0 1px var(--mute),0 6px 16px rgba(0,0,0,.28)}   /* a window on a dark ground (2026-09-21, the Compass row: the black ground with a still of its deck's contour lines, `resources/thumbs/compass-ground.js`; `dark` in cases.json): the window's own dark edge, Compass's black side bar, would have no end on it, so it wears the deck's 1px of the mute, where the grounds in a brand's color need nothing */
  .built .thumb img.poster{transition:opacity .4s var(--d,0s),transform 2.5s cubic-bezier(.2,.7,.2,1)}
  @media (hover:hover) and (pointer:fine){
    body:not(.spec) .built .thumb:hover img.poster{transform:scale(1.06)}
  }
  .built .thumb.x,body.spec .built .thumb{background:transparent;box-shadow:inset 0 0 0 1px var(--wireline);border-radius:0}
  .built .thumb.x b,body.spec .built .thumb b{opacity:0}
  .built .thumb.x .xb,body.spec .built .xb{opacity:1}
  .more{display:inline-block;margin-top:14px}   /* the regular link style too */
  /* the CV banner under the case studies (2026-09-19, Yaron's reference: a card with an icon tile, a title over a meta line, a button at the right; the arrow for its Hide): the whole card is the link. The desk gray as the fill with a hairline, the paper for the tile and the button, the one type size with the title in the ink at 500 and the meta line "Eleven roles since 1999" in the mute (a "· ⤓ PDF too" with the download glyph inline was cut the same day, Yaron); on hover the edge darkens and the title turns teal at .1s, the arrow nudges as every arrow does. In the spec the fill goes and the two texts greek, the outlines stay as the wireframe */
  .banner{position:relative;z-index:0;display:flex;align-items:center;gap:16px;margin-top:20px;padding:10px;border-radius:12px;background:var(--desk);box-shadow:0 0 0 1px var(--hair);color:var(--text);text-decoration:none;transition:background-color .1s,box-shadow .1s}
  .banner:hover{box-shadow:0 0 0 1px var(--edge)}
  /* the pile (2026-09-19, Yaron: "make this an actual paper stack that lives on top of the banner and is taller than it, like the intro paper stack"): the gate's loose pile at CV size. The top sheet is a portrait 66 by 92, the sheet color with the edge's hairline and the sheet's shadow, standing on the card 8px taller than it above and below (its negative margins take the card's padding and the overhang, so the card keeps its 76); a greeked résumé on it, a name bar in the mute and lines in the wire; two sheets behind, turned a degree and a half each way and pushed apart as the gate's are, at the card's -1 and -2 layers (the card is the stacking context), so they sit on the fill under the top sheet */
  .banner .pile{flex:none;position:relative;top:0;width:66px;height:92px;margin:-18px 0;border-radius:1px;transition:top .125s cubic-bezier(.2,.7,.2,1);border:1px solid var(--edge);box-shadow:var(--sheet-shadow);background-color:var(--sheet);background-image:linear-gradient(var(--mute),var(--mute)),linear-gradient(var(--wire),var(--wire)),linear-gradient(var(--wire),var(--wire)),linear-gradient(var(--wire),var(--wire)),linear-gradient(var(--wire),var(--wire)),linear-gradient(var(--wire),var(--wire)),linear-gradient(var(--wire),var(--wire));background-size:26px 3px,46px 2px,46px 2px,34px 2px,46px 2px,46px 2px,28px 2px;background-position:9px 12px,9px 25px,9px 32px,9px 39px,9px 50px,9px 57px,9px 64px;background-repeat:no-repeat}
  .banner .pile::before,.banner .pile::after{content:"";position:absolute;inset:-1px;z-index:-1;border-radius:1px;border:1px solid var(--edge);background:var(--sheet);box-shadow:var(--sheet-shadow);pointer-events:none;transition:transform .125s cubic-bezier(.2,.7,.2,1)}
  .banner .pile::after{transform:translate(3px,-2px) rotate(1.4deg)}    /* turned clockwise, pushed up and right */
  .banner .pile::before{z-index:-2;transform:translate(-3px,2px) rotate(-1.6deg)}   /* turned the other way, pushed down and left */
  /* on hover the pile is picked up a little (2026-09-19, Yaron: "make the stack move a little on hover"): the whole pile rises 2px by its offset (a transform on the top sheet would make it a stacking context and put the back sheets over it) and the two sheets behind fan out, turned a degree more each way and pushed 2 further, at the hover speed, with the arrow's nudge */
  .banner:hover .pile{top:-2px}
  .banner:hover .pile::after{transform:translate(5px,-4px) rotate(2.4deg)}
  .banner:hover .pile::before{transform:translate(-5px,4px) rotate(-2.6deg)}
  .banner .txt{flex:1;min-width:0;display:flex;flex-direction:column}
  .banner b{font-weight:500;color:var(--ink);transition:color .1s}
  .banner:hover b{color:var(--accent)}
  .banner small{font-size:var(--fs);color:var(--mute)}
  .banner .btn{flex:none;display:grid;place-items:center;width:40px;height:40px;margin-right:6px;border-radius:10px;background:var(--paper);box-shadow:0 0 0 1px var(--edge);color:var(--ink)}
  .banner .btn .ar{margin:0}
  body.spec .banner{background:transparent}
  body.spec .banner .btn{background:transparent;color:transparent}
  body.spec .banner .pile,body.spec .banner .pile::before,body.spec .banner .pile::after{background:transparent;box-shadow:none;border-color:var(--wireline)}   /* the pile as outlines in the spec, the résumé lines gone with the sheet's fill */
  @media (max-width:700px){.banner{gap:12px;padding:8px}.banner .pile{width:60px;height:100px;margin:-14px 0}.banner .btn{margin-right:2px}}   /* on phones the meta line wraps and the card is 94: the sheet 100, standing 3 taller each way */
  .notes{list-style:none;padding:0;margin:0}
  .notes li{display:grid;grid-template-columns:110px 1fr;gap:20px;padding:12px 0;border-top:1px solid var(--hair)}
  .notes li>*{transition:transform .125s cubic-bezier(.2,.7,.2,1),color .1s,text-decoration-color .1s,text-underline-offset .125s cubic-bezier(.2,.7,.2,1)}   /* the row answers the hover, not just the link (2026-09-05, Yaron): its contents slide 4px (the row's own hairline stays put), the title takes the link's hover, the date brightens */
  .notes li:hover>*{transform:translateX(4px)}
  .notes li:hover a{color:var(--accent);text-decoration-color:var(--accent);text-underline-offset:5px}
  .notes li:hover .d{color:var(--text)}
  .notes a{font-weight:500}
  .notes li:last-child{border-bottom:1px solid var(--hair)}
  .notes .d{font-size:12px;color:var(--mute);padding-top:2px;letter-spacing:.06em}
  footer.sec{margin-bottom:0}
  .endrow{display:flex;gap:24px;align-items:baseline;margin-top:0}
  .endrow .c{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--mute);transition:opacity .4s var(--d,0s)}
  /* after hours: the page ends, the desk shows, and on it lies a second sheet, the spec of the after-hours page. the sheet is the link */
  #after{position:relative;z-index:1;margin-top:56px;padding:64vh 0 0;   /* the band's edge 56px under the footer row, the header's own margin, as the subpages end (2026-09-06, Yaron: the 18vh was too much there, "the same smaller spacing in homepage too"); 40 on phones below */--fade:56vh;--paper:var(--after-end);color:var(--ink);transition:border-color .4s var(--d,0s);   /* the content starts 8vh under the falloff; color is set here, not just the token: links inherit a computed color, and the body's is the day ink */
    border-top:1px solid var(--page-edge);box-shadow:inset 0 4px 12px -4px rgba(0,0,0,.6);   /* the page is the top sheet on the desk: its cut edge, and the shadow it casts just under it (2026-09-05, replacing the paper-to-dark wash Yaron found too much) */
    background:linear-gradient(to bottom,var(--after-lit) 0,color-mix(in srgb,var(--after-lit) 76.6%,var(--after-end)) calc(var(--fade) * 0.125),color-mix(in srgb,var(--after-lit) 56.3%,var(--after-end)) calc(var(--fade) * 0.25),color-mix(in srgb,var(--after-lit) 39.1%,var(--after-end)) calc(var(--fade) * 0.375),color-mix(in srgb,var(--after-lit) 25%,var(--after-end)) calc(var(--fade) * 0.5),color-mix(in srgb,var(--after-lit) 14.1%,var(--after-end)) calc(var(--fade) * 0.625),color-mix(in srgb,var(--after-lit) 6.3%,var(--after-end)) calc(var(--fade) * 0.75),color-mix(in srgb,var(--after-lit) 1.6%,var(--after-end)) calc(var(--fade) * 0.875),var(--after-end) var(--fade));background-clip:padding-box}   /* the desk's falloff: lit at the edge, eased out (quadratic, most of the fall in the first third) so the middle greys never sit on screen. clipped to the padding box, and declared after the shorthand, which resets it: in the spec the cut edge goes transparent, and the gradient (repeating, so its end color, near black) showed through that 1px as a dark line (2026-09-05, Yaron) */
  #after .col{z-index:2}   /* content over the grain; the grain lies over the moon and the painting (the painting at 0, so the film does not stop at its edge) */
  #after::after{content:"";position:absolute;inset:0;z-index:-1;background:var(--paper);opacity:0;pointer-events:none;transition:opacity .4s var(--d,0s)}   /* the spec's paper: above the band's ground and inset shadow, below the drawn moon, the crossed box and the outline; fades with the band's --d like a block */
  body.spec #after{--paper:inherit;border-top-color:var(--wireline)}   /* the theme's paper, and the cut edge drawn in the wire grey, the line the moon ring hangs from (a transparent edge left no line at all; Yaron: "there should be tho"). no padding for the bar here: a first fix padded the page by the bar's 65px in the spec, which changed the page's height between states and slid the content when scrolled to the end (Yaron: the point is to bounce between build and spec without moving content); the drawn placeholder is shorter instead, see .fol */
  body.spec #after::after{opacity:1}
  body.spec #after::before{opacity:0}   /* no grain on the drawing */
  body.spec #after p{color:transparent}   /* the greeked line: #after p's ID outranked body.spec .g and the descenders peeked under the bars */
  #after .fol{z-index:0}
  #after .moon{--D:36vh;position:absolute;left:0;right:0;top:0;height:40vh;overflow:hidden;pointer-events:none}   /* the moon (a flat sunset disc until 2026-09-05, then Yaron's painted moon.png, teal in shadow and gold in light) hangs under the page's cut edge; the wrapper clips it, not the band */
  #after .moon i{position:absolute;left:50%;top:0;width:var(--D);height:var(--D);transform:translate(-50%,calc(-50% - .2 * var(--D) + var(--mp,0) * .38 * var(--D)));border-radius:50%;box-shadow:0 0 12vh 4vh var(--moon-glow);transition:box-shadow .4s var(--d,0s)}   /* the glow is the moon's own gold, the mean of its brightest quarter. the disc rides the scroll (2026-09-05, Yaron): its center starts .2 of its size above the edge (30% showing) and drops .38 of its size as the band's edge climbs the viewport (--mp, 0 at the bottom of the screen to 1 at the top), ending .18 below it (68% showing) */
  #after .moon .stars{position:absolute;inset:0;transition:opacity .4s var(--d,0s)}   /* sparse stars in the sky, placed by JS from a fixed seed, kept off the moon */
  #after .moon .st{position:absolute;width:var(--s,2px);height:var(--s,2px);border-radius:50%;background:#F3E6C2;opacity:.5;animation:twinkle var(--tw,3s) ease-in-out var(--dl,0s) infinite alternate}
  @keyframes twinkle{from{opacity:.12}to{opacity:.9}}
  body.spec #after .moon .stars{opacity:0}   /* the drawing has no stars */
  body.spec #after .moon .st{animation-play-state:paused}
  #after .moon img{display:block;width:105.5%;height:105.5%;margin:-2.75% 0 0 -2.75%;transition:opacity .4s var(--d,0s)}   /* the painted disc fills 95% of its PNG (1189 of 1254), so the image is scaled by 1254/1189 and offset half the difference: the limb lands on the square's edge, where the glow and the spec ring begin (a first cut left a 7px strip of bare desk between limb and glow, Yaron: "why do we have this blue stroke") */
  #after .moon::after{content:"";position:absolute;inset:0 0 -40px 0;box-shadow:inset 0 4px 12px -4px rgba(0,0,0,.6);transition:box-shadow .4s var(--d,0s)}
  body.spec #after .moon::after{box-shadow:none}   /* the page's shadow falls on the moon too; the box runs 40px past the wrapper so the shadow's faint bleed along its own bottom edge is clipped away (it drew a hairline across the sky at 40vh) */
  body.spec #after .moon i{box-shadow:inset 0 0 0 1px var(--wireline)}   /* in the spec the moon is a drawn circle, like the thumbnails are crossed boxes */
  body.spec #after .moon img{opacity:0}
  #after::before{content:"";position:absolute;inset:0;z-index:1;transition:opacity .4s var(--d,0s);background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0/180px 180px;opacity:.06;pointer-events:none}   /* grain over the desk, under the content: film, not a Photoshop gradient */
  #after .fol{--barh:65px;position:relative;display:block;margin-top:-5vw;pointer-events:none}   /* --barh: the fixed bar's height (12 + the 39.6 pill + 12 + the hairline); the drawn placeholder below stops that far short of the box */   /* the lockup sits over the painting's bare ceiling (Yaron: closer to the image): the image is 33.3vw tall and its ceiling is bare to 15% of that across the column's span at any desktop width, the window frames start at 24%, so 5vw lands the column's bottom in the dark with the frames 9% of the image lower */
  #after .fol img{display:block;width:100%;height:auto;transition:opacity .4s var(--d,0s);-webkit-mask-image:linear-gradient(transparent,#000 20px);mask-image:linear-gradient(transparent,#000 20px)}   /* a 20px fade at the top edge only, so the picture emerges from the ground over its first rows (2026-09-05, Yaron: "slight", "20px tops"); the desk still ends on the ceiling's color, so the painting continues it (a 28% fade-in was tried and rejected) */
  #after .fol .xb,#after .fol::after{position:absolute;inset:0;width:100%;height:calc(100% - var(--barh));opacity:0;transition:opacity .4s var(--d,0s)}   /* the crossed box is drawn on a box 65px shorter than the image's, so in the spec its bottom edge meets the Build bar's top edge when the page is scrolled to the end, and the image's own box keeps its height in both states: nothing moves between build and spec (2026-09-05, Yaron; the bar had cropped the box's bottom) */
  #after .fol .xb{stroke:var(--wireline);stroke-width:1}
  #after .fol::after{content:"";box-shadow:inset 0 0 0 1px var(--wireline);pointer-events:none}   /* the ring, on the same short box */
  body.spec #after .fol img{opacity:0}   /* in the spec the image is the drawing's placeholder, the crossed box, like the thumbnails */
  #after .fol .fx{position:absolute;inset:0;overflow:hidden;z-index:1;pointer-events:none;transition:opacity .4s var(--d,0s)}   /* the candles (2026-09-05, Yaron: "soft animation to the candles", real flames with "an echo of light moving"): a layer over the painting, clipped to its box */
  #after .fol .fxi{position:absolute;top:0;left:50%;height:100%;aspect-ratio:2170/725;transform:translateX(-50%)}   /* the picture's rendered content, so the flames' percentages hold on the phone's cover crop too (the layer is as tall as the box and as wide as the painting is at that height, centered like object-position 50%) */
  #after .fol .fl{position:absolute;left:var(--x);top:var(--y);width:var(--s,2.2%);aspect-ratio:1;transform:translate(-50%,-50%);opacity:var(--a,1)}   /* per candle: --s its size, --a its strength, --e the echo's spread, --k its softness (the gradient's mid stop), --t its period, --dl its phase, --lag the echo's beat behind the flame (2026-09-05, Yaron: slower, "more random variety between size, soft etc", "very subtle") */
  #after .fol .fl::before,#after .fol .fl::after{content:"";position:absolute;border-radius:50%;mix-blend-mode:screen;animation:flick var(--t) linear infinite var(--dl)}
  #after .fol .fl::before{inset:0;background:radial-gradient(closest-side,rgba(255,226,160,.45),rgba(255,176,84,.22) var(--k,42%),rgba(255,140,50,0) 100%)}   /* the flame: a small warm core that flickers */
  #after .fol .fl::after{inset:var(--e,-170%);background:radial-gradient(closest-side,rgba(255,190,100,.17),rgba(255,150,60,.07) 45%,rgba(255,130,40,0) 100%);animation-name:echo;animation-delay:calc(var(--dl) + var(--lag,.2s))}   /* the echo: the light the flame throws, four times the size, the same rhythm a beat behind, gentler */
  @keyframes flick{0%{opacity:.84;transform:scale(1,1)}11%{opacity:1;transform:translate(.8%,-3%) scale(1.05,1.1)}23%{opacity:.76;transform:translate(-1.5%,0) scale(.955,.985)}37%{opacity:.95;transform:translate(1.5%,-2.2%) scale(1.025,1.065)}52%{opacity:.8;transform:translate(0,.8%) scale(.98,1)}66%{opacity:1;transform:translate(-.8%,-3.8%) scale(1.055,1.115)}80%{opacity:.78;transform:translate(.8%,0) scale(.96,1.015)}100%{opacity:.84;transform:scale(1,1)}}
  @keyframes echo{0%{opacity:.84;transform:scale(1)}11%{opacity:1;transform:translate(.4%,-.8%) scale(1.04)}23%{opacity:.76;transform:translate(-.45%,0) scale(.98)}37%{opacity:.95;transform:translate(.45%,-.6%) scale(1.022)}52%{opacity:.8;transform:scale(.985)}66%{opacity:1;transform:translate(-.3%,-.9%) scale(1.045)}80%{opacity:.77;transform:translate(.25%,0) scale(.98)}100%{opacity:.84;transform:scale(1)}}
  body.spec #after .fol .fx{opacity:0}
  body.spec #after .fol .fl::before,body.spec #after .fol .fl::after{animation-play-state:paused}
  body.spec #after .fol .xb,body.spec #after .fol::after{opacity:1}
  #after .col{position:relative;max-width:640px;margin:0 auto;text-align:center}   /* the lockup is text alone, centered (2026-09-05, Yaron: the sheet image out) */
  #after h2{display:inline-block;vertical-align:top;font-size:32px;letter-spacing:-.018em;line-height:1.15;margin:0 0 var(--lh)}   /* the intro h1's setting (Yaron: "the same styling, ie larger"); inline-block so the pin's anchor is the words, not the column */
  #after p{margin:0;color:var(--text);text-wrap:balance}
  body:not(.spec) #after .col:not(.in) .atext > *{opacity:0}   /* the lockup waits, unseen, until the reader reaches it (2026-09-05, Yaron: animate the text in); in the spec the drawing shows its bars regardless */
  #after .col.in .atext > *{animation:rise .7s cubic-bezier(.2,.7,.2,1) backwards}   /* then the title, the line and the link rise in, 120ms apart; backwards fill only, so the spec's own opacity rules own the elements once it has run */
  #after .col.in .atext > :nth-child(2){animation-delay:.12s}
  #after .col.in .atext > :nth-child(3){animation-delay:.24s}
  @keyframes rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}   /* centered lines break evenly; without it the desktop paragraph left "work." alone on line two */

  /* ---------- bottom bar (spec) + chip (built) ---------- */
  #bar{position:fixed;left:0;right:0;bottom:0;z-index:90;display:flex;align-items:center;justify-content:space-between;gap:16px;
    padding:12px 20px;background:var(--paper);border-top:1px solid var(--hair);transition:transform .5s cubic-bezier(.4,0,.2,1),background-color .5s,border-color .5s}
  body:not(.spec) #bar{transform:translateY(110%)}
  #bar .meta{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
  #bar .meta b{color:var(--ink);font-weight:500}
  #build-btn{display:inline-flex;align-items:center;gap:8px;height:40px;background:var(--accent);color:var(--on-accent);border:0;border-radius:999px;padding:0 22px;cursor:pointer;
    transition:background-color .1s,transform .125s cubic-bezier(.2,.7,.2,1)}   /* the sans at the one size, sentence case, no tracking (2026-09-05, Yaron: "the normal non mono font and not all caps"; was the mono at 12px uppercase); the pill is 40 tall by rule, so the bar stays --barh whatever the icon's size */
  #build-btn .material-symbols-outlined{font-size:18px;width:18px;height:18px}   /* Material Symbols 'check' (2026-09-05, Yaron: a checkmark; was a typed ↵), the font since the port */
  #build-btn:hover{background:var(--accent-hover);transform:translateX(2px)}
  #chip{position:fixed;right:20px;bottom:20px;z-index:90;display:flex;align-items:center;gap:9px;
    background:var(--paper);border:0;box-shadow:0 0 0 1px var(--card-edge);border-radius:999px;padding:10px 16px;cursor:pointer;   /* the ring sits outside the pill, black at 9% by day, so it darkens whatever is under it, the painting included, like the note card's ring (2026-09-05, Yaron); the padding grew 1px so the pill keeps its size */
    font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink);
    opacity:0;pointer-events:none;transition:box-shadow .1s,background-color .5s,color .5s}
  #chip:hover{box-shadow:0 0 0 1px var(--accent)}
  #chip .ico{font-size:15px;width:15px;height:15px;margin-left:-2px}   /* Material Symbols 'architecture', the font since the port */
  #chip.on{opacity:1;pointer-events:auto}
  /* the bar waits for the line to leave the bottom edge when the spec reopens */
  body.spec #bar{transition-delay:.9s}

  /* ---------- the gate: sign off on the drawing ---------- */
  body.gate{overflow:hidden}
  #gate{position:fixed;inset:0;z-index:110;background:var(--desk);display:flex;flex-direction:column;padding:12px 0 64px;overflow:hidden auto;transition:opacity .5s,visibility .5s,background-color .5s}   /* the bottom lane is Skip's (26 up, 38 tall), so the centered pile never meets it */
  body:not(.gate) #gate{opacity:0;visibility:hidden}
  .sheet{position:relative;width:min(400px,86vw,max(256px,calc((100vh - 272px) / 1.27)));width:min(400px,86vw,max(256px,calc((100dvh - 272px) / 1.27)));   /* the mini is 1.27 widths tall; 272 = strip 124 + borders 2 + hint 58 + the gate's lanes 76 + 12 slack */background:var(--sheet);border:1px solid var(--edge);box-shadow:var(--sheet-shadow);
    transition:background-color .5s,border-color .5s}
  /* the stack: two sheets under the one you sign, a loose pile: turned about a degree in opposite directions and pushed apart, so paper shows on all four sides and no two edges run on one axis. they sit at the gate's -1 layer, so the top sheet can lift off and leave them */
  .stack{position:relative}
  .stack::before,.stack::after{content:"";position:absolute;inset:0;z-index:-1;background:var(--sheet);border:1px solid var(--edge);box-shadow:var(--sheet-shadow);pointer-events:none;transition:background-color .5s,border-color .5s}
  .stack::after{transform:translate(7px,-6px) rotate(.7deg)}    /* turned clockwise, pushed up and right: shows above the top edge and down the right side */
  .stack::before{z-index:-2;transform:translate(-8px,7px) rotate(-.8deg)}   /* turned the other way, pushed down and left: shows down the left side and under the bottom edge */
  /* the pile lands before anything is drawn on it: bottom sheet, middle, then the one you sign, each a quick settle onto the desk. `scale` composes with each sheet's turn; the fill is backwards only, so the lift's fade still owns opacity afterwards */
  @keyframes land{from{opacity:0;scale:1.03}to{opacity:1;scale:1}}
  .stack::before{animation:land .22s cubic-bezier(.2,.7,.2,1) 0s backwards}
  .stack::after{animation:land .22s cubic-bezier(.2,.7,.2,1) .09s backwards}
  .sheet{animation:land .22s cubic-bezier(.2,.7,.2,1) .18s backwards}
  /* and leaves the same way in reverse once you sign (or skip): the signed sheet is picked up first, then the middle, then the bottom, and the desk is bare at 400ms, when the gate starts fading to the spec. opacity is not set in the lift rules on purpose: a transition would outrank the animation */
  @keyframes pickup{to{opacity:0;scale:1.03}}
  #gate.lift .sheet{animation:pickup .22s cubic-bezier(.5,0,.8,.4) 0s forwards}
  #gate.lift .stack::after{animation:pickup .22s cubic-bezier(.5,0,.8,.4) .09s forwards}
  #gate.lift .stack::before{animation:pickup .22s cubic-bezier(.5,0,.8,.4) .18s forwards}
  /* the mini wireframe */
  /* the mini wireframe is one SVG (2026-09-04): every mark is a stroke that draws along its own length by dash offset (pathLength 1, so the dash is normalized), the ticks, the labels and the mark fade in at their slot. --k is the inverse of the sheet's scale, set by JS, so hairlines stay 1px and the type 7px at any sheet size; the bars scale with the drawing */
  .mini{display:block;width:100%;height:auto;overflow:visible}
  .mini .s{fill:none;stroke-dasharray:1;stroke-dashoffset:0;transition:stroke-dashoffset var(--dur,.3s) linear var(--gd,0s)}
  .mini .f{transition:opacity .25s ease var(--gd,0s)}
  #gate.drafting .mini .s{stroke-dashoffset:1}
  #gate.drafting .mini .f{opacity:0}
  .mini .h{stroke-width:calc(1px * var(--k,1))}
  .mini .bar{stroke:var(--wire);stroke-linecap:round}
  .mini .b7{stroke-width:7}
  .mini .b4{stroke-width:4}
  .mini .rule{stroke:var(--hair)}
  .mini .box{stroke:var(--wireline)}
  .mini .dim{stroke:var(--accent-soft)}
  .mini .mark{fill:var(--accent)}   /* the drafter's mark on the dimension line */
  .mini text{fill:currentColor;font-size:calc(7px * var(--k,1));dominant-baseline:text-before-edge}
  .mlabel{font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
  .mtick{font-weight:500;color:var(--accent-text);opacity:.7;letter-spacing:.08em}
  /* SE-class screens: the fourth list row and the second rules are dropped and what follows moves up (one row pitch, then a rule pitch more); the viewBox shrinks to match in fitMini() */
  .mini.se .g4,.mini.se .g2{display:none}
  .mini.se .gb{transform:translateY(-35.2px)}
  .mini.se .gl{transform:translateY(-58.2px)}
  /* the title block strip */
  .stb{border-top:1px solid var(--hair);display:grid;grid-template-columns:1.2fr 1.1fr .72fr 1.05fr;grid-template-rows:1fr 1fr;transition:opacity .5s ease var(--strip,.55s)}   /* fades in as the pen lifts */
  #gate.drafting .stb{opacity:0}
  /* below the 400px sheet (short desktop windows) the strip scales with the sheet via --s, set by JS on the sheet: a scaled drawing, so no cell ever wraps */
  .stb .cell{padding:calc(10px * var(--s,1)) calc(12px * var(--s,1)) calc(9px * var(--s,1));border-right:1px solid var(--hair)}
  .stb .c-project{grid-area:1/1/2/2}
  .stb .c-designed{grid-area:1/2/2/3}
  .stb .c-date{grid-area:1/3/2/4}
  .stb .c-built{grid-area:2/1/3/3;border-top:1px solid var(--hair)}
  .stb .c-sheet{grid-area:2/3/3/4;border-top:1px solid var(--hair)}
  .sign{grid-area:1/4/3/5}
  .stb b{display:block;font-weight:400;font-size:calc(8px * var(--s,1));letter-spacing:.14em;color:var(--mute);text-transform:uppercase;margin-bottom:calc(5px * var(--s,1))}
  .stb span{display:block;line-height:calc(26px * var(--s,1));font-size:calc(9.5px * var(--s,1));letter-spacing:.02em;color:var(--ink);text-transform:uppercase}
  .sign{position:relative;touch-action:none;overflow:hidden;padding:calc(10px * var(--s,1)) calc(12px * var(--s,1)) calc(9px * var(--s,1));
    cursor:var(--pen) 4 20, crosshair}
  .sign b{color:var(--accent-text)}
  .sign .xline{position:absolute;left:calc(12px * var(--s,1));right:calc(12px * var(--s,1));bottom:calc(14px * var(--s,1));border-bottom:1px dashed var(--accent-soft);font-size:calc(12px * var(--s,1));color:var(--accent-text);pointer-events:none;padding-bottom:2px;white-space:nowrap}
  .sign svg{position:absolute;inset:0;width:100%;height:100%}
  .sign .ants{pointer-events:none;overflow:visible}
  .sign svg polyline{fill:none;stroke:var(--accent);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  #ghost{fill:none;stroke:var(--accent);stroke-width:2;vector-effect:non-scaling-stroke;opacity:0;stroke-dasharray:420;stroke-dashoffset:420}
  .sign.hint #ghost{animation:ghostdraw 2.2s ease forwards}
  @keyframes ghostdraw{0%{opacity:0;stroke-dashoffset:420}10%{opacity:.32}72%{opacity:.32;stroke-dashoffset:0}100%{opacity:0;stroke-dashoffset:0}}
  /* the approved stamp */
  .stamp{position:absolute;right:calc(16px * var(--s,1));bottom:calc(34px * var(--s,1));z-index:2;pointer-events:none;font-weight:500;font-size:calc(13px * var(--s,1));letter-spacing:.3em;text-transform:uppercase;color:var(--red);border:2px solid var(--red);border-radius:4px;padding:calc(8px * var(--s,1)) calc(10px * var(--s,1)) calc(8px * var(--s,1)) calc(14px * var(--s,1));transform:rotate(-7deg) scale(1.7);opacity:0}
  .sheet.stamped .stamp{transition:transform .26s cubic-bezier(.2,1.7,.45,1),opacity .16s;transform:rotate(-7deg) scale(1);opacity:.92}
  .gwrap{position:relative;margin:auto}
  /* the hint: one line under the pile, centered, in the sans at the one size. enters after the sheet drafts; the cell carries the emphasis now (the ants, SIGN HERE), so nothing nudges; once the stamp lands the line fades .18s behind it, before the pile is picked up */
  .ghint{margin:32px 0 0;text-align:center;color:var(--text);cursor:pointer;transition:opacity .4s ease var(--hintd,1.4s),transform .4s ease var(--hintd,1.4s),color .1s}
  .ghint:hover{color:var(--ink)}
  #gate.drafting .ghint{opacity:0;transform:translateY(6px)}
  #gate.approved .ghint{opacity:0;transition:opacity .3s cubic-bezier(.55,0,.85,.35) .18s}
  /* marching ants around the sign cell: the one thing moving on the sheet while it waits. 1px teal, 4 on 3 off, one period per .6s. paused when the stamp lands (the cell is done), off behind the built page */
  .ants rect{fill:none;stroke:var(--accent);stroke-width:1;x:.5px;y:.5px;width:calc(100% - 1px);height:calc(100% - 1px);stroke-dasharray:4 3;animation:ants .6s linear infinite}
  @keyframes ants{to{stroke-dashoffset:-7}}
  #gate.approved .ants rect{animation-play-state:paused}
  #gate.lift .ants rect{animation:none}
  /* SIGN HERE sits on the line beside the X, the strip's label size in the accent */
  .sign .sh{font-style:normal;margin-left:calc(10px * var(--s,1));font-size:calc(8px * var(--s,1));letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);vertical-align:1px}
  #gskip{position:fixed;left:50%;transform:translateX(-50%);bottom:26px;z-index:111;padding:6px 12px;color:var(--ink);background:none;border:0;cursor:pointer;text-decoration:underline;text-decoration-color:var(--hair);text-underline-offset:3px;transition:opacity .3s,color .1s,text-decoration-color .1s,text-underline-offset .125s cubic-bezier(.2,.7,.2,1)}   /* styled as a link, the same underline and hover (2026-09-05, Yaron) */
  #gskip:hover{color:var(--accent);text-decoration-color:var(--accent);text-underline-offset:5px}
  body:not(.gate) #gskip{display:none}
  #gate.lift+#gskip{opacity:0}
  .name-s{display:none}
  .name-l,.name-s{font-style:normal}
  @media (max-width:700px){.name-l{display:none}.name-s{display:inline}}
  .sigmini{height:26px;display:block}
  .sigmini polyline{fill:none;stroke:var(--accent);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  .sign svg polyline.dot,.sigmini polyline.dot{stroke-width:4}   /* a dot is the pen dwelling: a little fatter than the line */
  body.draft [data-tag],body.draft .tb{opacity:0}
  body.draft #grid{opacity:0}
  body.draft #bar,body.auto #bar,body.gate #bar{transform:translateY(110%)}
  body.cut *,body.cut *::before,body.cut *::after{transition:none!important}

  /* ---------- mobile ---------- */
  @media (max-width:1024px){
    main{padding:0 22px}
    #after{padding:56vh 0 0;--fade:50vh}
    #after{margin-top:40px}   /* the phone header's 40 under the footer row (the 1024 query, so tablets take it too: their header sits at 40 as well) */
    #after .moon{--D:40vw}   /* the wrapper keeps its 40vh: a first cut sized it 30vw and the vh-sized glow was clipped with a hard line under the moon */
    #after .fol{margin-top:0}   /* no overlap where the column runs to the edges: the shelves reach the image's top at the right */
    #after .col{width:calc(min(640px,100%) - 44px);margin:0 auto}   /* the sections' box (main is 640 border-box with 22px padding), so the tag and the outline sit on the grid; padded full-width, the tag hung on the screen's edge (2026-09-05, Yaron) */
    #slot{padding:0 22px}   /* one cell here too, as on the desktop: the logo row and the title block share the slot, which is as tall as the taller of them, so the intro never moves between states (2026-09-05, Yaron: the content jumped about 90px on his phone). the two used to stack in flow and collapse by max-height; now the block sets the slot on phones (276: 204 + its margins) and the built gap under the logo grows to fill it, the logo row still wins on tablets. one commit, so it can be reverted if the gap reads too big */
    #top{padding:40px 0 18vh}
    #grid{background:
      linear-gradient(to right,
        transparent 21px, var(--accent-edge) 21px 22px, transparent 22px calc(100% - 22px),
        var(--accent-edge) calc(100% - 22px) calc(100% - 21px), transparent calc(100% - 21px))}
    [data-tag]{outline-offset:12px}
    [data-tag]::before{top:-32px}
    #gate{padding:16px 0 76px}
    .stb{grid-template-columns:1.2fr 1.1fr .72fr;grid-template-rows:auto auto minmax(80px,auto)}
    .stb .c-date,.stb .c-sheet{border-right:0}
    .sign{grid-area:3/1/4/4;border-top:1px solid var(--hair)}
    .sheet{width:min(400px,86vw,max(240px,calc((100vh - 330px) / 1.42)));width:min(400px,86vw,max(240px,calc((100dvh - 330px) / 1.42)))}
  }
  @media (max-width:700px){
    section{margin-bottom:13vh}   /* the footer keeps its 0: this rule used to name footer.sec too, and on the subpages, whose main has a bottom padding, the 13vh sat under the footer row on phones (on the homepage it collapsed into the band's 18vh, so nothing moves there; 2026-09-06) */
    #top{padding-bottom:13vh}
    body:not(.deck) #slot:not(:has(.tb)){min-height:276px}   /* the subpages' headline sits where the homepage's does on phones (2026-09-17, Yaron: match the homepage, the deck excepted): the homepage's slot is as tall as its title block with its margins, 24 + 204.1 + 48, and a page without the block reserves the same; the deck's slot is its own fixed band */
    h1{font-size:26px}
    h2{font-size:18px}   /* under the 26px phone headline */
    .tb{grid-template-columns:1fr 1fr}
    .tb div{border-right:0;border-bottom:1px solid var(--accent-edge)}
    .tb div:nth-child(odd){border-right:1px solid var(--accent-edge)}
    .tb div:nth-last-child(-n+2){border-bottom:0}   /* the last row of two, so no cell doubles the block's own edge */
    .stb .cell{padding:8px 9px 7px}
    .stb span{font-size:8.5px}
    .sheet{width:min(320px,86vw,max(240px,calc((100vh - 330px) / 1.42)));width:min(320px,86vw,max(240px,calc((100dvh - 330px) / 1.42)))}
    .built li{grid-template-columns:1fr;grid-template-areas:"thumb" "text" "go";gap:10px 0}   /* stacked: the thumbnail full width above the text */
    .built li:first-child{padding-top:12px}   /* on phones the gap under a section title is 32 (the title's 20 plus this 12), was 38 with the row's 18; the desktop keeps 38 (2026-09-05, Yaron: "just reduce the top padding for the first row in mobile") */
    #after h2{font-size:26px}   /* the h1's phone size */
    #after .col::before,[data-tag]:has(> h1)::before{line-height:calc(26px * 1.15)}
    #after .fol img{height:60vw;object-fit:cover;object-position:50% 50%}   /* the painting is 3:1, so width-driven it was 130px tall on a phone (Yaron: too small, crop the sides): 60vw tall, the middle 56% of the width showing, the windows and the bar */
    #after .fol{margin-top:-7.2vw}   /* 12% of the image: across the phone's crop the ceiling is bare to 10% and the frames start at 24% (measured on nighthawk.png; hooooper.png stays under a mean of 12 to 26%, with pinpoints of light from 20%), so the lockup's bottom sits in the dark like the desktop's 5vw */
    .notes li{grid-template-columns:92px 1fr;gap:14px}
    #bar .meta b{display:block}#bar .meta .sep{display:none}   /* two lines: the url, then Spec 001 · Rev n, inside the same 65px bar (the rev used to hide here; 2026-09-05, Yaron) */
    .endrow{gap:12px}
    .tb .sdate::before,.tb .sagain-w::before{margin:0 .3em}   /* the labels' middle dot tighter, so "Approved · 2026-09-17" and "Status · Sign again" stay one line in the phone's cell down to 360px wide (the cell's content is 125 there; the two read about 123 and 116) */
    .reach,.endrow .c{font-size:10px}   /* the © and the links on one row down to 360px wide (at 11px and a 24px gap the row wrapped at 375; 2026-09-05, Yaron); the intro's line takes the same step so the two match */
    /* the note is a bottom sheet on phones: full width, over the bar, sliding up */
    #note{position:fixed;left:0!important;right:0;top:auto!important;bottom:0;width:auto;padding:22px 22px 30px;border-radius:0;box-shadow:0 0 0 1px var(--card-edge),var(--card-shadow-up);opacity:1;transform:translateY(100%);transition:transform .3s cubic-bezier(.2,.7,.2,1),visibility 0s .3s,background-color .5s}
    #note.on{transform:none;transition:transform .3s cubic-bezier(.2,.7,.2,1),visibility 0s,background-color .5s}
    #note .nx{top:18px;right:18px}
  }
  @media (max-width:700px) and (max-height:700px){
    .sheet{width:min(320px,86vw,max(240px,calc((100vh - 330px) / 1.28)));width:min(320px,86vw,max(240px,calc((100dvh - 330px) / 1.28)))}
  }
  @media (prefers-reduced-motion:reduce){
    *,*::before,*::after{transition:none!important;animation:none!important}
    #scan,#lap{display:none}
  }

  /* ==================== the subpages (the port, 2026-09-17): the blog index, the post, the CV end on the footer row, then the header's own margin ==================== */
  main.sub{padding-bottom:56px}   /* 56px, the logo's distance from the top (2026-09-06, Yaron: the 18vh under the footer, the section gap, was "way too much"; the homepage ends on the after-hours band instead) */
  @media (max-width:1024px){main.sub{padding-bottom:40px}}   /* the header sits at 40 from 1024px down (tablets and phones), so the end matches it there */

  /* ==================== the blog post (2026-09-05, from the prototype's post.html): the live post's rendered content in the homepage's type system ==================== */
  /* ---------- the post's header: the title in the display cut (the h1 rule), the date under it in the list's date voice, then two lines of air ---------- */
  .post h1{margin-bottom:8px}
  .post .post-date{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12px;line-height:var(--lh);letter-spacing:.06em;color:var(--mute);margin:0 0 52px}   /* mono metadata, so it survives greeking like the list's dates */

  /* ---------- the prose: the one size in text grey; section heads take the section title's setting (20px display); bold is a run-in head, Kräftig in ink, the object-name rank ---------- */
  .post h3{font-size:20px;font-weight:700;line-height:var(--lh);letter-spacing:-.012em;color:var(--ink);margin:52px 0 8px}   /* two lines of air above, a breath below (flush on the paragraph read cramped) */
  .post h4{font-size:inherit;font-weight:500;color:var(--ink);margin:var(--lh) 0 0}
  .post strong{font-weight:500;color:var(--ink)}
  .post ol,.post ul{margin:0 0 var(--lh);padding-left:1.4em;color:var(--text)}
  .post li{margin:0}
  .post li::marker{color:var(--mute)}
  .post blockquote{margin:0 0 var(--lh);padding-left:20px;border-left:2px solid var(--hair);color:var(--mute);font-style:italic}
  .post hr{border:0;border-top:1px solid var(--hair);margin:var(--lh) 0}
  .post img{display:block;max-width:100%;height:auto;border-radius:6px;margin:0 0 var(--lh)}
  /* code: the mono in ink on the hair for a word, on the desk grey for a block (the desk is the ground under the paper, so a block is a cut-out) */
  .post code{font-family:var(--mono);font-size:14px;letter-spacing:0;color:var(--ink);background:var(--hair);padding:1px 5px;border-radius:3px;transition:background-color .5s,color .5s}
  .post pre{font-family:var(--mono);font-size:13px;line-height:20px;color:var(--ink);background:var(--desk);padding:16px 18px;border-radius:6px;overflow-x:auto;margin:0 0 var(--lh);transition:background-color .5s,color .5s}
  .post pre code{font-size:inherit;color:inherit;background:none;padding:0;border-radius:0}
  /* the copy button copy-code.js adds to each block: mute, accent on hover, a fade over the code's tail; the "copied" pop is the accent pill */
  .code-block{position:relative}
  .code-block pre{padding-right:52px}
  .code-copy{position:absolute;top:0;right:0;bottom:0;width:52px;padding:0 14px 0 0;display:flex;align-items:center;justify-content:flex-end;border:0;background:linear-gradient(to right,transparent,var(--desk) 40%);color:var(--mute);cursor:pointer;border-radius:0 6px 6px 0;transition:color .1s}
  .code-copy:hover{color:var(--accent)}
  .code-copy svg{width:16px;height:16px}
  .code-copy-pop{position:absolute;top:50%;right:56px;transform:translateY(-50%);padding:4px 9px;border-radius:4px;font-family:var(--mono);font-size:11px;letter-spacing:.06em;white-space:nowrap;pointer-events:none;opacity:0;background:var(--accent);color:var(--on-accent);transition:opacity .2s}
  .code-copy-pop.show{opacity:1}
  /* a typed cursor in prose (the 101 post) */
  .post .cursor-blink{display:inline-block;width:.55em;height:1.05em;margin-left:3px;vertical-align:text-bottom;background-color:currentColor;animation:cursor-blink 1.1s step-end infinite}
  @keyframes cursor-blink{50%{opacity:0}}

  /* ---------- the demos: windows onto the apps, with the note card's ring and lift; the Denote scenes break out wider than the column ---------- */
  .post p:has(> .app-embed){margin:0 0 8px}
  .post .app-embed{position:relative;display:block;text-decoration:none}
  .post .app-embed iframe{display:block;width:100%;aspect-ratio:1180/640;border:0;border-radius:6px;box-shadow:0 0 0 1px var(--card-edge),var(--card-shadow);background:var(--paper);pointer-events:none;transition:box-shadow .5s,background-color .5s}
  .post .app-embed.embed-wide{width:min(880px,94vw);margin-left:50%;transform:translateX(-50%)}
  .post .embed-caption{font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:var(--mute);text-align:center;margin:0 0 var(--lh)}   /* the caption is metadata: the label voice, centered under the window */
  /* the terminal demos (terminal-demo.js draws them): the live site's illustration, its own colors inside, the site's ring and lift outside */
  .term-demo{position:relative;margin:0 0 var(--lh)}
  .term-window,.chat-window{border-radius:6px;overflow:hidden;box-shadow:0 0 0 1px var(--card-edge),var(--card-shadow);transition:opacity .45s ease,transform .45s ease,box-shadow .5s}
  .term-window{background:#1a1b1e}
  .term-window.t-closed{opacity:0;transform:scale(.96) translateY(6px)}
  .term-bar{position:relative;display:flex;align-items:center;gap:7px;height:34px;padding:0 12px;background:#2b2c30}
  .term-dot{width:11px;height:11px;border-radius:50%}
  .t-red{background:#ff5f57}.t-yellow{background:#febc2e}.t-green-dot{background:#28c840}
  .term-title{position:absolute;left:0;right:0;text-align:center;font-size:12px;color:#8e8e93;pointer-events:none}
  .term-body{height:224px;overflow-y:hidden;padding:12px 14px;font-family:'SF Mono',Menlo,Consolas,monospace;font-size:13px;line-height:1.6;color:#e7e7ea;overflow-wrap:break-word;transition:opacity .3s ease}
  .term-body.term-fade{opacity:0}
  .term-line{white-space:pre-wrap}
  .t-dim{color:#8e8e93}.t-green{color:#32d158}.t-orange{color:#d97757}.t-cwd{color:#fff;font-weight:600}
  .term-cursor{display:inline-block;width:7px;height:15px;margin-left:1px;vertical-align:text-bottom;background-color:#e7e7ea;animation:cursor-blink 1.1s step-end infinite}
  .term-key{display:inline-block;margin-left:8px;padding:0 5px;border:1px solid #4a4a4f;border-radius:4px;font-size:11px;line-height:1.5;color:#8e8e93;vertical-align:text-bottom}
  .term-box{border:1px solid #4a4a4f;border-radius:6px;padding:8px 12px;margin:8px 0}
  .term-box.t-claude{border-color:#d97757}
  .term-opt{padding:1px 6px;white-space:pre-wrap}
  .term-opt.sel{background:#d97757;color:#16161a;border-radius:3px}
  .term-input{display:flex;align-items:flex-start;gap:8px;border:1px solid #4a4a4f;border-radius:6px;padding:7px 11px;margin-top:10px}
  .term-in-text{flex:1;white-space:pre-wrap}
  .term-popup{position:absolute;right:14px;bottom:14px;width:58%;border-radius:8px;overflow:hidden;box-shadow:0 14px 36px rgba(0,0,0,.35);opacity:0;transform:scale(.92) translateY(10px);transform-origin:bottom right;transition:opacity .35s ease,transform .35s ease;z-index:2}
  .term-popup.on{opacity:1;transform:none}
  .term-pop-bar{position:relative;display:flex;align-items:center;gap:6px;height:28px;padding:0 10px}
  .term-pop-bar .term-dot{width:9px;height:9px}
  .term-pop-title{position:absolute;left:0;right:0;text-align:center;font-size:11px;pointer-events:none}
  .term-pop-body{display:flex;align-items:center;justify-content:center;min-height:92px;font-size:12px;font-family:system-ui,-apple-system,sans-serif}
  body:not(.night) .term-pop-finder .term-pop-bar{background:#ececec}
  body:not(.night) .term-pop-finder .term-pop-body{background:#fff;color:#999}
  body:not(.night) .term-pop-finder .term-pop-title{color:#666}
  body.night .term-pop-finder .term-pop-bar{background:#38383c}
  body.night .term-pop-finder .term-pop-body{background:#2b2c30;color:#8e8e93}
  body.night .term-pop-finder .term-pop-title{color:#b5b5ba}
  .term-pop-browser .term-pop-bar{background:#ececec}
  .term-pop-browser .term-pop-title{color:#666}
  .term-pop-browser .term-pop-body{background:#fff}
  .term-line.t-faded{opacity:.3;transition:opacity .7s ease}
  .ctx-grid{letter-spacing:2px;line-height:1.35;margin:3px 0}
  .chat-window{background:#faf9f5;display:flex;flex-direction:column}
  .chat-bar{position:relative;display:flex;align-items:center;gap:7px;height:34px;padding:0 12px;background:#f0eee6}
  .chat-title{position:absolute;left:0;right:0;text-align:center;font-size:12px;color:#8a8578;pointer-events:none}
  .chat-body{height:170px;overflow-y:hidden;padding:16px 16px 4px;font-family:system-ui,-apple-system,sans-serif;font-size:13px;line-height:1.55;color:#3d3929;transition:opacity .3s ease}
  .chat-body.term-fade{opacity:0}
  .chat-msg{max-width:86%;margin-bottom:12px}
  .chat-msg.you{margin-left:auto;width:fit-content;background:#e9e6dc;padding:6px 12px;border-radius:12px}
  .chat-msg.think{color:#8a8578}
  .chat-spark{color:#d97757}
  .chat-inputbar{margin:10px 16px 16px;border:1px solid #ddd9c9;border-radius:12px;padding:9px 12px;background:#fff;font-family:system-ui,-apple-system,sans-serif;font-size:13px;color:#3d3929;min-height:20px}
  .chat-placeholder{color:#a6a190}
  .chat-msg.card{display:flex;align-items:center;gap:10px;width:fit-content;min-width:55%;background:#fff;border:1px solid #ddd9c9;border-radius:10px;padding:9px 12px}
  .chat-card-icon{width:30px;height:30px;border-radius:7px;background:#d97757;color:#fff;display:flex;align-items:center;justify-content:center;font-family:'SF Mono',Menlo,Consolas,monospace;font-size:10px;flex-shrink:0}
  .chat-card-meta{display:flex;flex-direction:column;line-height:1.35}
  .chat-card-name{font-weight:600;font-size:12px}
  .chat-card-sub{font-size:11px;color:#a6a190}
  .chat-card-dl{margin-left:auto;width:24px;height:24px;border:1px solid #ddd9c9;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#8a8578;font-size:13px;flex-shrink:0}
  .chat-window .term-cursor{background-color:#3d3929;height:14px}
  .term-pop-agent1,.term-pop-agent2{width:46%;border:1px solid #38383c}
  .term-pop-agent1{top:12px;right:14px;bottom:auto;transform-origin:top right}
  .term-pop-agent1 .term-pop-bar,.term-pop-agent2 .term-pop-bar{background:#2b2c30}
  .term-pop-agent1 .term-pop-title,.term-pop-agent2 .term-pop-title{color:#b5b5ba}
  .term-pop-agent1 .term-pop-body,.term-pop-agent2 .term-pop-body{display:block;min-height:0;padding:9px 11px;background:#1a1b1e;color:#e7e7ea;font-family:'SF Mono',Menlo,Consolas,monospace;font-size:10px;line-height:1.7;text-align:left}
  .term-hello{font-size:30px;font-weight:800;color:#111;letter-spacing:-.5px}
  /* the code-outline shapes behind a post's header (code-shapes.js, the design engineer post): in the wire grey, under the text */
  .code-shapes{position:absolute;top:0;left:50%;width:min(1200px,100vw);height:660px;transform:translateX(-50%);overflow:hidden;pointer-events:none;z-index:-1}   /* the live site draws them 1200 wide (the viewBox) behind a wide header; here the column is 640, so the canvas is widened past it and centered, or the trio shrinks to half size */
  .code-shapes svg{display:block;width:100%;height:100%}
  .code-shapes text{font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace;fill:var(--wire)}

  /* ---------- the series nav and the way back ---------- */
  .post .series-nav{margin:52px 0 0;padding:20px 0;border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);transition:border-color .5s}
  .post .series-blurb{margin:0 0 8px}
  .post .series-list{margin:0;padding-left:1.4em}
  .post .series-list a{font-weight:500}   /* post titles are object names: Kräftig, as in the list */
  .post .series-here{color:var(--mute)}
  .post .post-footer{margin:52px 0 0}
  .post .series-nav + .post-footer{margin-top:var(--lh)}
  .ar.w{margin:0 .25em 0 0}   /* a leading arrow: the same nudge, the other way */
  a:hover .ar.w{transform:translateX(-3px)}

  @media (max-width:700px){
    .post h3{font-size:18px}   /* under the 26px phone headline, as the section titles */
  }
  @media (prefers-reduced-motion:reduce){
    .post .cursor-blink,.term-cursor{animation:none}
  }

  /* ==================== the CV (2026-09-06, from the prototype's cv.html): the live Work experience, all eleven roles, in the homepage's type system ==================== */
  /* ---------- the title row: the headline, and at the right end of its line, on its baseline, the Download PDF link: a regular link (ink, the hair underline, accent on hover) with the download icon after the words the way the arrows follow theirs (2026-09-06, Yaron: "a text link with an icon, not a solid button"; the first cut was the Build pill). the PDF itself is Yaron's, still to come ---------- */
  .cv .head{display:flex;align-items:baseline;justify-content:space-between;gap:24px;margin:0 0 var(--lh)}
  .cv .head h1{margin:0}
  .cv .dl{white-space:nowrap}
  .cv .dl .ar{vertical-align:-3px}   /* the icon's box centered on the words' cap height */
  .cv .dl .ar .material-symbols-outlined{font-size:16px;width:16px;height:16px}   /* Material Symbols 'download', the font (the prototype inlined the path at the same 16px); the icon takes the link's color, so it turns teal with the words */
  .cv .dl:hover .ar{transform:translateY(2px)}   /* the arrows' nudge, along its own direction (the shared rule slides an arrow 3px right) */

  /* ---------- a role: one hairline per row (the blog list's rule), the company | role | years line, then the paragraphs and the bullets in the post's prose setting ---------- */
  .role{padding:24px 0;border-top:1px solid var(--hair);transition:border-color .5s}
  .role.last{border-bottom:1px solid var(--hair)}
  .role .rh{display:grid;grid-template-columns:auto 1fr auto;grid-template-areas:"name role date";column-gap:16px;align-items:baseline;margin:0 0 8px}
  .role h3{grid-area:name;margin:0;font-size:inherit;font-weight:500;color:var(--ink)}   /* the company is the object name, Kräftig in ink, and carries the link (the live page's ↗ icon beside the name is the site's arrow after it) */
  .role h3 a{text-decoration:none;color:inherit;transition:color .1s}
  .role h3 a:hover{color:var(--accent)}
  .role .role-title{grid-area:role;margin:0;color:var(--text)}
  .role .date{grid-area:date;margin:0;font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12px;line-height:var(--lh);letter-spacing:.06em;color:var(--mute)}   /* the years in the list's date voice, at the row's right end */
  .role .badge{display:block;font-family:var(--mono);font-size:11px;line-height:var(--lh);letter-spacing:.08em;text-transform:uppercase;color:var(--text);margin:0 0 8px}   /* "Acquired by Compass": the label voice in text grey, on its own line under the row, where the live page has it */
  .role ul{margin:0 0 var(--lh);padding-left:1.4em;color:var(--text)}
  .role li{margin:0}
  .role li::marker{color:var(--mute)}
  .role > :last-child{margin-bottom:0}

  @media (max-width:700px){
    .role .rh{grid-template-columns:1fr auto;grid-template-areas:"name date" "role role"}   /* the name and the years on the first line, the role under them */
  }

  /* ==================== the case-study deck (2026-09-05 to 06, from the prototype's work.html): the sheet is the screen, in the brand's colors ==================== */
  /* the case study (2026-09-05, night): a deck. the sheet is the screen (2026-09-06, Yaron: "take over the entire screen", then 100%): one sheet is the window, edge to edge, in the case study's brand colors (no theme toggle here; the whole deck wears the brand, links included); the logo and an X that closes the deck float over its top at the site's header height, and the sheet's bottom band is the lane: the previous case study at the far left, the counter in the center (with Previous and Next on the desk), the next case study at the far right. on the desk the slide is the headline and its line on the left third, the image on the right two thirds, flipped by the keys, the lane's links, or a click on either half of the sheet, each turn a short slide and fade the way you are going. on a phone (2026-09-06, Yaron: swipe left and right, keep the bar, and scroll up and down inside a sheet, the text on top and the image under it at its own height) the sheets stand side by side in a strip that snaps, and each scrolls on its own; on the desk only the image side scrolls. the frame lands on open and lifts off on close. the slide number rides the hash. no spec layer here: the spec view is the homepage's alone */
  html{overscroll-behavior:none}   /* no root overscroll on the deck page: nothing outside the frame may stretch or bounce */
  body.deck{background:var(--desk);--band:65px;--in:22px;--head:136px;--lead:276.1px;overflow:hidden;height:100vh;overscroll-behavior:none}   /* --in: the inset the logo, the headline and the lane's ends share (the site's phone gutter here, wider on the desk); --head: the logo row's height from the window's top plus the gap under it (40 + 48 + 48 on phones, doubled from 24 on 2026-09-06, Yaron; 56 + 48 + 24 on the desk) */
  /* the brand: --brand is the sheet's ground, --on-brand the ink on it and --brand-accent the accent (the link hover, the logo; the ink when a brand names none), all set from the deck's data; the greys between ground and ink are mixes, the night set's ratios. the whole deck wears them (2026-09-06, Yaron: "the entire deck according to the brand colors. This means also link colors"): the sheet, and the header and lane that float over it */
  .deck .leaf,body.deck #slot,body.deck #lane{--paper:var(--brand);--sheet:var(--brand);--ink:var(--on-brand);--accent:var(--brand-accent);--accent-hover:var(--brand-accent);--text:color-mix(in srgb,var(--on-brand) 77%,var(--brand));--mute:color-mix(in srgb,var(--on-brand) 45%,var(--brand));--hair:color-mix(in srgb,var(--on-brand) 18%,var(--brand));--edge:color-mix(in srgb,var(--on-brand) 18%,var(--brand));--wireline:color-mix(in srgb,var(--on-brand) 28%,var(--brand));color:var(--ink)}   /* color is set, not inherited: it inherits as the body's computed value otherwise */
  body.deck #slot{position:absolute;left:0;right:0;top:0;z-index:3;height:var(--head);padding:0 var(--in);max-width:none;margin:0;background:linear-gradient(var(--brand) calc(100% - 48px),transparent);pointer-events:none}   /* inside the frame with the sheet and the lane (2026-09-06, Yaron saw the X shift a little on a phone swipe while the header was its own fixed box: one frame, so nothing can move on its own). it is a band: the brand's ground behind the logo row, fading out over the 48px under it, so a sheet's content scrolls under the logo and the X rather than through them; touches pass through its empty part to the sheet */
  #top .logo,#top .close{pointer-events:auto}
  body.deck #top{padding:40px 0 0}
  #top .close{display:block;width:24px;height:24px;color:var(--ink);transition:color .1s}   /* the X, where the toggle is on every other page: closes the deck, back to the case studies */
  #top .close .material-symbols-outlined{font-size:24px;width:24px;height:24px}   /* Material Symbols 'close', the font (the prototype inlined the path) */
  #top .close:hover{color:var(--accent)}
  #deck{position:fixed;inset:0;max-width:none;width:auto;margin:0;padding:0;animation:deckin .35s cubic-bezier(.2,.7,.2,1) both}   /* main's 640 cap is the column's, not the deck's. the frame lands as the page opens (the gate's landing, a touch slower for a whole screen) and lifts off on close */
  body.leave #deck{animation:deckout .25s cubic-bezier(.5,0,.8,.4) forwards}
  @keyframes deckin{from{opacity:0;transform:scale(1.02)}to{opacity:1;transform:none}}
  @keyframes deckout{to{opacity:0;transform:scale(1.02)}}
  @media (prefers-reduced-motion:reduce){#deck,body.leave #deck{animation:none}}
  /* a deck's ground (2026-09-19, the Compass deck's contour lines, scripts/contours.js): a canvas under the sheets, the frame's size. where a deck has one, the frame wears the brand and the strip and its sheets are clear, so the lines lie still under the turning sheets like the desk under the paper; the lane keeps its ground, so the lines stop at its hairline */
  #ground{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
  #deck[data-ground]{background:var(--brand)}
  #deck[data-ground] #sheets,#deck[data-ground] .leaf{background:transparent}
  #deck[data-ground] #slot{background:none}   /* the lines run to the screen's top (2026-09-20, Yaron: "make it go all the way up till the top of the screen, right now the top logo/X bar covers it"): the header's band gives up its ground here, and what it did, hiding a scrolled sheet behind the logo's row, is done by a mask on the strip of sheets instead, the band's own gradient turned inside out (clear down to 48 above the band's foot, whole at its foot), so a sheet still fades out under the logo and the X while the canvas behind it, a sibling the mask does not touch, shows through */
  #deck[data-ground] #sheets{-webkit-mask-image:linear-gradient(transparent calc(var(--head) - 48px),#000 var(--head));mask-image:linear-gradient(transparent calc(var(--head) - 48px),#000 var(--head))}
  /* the pile: on a phone a strip of sheets side by side that snaps one to the screen; each sheet scrolls up and down on its own, so a tall image is scrolled to, not shrunk */
  #sheets{position:absolute;inset:0;display:flex;overflow:auto hidden;scroll-snap-type:x mandatory;overscroll-behavior-x:contain;scrollbar-width:none;background:var(--brand)}   /* the strip wears the brand too (2026-09-17, Yaron saw a flicker at the edges on every turn): the turning sheets slide 16px and fade over it, so what shows behind them is the brand's ground, not the desk */
  #sheets::-webkit-scrollbar{display:none}
  .deck .leaf{flex:0 0 100%;height:100%;margin:0;position:relative;overflow:hidden auto;overscroll-behavior-y:contain;scroll-snap-align:start;background:var(--sheet);border:0;box-shadow:none;transition:background-color .5s}   /* a leaf of the deck, not `.sheet`, which is the gate's class and carries its sizing and its landing; margin 0: a section carries the page's 18vh section gap; the sheet is the screen, so no edge and no halo */
  /* the slide: on a phone one column, the headline and its line first, the image under them at its own height; the header's row above, the lane's band below */
  .slide{display:grid;gap:24px;padding:var(--lead) var(--in) calc(var(--band) + 24px);align-content:start}   /* --lead: where a sheet's headline starts. on a phone 276.1, where every other page's headline sits (2026-09-20, Yaron: "make the title align with all the other titles on the site", phones only; the homepage's slot is 24 + 204.1 + 48 and the subpages reserve the same, the deck had been left out of that on 2026-09-17 and sat at 136). the header's band keeps its own height, --head, so a scrolled sheet still passes under the logo's row; on the desk the two are one */
  .slide h2{font-size:26px;font-weight:700;line-height:1.15;letter-spacing:-.018em;color:var(--ink);margin:0 0 var(--lh)}   /* the page headline's setting: 26 on phones, 32 on the desk, per the one-size rule; a deck size is the next knob if this reads small beside the image */
  .slide p{margin:0;color:var(--text)}
  .slide .img{position:relative;width:100%}   /* the image at the sheet's width and its own height, so a tall one runs past the screen and the sheet scrolls to it (2026-09-06, Yaron: allow scrolling, do not shrink it) */
  .slide .img img{display:block;width:100%;height:auto}
  .slide .img.ph{aspect-ratio:16/10;box-shadow:inset 0 0 0 1px var(--wireline)}   /* no screens in the repo yet: the wireframe's image, a crossed box, stands in where a sheet has no image */
  .slide .img .xb{position:absolute;inset:0;width:100%;height:100%;stroke:var(--wireline);stroke-width:1}
  /* a chapter's figures (2026-09-19, the Compass story: Yaron's interview deck, 23 slides, told in five sheets): a sheet is a chapter, its text the chapter's thesis in a few paragraphs (`paras`), and the image side a run of figures (`images`, the class `figs`: `.stack` is the gate's pile and carries its two under-sheets), one per slide the chapter took in, each with the slide's own sentence under it as the caption, at the one size in the mute, never wider than the site's column. A figure with no `src` yet is the crossed box at the picture's own proportions, naming the picture it waits for in the same small mono, as written */
  .slide p+p{margin-top:var(--lh)}
  .slide p a{color:var(--ink)}   /* a link in a sheet's words (2026-09-19, the last sheet's Get in touch) stands in the ink like the lane's links; inheriting the paragraph's grey over the site's hairline underline it could not be found */
  /* the cover's facts (2026-09-19, Yaron: "more of a Goal: Role: Outcome: etc. More of an exec summary"): the first sheet reads as a summary table, the blog list's row (a label at the left in the list's date voice, the mono as written, the words at the right, a hairline over each row), the label on the words' first baseline; every measure is set in the slide's size, so the rows grow with the deck's type on a big screen */
  .slide .facts{margin:0}
  .slide .facts>div{display:grid;grid-template-columns:5.5em 1fr;gap:1.25em;align-items:baseline;padding:.75em 0;border-top:1px solid var(--hair)}
  .slide .facts>div:first-child{border-top:0;padding-top:0}   /* no line between the headline and the first fact (2026-09-19, Yaron), and no padding for it: Goal starts where a chapter's first paragraph does, the headline's 16 under it */
  .slide .facts dt{font-family:var(--mono);font-size:.75em;line-height:1.3;letter-spacing:.06em;color:var(--mute)}   /* the blog list's date, 12 at the site's size, as written: no capitals (2026-09-19, Yaron: "we dont use all caps anywhere. dont use it here then") */
  .slide .facts dd{margin:0;color:var(--text)}
  .slide>div:first-child{container:words/inline-size}   /* the rows answer to the text third's own width, not the window's: the third is a share of the sheet with a floor of 280, so the same cramped column turns up at many window sizes */
  @container words (max-width:380px){.slide .facts>div{grid-template-columns:1fr;gap:.25em}}   /* a narrow third (2026-09-19, Yaron, at a window about 1000 wide, the words squeezed to 172 beside the label: "move the text under the title goal role etc"): under 380 the label sits over its words, which take the whole column; from 380 up (a window of about 1380 and wider) the label stays at their side; the label's own line is 1.3, so a stacked row is its words plus 20 */
  .slide .img.figs{display:grid;gap:90px}   /* between a figure with its caption and the next: half as much again, twice (2026-09-21, Yaron, with sheet 2 whole: "let's add 50% more vertical spacing between each section", then "add another 50%"), 90 on a phone from 40, six and three quarter sizes on the desk from three (108 from 48 at the 1512 desk), so each figure reads as its own beat of the argument and a caption belongs to the picture over it, not the one under it */
  .slide figure{margin:0;min-width:0}
  .slide figcaption{margin-top:12px;max-width:640px;color:var(--mute)}
  .slide .figs img{border-radius:6px;border:1px solid var(--mute)}   /* a screen on the sheet (2026-09-19, the first real pictures, the cover's four): the thumbnails' corners and a 1px border in the mute, the deck's middle grey (Yaron, after a hairline ring and then 2px of white: "do 1px and make it grey, not white. Use a token"; of the deck's greys the hair and the wireline leave Compass's black side bar open on the black sheet, the text grey reads as white, the mute closes it and stays grey). a border inside the picture's box, not a ring outside it: the image column clips what hangs over its sides */
  .slide .quad{display:grid;gap:16px}   /* a figure of several screens (`grid` in the data, the cover's four as his Executive summary slide set them): one under another on a phone, where a half-width screen is 165px and unreadable, two by two on the desk */
  /* a figure of groups of columns (2026-09-21, `groups` in the data; the problem sheet's Consumer beside MLS, twelve screens from Yaron as his slide set them): each group is its name over two columns, each column its label over its screens, stacked at their own heights, so nothing is cropped and the columns end where they end. the two groups stand side by side on the desk and one under the other on a phone, where a group's two columns still stand side by side: the screens are small there, and the point is the pattern, maps and photos on one side, tables and forms on the other */
  .slide .duo{display:grid;gap:32px}
  .slide .grp>b{display:block;margin:0 0 .5em;font-weight:500;color:var(--ink)}
  .slide .grp .cols{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .slide .col{display:grid;gap:12px;align-content:start;min-width:0}
  .slide .col>span{font-family:var(--mono);font-size:.75em;line-height:1.3;letter-spacing:.06em;color:var(--mute)}
  .slide .duo img{border:0}   /* no border on these (2026-09-21, Yaron: "remove the borders from these screenshots (only these for now)"): twelve small screens with twelve grey frames read as a grid of boxes; the corners stay */
  /* a figure that flows (2026-09-21, `flow` in the data; the problem sheet's second figure, his "Uh oh" slide: three consumer sites, an arrow under each, the earlier Compass search they became): a row of small screens, the site's own down arrow under each in the mute, then the one screen at the column's width. three across on a phone too, the row is the point. no border on these either, as on the twelve above them on the same sheet, my call */
  .slide .flow{display:grid;gap:0}
  .slide .flow .from,.slide .flow .arrows{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
  .slide .flow .from{align-items:end}   /* screens of unequal heights (the three MLS forms) stand on the arrows' row, so each arrow is as near its screen as the next */
  .slide .flow .arrows{padding:.4em 0 .5em;font-size:1.5em;line-height:1;text-align:center;color:var(--mute)}
  .slide .flow img{border:0}
  .slide figure.bare img{border:0}   /* a single picture without the border (`bare` in the data): the problem sheet's map, so the whole sheet is of a piece, every figure above it being borderless; a light picture ends itself on the black sheet, the border was for screens with a dark edge */
  /* the trip (2026-09-21, the approach sheet; Yaron: "since we flew to SF maybe we can have a mini plane and flight path animation, then the photo put it inside a Kodak kinda frame... I dont want huge photos of the team and the doc"). three small pieces:
     the sky, a dotted route from New York at the right to San Francisco at the left, the way the flight went, and a mini plane that flies it once, the first time the figure is half on screen with its sheet showing (deck.js: the plane and the route's reveal are one clock, by the route's own length; without a script, or where motion is not wanted, the route is whole and the plane parked at its end). the cities are words on the page, not in the drawing, so they keep their size on a phone, and the plane is held at 24px the same way (--k, from the script);
     a kept thing with its words beside it (`keep` in the data): the thing small at the left, a third of the figure at most, its caption at its right. a snap is the photo as a print, a warm white border, turned four degrees, the camera's orange date in its corner, and it lands as the plane does, its words after it; a sheaf is a document's page on two more sheets, the site's loose pile, and it fans a little under the pointer; a chart is a drawing (below);
     rows of screens (`shots`): so many across, each at its own height; the approach's three mockups one to a row at the figure's width, the two flow maps under them two across, so the mockups are the larger (Yaron: "the mocks here are also important but they turn out smaller than the diagrams"). a picture ends itself on the black sheet if it is light (`bare`), and wears the border if its edge is dark, as the Compass side bar is */
  .slide .sky{position:relative;aspect-ratio:4/1;margin-bottom:.75em}
  .slide .sky svg{display:block;width:100%;height:100%;overflow:visible}
  .slide .route{stroke:var(--mute);stroke-width:2;stroke-linecap:round;stroke-dasharray:.1 7;vector-effect:non-scaling-stroke}
  .slide .plane{fill:var(--ink)}
  .slide .glyph{transform:scale(var(--k,1))}
  .slide .city{position:absolute;width:0;height:0}
  .slide .city::before{content:"";position:absolute;left:-3px;top:-3px;width:6px;height:6px;border-radius:50%;background:var(--mute)}
  .slide .city span{position:absolute;top:10px;white-space:nowrap;font-family:var(--mono);font-size:.75em;line-height:1.3;letter-spacing:.06em;color:var(--mute)}
  .slide .city.from{left:94%;top:60%} .slide .city.from span{right:-3px}
  .slide .city.to{left:6%;top:75%} .slide .city.to span{left:-3px}
  .slide .keep{display:grid;grid-template-columns:minmax(120px,30%) 1fr;gap:1.75em;align-items:center}
  .slide .keep figcaption{margin:0}
  .slide .thing{position:relative;max-width:300px}
  .slide .thing img{display:block;width:100%;height:auto}
  .slide .thing.snap{margin:3% 3% 3% 7%;padding:4.5%;background:#F4F1E8;border-radius:2px;transform:rotate(-4deg);box-shadow:0 1px 2px rgba(0,0,0,.5),0 10px 28px rgba(0,0,0,.45)}
  .slide .thing.snap img{border:0;border-radius:1px}
  .slide .dated{position:absolute;right:10%;bottom:8.5%;font-family:var(--mono);font-size:.6875em;line-height:1;letter-spacing:.1em;color:#FF9D3D;text-shadow:0 0 4px rgba(255,120,0,.75)}
  .slide .thing.sheaf{transform:rotate(2.5deg);margin:4% 5% 4% 8%}   /* the margins keep a turned thing's corners inside the image column, which clips at its sides */
  .slide .thing.sheaf img{position:relative;border:0;border-radius:1px;box-shadow:0 1px 2px rgba(0,0,0,.45),0 8px 22px rgba(0,0,0,.35)}
  .slide .thing.sheaf::before,.slide .thing.sheaf::after{content:"";position:absolute;inset:0;background:#EBEBEB;border-radius:1px;box-shadow:0 1px 2px rgba(0,0,0,.45);transition:transform .125s cubic-bezier(.2,.7,.2,1)}
  .slide .thing.sheaf::before{z-index:-1;transform:rotate(-3.5deg) translate(-3px,2px)}
  .slide .thing.sheaf::after{z-index:-2;background:#DEDEDE;transform:rotate(2.5deg) translate(4px,-2px)}
  @media (hover:hover){
    .slide .thing.sheaf:hover::before{transform:rotate(-5.5deg) translate(-6px,3px)}
    .slide .thing.sheaf:hover::after{transform:rotate(4.5deg) translate(7px,-4px)}
  }
  /* a chart (2026-09-21, the framework's diagram; Yaron: "can you recreate this diagram? the image is a bit blurry. Would be nice to animate it when the diagram loads"): a drawing, not a picture, written by resources/redesign/framework-diagram.py into _includes/diagrams, his nodes, colors and lines on a white card, the type the site's. it wants to be read, so it is wider than a kept thing, 46% of the figure on the desk with its caption beside it, and the figure's width on a phone with the caption under. it draws itself once, in the order the flow goes, when half of it is on screen (the same `data-play` as the flight): nodes pop, lines draw by their offset (every path is one unit long by `pathLength`), heads arrive as their lines do, the dashed influences last, each revealed through a fat copy of itself in a mask because a dashed line drawn by its own offset drags its dashes. every element carries its place on the clock, --d and --t. whole from the start without a script, or where motion is not wanted */
  .slide .thing.chart{max-width:480px}
  .slide .keep:has(.chart){grid-template-columns:1fr}
  .slide .dgm{display:block;width:100%;height:auto;background:#fff;border-radius:6px;font-family:var(--sans)}
  .slide .dgm text{fill:#1A1A1A;text-anchor:middle;dominant-baseline:central;font-weight:400}
  .slide .dgm text.b{font-weight:700}
  .slide .dgm .pop{transform-box:fill-box;transform-origin:center}
  .js figure[data-play]:not(.play) :is(.dgm,.marks)>*,.js figure[data-play]:not(.play) .tag{opacity:0}
  figure.play .dgm .pop{animation:dgpop .35s cubic-bezier(.2,.7,.2,1) var(--d,0s) both}
  figure.play :is(.dgm,.marks) .draw{stroke-dasharray:1;animation:dgdraw var(--t,.4s) cubic-bezier(.4,0,.4,1) var(--d,0s) both}
  figure.play :is(.dgm,.marks) .head{animation:dgfade .12s linear var(--d,0s) both}
  figure.play .tag{animation:dgfade .3s ease-out var(--d,0s) both}
  /* a marked screen (2026-09-21, the last sheet; Yaron: "you already have the images. It's from the first slide"): his slide's annotations, query inputs, exit points / actions, customization and results pointing into the shipped screen, redrawn over the cover's list and map by resources/redesign/annotated-screen.py: the labels words on the page in the ink, the lines his red, drawing themselves once like the diagram, a label and then its lines, in the framework's order. the screen is the figure's width, the size of the screens listed under it (his word, the same day; the first cut was his slide's, the screen two thirds of the figure with the labels at its sides), the labels over it and Results under it. two compositions, chosen by the figure's own width: from 760 up the labels in one row, under that in two */
  .slide figure.marked{container-type:inline-size}
  .slide .comp{position:relative;aspect-ratio:692/640}
  .slide .comp .scr{position:absolute;left:var(--xt);top:var(--yt);width:var(--wt);height:auto}
  .slide .comp .marks{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
  .slide .comp .marks.wide{display:none}
  .slide .comp .tag{position:absolute;left:var(--xt);top:var(--yt);transform:translate(var(--axt),-50%);white-space:nowrap;font-size:.875em;line-height:1.2;font-weight:500;color:var(--ink)}
  @container (min-width:760px){
    .slide .comp{aspect-ratio:1200/940}
    .slide .comp .scr{left:var(--x);top:var(--y);width:var(--w)}
    .slide .comp .marks.wide{display:block}
    .slide .comp .marks.tall{display:none}
    .slide .comp .tag{left:var(--x);top:var(--y);transform:translate(var(--ax),-50%);font-size:1em}
  }
  @keyframes dgpop{from{opacity:0;transform:scale(.92)}}
  @keyframes dgdraw{from{stroke-dashoffset:1}}
  @keyframes dgfade{from{opacity:0}}
  .slide .shots{display:grid;gap:12px}
  .slide .shotrow{display:grid;grid-template-columns:repeat(var(--cols,2),1fr);gap:12px;align-items:start}
  .slide .shotrow img.bare{border:0}
  .slide .shotrow figcaption{margin:0;align-self:center}   /* a row can hold the figure's words as its last cell (`says`; the launch charts, 2026-09-21: his charts are 966 wide, soft at the figure's width on a retina screen, so each takes half of it, the twelve months beside the caption that reads it, the two close-ups side by side under them) */
  @media (max-width:700px){.slide .shotrow.onecol{grid-template-columns:1fr}}   /* and a row can stand one to a line on a phone (`stack` in the data, the class `onecol`: `.stack` is the gate's pile, whose two under-sheets showed around the rows on the first cut, the second time that name has bitten), where half of 346 is too small to read a chart */
  /* before it plays, with the script on: the route unseen, the plane and the print not yet there. the print lands as the plane does, 2.6s in */
  .js .trip:not(.play) .route,.js .trip:not(.play) .plane,.js .trip:not(.play) .snap,.js .trip:not(.play) figcaption{opacity:0}
  .trip.play .snap{animation:snapin .5s cubic-bezier(.2,.7,.2,1) 2.5s both}
  .trip.play figcaption{animation:dgfade .5s ease-out 3.1s both}   /* the words after the picture they are about (2026-09-21, Yaron: "make this sentence appear only after the photo does"): the print has landed at 3.0s */
  @keyframes snapin{from{opacity:0;transform:translateY(-10px) rotate(-9deg) scale(1.05)}}
  @media (prefers-reduced-motion:reduce){.trip.play .snap,.trip.play figcaption{animation:none}}
  .leaf.seen .quad img{animation:figin .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(.3s + var(--n,0)*.15s)}   /* the screens of a grid arrive one at a time (2026-09-19, Yaron: "fade in each 4 images one at a time"): a fade alone, half a second each, in reading order, .15s apart, the first as the frame finishes landing; once a visit, keyed to the sheet's first showing (`seen`, from deck.js), and visible from the start where there is no script or no wish for motion */
  @keyframes figin{from{opacity:0}}
  @media (prefers-reduced-motion:reduce){.leaf.seen .quad img{animation:none}}
  /* every other picture rises in as it comes on screen (2026-09-22, Yaron: "add some animations to each image when it loads on scroll"; rise, his pick over a fade and a wipe): the after-hours tiles' motion, from 12px below and unseen to its place in .7s on the house ease, once a visit, the first time the unit is on screen while its sheet is current (deck.js). units that arrive together are staggered 70ms apart in the order they are written (--i, set per batch), and the screenful a sheet arrives with waits .3s for the turn, as the cover's screens do (--w). a unit is a picture, a column of the problem sheet's groups, a group's label, a flow's arrows, a kept thing, a caption; a picture that has not loaded rises when it has. by the `translate` property, so a turned thing keeps its rotate. the figures with an entrance of their own (the cover's grid, the flight, the diagram, the marked screen) keep it */
  .figs .ri:not(.in){opacity:0}
  .figs .ri.in{animation:figrise .7s cubic-bezier(.2,.7,.2,1) calc(var(--w,0s) + var(--i,0)*70ms) backwards}
  @keyframes figrise{from{opacity:0;translate:0 12px}}
  @media (prefers-reduced-motion:reduce){.figs .ri.in{animation:none}}
  .slide .figs .ph{position:relative;box-shadow:inset 0 0 0 1px var(--wireline)}
  .slide .figs .ph b{position:absolute;z-index:1;left:50%;top:50%;transform:translate(-50%,-50%);max-width:80%;padding:4px 10px;background:var(--sheet);text-align:center;font-family:var(--mono);font-weight:400;font-size:12px;line-height:1.3;letter-spacing:.06em;color:var(--mute)}
  /* the lane: the sheet's bottom band, a hairline on top, the sheet nav centered on it, Previous and Next with the counter between (2026-09-21, Yaron: "remove the option to toggle between case studies. Get rid of them for all screens": the previous and next case study, which stood at the band's ends on the desk since 2026-09-06 and left the phone's band on 2026-09-20, are gone from every screen, and `prev`/`next` from decks.json with them; a deck's only way out is the X, Escape, or the logo). Previous and Next only on the desk: a phone has its arrow buttons */
  #lane{position:absolute;left:0;right:0;bottom:0;z-index:2;height:var(--band);padding:0 var(--in);background:var(--brand);border-top:1px solid var(--hair);display:flex;justify-content:center;align-items:center;transition:border-color .5s}   /* on the brand's ground: a sheet's content scrolls under the band */
  #lane nav{display:flex;align-items:baseline;gap:24px}
  #lane .co{display:none}   /* on a phone the counter without the deck's name: the band is 346 wide */
  @media (max-width:700px){
    /* the lane on a phone (2026-09-20, Yaron: "remove navigating between casestudies and instead let's have only a left right arrow buttons that toggle between slides of the casestudy itself", phones only): Previous and Next are two arrow buttons at the band's ends, the counter between them; the button is the CV banner's (40, 10px corners, a 1px ring), its words kept for a screen reader in the link's label. a tap turns the strip the way a swipe does; at the deck's first and last sheet the button greys and rests */
    #lane .lbl{display:none}
    #lane nav{width:100%;justify-content:space-between;align-items:center}
    #lane #prev,#lane #next{position:relative;display:grid;place-items:center;width:40px;height:40px;border-radius:10px;box-shadow:0 0 0 1px var(--wireline);text-decoration:none;transition:color .1s,box-shadow .1s}
    #lane #prev::after,#lane #next::after{content:"";position:absolute;inset:-12px}   /* the finger's target, 64 across */
    #lane #prev .ar,#lane #next .ar{margin:0}
    #lane #prev[aria-disabled="true"],#lane #next[aria-disabled="true"]{box-shadow:0 0 0 1px var(--hair)}
  }
  #lane .count{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
  #lane a[aria-disabled="true"]{color:var(--mute);text-decoration:none;pointer-events:none}
  .sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

  @media (min-width:701px){
    /* the desk: one sheet at a time, the rest in the pile; the slide in two columns, a third to the text and two thirds to the image (2026-09-06, Yaron: "half the screen for text is a lot"), the text never under 280 */
    body.deck{--in:clamp(48px,6vw,120px);--head:128px;--lead:128px}
    body.deck #top{padding:56px 0 0}   /* the logo 56px from the window's top, as on every page */
    #sheets{display:block;overflow:hidden;scroll-snap-type:none}
    .deck .leaf{position:absolute;inset:0;height:auto;overflow:hidden;display:grid;grid-template-rows:1fr}
    .deck .leaf:not(.cur){visibility:hidden}
    /* the turn (2026-09-06, Yaron: the cut was jarring): the leaving sheet fades as it slides 16px the way you are going, the arriving one fades in from the other side, the frame and the lane holding still; a phone has its swipe and gets none of this */
    .deck .leaf.in{animation:turnin .28s cubic-bezier(.2,.7,.2,1) both}
    .deck .leaf.out{visibility:visible;pointer-events:none;animation:turnout .18s cubic-bezier(.5,0,.8,.4) forwards}
    #sheets[data-dir="back"] .leaf.in{animation-name:turnin-back}
    #sheets[data-dir="back"] .leaf.out{animation-name:turnout-back}
    @keyframes turnin{from{opacity:0;transform:translateX(16px)}}
    @keyframes turnin-back{from{opacity:0;transform:translateX(-16px)}}
    @keyframes turnout{to{opacity:0;transform:translateX(-16px)}}
    @keyframes turnout-back{to{opacity:0;transform:translateX(16px)}}
    @media (prefers-reduced-motion:reduce){.deck .leaf.in,.deck .leaf.out{animation:none}.deck .leaf.out{visibility:hidden}}
    .slide{grid-template-columns:minmax(280px,1fr) 2fr;grid-template-rows:minmax(0,1fr);gap:6%;align-items:center;align-content:stretch;min-height:0}
    /* the deck's type grows with the screen (2026-09-19, Yaron: "for large screens, only in the case studies, can we up the font sizes"): the sheet is the screen and its columns are shares of it, so on a big window the one size read small and its lines ran past a hundred characters. The slide's size follows the window from the 1512 by 860 desk up, by the smaller of its width and its height (16px is 1.0582vw there and 1.8605vh, so a wide, short window cannot outgrow its room), never under 16, never over 24; the line keeps the site's 26 to 16, the headline stays two sizes, and the caption's gap, its measure and the gap between figures are set in the size, so at the 1512 desk every number is what it was. The frame's own words, the lane and the label voice, stay the site's size like the logo and the X */
    .slide{--fs:clamp(16px,min(1.0582vw,1.8605vh),24px);--lh:calc(var(--fs)*1.625);font-size:var(--fs);line-height:var(--lh)}
    .slide h2{font-size:calc(var(--fs)*2)}   /* one line of the slide's own size under the headline (2026-09-19, Yaron: "more spacing between the title and content"; it was half the headline's size, 16 at the desk): 26 at the desk and on a phone, 36 at his big window, on every sheet */
    .slide figcaption{margin-top:.75em;max-width:40em}
    .slide>div:first-child{max-height:100%;overflow:hidden auto;overscroll-behavior:contain;scrollbar-width:thin}   /* the net under the text third (2026-09-19): a chapter's words are longer than a bullet was, and on a short laptop window they could outgrow their row, where the sheet would cut them top and bottom; there the text scrolls in its own box like the image side, and everywhere else nothing changes */
    .slide .img{align-self:stretch;min-height:0;overflow:hidden auto;overscroll-behavior:contain;display:flex;flex-direction:column;scrollbar-width:thin}   /* the image side is the one thing that scrolls on the desk (2026-09-06, Yaron): the column stretches to its row, a tall image scrolls inside it from the top, a short one sits centered (auto margins collapse when the image overflows) */
    .slide .img img{margin:auto 0;flex:none}
    .slide .img.ph{aspect-ratio:auto}
    .slide .img.figs{display:flex;gap:calc(var(--fs)*6.75)}   /* the figures in the scrolling column: a short run sits centered like a single image (the auto margins at its two ends collapse when it overflows), a tall one scrolls from its top */
    .slide .img.figs figure{flex:none;width:100%;max-width:1020px;margin-inline:auto}   /* a figure stops growing at 1020 (2026-09-21, Yaron: "for very large screens only, can we have all images in the case study around 30% smaller? They can all shrink and be aligned horizontally to where they are now"): the image column is two thirds of the sheet, 1454 at his 2560 window, where a figure is now 70% of it, centered in the column it used to fill (his second word, the same day: "align the column of images center to the area it was in before"; the first cut held the column's left edge. the width is said outright because side margins of auto stop a flex item stretching, and a crossed box has no width of its own); the column passes 1020 at a window of about 1850, so nothing under that changes, and a cap was chosen over a breakpoint so that nothing jumps as a window is dragged wider */
    .slide .img.figs img{margin:0}   /* the lone image's auto margins (the rule above, which centers it in its column) are not for a figure's pictures: in a row of unequal screens they floated the short ones to the row's middle */
    .slide .quad{grid-template-columns:1fr 1fr;gap:calc(var(--fs)*1.5)}
    .slide .duo{grid-template-columns:1fr 1fr;gap:calc(var(--fs)*2.5)}
    .slide .grp .cols,.slide .col{gap:calc(var(--fs)*.75)}
    .slide .flow .from,.slide .flow .arrows{gap:calc(var(--fs)*.75)}
    .slide .shots,.slide .shotrow{gap:calc(var(--fs)*.75)}
    .slide .keep:has(.chart){grid-template-columns:minmax(280px,46%) 1fr}
    .slide .img.figs figure:first-child{margin-top:auto}
    .slide .img.figs figure:last-child{margin-bottom:auto}
    #lane #prev,#lane #next,#lane .co{display:inline}
  }

  /* ==================== after hours (2026-09-06, from the prototype's after-hours.html): the night side of the desk ==================== */
  /* after hours (2026-09-06): the night side of the desk. the homepage's band is the top of this page's world: the desk gone dark, the moon, the stars. here the sheet is put away, so there is no paper, no toggle (night only, Yaron), no spec layer (the spec view is the homepage's alone), and the content is the live site's four off-hours sections, complete: the mixes, all the books, the recipes and the eighteen laws. wider than the paper's column (the 640 belongs to the sheet): text keeps the 640 measure, the grids run 1080. the moon is the homepage's, the same size, whole for the first time, in the slot the theme icon holds on every other page (Yaron). the accent is the moon's gold; the logo keeps the brand's teal */
  body.ah{--paper:#020609;--desk:#020609;--sheet:#0c1218;   /* the homepage's --after-end, the painting's ceiling: the ground here */
    --accent:#E7C563;--accent-hover:#F1D883;--on-accent:#1A1A1A;--accent-text:#E7C563;--accent-soft:rgba(231,197,99,.55);--accent-edge:rgba(231,197,99,.30);   /* the moon's gold (the mean of its brightest quarter, the glow's color) is this page's accent: links, the badge, the play glyphs, the player's line. ink on the gold fills: 9:1 */
    --D:36vh;--barh:65px;position:relative}   /* --D: the moon's size, the homepage's; --barh: the player's height, the Build bar's. positioned so the sky can span the page */
  body.ah #top .logo svg{fill:#00BEB1}   /* the brand's teal stays on the logo, as on the decks */
  body.ah #slot,body.ah main{max-width:1124px;padding-left:22px;padding-right:22px}   /* 1080 between the gutters */
  body.ah main{padding-bottom:56px}   /* the page ends on the footer row, then the header's own margin, like every subpage */
  body.ah.playing main{padding-bottom:calc(56px + var(--barh))}   /* room for the player while a mix plays */
  @keyframes fadein{from{opacity:0}to{opacity:1}}
  body.ah #top,body.ah main{animation:fadein .6s cubic-bezier(.2,.7,.2,1) backwards}   /* the page opens from the black the homepage's band ends in */

  /* ---------- the sky: the whole page's height, behind everything, stars only where no content is (the margins beside the container down the page, the band above the headline); they come out as the page opens, one now and then falls. it was fixed to the screen at first: the content scrolled over the stars and they showed through the translucent cards and between the letters (2026-09-06, Yaron: "content should be above the stars") ---------- */
  #sky{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
  #sky .st{position:absolute;width:var(--s,2px);height:var(--s,2px);border-radius:50%;background:#F3E6C2;animation:twinkle var(--tw,3s) ease-in-out var(--dl,0s) infinite alternate,starin .6s cubic-bezier(.2,.7,.2,1) var(--ad,0s) backwards}   /* the homepage's stars (twinkle is the shared keyframe); starin scales each up from nothing on its own delay in the first second, so the sky fills in rather than switches on */
  @keyframes starin{from{scale:0}to{scale:1}}
  #sky .shoot{position:absolute;width:110px;height:1px;background:linear-gradient(90deg,rgba(243,230,194,0),#F3E6C2);opacity:0;transform-origin:100% 50%}   /* a shooting star: a line whose bright end leads; rotate and translate are set per fall */
  #sky .shoot.go{animation:shoot .8s cubic-bezier(.3,.6,.3,1) forwards}
  @keyframes shoot{0%{opacity:0;translate:0 0}12%{opacity:.85}100%{opacity:0;translate:var(--dx,-200px) var(--dy,90px)}}

  /* ---------- the moon: the homepage's, at the header's right where the theme icon sits elsewhere, whole. it lags the scroll a little, so it hangs in the sky rather than riding the page ---------- */
  body.ah .moon{position:absolute;top:56px;right:22px;width:var(--D);height:var(--D);pointer-events:none;translate:0 var(--sy,0px);animation:fadein .9s cubic-bezier(.2,.7,.2,1) .1s backwards}
  body.ah .moon i{position:relative;display:block;width:100%;height:100%;border-radius:50%;box-shadow:0 0 12vh 4vh var(--moon-glow)}   /* the glow is the moon's own gold */
  body.ah .moon img{position:absolute;left:-2.75%;top:-3.72%;width:105.6%;height:106.5%}   /* the painted disc's opaque box in the PNG is x 32 to 1221, y 43 to 1222 of 1254 (PIL, alpha over 64): 1189 wide, 1179 tall, its center 5.5px low. the homepage scales both axes by 1254/1189 and offsets both by 2.75%, which lands the sides and the bottom but leaves the top 0.9% of the box bare (3.8px at 440), a dark sliver the page's edge hid there and the whole moon shows here; so the axes are fitted separately, each edge a quarter pixel outside the box. absolute, not a negative margin: a margin collapsed through the box and lifted it 12px */   /* the painted disc fills 95% of its PNG; scaled so the limb lands on the square's edge, where the glow begins (the homepage's numbers) */

  .ah .lede{max-width:min(640px,calc(100% - var(--D) - 32px))}   /* the intro keeps 32px clear of the moon on the desk; under 1024 the moon is above it */

  /* ---------- the sections: text at the column's measure, grids across the container ---------- */
  .ah .p6{max-width:640px}
  .ah .credit{font-family:var(--mono);font-size:12px;letter-spacing:.04em;color:var(--mute)}   /* the live page's metatext line under the laws' paragraph */
  .ah .tiles,.ah .laws{list-style:none;margin:0;padding:0;display:grid;gap:24px}
  .ah .mixes{grid-template-columns:repeat(4,1fr)}   /* four covers in a row: 252px each at 1080 */
  .ah .books,.ah .recipes{grid-template-columns:repeat(5,1fr);gap:32px 24px}   /* five covers in a row: 196.8px, the files' own 200 (the newest year has five); the five recipes take the same grid */
  .ah .laws{grid-template-columns:repeat(3,1fr)}
  .ah .more{margin-top:24px}
  .ah h2+.tiles,.ah h2+.laws{padding-top:18px}   /* the lists' rhythm (2026-09-22, Yaron felt the after-hours spacing "a tad smaller"): a homepage list's first row carries 18px of padding under the title's 20, so its content starts 38 under the title; a grid that follows its title straight (books, recipes) gets the same 18 as padding, since a margin would collapse into the title's 20; the mixes and laws grids follow a paragraph and keep its margin */
  .ah .tiles:last-child,.ah .laws:last-child{padding-bottom:18px}   /* and a homepage list's last row carries 18 under it before the section gap: the grids that end their section (books, laws) get the same; mixes and recipes end on their View more link like the blog on All posts, no extra */
  /* the tiles rise in as they come on screen, the lockup's motion, staggered across the row (--i is the column) */
  .ah .tile:not(.in),.ah .law:not(.in){opacity:0}
  .ah .tile.in,.ah .law.in{animation:rise .7s cubic-bezier(.2,.7,.2,1) calc(var(--i,0) * 70ms) backwards}
  /* a mix: the cover is a play button. the glyph shows on hover, and stays on the one that is playing (a pause glyph then) */
  .ah .mix .play{position:relative;display:block;width:100%;padding:0;border:0;background:var(--sheet);border-radius:6px;overflow:hidden;cursor:pointer;color:inherit;transition:box-shadow .15s}
  .ah .mix .play:hover,.ah .mix.cur .play{box-shadow:0 0 0 1px var(--accent-edge)}
  .ah .mix img{display:block;width:100%;height:auto;aspect-ratio:1;transition:transform .35s cubic-bezier(.2,.7,.2,1)}
  .ah .mix .play:hover img{transform:scale(1.03)}
  .ah .mix .pp{position:absolute;left:50%;top:50%;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;box-shadow:var(--card-shadow);opacity:0;scale:.9;transition:opacity .15s,scale .2s cubic-bezier(.2,.7,.2,1),background-color .15s}
  .ah .mix .play:hover .pp,.ah .mix .play:focus-visible .pp,.ah .mix.cur .pp{opacity:1;scale:1}
  .ah .mix .play:hover .pp{background:var(--accent-hover)}
  .ah .mix .pp .material-symbols-outlined{font-size:26px;width:26px;height:26px;font-variation-settings:'FILL' 1,'wght' 400,'GRAD' 0,'opsz' 24}   /* play_arrow and pause, the font, solid (the prototype inlined the filled paths) */
  .ah .mix .pp .pa,.ah .mix.cur.playing .pp .pl{display:none}
  .ah .mix.cur.playing .pp .pa{display:block}
  /* a book: the cover (the link), the title (the link again, the arrow after it), by whom, the blurb. the cover lifts and turns a few degrees on hover, like being picked up; Currently reading is a gold sticker on it. one grid, newest first: the live page's year headings are gone (2026-09-06, Yaron: "remove the date dividers") */
  .ah .book .cover{display:block;margin:0 0 12px;text-decoration:none;perspective:700px}
  .ah .book .cv{position:relative;display:block;border-radius:3px;box-shadow:0 0 0 1px var(--card-edge),var(--card-shadow);transition:transform .3s cubic-bezier(.2,.7,.2,1),box-shadow .3s;transform-origin:50% 100%}
  .ah .book:hover .cv{transform:translateY(-4px) rotateY(-7deg);box-shadow:0 0 0 1px var(--card-edge),0 12px 32px rgba(0,0,0,.6)}
  .ah .book img{display:block;width:100%;height:auto;aspect-ratio:200/310;border-radius:3px;background:var(--sheet)}
  .ah .book .now{position:absolute;left:8px;top:8px;font-family:var(--mono);font-weight:400;font-size:10px;line-height:1.3;letter-spacing:.1em;text-transform:uppercase;color:var(--on-accent);background:var(--accent);padding:3px 6px;border-radius:3px;white-space:nowrap}
  .ah .book h3{margin:0;font-size:inherit;font-weight:500;color:var(--ink)}
  .ah .book h3 a{text-decoration:none;color:inherit;transition:color .1s}
  .ah .book h3 a:hover,.ah .book:hover h3 a{color:var(--accent)}
  .ah .book .by{margin:0 0 4px;font-family:var(--mono);font-size:12px;line-height:var(--lh);letter-spacing:.06em;color:var(--mute)}
  .ah .book p{margin:0;color:var(--text)}
  /* a recipe: a square tile with Portionboy's mark centered in it (2026-09-06, Yaron: thumbnails, the logo as the center; the recipes had been a dated list), the title with its arrow and the date under it; the tile lifts and the mark turns gold on hover */
  .ah .recipe .cover{display:block;margin:0 0 12px;text-decoration:none}
  .ah .recipe .cv{display:grid;place-items:center;aspect-ratio:1;border-radius:6px;background:rgba(255,255,255,.035);box-shadow:0 0 0 1px var(--card-edge);color:var(--ink);transition:transform .3s cubic-bezier(.2,.7,.2,1),color .15s}
  .ah .recipe:hover .cv{transform:translateY(-4px);color:var(--accent)}
  .ah .recipe .pb{display:block;width:50%;height:auto;aspect-ratio:1;fill:currentColor}   /* the mark: one path, its own navy on the site, the ink here; half the tile (the carrot fills about two thirds of its box, so it reads at about a third of the tile) */
  .ah .recipe h3{margin:0;font-size:inherit;font-weight:500;color:var(--ink)}
  .ah .recipe h3 a{text-decoration:none;color:inherit;transition:color .1s}
  .ah .recipe h3 a:hover,.ah .recipe:hover h3 a{color:var(--accent)}
  .ah .recipe .by{margin:0;font-family:var(--mono);font-size:12px;line-height:var(--lh);letter-spacing:.06em;color:var(--mute)}   /* the date, in the list's voice */
  /* a law: a card on the night, the drawing drawn as the card comes on screen (its strokes by the pen, its fills settling in), then the name and the text */
  .ah .law{padding:20px 24px 24px;border-radius:6px;background:rgba(255,255,255,.035);box-shadow:0 0 0 1px var(--card-edge)}
  .ah .law .ic{margin:0 0 14px;color:var(--ink)}
  .ah .law .ic svg{display:block;width:100%;height:auto;overflow:visible}
  .ah .law h3{margin:0 0 4px;font-size:inherit;font-weight:500;color:var(--ink)}
  .ah .law p{margin:0;color:var(--text)}
  .ah .law svg .s,.ah .law svg .f,.ah .law svg .fo{--dly:calc(var(--gd,0s) * (1 - var(--rev,0)) + var(--gr,0s) * var(--rev,0) + var(--cd,0s))}   /* a mark's delay: its place in the pen's order (--gd) drawing, its place from the end (--gr) unwinding (--rev 1 on the card), plus the column's stagger (--cd, on the card) */
  .ah .law svg .s{fill:none;stroke-dasharray:1;stroke-dashoffset:0;transition:stroke-dashoffset var(--dur,.3s) linear var(--dly)}   /* a stroke draws along its own length (pathLength 1), at the gate sheet's pen speed, each mark starting a beat after the last */
  .ah .law svg .f,.ah .law svg .fo{transition:opacity .3s ease var(--dly),transform .45s cubic-bezier(.2,.7,.2,1) var(--dly)}
  .ah .law svg .f{transform-box:fill-box;transform-origin:center}   /* a fill settles in from small; a fill that carries its own transform attribute only fades (a CSS transform would replace it) */
  .ah .law:not(.drawn) svg .s{stroke-dashoffset:1}   /* the drawing is keyed to .drawn (set with .in as the card arrives) so a hover can draw it again without replaying the card's rise (2026-09-06, Yaron) */
  .ah .law:not(.drawn) svg .f{opacity:0;transform:scale(.4)}
  .ah .law:not(.drawn) svg .fo{opacity:0}

  /* ---------- the player: a bar at the bottom, the Build bar's height and place. the mix plays here through SoundCloud's widget while you keep reading; the gold line along its top is the progress, and a click on it seeks ---------- */
  #player{position:fixed;left:0;right:0;bottom:0;z-index:90;height:var(--barh);background:var(--paper);border-top:1px solid var(--hair);transform:translateY(110%);transition:transform .3s cubic-bezier(.2,.7,.2,1)}
  #player.on{transform:none}
  #player .track{position:absolute;left:0;right:0;top:-7px;height:14px;cursor:pointer}   /* the seek hit area, around the bar's top edge */
  #player .track i{position:absolute;left:0;right:0;top:6px;height:2px;background:var(--accent);transform-origin:0 50%;transform:scaleX(var(--p,0))}
  #player .in{max-width:1124px;height:100%;margin:0 auto;padding:0 22px;display:flex;align-items:center;gap:16px}
  #player img{display:block;width:40px;height:40px;border-radius:4px;background:var(--sheet)}
  #player .tt{display:contents}   /* the title and the SoundCloud link: separate flex items on the desk (the link at the far end), one block on the phone, the link under the title (2026-09-06, Yaron) */
  #player .ti{flex:1;order:1;min-width:0;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #player .tm{order:2;font-family:var(--mono);font-size:12px;letter-spacing:.06em;color:var(--mute);font-variant-numeric:tabular-nums;white-space:nowrap}
  #player .pp{order:3;width:40px;height:40px;padding:0;border:0;border-radius:50%;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;cursor:pointer;transition:background-color .15s}
  #player .pp:hover{background:var(--accent-hover)}
  #player .pp .material-symbols-outlined{font-size:24px;width:24px;height:24px;font-variation-settings:'FILL' 1,'wght' 400,'GRAD' 0,'opsz' 24}
  #player .pp .pl,#player.paused .pp .pa{display:none}
  #player.paused .pp .pl{display:block}
  #player .sc{order:4;white-space:nowrap}
  #sc{position:fixed;left:-9999px;top:0;width:300px;height:100px;border:0;opacity:0;pointer-events:none}   /* the widget's iframe, off screen: the bar is the player */

  @media (max-width:1024px){
    body.ah{--D:40vw}   /* the homepage's phone moon */
    body.ah .moon{top:40px}   /* the phone header's margin */
    body.ah #top{padding-bottom:max(18vh,calc(var(--D) - 8px))}   /* the headline clears the moon by 40px where the two would meet (the moon's bottom is 40 + D, the logo row 40 + 48) */
    body.ah main{padding-bottom:40px}
    body.ah.playing main{padding-bottom:calc(40px + var(--barh))}
    .ah .lede{max-width:640px}
    .ah .books,.ah .recipes{grid-template-columns:repeat(4,1fr)}
    .ah .laws{grid-template-columns:repeat(2,1fr)}
  }
  @media (max-width:700px){
    body.ah #top{padding-bottom:max(13vh,calc(var(--D) - 8px))}
    .ah .mixes{grid-template-columns:repeat(2,1fr);gap:16px}
    .ah .books{grid-template-columns:1fr;gap:24px}
    .ah .book{display:grid;grid-template-columns:100px 1fr;gap:16px;align-items:start}   /* a row on the phone: the cover at the left, the text beside it (two-across left the blurb at eighteen characters a line) */
    .ah .book .cover{margin:0;perspective:none}   /* no tilt on the phone, and a perspective would make the cover the sticker's containing block */
    .ah .book{position:relative}   /* the Currently reading sticker leaves the cover on the phone (it covered a third of a 100px cover) and sits at the top of the text column, the text starting under it */
    .ah .book .cv{position:static}
    .ah .book .now{left:116px;top:2px}
    .ah .book:has(.now) .bt{padding-top:26px}
    .ah .recipes{grid-template-columns:repeat(2,1fr);gap:24px 16px}   /* two across on the phone, the titles wrapping under */
    .ah .laws{grid-template-columns:1fr;gap:16px}
    .ah h2+.tiles,.ah h2+.laws{padding-top:12px}   /* the phone's first row, 12 under the title's 20 */
    #player .tm{display:none}
    #player .tt{display:flex;flex-direction:column;flex:1;min-width:0;gap:1px;align-items:flex-start}   /* the link under the title, in the label voice */
    #player .tt .ti{flex:none;max-width:100%}
    #player .sc{font-family:var(--mono);font-size:11px;line-height:1.3;letter-spacing:.08em;text-transform:uppercase;color:var(--text);text-decoration:none}
    #player .sc:hover{color:var(--accent)}
    #player .in{gap:12px}
  }
