/* Workflow first explainer: this page's figures only. The project in three parts, the same handoff
   as four people draw it, thirty handovers arriving at one desk, forty steps cut to eighteen, the
   survivors sorted into two piles, and day thirty twice. Shared chrome is in explainer.css, which
   loads first. Every finished state exists in HTML; motion is additive, runs once and rests
   visible. This page has no script of its own. The running example is one handoff, sales to legal.
   The page's running object is the process as a row of steps: four people's partial maps in 02,
   forty steps struck to eighteen in 04, the eighteen sorted into two piles in 05, and the month
   after the build laid out on the same kind of row in 07.
   COLOUR GRAMMAR, written down on 2026-09-22 on the model of /mcp and /buy-vs-build, so anything
   added later can be coloured by asking what it IS rather than what would look good.
   Yellow and pink are ROLES here, as pink is on /buy-vs-build: sales is yellow and legal is pink,
   in the avatars, on the notes sales sends and on the desk legal works at, and a step somebody
   still does by hand is yellow because a salesperson or a lawyer is doing it. Ops and finance are
   #f7f4e8, people with no colour of their own, which is also what frees green. Green
   (--green-bg, #2f5a1f ink): settled, released, landed. The eighteen that are left, the note that
   says what changed, the week in the room, the day thirty that worked. Salmon (#fbf3ee surfaces,
   #b4531d ink, #ffd7d7 and #7a3a14 for a stall): the thing that does not work. The step only one
   person drew, a stall, a question going back, the rollout that reverted. Cream (#f7f4e8) inside a
   black outline: a product somebody sold you, which here is the struck steps, because they exist for a
   system that was switched off or a form nobody removed. Blue-light: AI alone (.wf-ai). --ex-tint:
   the thing being built, the build third of the hero and the AI pile. #b9b9b9 bars, the shared
   .ex-blur: text you are not meant to read. Dashed edges on #f7f4e8: nothing there, the empty
   stretch after a training and the rest of a pile.
   One trap, the same as /buy-vs-build's: site.css defines --green-bg twice and the later value
   wins, so keep using the token and do not swap in the literal for one element.
   Do not spend a colour that is already spoken for. */

.wf-page .ex-head .h-display{text-wrap:balance}
/* The line after each figure is the next beat, hanging from the figure on a dashed stem. */
.wf-page .ex-punch{position:relative;margin-top:0;padding-top:64px}
.wf-page .ex-punch::before{content:"";position:absolute;left:50%;top:0;width:1.5px;height:44px;margin-left:-.75px;background:repeating-linear-gradient(to bottom,rgba(0,0,0,.45) 0 4px,transparent 4px 9px)}
.wf-page .ex-punch::after{content:"";position:absolute;left:50%;top:44px;width:7px;height:7px;margin-left:-3.5px;border-radius:50%;background:#000}
/* Somebody in the work whose colour this page has not given out. */
.wf-page .ex-avatar--grey{background-color:var(--cream)}

/* The AI mark on a step, inline, at the size a figure's own card wants. */
.wf-ai{display:inline-grid;place-items:center;width:26px;height:26px;flex:0 0 26px;border:1.5px solid #000;border-radius:50%;background:var(--blue-light);font:500 10px/1 "Neue Montreal",system-ui,sans-serif;font-style:normal;letter-spacing:.02em}
/* The step that only one of four people drew. */
.wf-mark{display:inline-block;width:11px;height:11px;flex:0 0 11px;border:1.5px solid #b4531d;border-radius:50%;background:#fbf3ee}

/* ------------------------------------------------------------------ 01 HERO
   Rebuilt 2026-09-23 on /agents' process bar: one bar made of three segments, one per part of the
   project, and above each segment the same whiteboard getting further along, so the three parts
   read as one object changing rather than three different pictures. Before, ten notes with five cut
   to empty outlines; the build, the cut notes gone and the AI mark on two of the five left; the
   month after, the same board in use, green, with two people beside it. The middle segment's mono
   label carries the belief the page argues with, "What most people call the project", in blue. The
   segments fill in order once the bar is seen and rest filled; the thumbnails wait at .35 and rise.
   Colour is this page's grammar: yellow is the people's notes, --ex-tint the thing being built,
   green settled. */
.wf-proj{width:100%;margin:40px 0 0;padding:28px 28px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);text-align:left}
.wf-proj__stops{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}
.wf-proj__stops>li{display:flex;flex-direction:column;gap:14px;min-width:0}
.wf-proj__thumb{margin:0 14px 0 0;aspect-ratio:160/100;border:1.5px solid #000;border-radius:12px;background:#fdfcf8 radial-gradient(rgba(0,0,0,.07) 1px,transparent 1.2px) 0 0/14px 14px;overflow:hidden;transition:opacity .5s var(--ease),transform .5s var(--ease);transition-delay:calc(var(--i,0) * 320ms)}
.wf-proj__thumb svg{display:block;width:100%;height:100%}
.wf-proj__seg{position:relative;isolation:isolate;display:flex;align-items:center;height:44px;padding:0 16px;border:1.5px solid #000;border-left-width:0;background:#fff;font:500 14.5px/1.2 "Neue Montreal",system-ui,sans-serif;white-space:nowrap}
/* The segment's colour is a layer under its label, so the loop can fill it left to right. */
.wf-proj__seg::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;background:var(--seg,var(--yellow-bg));clip-path:inset(0 0 0 0)}
.wf-proj__stops>li:first-child .wf-proj__seg{border-left-width:1.5px;border-radius:12px 0 0 12px}
.wf-proj__stops>li.is-build{--seg:var(--ex-tint)}
.wf-proj__stops>li.is-after{--seg:var(--green-bg)}
.wf-proj__stops>li.is-after .wf-proj__seg{border-radius:0 12px 12px 0}
.wf-proj__txt{padding-right:24px}
.wf-proj__k{display:block;font:500 11px/1.3 ui-monospace,"SF Mono",Menlo,monospace;letter-spacing:.06em;text-transform:uppercase;color:#333}
.wf-proj__stops>li.is-build .wf-proj__k{color:var(--blue)}
.wf-proj__txt .wf-proj__h{margin:7px 0 6px;color:#000;font:500 19px/1.25 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em}
.wf-proj__txt p{margin:0;font:400 14.5px/1.5 "Neue Montreal",system-ui,sans-serif;color:var(--muted)}
.ex-js .wf-proj:not(.is-seen) .wf-proj__thumb{opacity:.35;transform:translateY(8px)}
.wf-proj>figcaption:not(.ex-sr-only){margin:26px -28px 0;padding:14px 28px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}
@media(prefers-reduced-motion:reduce){.wf-proj__thumb{transition:none}}
/* THE LOOP, 2026-09-23. /agents' hero is one loop carrying the whole offer; this hero's one idea
   is the same board going through three stages, so it loops through them on one 12s clock. Before
   (0 to 30%): the five cut notes come off one at a time and leave their outlines. The build (33 to
   60%): the AI lands on two of the five left. The month after (63 to 92%): the two people and the
   tick arrive. The bar is the clock: each segment starts white and fills with its colour, left to
   right, during its phase (Bruno's call over a blue timer line under the bar), and nothing else
   marks the stage: one device for one job. Every element's base style is its finished frame, so reduced
   motion shows the three finished boards and a full bar. */
.wf-proj .h-ai,.wf-proj .h-pop{transform-box:fill-box;transform-origin:center}
.wf-proj .h-cut{opacity:0}
@media(prefers-reduced-motion:no-preference){
  .wf-proj.is-seen .h-cut{animation:wf-h-cut 12s var(--ease) calc(var(--k) * .45s) infinite both}
  .wf-proj.is-seen .h-ai{animation:wf-h-ai 12s var(--ease) calc(var(--k) * .5s) infinite both}
  .wf-proj.is-seen .h-pop{animation:wf-h-pop 12s var(--ease) calc(var(--k) * .45s) infinite both}
  .wf-proj.is-seen .wf-proj__stops>li:nth-child(1) .wf-proj__seg::before{animation:wf-h-t1 12s linear infinite both}
  .wf-proj.is-seen .wf-proj__stops>li:nth-child(2) .wf-proj__seg::before{animation:wf-h-t2 12s linear infinite both}
  .wf-proj.is-seen .wf-proj__stops>li:nth-child(3) .wf-proj__seg::before{animation:wf-h-t3 12s linear infinite both}
}
@keyframes wf-h-cut{0%,8%{opacity:1}13%,94%{opacity:0}100%{opacity:1}}
@keyframes wf-h-ai{0%,36%{opacity:.35;transform:scale(.4)}42%,94%{opacity:1;transform:none}100%{opacity:.35;transform:scale(.4)}}
@keyframes wf-h-pop{0%,65%{opacity:.35;transform:scale(.6)}71%,94%{opacity:1;transform:none}100%{opacity:.35;transform:scale(.6)}}
/* The fill is a clip, not a scale: a scaled layer drags the segment's rounded corner along as a
   blob at its leading edge; a clip keeps the corners where they are and the edge straight. */
@keyframes wf-h-t1{0%{clip-path:inset(0 100% 0 0)}30%,94%{clip-path:inset(0 0 0 0)}100%{clip-path:inset(0 100% 0 0)}}
@keyframes wf-h-t2{0%,33%{clip-path:inset(0 100% 0 0)}60%,94%{clip-path:inset(0 0 0 0)}100%{clip-path:inset(0 100% 0 0)}}
@keyframes wf-h-t3{0%,63%{clip-path:inset(0 100% 0 0)}92%,94%{clip-path:inset(0 0 0 0)}100%{clip-path:inset(0 100% 0 0)}}

/* -------------------------------------------- 02 HOW IT WORKS: four people, four processes
   Nothing is torn here. Four people drew four things, each of them correct about their own part,
   which is a different claim from one record pulled apart and needs a different picture. */
.wf-sketch{max-width:1080px;margin:56px auto 0;padding:26px 26px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);text-align:left}
/* Four across: the four maps are one comparison, and read side by side at the drawings' own size
   they take half the height two rows of half-empty cards did. Two across under 1100, one on a phone. */
.wf-sketch__grid{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:0;padding:0}
.wf-sketch__grid>li{display:flex;flex-direction:column;gap:10px;min-width:0;padding:16px 16px 18px;border:1.5px solid #000;border-radius:14px;background:#fff}
.wf-sketch__who{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.wf-sketch__who .ex-avatar{align-self:center}
.wf-sketch__who b{font:500 16px/1.2 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em}
.wf-sketch__who span{font-size:12.5px;color:var(--muted)}
/* Each person's map is a column of steps in HTML, not a drawing with words inside it: the series
   sets words as type, and the SVG version set them at 7 to 24px depending on the card's width.
   One chip per step, joined by a short line, so the four columns can be compared by length at a
   glance, which is the section's point: legal's is twice anybody else's. The colour of a chip is
   whose step it is (sales yellow-bg, legal pink), salmon is where it stalls, and a dashed chip is
   off the map: a question mark after sales lets go, and everything before finance picks it up. */
.wf-flow{list-style:none;display:flex;flex-direction:column;gap:12px;margin:4px 0 6px;padding:0}
.wf-flow>li{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:34px;padding:7px 11px;border:1.5px solid #000;border-radius:9px;background:#fff;font:500 13px/1.25 "Neue Montreal",system-ui,sans-serif}
.wf-flow>li+li::before{content:"";position:absolute;left:17px;top:-13.5px;width:1.5px;height:12px;background:#000}
.wf-flow--sales>li{background:var(--yellow-bg)}
.wf-flow--legal>li.is-ask{background:var(--pink)}
.wf-flow>li.is-stall{background:#ffd7d7;border-color:#b4531d;color:#7a3a14}
.wf-flow>li.is-off,.wf-flow>li.is-theirs{justify-content:flex-start;border-style:dashed;border-color:#8a8a8a;background:#f7f4e8;color:var(--muted);font-weight:400}
.wf-flow>li.is-theirs{justify-content:space-between}
.wf-flow>li.is-off+li::before,.wf-flow>li+li.is-off::before{background:repeating-linear-gradient(to bottom,#8a8a8a 0 3px,transparent 3px 6px)}
.wf-flow__q{display:inline-grid;place-items:center;width:18px;height:18px;flex:0 0 18px;margin-right:8px;border:1.5px solid #b4531d;border-radius:50%;background:#fbf3ee;color:#b4531d;font:500 10.5px/1 "Neue Montreal",system-ui,sans-serif}
.wf-flow__back,.wf-flow__tag{flex:none;font:400 11px/1.2 "Neue Montreal",system-ui,sans-serif;color:#333;white-space:nowrap}
.wf-flow__back::before{content:"\21A9";margin-right:4px}
.wf-flow__tag--n{padding:2px 7px;border:1.5px solid #b4531d;border-radius:999px;background:#fff;color:#7a3a14;font-weight:500}
.wf-sketch__grid p{margin:auto 0 0;padding-top:4px;font:500 14px/1.45 "Neue Montreal",system-ui,sans-serif;color:#333}
.wf-sketch__note{display:flex;align-items:center;gap:10px;margin:16px 0 0;padding:13px 16px;border:1.5px dashed #b4531d;border-radius:12px;background:#fbf3ee;font:500 14.5px/1.45 "Neue Montreal",system-ui,sans-serif;color:#7a3a14}
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-sketch .wf-flow>li{opacity:.35;transform:translateY(6px)}
  .ex-js .wf-sketch .wf-sketch__note{opacity:.35;transform:translateY(6px)}
  /* The four people draw at once: each column builds top down on the same clock, so the short
     maps finish while legal's is still going. */
  .wf-sketch.is-seen .wf-flow>li{animation:ex-arrive .4s var(--ease) calc(.25s + var(--j,0) * .2s) both}
  .wf-flow>li:nth-child(2){--j:1}.wf-flow>li:nth-child(3){--j:2}.wf-flow>li:nth-child(4){--j:3}.wf-flow>li:nth-child(5){--j:4}.wf-flow>li:nth-child(6){--j:5}
  .wf-sketch.is-seen .wf-sketch__note{animation:ex-arrive .5s var(--ease) 1.7s both}
}
.wf-sketch>figcaption:not(.ex-sr-only){margin:26px -26px 0;padding:14px 26px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}

/* --------------------------------------------- 03 THE PROBLEM: thirty handovers, one desk
   Three handovers drawn in full and the rest counted, because thirty of anything at phone width
   is a texture. The four facts are listed on every note so the reader can see which are missing. */
.wf-intake{max-width:1080px;margin:56px auto 0;padding:26px 26px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);display:grid;grid-template-columns:1fr 1fr;gap:34px;text-align:left}
.wf-intake__fan>ul{list-style:none;display:flex;flex-direction:column;gap:10px;margin:12px 0 0;padding:0}
.wf-intake__fan>ul>li{padding:13px 15px 14px;border:1.5px solid #000;border-radius:12px;background:#fff;box-shadow:3px 3px 0 -1px rgba(0,0,0,.1)}
.wf-note__who{display:flex;align-items:center;gap:8px;font:500 11px/1.2 "Neue Montreal",system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.wf-intake__fan>ul>li>b{display:block;margin:8px 0 10px;font:500 16px/1.25 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em}
.wf-note__facts{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:0}
.wf-note__facts li{padding:4px 10px;border:1.5px dashed rgba(0,0,0,.35);border-radius:999px;font:400 11.5px/1.2 "Neue Montreal",system-ui,sans-serif;color:var(--muted)}
.wf-note__facts li.is-there{border-style:solid;border-color:#000;background:var(--yellow);color:#000;font-weight:500}
/* A fact this note does not carry, on the two notes after the first. The first note writes all
   four, because it is the one that teaches the pattern; after it, only the facts that arrived keep
   their words and the rest stand as the shared .ex-blur, so the three notes still read as the same
   four rows in the same order. The pill keeps its dashed edge, which is what still says missing.
   Deleting the missing rows instead was the obvious move and is the one /buy-vs-build tried and
   rejected on its corners figure: it leaves the reader to make the join alone. 6.4px of padding on
   a 9px bar is the 21.8px a pill of 11.5px words occupies, so the rows stay level. */
.wf-note__facts li.is-blur{display:flex;align-items:center;padding:6.4px 10px}
.wf-intake__stack{display:block;margin-top:12px;padding:12px 15px;border:1.5px dashed rgba(0,0,0,.4);border-radius:12px;background:#f7f4e8;font:400 13.5px/1.4 "Neue Montreal",system-ui,sans-serif;color:var(--muted)}
/* Everything on the left arrives at this one desk: a dashed connector from the notes' edge to the
   desk, landing on a dot, the way /mcp's chain joins its stops. Gone once the two stack. */
.wf-intake__desk::before{content:"";position:absolute;right:100%;top:50%;width:34px;height:1.5px;background:repeating-linear-gradient(to right,rgba(0,0,0,.5) 0 4px,transparent 4px 8px)}
.wf-intake__desk::after{content:"";position:absolute;left:-6px;top:50%;width:9px;height:9px;margin-top:-4.5px;border:1.5px solid #000;border-radius:50%;background:var(--blue)}
/* The desk is white with legal's pink as its one accent, the avatar: a fully pink panel read as a
   flood next to three white notes. */
.wf-intake__desk{position:relative;align-self:center;padding:20px 20px 22px;border:1.5px solid #000;border-radius:14px;background:#fff;box-shadow:var(--ex-shadow)}
.wf-intake__desk>b{display:block;margin:8px 0 12px;font:500 24px/1.15 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.02em}
.wf-intake__who{display:flex;align-items:center;gap:10px;padding-bottom:14px;border-bottom:1.5px solid rgba(0,0,0,.25);font:400 13.5px/1.4 "Neue Montreal",system-ui,sans-serif}
.wf-intake__asks{list-style:none;display:flex;flex-direction:column;gap:8px;margin:14px 0 0;padding:0}
.wf-intake__asks li{position:relative;padding:9px 12px 10px 30px;border:1.5px solid #000;border-radius:12px 12px 12px 4px;background:#fff;font:400 13.5px/1.35 "Neue Montreal",system-ui,sans-serif}
.wf-intake__n{position:absolute;right:10px;top:50%;transform:translateY(-50%);padding:2px 7px;border:1.5px solid #b4531d;border-radius:999px;background:#fbf3ee;color:#7a3a14;font:500 11px/1.2 "Neue Montreal",system-ui,sans-serif;font-variant-numeric:tabular-nums}
.wf-intake__asks li::before{content:"?";position:absolute;left:10px;top:50%;transform:translateY(-50%);width:14px;height:14px;display:grid;place-items:center;border:1.5px solid #b4531d;border-radius:50%;background:#fbf3ee;color:#b4531d;font:500 8.5px/1 "Neue Montreal",system-ui,sans-serif}
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-intake .wf-intake__fan>ul>li,.ex-js .wf-intake .wf-intake__asks li{opacity:.35;transform:translateY(7px)}
  .wf-intake.is-seen .wf-intake__fan>ul>li{animation:ex-arrive .45s var(--ease) calc(.2s + var(--i) * .25s) both}
  .wf-intake.is-seen .wf-intake__asks li{animation:ex-arrive .45s var(--ease) calc(1.1s + var(--i) * .22s) both}
}
.wf-intake>figcaption:not(.ex-sr-only){grid-column:1/-1;margin:26px -26px 0;padding:14px 26px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}

/* ---------------------------------------------------- 04 THE SHIFT: forty notes, then eighteen
   The handoff drawn as what it was on the day: forty sticky notes on a whiteboard, ten to a row, so
   the count is a shape the reader can take in at a glance rather than a strip that wraps wherever
   the viewport says. Every one of the forty is drawn, because the count is the argument. A cut
   step is not struck through; it is taken off the board and leaves an empty dashed outline where it
   was, which is the series' own mark for a thing no longer there (/buy-vs-build's empty months),
   and it keeps the eighteen legible, which forty diagonal strikes did not. The three stalls are
   salmon notes with a pin, and the cards under the board carry the same note, so the reader joins
   the two without a pointer line. Sticky notes are yellow because a person wrote each one. */
.wf-map{max-width:1080px;margin:56px auto 0;padding:24px 26px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);text-align:left}
.wf-map__head{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap}
.wf-map__tag{display:inline-block;padding:6px 11px;border:1.5px solid #000;border-radius:999px;background:#fff;font:500 11px/1 "Neue Montreal",system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase}
.wf-map__tally{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.wf-map__tally>i{position:relative;width:34px;height:1.5px;background:#000;flex:none}
.wf-map__tally>i::after{content:"";position:absolute;right:0;top:50%;width:7px;height:7px;margin-top:-4px;border-top:1.5px solid #000;border-right:1.5px solid #000;transform:rotate(45deg)}
.wf-map__count{display:flex;align-items:baseline;gap:8px;font-size:13.5px;color:var(--muted)}
.wf-map__count b{font:500 30px/1 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.03em;color:#000;font-variant-numeric:tabular-nums}
.wf-map__count--after b{color:#2f5a1f}
.wf-map__board{list-style:none;display:grid;grid-template-columns:repeat(10,1fr);gap:10px;margin:18px 0 0;padding:20px;border:1.5px solid #000;border-radius:14px;background:#fff}
.wf-note{position:relative;display:block;height:44px;border:1.5px solid #000;border-radius:7px;background:#fff;box-shadow:2px 2px 0 rgba(0,0,0,.08);font-style:normal}
.wf-note i{position:absolute;left:9px;top:7px;font:500 12px/1 "Neue Montreal",system-ui,sans-serif;font-style:normal;font-variant-numeric:tabular-nums}
.wf-note.is-cut{background:transparent;border-color:transparent;box-shadow:none}
.wf-note.is-cut::after{content:"";position:absolute;inset:-1.5px;border:1.5px dashed #b9b9b9;border-radius:7px}
.wf-note.is-cut i{color:#b9b9b9}
/* What was written on the note, drawn as the shared .ex-blur: the number is the one thing on a
   note the reader needs, so the words are a grey line rather than twenty-two tiny labels. */
.wf-note .ex-blur{position:absolute;left:9px;bottom:9px;max-width:calc(100% - 18px)}
.wf-note.is-stall{background:#ffd7d7}
.wf-note.is-stall::before{content:"";position:absolute;right:8px;top:8px;width:8px;height:8px;border-radius:50%;background:#b4531d}
/* The same note, small, heading each stall card. */
.wf-note--mini{display:inline-grid;place-items:center;width:30px;height:22px;margin-right:9px;vertical-align:middle;font:500 11px/1 "Neue Montreal",system-ui,sans-serif;letter-spacing:0;color:#000;box-shadow:none}
.wf-note--mini.is-stall::before{content:none}
.wf-map__stalls{list-style:none;display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:18px 0 0;padding:0}
.wf-map__stalls li{padding:13px 16px 15px;border:1.5px solid #b4531d;border-radius:12px;background:#fbf3ee}
.wf-map__n{display:flex;align-items:center;font:500 11px/1.2 "Neue Montreal",system-ui,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:#b4531d;margin-bottom:9px}
.wf-map__stalls b{font:500 15px/1.3 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em;color:#7a3a14}
/* THE CUT. The board arrives with all forty notes up; then the twenty-two come off one at a time,
   in the order written on them (--k, 0 to 21), each note's fill and edge fading while its dashed
   outline fades in, so the board thins to eighteen in front of the reader. Only then does the 18
   land, and only then the three stalls. It rests on the finished board, which is also what reduced
   motion and no JavaScript show. This replaced a running counter drawn with an @property integer:
   Safari stopped it at 19 instead of 18, and a number that can end wrong is worse than one that
   arrives once. */
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-map:not(.is-seen) .wf-note.is-cut{background:#fff;border-color:#000;box-shadow:2px 2px 0 rgba(0,0,0,.08)}
  .ex-js .wf-map:not(.is-seen) .wf-note.is-cut::after{opacity:0}
  .ex-js .wf-map:not(.is-seen) .wf-note.is-cut i{color:#000}
  .ex-js .wf-map .wf-map__count--after,.ex-js .wf-map .wf-map__tally>i{opacity:.35}
  .ex-js .wf-map .wf-map__stalls li{opacity:.35;transform:translateY(7px)}
  .wf-map.is-seen .wf-note.is-cut{animation:wf-cut .8s var(--ease) calc(.4s + var(--k) * .09s) both}
  .wf-map.is-seen .wf-note.is-cut::before{animation:wf-strike .8s var(--ease) calc(.4s + var(--k) * .09s) both}
  .wf-map.is-seen .wf-note.is-cut::after{animation:wf-cut-edge .8s var(--ease) calc(.4s + var(--k) * .09s) both}
  .wf-map.is-seen .wf-note.is-cut i{animation:wf-cut-num .8s var(--ease) calc(.4s + var(--k) * .09s) both}
  .wf-map.is-seen .wf-map__tally>i{animation:ex-arrive .4s var(--ease) 3.1s both}
  .wf-map.is-seen .wf-map__count--after{animation:ex-arrive .5s var(--ease) 3.25s both}
  .wf-map.is-seen .wf-map__stalls li{animation:ex-arrive .5s var(--ease) calc(3.5s + var(--i) * .15s) both}
}
@keyframes wf-run{0%{opacity:.35;transform:none;background:#fdfcf8;box-shadow:none}22%{opacity:1;background:#f4f8ff;box-shadow:inset 3px 0 0 var(--blue)}70%{background:#f4f8ff;box-shadow:inset 3px 0 0 var(--blue)}100%{opacity:1;transform:none;background:#fdfcf8;box-shadow:inset 3px 0 0 transparent}}
@keyframes wf-pill{from{opacity:.35;transform:scale(.9)}to{opacity:1;transform:none}}
/* A PEN STRIKE FIRST (exploration, 2026-09-23): each note is struck through by hand before it comes
   off, the way a room crosses steps off a real whiteboard, and then the strike goes with the note.
   The strike is transient; the board still rests on the empty outlines. */
.wf-note.is-cut::before{content:"";position:absolute;inset:7px 6px;background:linear-gradient(to top right,transparent calc(50% - 1px),#b4531d calc(50% - 1px),#b4531d calc(50% + 1px),transparent calc(50% + 1px));opacity:0;pointer-events:none}
@keyframes wf-strike{0%{opacity:1;clip-path:inset(0 100% 0 0)}35%,62%{opacity:1;clip-path:inset(0 0 0 0)}100%{opacity:0;clip-path:inset(0 0 0 0)}}
@keyframes wf-cut{0%,45%{background:#fff;border-color:#000;box-shadow:2px 2px 0 rgba(0,0,0,.08)}100%{background:transparent;border-color:transparent;box-shadow:2px 2px 0 rgba(0,0,0,0)}}
@keyframes wf-cut-edge{0%,45%{opacity:0}100%{opacity:1}}
@keyframes wf-cut-num{0%,45%{color:#000}100%{color:#b9b9b9}}
.wf-map>figcaption:not(.ex-sr-only){margin:26px -26px 0;padding:14px 26px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}

/* ------------------------------------ 05 INSIDE THE WORKFLOW: the eighteen, sorted into two
   A sort, not a line. Multiplayer's assembly line already owns the sequence; what this page has
   to teach is the rule for telling the two kinds of step apart. */
.wf-sort{max-width:1080px;margin:56px auto 0;padding:26px 26px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);display:grid;grid-template-columns:1fr 1fr;gap:20px;text-align:left}
.wf-sort__col{padding:20px 20px 22px;border:1.5px solid #000;border-radius:14px}
.wf-sort__col--ai{background:var(--ex-tint)}
.wf-sort__col--people{background:#fff}
.wf-sort__head{display:flex;align-items:flex-start;gap:12px;padding-bottom:16px;border-bottom:1.5px solid rgba(0,0,0,.2)}
.wf-sort__head b{display:block;font:500 18px/1.2 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.015em}
.wf-sort__head small{display:block;margin-top:4px;font-size:13px;line-height:1.4;color:var(--muted)}
.wf-sort__col>ul{list-style:none;display:flex;flex-direction:column;gap:10px;margin:16px 0 0;padding:0}
/* Every step keeps the number of its note on the whiteboard, so the sort reads as the same
   eighteen notes put into two piles, and says who does it, in the chip the layer on /buy-vs-build
   uses for the same job. The eleven the page does not name are there as their notes. */
.wf-sort__col>ul>li{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:12px 14px 13px;border:1.5px solid #000;border-radius:12px;background:#fdfcf8}
.wf-sort__col>ul>li .wf-note--mini{margin:0}
.wf-sort__verb{display:inline-flex;align-items:center;gap:6px;padding:3px 9px 3px 3px;border:1.5px solid #000;border-radius:999px;background:#fff;font:500 12px/1 "Neue Montreal",system-ui,sans-serif;font-style:normal;white-space:nowrap}
.wf-sort__verb .wf-ai,.wf-sort__verb .ex-avatar{width:22px;height:22px;flex:0 0 22px;font-size:9.5px}
.wf-sort__col>ul>li.wf-sort__rest{grid-template-columns:1fr}
.wf-sort__notes{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px}
.wf-sort__notes .wf-note--mini{margin:0;width:28px;height:20px;font-size:10.5px}
.wf-sort__col>ul>li b{display:block;font:500 15px/1.3 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em}
.wf-sort__col>ul>li div>span:not(.wf-sort__notes){display:block;margin-top:4px;font-size:12.5px;line-height:1.45;color:var(--muted)}
.wf-sort__rest{border-style:dashed !important;border-color:rgba(0,0,0,.4) !important;background:#f7f4e8 !important}
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-sort .wf-sort__col>ul>li{opacity:.35;transform:translateY(7px)}
  /* The AI pile runs, the way /agents' agent screen does: each step waits at .35, lights with the
     blue inset bar while the AI does it, and its chip lands when it is done. Then the people's
     pile rises, untouched. (2026-09-23) */
  .ex-js .wf-sort .wf-sort__col--ai .wf-sort__verb{opacity:.35;transform:scale(.9)}
  .wf-sort.is-seen .wf-sort__col--ai>ul>li{animation:wf-run 1s var(--ease) calc(.3s + var(--i) * .6s) both}
  .wf-sort.is-seen .wf-sort__col--ai .wf-sort__verb{animation:wf-pill .3s var(--ease) calc(.95s + var(--i) * .6s) both}
  .wf-sort.is-seen .wf-sort__col--people>ul>li{animation:ex-arrive .45s var(--ease) calc(2.9s + var(--i) * .15s) both}
}
.wf-sort>figcaption:not(.ex-sr-only){grid-column:1/-1;margin:26px -26px 0;padding:14px 26px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}

/* --------------------------------------------------- 07 OVER TIME: thirty days, drawn twice
   The page's only two-track figure, and it is here because this is the one place the argument is
   a comparison over time. The beats are sized by how long they last, so the empty stretch on the
   first track is as wide as it actually is. */
.wf-day30{max-width:1080px;margin:56px auto 0;padding:22px 26px 0;background:var(--ex-card);border:1.5px solid #000;border-radius:18px;box-shadow:var(--ex-shadow);text-align:left}
/* The scale is a rail of thirty marks, one a day, so the widths of the beats below read as days. */
.wf-day30__scale{display:flex;justify-content:space-between;padding-bottom:16px;border-bottom:1.5px solid rgba(0,0,0,.35);background:repeating-linear-gradient(to right,rgba(0,0,0,.3) 0 1.5px,transparent 1.5px calc((100% - 1.5px) / 29)) left bottom / 100% 7px no-repeat;font:500 11px/1.2 "Neue Montreal",system-ui,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.wf-day30__track{position:relative;padding:44px 0 22px}
.wf-day30__track+.wf-day30__track{border-top:1px solid var(--line)}
.wf-day30__tag{position:absolute;top:12px;left:0;display:inline-block;padding:5px 11px;border:1.5px solid #000;border-radius:999px;font:500 11px/1 "Neue Montreal",system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase}
.wf-day30__track--mess .wf-day30__tag{background:#fbf3ee}
.wf-day30__track--first .wf-day30__tag{background:var(--green-bg)}
.wf-day30__track ul{list-style:none;display:flex;gap:8px;margin:0;padding:0}
.wf-day30__track li{flex:var(--f) 1 0;min-width:0;padding:13px 14px 14px;border:1.5px solid #000;border-radius:12px;background:#fff}
.wf-day30__track li b{display:block;font:500 14.5px/1.25 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.01em}
.wf-day30__track li span{display:block;margin-top:5px;font-size:12px;line-height:1.4;color:var(--muted)}
.wf-day30__track li.is-empty{border-style:dashed;border-color:rgba(0,0,0,.35);background:#f7f4e8;display:grid;place-items:center;text-align:center}
.wf-day30__track li.is-empty span{margin:0}
.wf-day30__track li.is-room{background:var(--green-bg)}
.wf-day30__track li.is-end{background:#fbf3ee;border-color:#b4531d}
.wf-day30__track li.is-end b{color:#7a3a14}
.wf-day30__track li.is-end.is-good{background:var(--green-bg);border-color:#2f5a1f}
.wf-day30__track li.is-end.is-good b{color:#245219}
/* THE CLOCK. It used to bring the first track in and then the second, which read as two lists.
   The argument is that both tracks are the same thirty days from the same build, so one clock runs
   across both at once: a line sweeps day 1 to day 30 over 4s on each track, in step, and every beat
   arrives as the line reaches its left edge. The delays are the beats' own start positions, read
   off the --f values in the markup (1.2 / 3.4 / 1.6 on the first track and 1 / 1.6 / 1.1 / 1.5 /
   1.6 on the second, so starts at 0, .19, .74 and 0, .15, .38, .54, .76 of the width), times 4s,
   after .3s. Change an --f and change its delay. The two day-thirty cards land within a tenth of a
   second of each other, which is the picture: same day, two endings. The line is a transient clock
   and fades at the far end; nothing rests hidden. Stacked below 1000px the tracks stop being a
   timeline, so the sweep goes and the beats keep the same order. */
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-day30 .wf-day30__track li{opacity:.35;transform:translateY(7px)}
  .wf-day30.is-seen .wf-day30__track li{animation:ex-arrive .4s var(--ease) var(--t,.3s) both}
  .wf-day30__track--mess li:nth-child(1){--t:.3s}.wf-day30__track--mess li:nth-child(2){--t:1.06s}.wf-day30__track--mess li:nth-child(3){--t:3.26s}
  .wf-day30__track--first li:nth-child(1){--t:.3s}.wf-day30__track--first li:nth-child(2){--t:.89s}.wf-day30__track--first li:nth-child(3){--t:1.83s}.wf-day30__track--first li:nth-child(4){--t:2.48s}.wf-day30__track--first li:nth-child(5){--t:3.36s}
  .wf-day30__track::after{content:"";position:absolute;left:0;top:30px;bottom:16px;width:1.5px;background:#000;opacity:0;pointer-events:none}
  .wf-day30.is-seen .wf-day30__track::after{animation:wf-sweep 4s linear .3s both}
}
@keyframes wf-sweep{0%{left:0;opacity:.6}92%{left:100%;opacity:.6}100%{left:100%;opacity:0}}
.wf-day30>figcaption:not(.ex-sr-only){margin:22px -26px 0;padding:14px 26px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center;border-radius:0 0 18px 18px}

/* ------------------------------------------ 07 OVER TIME: the change log (added 2026-09-23)
   Sections 06 and 07 used to say the same thing twice: three rollout cards, then the same beats on
   the thirty-day track. The track moved up into 06 with the cards' content in its beats, and Over
   time now covers what the page never did, the months after launch. It is the screen the team keeps
   the process in, a change log: every version a dated note, the step count the whiteboard now reads,
   and the stalls left. The numbers are the page's own: 18 at launch; +2 and -1 when the pilot corrects
   the map (19); three email steps merged into one shared draft (17), which also clears stall 9, the
   one stall AI never took; then a second region on the same map. Rows run in once, the /agents way:
   each waits at .35, lights with the blue inset bar, and settles. */
.wf-log{max-width:1080px;margin:56px auto 0;background:#fff;border:1.5px solid #000;border-radius:18px;box-shadow:16px 16px 0 -2px rgba(0,0,0,.06);overflow:hidden;text-align:left}
.wf-log__bar{display:flex;align-items:center;gap:14px;padding:12px 16px;border-bottom:1.5px solid #000;background:var(--ex-card)}
.wf-log__dots{display:flex;gap:6px}
.wf-log__dots i{width:9px;height:9px;border:1.2px solid #000;border-radius:50%;background:#fff}
.wf-log__bar>b{margin-right:auto;font:500 15px/1.2 "Neue Montreal",system-ui,sans-serif}
.wf-log__tally{display:flex;align-items:center;gap:8px;font:400 12.5px/1 ui-monospace,"SF Mono",Menlo,monospace;color:#333;font-variant-numeric:tabular-nums}
.wf-log__tally b{font-weight:500;color:#2f5a1f}
.wf-log__tally i{position:relative;width:16px;height:1.5px;background:#000}
.wf-log__tally i::after{content:"";position:absolute;right:0;top:50%;width:5px;height:5px;margin-top:-3px;border-top:1.5px solid #000;border-right:1.5px solid #000;transform:rotate(45deg)}
.wf-log__table{padding:8px 18px 14px}
.wf-log__tr{display:grid;grid-template-columns:118px minmax(0,1fr) 64px 64px;align-items:center;gap:18px;padding:14px 10px;border-bottom:1px solid rgba(0,0,0,.1);border-radius:6px;font:400 15px/1.45 "Neue Montreal",system-ui,sans-serif}
.wf-log__tr:last-child{border-bottom:0}
.wf-log__tr--h{padding-top:6px;padding-bottom:10px;font:500 11px/1.2 ui-monospace,"SF Mono",Menlo,monospace;letter-spacing:.06em;text-transform:uppercase;color:#333}
.wf-log__tr>span:nth-child(3),.wf-log__tr>span:nth-child(4){justify-self:end}
.wf-log__v{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.wf-log__v b{display:inline-flex;align-items:center;height:24px;padding:0 9px;border:1.2px solid #000;border-radius:7px;background:var(--green-bg);font:500 12.5px/1 "Neue Montreal",system-ui,sans-serif;white-space:nowrap}
.wf-log__v em{font:400 12px/1.2 ui-monospace,"SF Mono",Menlo,monospace;font-style:normal;color:var(--muted)}
.wf-log__n{font:500 24px/1 "Neue Montreal",system-ui,sans-serif;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.wf-st{display:inline-grid;place-items:center;min-width:34px;height:26px;padding:0 10px;border:1.2px solid #000;border-radius:99px;font:500 13px/1 "Neue Montreal",system-ui,sans-serif;font-variant-numeric:tabular-nums}
.wf-st--flag{background:#ffd7d7;color:#7a3a14}
.wf-st--ok{background:var(--green-bg)}
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-log .wf-log__tr:not(.wf-log__tr--h){opacity:.35}
  .wf-log.is-seen .wf-log__tr:not(.wf-log__tr--h){animation:wf-run 1.1s var(--ease) calc(.3s + var(--r) * .65s) both}
}
.wf-log>figcaption:not(.ex-sr-only){padding:14px 24px 16px;border-top:1.5px solid #000;background:var(--cream);font:500 15px/1.4 "Neue Montreal",system-ui,sans-serif;text-align:center}
@media (max-width:760px){
  .wf-log__bar{flex-wrap:wrap}
  .wf-log__tally{flex-basis:100%;order:3}
  .wf-log__table{padding:6px 12px 10px}
  .wf-log__tr{grid-template-columns:minmax(0,1fr) auto auto;gap:10px 12px}
  .wf-log__tr>span:nth-child(2){grid-column:1/-1;grid-row:2}
  .wf-log__v{flex-direction:row;align-items:center;gap:10px}
  .wf-log__tr--h{display:none}
}

/* ------------------------------------------------------------------- 11 The closing drawing
   Multiplayer's rail-and-tiles construction with this page's subjects: the map with steps struck
   off, the AI mark landing on one, the pilot team, the note that says what changed, the approval
   that stayed with a person. Copied rather than redrawn, per the standard. */
.wf-cta__art .ex-cta__tile{fill:var(--ex-tint);stroke:#000;transition:fill .6s var(--ease) .5s}
.wf-cta__art .ex-cta__chip,.wf-cta__art .ex-cta__cursor{transform-box:fill-box;transform-origin:center;transition:transform .7s cubic-bezier(.34,1.4,.64,1) .4s,opacity .4s var(--ease) .4s}
.ex-js .wf-cta__art .ex-cta__rider{opacity:0}
@media(prefers-reduced-motion:no-preference){
  .ex-js .wf-cta__art:not(.is-seen) .ex-cta__tile{fill:#fff}
  .ex-js .wf-cta__art:not(.is-seen) .ex-cta__chip{transform:translateY(-30px) scale(.7);opacity:0}
  .ex-js .wf-cta__art:not(.is-seen) .ex-cta__cursor{transform:translate(26px,-30px);opacity:0}
  .wf-cta__art.is-seen .ex-cta__rider{animation:ex-cta-ride 7s cubic-bezier(.45,0,.55,1) 1.4s infinite}
  .wf-cta__art.is-seen .ex-cta__chip{animation:ex-breathe 4.5s ease-in-out 1.4s infinite}
  .wf-cta__art.is-seen .ex-cta__cursor{animation:ex-cta-nudge 7s ease-in-out 1.4s infinite}
}
@keyframes ex-cta-ride{0%{transform:translateX(0);opacity:0}6%{opacity:1}80%{transform:translateX(414px);opacity:1}88%,100%{transform:translateX(414px);opacity:0}}
@keyframes ex-cta-nudge{0%,100%{transform:translate(0,0)}50%{transform:translate(-2px,2px)}}

/* ------------------------------------------------------------------------------ SMALLER */
@media (max-width:1100px){
  .wf-sketch__grid{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:1000px){
  .wf-intake{grid-template-columns:1fr}
  .wf-intake__desk::before,.wf-intake__desk::after{content:none}
  .wf-sort{grid-template-columns:1fr}
  .wf-map__stalls{grid-template-columns:1fr}
  /* Thirty days stacks rather than shrinking: five beats squeezed into a phone row would set
     their own type at nine pixels, and the widths stop meaning anything at that size anyway. */
  .wf-day30__track ul{flex-direction:column}
  .wf-day30__track li{flex:0 0 auto}
  .wf-day30__track li.is-empty{padding:18px 14px}
  .wf-day30__scale{display:none}
  .wf-day30__track::after{content:none}
}
@media (max-width:900px){
  .wf-proj__stops{grid-template-columns:minmax(0,1fr);gap:18px}
  .wf-proj__stops>li{display:grid;grid-template-columns:132px minmax(0,1fr);grid-template-rows:auto auto;column-gap:16px;row-gap:8px;align-items:center}
  .wf-proj__thumb{grid-row:1/3;width:132px;margin:0}
  .wf-proj__seg{justify-self:start;height:auto;padding:5px 12px;border-left-width:1.5px!important;border-radius:99px!important;align-self:end;font-size:13px}
  .wf-proj__txt{padding:0;align-self:start}
  .wf-sketch__grid{grid-template-columns:1fr}
}
@media (max-width:640px){
  .wf-map__board{grid-template-columns:repeat(5,1fr);gap:8px;padding:14px}
  .wf-map__tally{gap:16px}
  .wf-map__tally>i{display:none}
  .wf-map__count b{font-size:24px}
  .wf-note{height:38px}
  .wf-note i{left:7px;top:6px;font-size:11px}
  .wf-proj,.wf-sketch,.wf-intake,.wf-map,.wf-sort,.wf-day30{padding-left:18px;padding-right:18px}
  .wf-proj>figcaption:not(.ex-sr-only),.wf-sketch>figcaption:not(.ex-sr-only),.wf-intake>figcaption:not(.ex-sr-only),.wf-map>figcaption:not(.ex-sr-only),.wf-sort>figcaption:not(.ex-sr-only),.wf-day30>figcaption:not(.ex-sr-only){margin-left:-18px;margin-right:-18px;padding-left:18px;padding-right:18px}
  .wf-note__facts li{font-size:11px;padding:4px 8px}
}

/* ============================================================ THE /agents PASS, 2026-09-23
   Bruno named Justin's /agents lander the design reference. Four things from it hold across this page:
   nothing rests at opacity 0 waiting to be revealed (pending things sit at .35 and brighten, which
   is also why every figure's pre-motion state above reads .35), the small drawings are software
   objects on a dotted drawing board with one quiet loop each, inline links read as links, and the
   person glyph is Justin's, filled head and white body, until he says otherwise. */
.wf-page.ex-js [data-ex-reveal]:not(.is-seen)>*{opacity:.35;transform:translateY(10px)}
@media(prefers-reduced-motion:no-preference){
  .wf-page.ex-js [data-ex-reveal].is-seen>*{animation:ag-rise .5s var(--ease) calc(var(--i,0) * .11s) both}
}
@keyframes ag-rise{from{opacity:.35;transform:translateY(10px)}to{opacity:1;transform:none}}
.wf-page :is(.ex-art,.ex-myth__art,.ex-rules__art,.ex-start__art){background:#fdfcf8 radial-gradient(rgba(0,0,0,.07) 1px,transparent 1.2px) 0 0/16px 16px}
.wf-page .ex-art{padding:12px 14px}
.wf-page :is(.ex-head .lead,.ex-myth p,.ex-rules__body p,.ex-start__steps p) a{color:var(--blue);font-weight:500;text-decoration:none}
.wf-page :is(.ex-head .lead,.ex-myth p,.ex-rules__body p,.ex-start__steps p) a:hover{color:var(--blue-deep);text-decoration:underline;text-underline-offset:4px}
/* THE SMALL DRAWINGS' QUIET LOOPS, from /agents' kit cards (2026-09-23): one loop per drawing, on
   its own clock, and only once its grid has been seen. Every element's base style is its finished
   frame, so reduced motion and no JavaScript both show the finished picture. Nothing here moves one
   object into another; the loops breathe, ride a wire, tick or swap a state in place. */
.wf-page [data-ex-reveal] :is(.k-dot,.k-pop,.k-tick,.k-breathe,.k-pulse,.k-prog){transform-box:fill-box;transform-origin:center}
.wf-page [data-ex-reveal] .k-prog{transform-origin:0 50%}
.wf-page [data-ex-reveal] .k-hand{transform-box:view-box}
.wf-page [data-ex-reveal] .k-ride{offset-rotate:0deg}
.wf-page [data-ex-reveal] .k-swap-b,.wf-page [data-ex-reveal] .k-ghost{opacity:1}
.wf-page [data-ex-reveal] .k-swap-a{opacity:0}
.wf-page [data-ex-reveal] .k-dim{opacity:.4}
.wf-page [data-ex-reveal] .k-sign{stroke-dasharray:1;stroke-dashoffset:0}
@media(prefers-reduced-motion:no-preference){
  .wf-page [data-ex-reveal].is-seen .k-dot{animation:k-dot 3.6s var(--ease) var(--d,0s) infinite}
  .wf-page [data-ex-reveal].is-seen .k-pop{animation:k-pop 5s var(--ease) var(--d,0s) infinite backwards}
  .wf-page [data-ex-reveal].is-seen .k-tick{animation:k-tick 3.6s var(--ease) var(--d,0s) infinite}
  .wf-page [data-ex-reveal].is-seen .k-breathe{animation:k-breathe 4.5s ease-in-out infinite}
  .wf-page [data-ex-reveal].is-seen .k-pulse{animation:k-dot 4s var(--ease) 1s infinite}
  .wf-page [data-ex-reveal].is-seen .k-prog{animation:k-prog 6.5s ease-in-out infinite alternate}
  .wf-page [data-ex-reveal].is-seen .k-ride{animation:k-ride var(--dur,4.5s) linear var(--d,0s) infinite}
  .wf-page [data-ex-reveal].is-seen .k-hand{animation:k-spin 9s linear infinite}
  .wf-page [data-ex-reveal].is-seen .k-march{animation:k-march 1s linear infinite}
  .wf-page [data-ex-reveal].is-seen .k-ghost{animation:k-ghost 5s ease-in-out infinite}
  .wf-page [data-ex-reveal].is-seen .k-swap-a{animation:k-swap-a 7s var(--ease) infinite}
  .wf-page [data-ex-reveal].is-seen .k-swap-b{animation:k-swap-b 7s var(--ease) infinite}
  .wf-page [data-ex-reveal].is-seen .k-flip{animation:k-flip 6s var(--ease) infinite}
  .wf-page [data-ex-reveal].is-seen .k-lift{animation:k-lift 4s ease-in-out infinite alternate}
  .wf-page [data-ex-reveal].is-seen .k-sign{animation:k-sign 6s var(--ease) infinite}
}
@keyframes k-dot{0%,22%,100%{transform:none}10%{transform:scale(1.22)}}
@keyframes k-pop{0%{transform:scale(.6);opacity:.35}9%,84%{transform:none;opacity:1}100%{transform:none;opacity:.35}}
@keyframes k-tick{0%,14%,30%,100%{transform:none}22%{transform:scale(1.25)}}
@keyframes k-breathe{0%,100%{transform:none}50%{transform:scale(1.07)}}
@keyframes k-prog{0%,15%{transform:scaleX(.3)}75%,100%{transform:none}}
@keyframes k-ride{0%{offset-distance:0%;opacity:0}10%,86%{opacity:1}100%{offset-distance:100%;opacity:0}}
@keyframes k-spin{to{transform:rotate(360deg)}}
/* One dash-and-gap pair per lap, so the loop has no seam. The pattern is 4 3, so the default is 7;
   components/workflow-first.js fits both the pattern and --march to each outline as drawn. */
@keyframes k-march{from{stroke-dashoffset:0}to{stroke-dashoffset:var(--march,-7px)}}
@keyframes k-ghost{0%,100%{opacity:1}50%{opacity:.35}}
@keyframes k-swap-a{0%,42%{opacity:1}50%,92%{opacity:0}100%{opacity:1}}
@keyframes k-swap-b{0%,42%{opacity:0}50%,92%{opacity:1}100%{opacity:0}}
@keyframes k-flip{0%,30%{opacity:0}38%,92%{opacity:1}100%{opacity:0}}
@keyframes k-lift{from{transform:none}to{transform:translateY(-4px)}}
@keyframes k-sign{0%,8%{stroke-dashoffset:1}40%,100%{stroke-dashoffset:0}}

/* STROKE WEIGHT IS MEASURED ON SCREEN (2026-09-23). A stroke of 1.5 in a 160-unit view box drawn
   540px wide is a 5px line; the same 1.5 in a 440-unit card drawn 330px wide is 1.1px. /agents
   draws its figures in HTML with 1.5px borders, so every line is the same weight at every size, and
   Bruno sent the first version of this pass back for exactly that difference. Every drawing this
   page generates therefore keeps its stroke in screen pixels: 1.5px for objects, 1.2px for chips,
   whatever width the slot renders at. The signature is the one exception, because it draws itself
   with pathLength, which needs user units; its width is set so it lands at 1.5px in its slot.
   Check with scripts/qa/stroke-probe.js, never by eye. */
.wf-page :is(.ex-art,.ex-myth__art,.ex-rules__art,.ex-start__art) svg :not(.k-sign),
.wf-page .wf-proj__thumb svg :not(.k-sign){vector-effect:non-scaling-stroke}


/* THE DOOR IN (2026-09-23). /agents gives one card a coloured offset shadow instead of the grey
   one: the card the client tries before committing. Bruno's call: it breaks the black-translucent
   rule, and it is worth using sometimes, for that one job. Here it is the last start step, the one
   an AI Jumpstart is for, so it is the only coloured shadow on the page. */
.wf-page .ex-start__steps li:nth-child(3){box-shadow:5px 5px 0 var(--green-bg),5px 5px 0 1.5px #000}

