/* PDF Cuter — Mosaic workspace. Ported from the signed-off design; logic in frontend/src/workspace/. */
/* Self-hosted fonts (latin subset, the weights the design uses): no third-party requests. */
@font-face{font-family:"Bricolage Grotesque";font-style:normal;font-display:swap;font-weight:200 800;src:url(/static/assets/bricolage-grotesque-latin-opsz-normal.woff2) format("woff2-variations"),url(/static/assets/bricolage-grotesque-latin-opsz-normal.woff2) format("woff2")}
@font-face{font-family:"DM Sans";font-style:normal;font-display:swap;font-weight:100 1000;src:url(/static/assets/dm-sans-latin-opsz-normal.woff2) format("woff2-variations"),url(/static/assets/dm-sans-latin-opsz-normal.woff2) format("woff2")}
@font-face{font-family:"DM Mono";font-style:normal;font-display:swap;font-weight:400;src:url(/static/assets/dm-mono-latin-400-normal.woff2) format("woff2")}
@font-face{font-family:"DM Mono";font-style:normal;font-display:swap;font-weight:500;src:url(/static/assets/dm-mono-latin-500-normal.woff2) format("woff2")}

body{margin:0;background:#FAFAF7}
html{-webkit-text-size-adjust:100%}
.app{--ground:#FAFAF7;--ink:#121212;--muted:#5F5F5A;--face:#2B2B29;--hair:rgba(18,18,18,.14);--mat:#ECEBE4;--paper:#FFFFFF;--accent:#FFD23F;--alert:#B3261E;--gap:14px;--spring:cubic-bezier(.2,1.4,.3,1);--settle:cubic-bezier(.16,1,.3,1);--gw:clamp(560px,calc(1.04 * (100vh - 260px) + 98px),776px);background:var(--ground);color:var(--ink);font-family:"DM Sans",system-ui,sans-serif;font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased;overflow-x:clip}
@supports (height:100svh){.app{--gw:clamp(560px,calc(1.04 * (100svh - 260px) + 98px),776px)}}
.app *,.app *::before,.app *::after{box-sizing:border-box}
.app h1,.app h2,.app h3,.app p{margin:0}
:where(.app) button{font:inherit;color:inherit}
.app :focus-visible{outline:3px solid var(--ink);outline-offset:3px}
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mono{font-family:"DM Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums}
.ic{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
kbd{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 5px;border-radius:6px;background:#fff;box-shadow:inset 0 0 0 1.5px var(--ink);font:500 12px/1 "DM Mono",monospace;color:var(--ink)}

/* ---------- header: its edges are the layout's edges ---------- */
.top{position:relative;z-index:50;display:flex;align-items:center;gap:28px;min-height:64px;padding:10px max(32px,calc((100% - var(--gw) - 460px) / 2));border-bottom:1px solid var(--ink);background:var(--ground)}
.brand{display:flex;align-items:center;gap:8px;font:800 20px/1 "Bricolage Grotesque",sans-serif;letter-spacing:-.015em;white-space:nowrap;cursor:default}
.mark{display:block;width:36px;height:31px;flex:none}
.mark svg{display:block;width:100%;height:100%;overflow:visible}
.mark rect{transform-box:fill-box;transform-origin:50% 50%;transition:transform 560ms var(--spring)}
.mark .mk-b{fill:#2858CD;transform:rotate(-11deg)}
.mark .mk-f{fill:#FFA28F;stroke:var(--ground);stroke-width:10;stroke-linejoin:round;transform:rotate(10deg)}
.brand:hover .mark .mk-b{transform:translate(-10px,3px) rotate(-16deg)}
.brand:hover .mark .mk-f{transform:translate(10px,-3px) rotate(15deg)}
.steps{flex:1;display:flex;justify-content:center;min-width:0}
.steps ol{display:flex;flex-wrap:wrap;align-items:center;row-gap:6px;list-style:none;margin:0;padding:0}
.step{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;color:var(--muted);white-space:nowrap}
.step + .step::before{content:"";display:block;width:28px;height:2px;margin:0 10px 0 2px;background:var(--hair);transition:background 500ms}
.step.done + .step::before{background:var(--ink)}
.shape{width:16px;height:16px;flex:none;overflow:visible}
.shape path{fill:transparent;stroke:currentColor;stroke-width:1.5;stroke-linejoin:round;transition:fill 400ms,stroke 400ms}
.step.done,.step.cur{color:var(--ink)}
.step.done .shape path{fill:var(--ink);stroke:var(--ink)}
.step.cur .shape path{fill:var(--ink);stroke:var(--ink)}
.step.cur{font-weight:600}
.step.cur .step-label{box-shadow:0 2px 0 var(--ink)}
.step.skip .step-label{text-decoration:line-through;text-decoration-thickness:1.5px}
.step-note{font:500 12px/1 "DM Mono",monospace;color:var(--muted);padding:3px 6px;border-radius:999px;box-shadow:inset 0 0 0 1.5px var(--hair)}
.tools{display:flex;align-items:center;gap:16px;margin-left:auto}
.details{position:relative}
.pill-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 14px;border:1.5px solid var(--ink);border-radius:999px;background:transparent;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;transition:background 200ms,transform 300ms var(--spring)}
.pill-btn:hover{background:var(--mat)}
.pill-btn:active{transform:translateY(1px)}
.pill-btn .ic{width:14px;height:14px;transition:transform 320ms var(--spring)}
.pill-btn[aria-expanded="true"] .ic{transform:rotate(180deg)}
.details .pop{position:absolute;right:0;top:44px;width:390px;max-width:calc(100vw - 24px);padding:18px;background:#fff;border-radius:16px;box-shadow:0 0 0 1px var(--hair),0 24px 48px -28px rgba(18,18,18,.35);animation:popIn 380ms var(--spring) both;transform-origin:85% 0}
.pop dl{display:grid;grid-template-columns:104px minmax(0,1fr);gap:12px 14px;margin:0}
.pop dt{font:500 12px/1.5 "DM Mono",monospace;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.pop dd{margin:0;font-size:14px;line-height:1.4}
.pop dd span{display:block;font:500 12px/1.5 "DM Mono",monospace;color:var(--muted)}
.conn{display:inline-flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);white-space:nowrap}
.conn i{width:8px;height:8px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--ink);animation:breathe 2.4s ease-in-out infinite}

/* ---------- layout: the composition centres on the grid ---------- */
.layout{display:grid;grid-template-columns:min(var(--gw),calc(100% - 370px)) minmax(330px,420px);justify-content:center;gap:40px;max-width:calc(var(--gw) + 524px);margin:0 auto;padding:22px 32px 48px;align-items:start}
.stage{position:relative;min-width:0}
/* the stage head never reflows: fixed rows, every line single and clipped */
.stage-head{display:grid;grid-template-columns:fit-content(max(52%,calc(100% - 320px))) minmax(0,1fr);grid-template-rows:28px 24px;align-items:center;column-gap:16px;row-gap:4px;max-width:var(--gw);height:56px;margin:0 0 10px;padding:0}
/* review: the readout (≤ 42 chars, 302px of 12px mono) keeps its 320px at every stage width; a narrow stage ellipsizes the filename instead (its title attribute keeps it whole) */
.layout.s-review .stage-head{grid-template-columns:fit-content(max(0%,calc(100% - 320px))) minmax(0,1fr)}
.sh-row{display:flex;align-items:center;gap:12px;min-width:0}
.sh-title{min-width:0;font:700 20px/1.2 "Bricolage Grotesque",sans-serif;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sh-title.file{font:500 14px/1.2 "DM Mono",monospace;letter-spacing:0}
.sh-sub{grid-column:1 / -1;display:flex;align-items:center;min-width:0;height:24px;overflow:hidden;white-space:nowrap;font:500 12px/1.4 "DM Mono",monospace;color:var(--muted)}
.sh-sub > span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.readout{justify-self:end;min-width:0;max-width:100%;font:500 12px/1.4 "DM Mono",monospace;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.readout.uA{animation:tickUpA 360ms var(--spring)}
.readout.uB{animation:tickUpB 360ms var(--spring)}
.readout.dA{animation:tickDnA 360ms var(--spring)}
.readout.dB{animation:tickDnB 360ms var(--spring)}
.keys{display:flex;flex-wrap:nowrap;align-items:center;gap:14px;color:var(--ink)}
.keys > span{display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
.confirm{display:inline-flex;flex-wrap:nowrap;align-items:center;gap:10px;font:600 12px/1.3 "DM Sans",sans-serif;color:var(--ink)}
.cbtn{height:32px;padding:0 13px;border-radius:999px;border:1.5px solid var(--ink);background:#fff;font:600 12px/1 "DM Sans",sans-serif;cursor:pointer;transition:background 200ms,transform 300ms var(--spring)}
.sh-sub .cbtn{height:24px;padding:0 11px}
.cbtn:hover{background:var(--mat)}
.cbtn:active{transform:scale(.95)}
.cbtn.go{background:var(--ink);color:#fff}
.cbtn.go:hover{background:var(--face)}
.grid-wrap{position:relative;max-width:var(--gw);margin:0}
.grid{position:relative;display:grid;grid-template-columns:repeat(var(--cols,8),minmax(0,1fr));gap:var(--gap);padding:12px 0;user-select:none;-webkit-user-select:none}
.grid:focus-visible{outline:none}
.grid.review{touch-action:pan-y}
.grid.painting,.grid.painting .tile{cursor:crosshair}
.grid.painting .seam{pointer-events:none}
.grid.dragb,.grid.dragb .tile,.grid.dragb .seam{cursor:grabbing}
.grid.dragb.dragp .spill{opacity:0}
/* the grabbed Join pill turns into the split you carry */
.grid.dragb .seam.hot.join .spill{background:var(--ink);color:#fff;box-shadow:0 6px 0 -1px rgba(18,18,18,.22)}

/* ---------- cells ---------- */
.cell{--cb:var(--c,var(--mat));position:relative;aspect-ratio:.78;transition:opacity 280ms var(--settle),transform 460ms var(--spring)}
.cell.dim{opacity:.3}
.cell.lift{transform:translateY(-6px);z-index:2}
.tile{position:absolute;inset:0;display:block;width:100%;padding:0;margin:0;border:0;background:transparent;border-radius:6px;cursor:pointer;perspective:800px;z-index:1;transform:translateX(var(--nx,0px));transition:transform 380ms var(--spring),opacity 160ms,filter 520ms var(--settle) var(--fd,0ms)}
.grid:not(.review):not(.upl) .tile{cursor:default}
.cell.away .tile{opacity:.1}
.cell.pend .tile{filter:saturate(.1) opacity(.5)}
.cell.dA .tile{animation:detA 240ms var(--spring)}
.cell.dB .tile{animation:detB 240ms var(--spring)}
.tile > .flip{position:absolute;inset:0;display:block;transform-style:preserve-3d;transition:transform 760ms var(--spring) var(--d,0ms)}
.cell.read .flip{transform:rotateY(180deg)}
.face{position:absolute;inset:0;display:block;border-radius:6px;backface-visibility:hidden;-webkit-backface-visibility:hidden}
.front{transform:rotateY(180deg)}

/* back face: the idle toy (rendered only before the pages are read) */
.shell{position:absolute;inset:0;display:block;transform:translate(calc(var(--lx,0) * 1px),calc(var(--ly,0) * 1px)) scale(calc(1 + var(--w,0) * .1));transition:transform 680ms var(--spring) var(--rd,0ms)}
.edge{position:absolute;inset:0;display:block;border:1.5px solid var(--ink);border-radius:6px;opacity:calc(.28 + var(--w,0) * .72);transition:opacity 460ms var(--settle) var(--rd,0ms)}
.cell.idle .edge{animation:breathe 6s ease-in-out infinite;animation-delay:calc(var(--diag) * -300ms)}
.tint{position:absolute;inset:3px;display:block;border-radius:6px;background:var(--pal);opacity:calc(var(--w,0) * var(--w,0));transform:scale(calc(.35 + var(--w,0) * .65));transition:opacity calc(220ms + (1 - var(--w,0)) * 1100ms) var(--settle) var(--rd,0ms),transform 520ms var(--spring) var(--rd,0ms)}
.grid.dragging .tint{opacity:1;transform:scale(1);transition:opacity 260ms var(--settle) var(--rd,0ms),transform 520ms var(--spring) var(--rd,0ms)}
.grid.dragging .edge{opacity:1}
/* a dropped file drains the colour back into itself, radiating from the drop point */
.layout.s-consent .tint{opacity:0;transform:scale(.2);transition:opacity 380ms var(--settle) var(--rd,0ms),transform 420ms cubic-bezier(.5,0,.75,0) var(--rd,0ms)}
.ghost{position:absolute;left:8%;right:8%;top:6%;bottom:17%;display:block;opacity:calc(.11 + var(--w,0) * .28);transition:opacity 600ms var(--settle) var(--rd,0ms)}
.pulse{position:absolute;inset:0;display:block;border-radius:6px;border:1.5px solid var(--ink);opacity:0;pointer-events:none}
.cell.pA .pulse{animation:pingA 780ms var(--settle) var(--pd,0ms) both}
.cell.pB .pulse{animation:pingB 780ms var(--settle) var(--pd,0ms) both}
.bno{position:absolute;inset:0;display:grid;place-items:center;font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted);animation:deal 520ms var(--spring) both;animation-delay:calc(var(--i) * 14ms)}
/* the page numbers deal in once the drained colour has gone */
.layout.s-consent .bno{animation-delay:calc(var(--i) * 14ms + 320ms)}
.cell.fly .edge{opacity:.6;animation:none}
.cell.wait .edge{border-style:dashed;opacity:.4;animation:none}
.grid.queued .cell.wait .edge{animation:qsweep 1.6s ease-in-out infinite;animation-delay:calc(var(--diag) * 70ms)}
.scanbox{position:absolute;left:8px;right:8px;top:10%;bottom:14%;display:block;overflow:hidden;opacity:.35}
/* pages waiting to be read sweep in unison */
.scan{position:absolute;left:0;right:0;top:0;height:100%;display:block;border-top:1.5px solid var(--ink);animation:scan 2.6s cubic-bezier(.45,0,.55,1) infinite}

/* page faces: one svg, five paths */
.pf{position:absolute;inset:0;display:block;width:100%;height:100%;overflow:visible}
.pf .l{fill:#D7D5CC}
.pf .t{fill:var(--face)}
.pf .r{fill:var(--face);opacity:.65}
.pf .b{fill:#F4F3EE;stroke:#D7D5CC;stroke-width:1px;vector-effect:non-scaling-stroke}
.pf .h{fill:#E4E2D9}
.ghost .pf path{fill:var(--ink);opacity:1}
.ghost .pf .b{fill:none;stroke:var(--ink)}

/* front face: the page on its colour mat */
.mat{position:absolute;inset:0;display:block;border-radius:6px;background:var(--pc,var(--mat));overflow:hidden}
.flood{position:absolute;left:var(--fox,0%);top:var(--foy,50%);width:340%;aspect-ratio:1;display:block;border-radius:50%;background:var(--c,var(--mat));transform:translate(-50%,-50%)}
.cell.g1 .flood{animation:floodA 620ms var(--settle) var(--fd,0ms) both}
.cell.g2 .flood{animation:floodB 620ms var(--settle) var(--fd,0ms) both}
/* ghost bloom: a hot seam paints its consequence on the rims, radiating from the seam */
.gc{position:absolute;inset:0;display:block;background:var(--pv,transparent);opacity:0;transition:opacity 160ms linear}
.cell.pv .gc{opacity:.7;transition:opacity 280ms var(--settle) var(--pvd,0ms)}
.paper{position:absolute;left:8%;right:8%;top:6%;bottom:17%;display:block;background:var(--paper);border-radius:2px;box-shadow:0 0 0 1px rgba(18,18,18,.1),0 2px 0 rgba(18,18,18,.08);overflow:hidden;transition:transform 240ms var(--settle),box-shadow 240ms var(--settle)}
.cell.g1 .paper{animation:bumpA 600ms var(--spring) calc(var(--fd,0ms) + 40ms)}
.cell.g2 .paper{animation:bumpB 600ms var(--spring) calc(var(--fd,0ms) + 40ms)}
/* hover: the page lifts off its mat — reads on every colour */
.grid.review .cell:not(.dim) .tile:hover .paper{transform:translateY(-3px);box-shadow:0 0 0 1px rgba(18,18,18,.14),0 5px 0 rgba(18,18,18,.16)}
.sig{position:absolute;width:34%;height:auto;overflow:visible}
.sig path{fill:none;stroke:var(--face);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.sheen{position:absolute;inset:0;z-index:2;display:block;overflow:hidden;border-radius:6px;pointer-events:none}
.sheen::before,.sheen::after{content:"";position:absolute;top:-20%;bottom:-20%;left:0;width:34%;background:rgba(18,18,18,.08);opacity:0;transform:translateX(-120%) skewX(-18deg)}
.cell.wrun .sheen::before{animation:sheen 1.4s var(--settle) infinite;animation-delay:calc(var(--i) * 18ms)}
.cell.wrun2 .sheen::after{animation:sheen 1.4s var(--settle) infinite;animation-delay:calc(var(--i) * 18ms + 700ms)}
/* page numbers live on the paper's corner, only where the pointer or the cursor is */
/* the row's first page number sits in the margin, outside the tiles: 1, 9, 17 … (phones 1, 7, 13 …) */
.rno{position:absolute;right:calc(100% + 12px);top:0;font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted);white-space:nowrap;pointer-events:none}
.grid.packing .rno{visibility:hidden}
.pno{position:absolute;right:12%;top:8%;z-index:2;padding:2px 3px;border-radius:2px;background:var(--paper);font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--ink);opacity:0;pointer-events:none;transition:opacity 160ms linear,transform 240ms var(--settle)}
.grid.review .tile:hover .pno,.cell.cu .pno{opacity:1}
/* the number tab is part of the paper: it lifts with it */
.grid.review .cell:not(.dim) .tile:hover .pno{transform:translateY(-3px)}
.stamp{position:absolute;left:-8px;top:-9px;z-index:4;min-width:36px;height:32px;padding:0 6px;display:grid;place-items:center;border-radius:6px;background:var(--c);color:var(--tk);font:800 20px/1 "Bricolage Grotesque",sans-serif;letter-spacing:-.01em;font-variant-numeric:tabular-nums;box-shadow:0 0 0 1.5px var(--ink)}
.stamp b,.stamp::before{grid-area:1 / 1;display:block;font:inherit}
.cell.g1 .stamp{animation:stampA 480ms var(--fd,0ms) both}
.cell.g2 .stamp{animation:stampB 480ms var(--fd,0ms) both}
.cell.rA .stamp b{animation:renumA 300ms var(--settle) var(--rnd,0ms) both}
.cell.rB .stamp b{animation:renumB 300ms var(--settle) var(--rnd,0ms) both}
/* a number learned late: the dash holds its place until the number drops in */
.cell.rA .stamp.wk::before,.cell.rB .stamp.wk::before{content:"–";animation:dashOut 160ms linear var(--rnd,0ms) both}
/* a join swallows the absorbed stamp */
.cell .stamp.out{background:var(--pc);animation:stampOut 240ms cubic-bezier(.5,0,.75,0) both}
/* the island's name: its first text line, written across its tiles in the bottom band */
.isl{position:absolute;left:8px;bottom:calc(8.5% - 6px);z-index:3;max-width:calc(var(--ls,1) * (100% + var(--gap)) - 22px);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font:600 12px/1 "DM Sans",sans-serif;color:var(--tk,var(--muted));pointer-events:none;transform:translateX(var(--nx,0px));animation:islIn 420ms var(--settle) var(--fd,0ms) backwards;transition:color 200ms linear calc(var(--fd,0ms) + 160ms),opacity 200ms linear,transform 380ms var(--spring)}
.cell.away .isl,.cell.dim .isl{opacity:.1}
/* page 1's name waits for its page to turn over */
.cell.read:not(.g1):not(.g2) .isl{animation-delay:calc(var(--d) + 520ms)}
.tile .cur{position:absolute;inset:-4px;z-index:3;border:3px solid var(--ink);border-radius:10px;pointer-events:none;animation:curIn 360ms var(--spring) both}
.grid:not(:focus-visible) .cur:not(.sel){opacity:0}

/* seams: the magnetic split / join pill, and the one mark each decision leaves */
.seam{position:absolute;top:24px;bottom:0;left:calc(var(--gap) * -1 - 5px);width:calc(var(--gap) + 10px);z-index:6;display:block;cursor:pointer;touch-action:pan-y}
.seam.tail{left:auto;right:calc(var(--gap) * -1 - 5px)}
.seam.join{cursor:grab}
.seam-line{position:absolute;left:50%;top:7%;bottom:7%;width:0;border-left:1.5px dashed var(--ink);transform:translateX(-.75px) scaleY(var(--sl,0));transition:transform 380ms var(--spring)}
.seam.join .seam-line{border-left-style:solid;border-left-width:3px;transform:translateX(-1.5px) scaleY(var(--sl,0))}
/* AI split, not yet checked: a perforation — bare gap, dashed line */
.seam.aj:not(.near) .seam-line{border-left-style:dashed;border-left-width:1.5px;transform:translateX(-.75px) scaleY(var(--sl,0))}
/* AI no split, not yet checked: the zipper teeth carry it — no line */
.seam.aj.nos:not(.near) .seam-line{opacity:0}
.spill{position:absolute;left:50%;top:calc(50% - 12px);z-index:2;display:inline-flex;align-items:center;gap:5px;height:32px;padding:0 13px 0 10px;border-radius:999px;background:var(--ink);color:#fff;font:600 12px/1 "DM Sans",sans-serif;white-space:nowrap;pointer-events:none;opacity:var(--po,0);transform:translate(-50%,-50%) translate(var(--px,0px),var(--py,0px)) scale(var(--ps,0));transition:transform 320ms var(--spring),opacity 140ms linear;box-shadow:0 4px 0 -1px rgba(18,18,18,.22);animation:pillIn 260ms var(--spring)}
.seam.hot .spill{pointer-events:auto}
.seam.hot:active .spill{transform:translate(-50%,-50%) translate(var(--px,0px),var(--py,0px)) scale(.88);transition-duration:110ms}
.seam.join .spill{background:#fff;color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink),0 4px 0 -1px rgba(18,18,18,.22)}
.spill .ic{width:14px;height:14px;stroke-width:2.2}
.spill .ev{position:absolute;left:50%;top:calc(100% + 6px);height:20px;padding:0 7px;display:inline-flex;align-items:center;border-radius:999px;background:var(--ground);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink);font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;white-space:nowrap;pointer-events:none;transform:translateX(-50%)}
/* the flag: ink diamond + the AI's score, the only yellow on the grid */
.ajar{position:absolute;left:50%;top:calc(50% - 12px);z-index:1;height:24px;padding:0 7px 0 6px;display:inline-flex;align-items:center;gap:5px;border-radius:999px;background:var(--accent);color:var(--ink);box-shadow:0 0 0 1.5px var(--ink);font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;white-space:nowrap;pointer-events:none;transform:translate(-50%,-50%);animation:ajarIn 480ms var(--spring) var(--fgd,240ms) both,ajarBreath 6s ease-in-out calc(var(--fgd,240ms) + 480ms) infinite}
.ajar i{width:7px;height:7px;flex:none;background:var(--ink);transform:rotate(45deg)}
.ajar .ic{width:12px;height:12px;stroke-width:2.8}
.ajar.done{animation:ajarDone 640ms var(--spring) both}
/* after a decision: checked (ground ✓) or changed by you (ink ✎), at the seam mid-point */
.smark{position:absolute;left:50%;top:calc(50% - 12px);width:16px;height:16px;border-radius:50%;display:grid;place-items:center;pointer-events:none;transform:translate(-50%,-50%);animation:smarkIn 420ms var(--spring) both}
.smark .ic{width:10px;height:10px;stroke-width:2.6}
.smark.ok{background:var(--ground);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink)}
.smark.you{background:var(--ink);color:#fff;box-shadow:0 0 0 1.5px var(--ground)}
.smark.you .ic{width:9px;height:9px;stroke-width:2.4}
.seam.near .ajar,.seam.near .smark{visibility:hidden}
/* a seam at the start of a row keeps its mark inside the grid */
.cell.rs > .seam .ajar{left:calc(100% + 22px)}
.cell.rs > .seam .smark{left:calc(100% + 6px)}
.bridge{position:absolute;top:0;bottom:0;left:100%;width:var(--gap);display:block;background:var(--cb);transform:scaleX(0);transform-origin:0 50%;transition:transform 160ms cubic-bezier(.5,0,.75,0),background-color 160ms linear calc(var(--bd,0ms) + 60ms);pointer-events:none}
.bridge.on{transform:none;transition:transform 220ms var(--settle) calc(var(--bd,0ms) + 90ms),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
/* open zipper: AI said "no split", nobody has checked it yet — two rows of teeth, offset so they interlock */
.cell.ajr .bridge.on{left:calc(100% - 2px);width:calc(var(--gap) + 4px);background:repeating-linear-gradient(180deg,var(--cb) 0 5px,transparent 5px 9px) 0 0 / 50% 100% no-repeat,repeating-linear-gradient(180deg,transparent 0 4px,var(--cb) 4px 9px) 100% 0 / 50% 100% no-repeat}
/* Keep: the teeth close into a solid bridge, top to bottom */
.cell.zc .bridge.on{left:calc(100% - 2px);width:calc(var(--gap) + 4px);background:linear-gradient(var(--cb),var(--cb)) 0 0 / 100% 100% no-repeat,repeating-linear-gradient(180deg,var(--cb) 0 5px,transparent 5px 9px) 0 0 / 50% 100% no-repeat,repeating-linear-gradient(180deg,transparent 0 4px,var(--cb) 4px 9px) 100% 0 / 50% 100% no-repeat;animation:zipFill 420ms var(--settle) both}
.cell.ed .bridge{display:none}
.vbridge{position:absolute;left:0;right:0;top:100%;height:var(--gap);display:block;background:var(--cb);transform:scaleY(0);transform-origin:50% 0;transition:transform 160ms cubic-bezier(.5,0,.75,0),background-color 160ms linear calc(var(--bd,0ms) + 60ms);pointer-events:none}
.cell.vd .vbridge{transform:none;transition:transform 240ms var(--settle) calc(var(--bd,0ms) + 120ms),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
.corner{position:absolute;left:100%;top:100%;width:var(--gap);height:var(--gap);display:block;background:var(--cb);transform:scale(0);transform-origin:0 0;transition:transform 160ms cubic-bezier(.5,0,.75,0),background-color 160ms linear calc(var(--bd,0ms) + 60ms);pointer-events:none}
.cell.kd .corner{transform:none;transition:transform 240ms var(--settle) calc(var(--bd,0ms) + 170ms),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
/* the ghost bloom paints the bridges too: the preview is the whole island it would become */
.bridge::after,.vbridge::after,.corner::after{content:"";position:absolute;inset:0;background:var(--pv,transparent);opacity:0;transition:opacity 160ms linear}
.cell.pv .bridge::after,.cell.pv .vbridge::after,.cell.pv .corner::after{opacity:.7;transition:opacity 280ms var(--settle) var(--pvd,0ms)}
.cell.ajr .bridge::after{display:none}
/* on commit the preview holds until the real flood has covered it, then lets go — never a frame of the old colour */
.cell.ghA .gc,.cell.ghA .bridge::after,.cell.ghA .vbridge::after,.cell.ghA .corner::after{opacity:.7;animation:ghOutA 200ms linear calc(var(--fd,0ms) + 240ms) forwards}
.cell.ghB .gc,.cell.ghB .bridge::after,.cell.ghB .vbridge::after,.cell.ghB .corner::after{opacity:.7;animation:ghOutB 200ms linear calc(var(--fd,0ms) + 240ms) forwards}
.cutflash{position:absolute;left:calc(var(--gap) / -2 - 1.5px);top:-6px;bottom:-6px;z-index:6;width:3px;border-radius:2px;background:var(--ink);transform-origin:50% 0;pointer-events:none;animation:blade 420ms cubic-bezier(.3,0,.2,1) both}
.crack{position:absolute;left:calc(var(--gap) / -2);top:0;bottom:0;z-index:7;width:0;pointer-events:none}
.crack b{position:absolute;left:-1.5px;top:-6px;bottom:-6px;width:3px;border-radius:2px;background:var(--ink);transform-origin:50% 0;animation:blade 420ms cubic-bezier(.3,0,.2,1) both}
.crack.join b{left:-7px;top:0;bottom:0;width:14px;border-radius:2px;background:var(--cb);animation:zip 360ms var(--settle) both}
.grid.packing .tile{transform:translate(var(--gx,0px),var(--gy,0px)) scale(.4);opacity:0;transition:transform 420ms cubic-bezier(.5,0,.2,1) var(--kd,0ms),opacity 260ms linear calc(var(--kd,0ms) + 160ms)}
.grid.packing .cell.st .tile{transform:none;opacity:1}
.grid.packing .cur,.grid.packing .smark,.grid.packing .ajar,.grid.packing .isl{visibility:hidden}
.grid.packing .bridge,.grid.packing .vbridge,.grid.packing .corner,.grid.packing .seam{opacity:0;transition:opacity 200ms}

/* pointer tag, the split you carry, toast */
.ptag{position:absolute;left:0;top:0;z-index:9;display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 9px;border-radius:6px;background:var(--ink);color:#fff;font:500 12px/1 "DM Mono",monospace;white-space:nowrap;pointer-events:none;transform:translate(calc(var(--tx,0) * 1px + 16px),calc(var(--ty,0) * 1px + 18px));transition:transform 180ms var(--settle)}
.ptag i{width:9px;height:9px;border-radius:2px;background:var(--tc);box-shadow:0 0 0 1px #fff}
.dragpill{position:absolute;left:0;top:0;z-index:9;display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 13px 0 10px;border-radius:999px;background:var(--ink);color:#fff;box-shadow:0 6px 0 -1px rgba(18,18,18,.22);font:600 12px/1 "DM Sans",sans-serif;white-space:nowrap;pointer-events:none;transform:translate(calc(var(--dx,0) * 1px),calc(var(--dy,0) * 1px)) translate(-50%,-50%);transition:transform 240ms var(--spring)}
.dragpill .ic{width:14px;height:14px;stroke-width:2.2}
.dragpill .mono{font-weight:500;opacity:.8}
.dragpill.rel{animation:dpRel 310ms linear both}
.toast-dock{position:absolute;left:0;top:0;z-index:45;width:100%;max-width:var(--gw);height:56px;display:flex;align-items:center;justify-content:flex-end;pointer-events:none}
.toast{pointer-events:auto;display:inline-flex;align-items:center;gap:12px;max-width:min(100%,440px,56%);min-height:40px;padding:4px 4px 4px 16px;border-radius:22px;background:var(--ink);color:#fff;font-size:14px;line-height:1.25}
.toast.bare{padding:8px 16px}
.toast span{min-width:0;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.toast.tA{animation:toastA 460ms var(--spring) both}
.toast.tB{animation:toastB 460ms var(--spring) both}
.toast.out{animation:toastOut 200ms ease-in both}
.toast button{flex:none;height:32px;padding:0 14px;border-radius:999px;border:0;background:#fff;color:var(--ink);font-weight:600;cursor:pointer;white-space:nowrap;transition:transform 300ms var(--spring)}
.toast button:active{transform:scale(.94)}
.toast :focus-visible{outline-color:#fff}

/* ---------- inspect card: sized from the stage; one column when the text would be cramped ---------- */
.scrim{position:absolute;inset:-10px;z-index:30;border-radius:16px;background:rgba(250,250,247,.64);animation:fadeIn 220ms var(--settle) both}
.scrim.out{animation:fadeOut 200ms var(--settle) both}
.insp{position:absolute;z-index:31;left:var(--cl);top:var(--ct);width:var(--cw);transform-origin:calc(20px + var(--ox)) 20px;animation:zoomIn 360ms var(--settle) both;outline:none}
.insp.out{animation:zoomOut 200ms cubic-bezier(.55,0,.8,.2) both}
.insp:focus-visible .insp-bg,.insp.narrow.tall:focus-visible{box-shadow:0 0 0 3px var(--ink),0 24px 48px -28px rgba(18,18,18,.35)}
.insp.tall .insp-info{max-height:calc(var(--mh,calc(100vh - 24px)) - 64px);overflow:auto;padding-right:4px}
.insp.narrow.tall{max-height:var(--mh,calc(100vh - 24px));overflow:auto;border-radius:16px;background:#fff;box-shadow:0 0 0 1px var(--hair),0 24px 48px -28px rgba(18,18,18,.35)}
.insp.narrow.tall .insp-info{max-height:none;overflow:visible}
.insp.narrow.tall .insp-bg{display:none}
.insp-bg{position:absolute;inset:0;border-radius:16px;background:#fff;box-shadow:0 0 0 1px var(--hair),0 24px 48px -28px rgba(18,18,18,.35);animation:fadeIn 300ms var(--settle) 40ms both}
.insp.out .insp-bg{animation:fadeOut 160ms both}
.insp-body{position:relative;display:grid;grid-template-columns:auto minmax(0,1fr);gap:24px;padding:20px}
.insp.narrow .insp-body{grid-template-columns:minmax(0,1fr);gap:18px}
.pcol{display:flex;flex-direction:column;align-items:center;align-self:start;gap:14px}
.insp.narrow .pcol{justify-self:center}
.pair{display:flex;align-items:center;width:calc(var(--prevW) + var(--seamW) + var(--faceW))}
.pface{position:relative;flex:none;width:var(--prevW);aspect-ratio:.78;opacity:.6;animation:fadeIn 360ms var(--settle) 120ms both}
.pface.none{display:grid;place-items:center;padding:8px;border-radius:6px;box-shadow:inset 0 0 0 1.5px var(--hair);text-align:center;font:500 12px/1.4 "DM Mono",monospace;color:var(--muted);opacity:1}
.insp.out .pface{animation:fadeOut 160ms both}
.pseam{position:relative;z-index:2;flex:none;width:var(--seamW);align-self:stretch;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;animation:fadeIn 360ms var(--settle) 160ms both}
.insp.out .pseam{animation:fadeOut 160ms both}
/* the card's seam is the grid's seam, magnified: the flag lives here too */
.pseam .ajar{position:relative;left:auto;top:auto;transform:none;animation:none}
.bpill{display:inline-flex;align-items:center;gap:6px;height:48px;padding:0 14px 0 11px;border-radius:999px;border:0;background:var(--ink);color:#fff;font:600 12px/1 "DM Sans",sans-serif;white-space:nowrap;cursor:pointer;box-shadow:0 4px 0 -1px rgba(18,18,18,.22);transition:transform 380ms var(--spring)}
.bpill .ic{width:14px;height:14px}
.bpill:hover{transform:scale(1.06)}
.bpill:active{transform:scale(.92);transition-duration:110ms}
.bpill.join{background:#fff;color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink),0 4px 0 -1px rgba(18,18,18,.22)}
.insp-face{position:relative;flex:none;width:var(--faceW);aspect-ratio:.78}
.insp-face .stamp{left:-10px;top:-12px;height:44px;min-width:56px;font-size:28px}
.insp-face .pno,.pface .pno{opacity:1}
.pnav{display:flex;align-items:center;justify-content:center;gap:12px;font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted)}
.insp-info{min-width:0;display:flex;flex-direction:column;gap:14px;animation:infoIn 400ms var(--settle) 120ms both}
.insp.out .insp-info{animation:fadeOut 160ms both}
.ihead{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.ih-txt{min-width:0}
.ititle{margin-top:4px;font:800 28px/1.05 "Bricolage Grotesque",sans-serif;letter-spacing:-.02em}
.eyebrow{font:500 12px/1.3 "DM Mono",monospace;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.xbtn,.nav-btn{flex:none;width:32px;height:32px;border-radius:50%;border:1.5px solid var(--ink);background:#fff;display:grid;place-items:center;cursor:pointer;transition:background 200ms,transform 320ms var(--spring)}
.nav-btn{width:32px;height:32px}
.nav-btn .ic{width:16px;height:16px}
.xbtn:hover{background:var(--mat);transform:rotate(90deg)}
.nav-btn:hover{background:var(--mat)}
.nav-btn:active{transform:scale(.92)}
.nav-btn:disabled,.nav-btn[aria-disabled="true"]{opacity:.35;cursor:not-allowed;background:#fff;transform:none}
/* evidence first: how the page before ends, how this one starts */
.seamtext{display:grid;gap:4px;margin:-4px 0 0}
.seamtext div{display:grid;grid-template-columns:76px minmax(0,1fr);gap:8px;align-items:baseline}
.seamtext dt{font:500 12px/1.4 "DM Mono",monospace;color:var(--muted)}
.seamtext dd{margin:0;font:400 14px/1.4 "DM Sans",sans-serif;color:var(--ink);overflow-wrap:anywhere}
.dec{display:grid;gap:10px;padding:14px;border-radius:16px;background:var(--ground);box-shadow:inset 0 0 0 1.5px var(--hair)}
.dec-k{font:500 12px/1.2 "DM Mono",monospace;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.dec-v{font:700 20px/1.2 "Bricolage Grotesque",sans-serif;letter-spacing:-.01em}
.state{display:inline-flex;align-items:center;gap:6px;justify-self:start;min-height:24px;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:600}
.state .ic{width:12px;height:12px}
.state.ok{box-shadow:inset 0 0 0 1.5px var(--ink)}
.state.you{background:var(--ink);color:#fff}
/* two answers, equal weight: confidence is a hint, not a vote */
.decide{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}
.insp.narrow .decide{grid-template-columns:1fr 1fr}
.dbtn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:0;height:48px;padding:0 16px 0 12px;border-radius:999px;border:1.5px solid var(--ink);background:#fff;color:var(--ink);font:600 14px/1 "DM Sans",sans-serif;white-space:nowrap;cursor:pointer;transition:background 200ms,color 200ms,transform 300ms var(--spring)}
.dbtn .ic{width:16px;height:16px}
.dbtn:hover{background:var(--ink);color:#fff}
.dbtn:active{transform:scale(.95)}
.note{font-size:12px;line-height:1.5;color:var(--muted)}
.note b{font-weight:600;color:var(--ink)}
.ptext{margin:6px 0 0;padding:12px 14px;border-radius:6px;background:var(--mat);font:400 12px/1.6 "DM Mono",monospace;white-space:pre-wrap;overflow-wrap:anywhere;max-height:88px;overflow:auto}
.ptext-none{margin-top:6px;padding:12px 14px;border-radius:6px;box-shadow:inset 0 0 0 1.5px var(--hair);font-size:12px;color:var(--muted)}

/* ---------- buttons: the hard butter shadow belongs to the one primary action ---------- */
.btn{--mx:0px;--my:0px;--pr:0px;position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 22px;border-radius:999px;border:1.5px solid var(--ink);background:var(--ink);color:#fff;font:600 16px/1 "DM Sans",sans-serif;cursor:pointer;white-space:nowrap;box-shadow:4px 4px 0 0 var(--accent);transform:translate(calc(var(--mx) + var(--pr)),calc(var(--my) + var(--pr)));transition:transform 380ms var(--spring),box-shadow 420ms var(--spring),background 200ms,color 200ms}
.btn:hover{background:var(--face)}
.btn:active{--pr:3px;box-shadow:1px 1px 0 0 var(--accent);transition-duration:90ms}
/* decisions still waiting: the primary holds back (no butter, no lean) */
.btn.wait{background:transparent;color:var(--ink);box-shadow:4px 4px 0 0 transparent}
.btn.wait:hover{background:var(--mat)}
.btn.wait:active{box-shadow:1px 1px 0 0 transparent}
.btn:focus-visible{outline:3px solid var(--ink);outline-offset:4px}
label.btn:has(input:focus-visible){outline:3px solid var(--ink);outline-offset:4px}
.btn:disabled,.btn[aria-disabled="true"]{background:#DAD9D1;color:var(--muted);border-color:#AFAEA5;box-shadow:none;cursor:not-allowed;transform:none}
.btn[aria-disabled="true"]:active{--pr:0px;box-shadow:none}
.btn.wide{width:100%}
.btn2{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 18px;border-radius:999px;border:1.5px solid var(--ink);background:transparent;color:var(--ink);font:600 14px/1 "DM Sans",sans-serif;cursor:pointer;white-space:nowrap;transition:background 200ms,transform 300ms var(--spring)}
.btn2:hover{background:var(--mat)}
.btn2:active{transform:translateY(2px)}
.btn2:disabled,.btn2[aria-disabled="true"]{opacity:.4;cursor:not-allowed;background:transparent;transform:none}
.btn2 .ic{width:16px;height:16px}
.btn2.icon{flex:none;min-width:48px;padding:0 14px}
.tbtn{border:0;background:none;padding:6px 2px;font:600 14px/1.2 "DM Sans",sans-serif;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1.5px;cursor:pointer;color:var(--ink)}
.tbtn:hover{text-decoration-thickness:3px}
.tbtn.sm{padding:2px 0;font-size:12px}

/* ---------- side panels ---------- */
.side{position:sticky;top:20px;display:flex;flex-direction:column;gap:20px;min-width:0}
.panel{display:flex;flex-direction:column;gap:16px;animation:panelIn 520ms var(--settle) both}
.h1{font:800 44px/1.02 "Bricolage Grotesque",sans-serif;letter-spacing:-.03em}
.h2{font:800 28px/1.08 "Bricolage Grotesque",sans-serif;letter-spacing:-.02em}
.lede{font-size:16px;line-height:1.5;color:var(--ink);max-width:42ch}
.small{font-size:12px;line-height:1.5;color:var(--muted)}
.hint{font-size:14px;line-height:1.45;color:var(--ink)}
.row{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.err{padding:10px 12px;border-radius:6px;background:#FFF1EF;box-shadow:inset 0 0 0 1.5px var(--alert);color:#8C1D18;font-size:14px}
.filecard{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:14px;padding:14px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px var(--hair)}
.fileicon{position:relative;width:44px;height:54px;border-radius:6px;background:var(--ink);color:#fff;display:flex;align-items:flex-end;justify-content:center;padding-bottom:8px;font:500 12px/1 "DM Mono",monospace}
.fileicon::before{content:"";position:absolute;right:0;top:0;width:14px;height:14px;background:#fff;clip-path:polygon(0 0,100% 100%,100% 0)}
.fname{font:500 14px/1.3 "DM Mono",monospace;overflow-wrap:anywhere}
.fmeta{margin-top:2px;font:500 12px/1.4 "DM Mono",monospace;color:var(--muted)}
.consent{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:start;padding:14px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1.5px var(--hair);cursor:pointer;transition:box-shadow 200ms,background 200ms}
.consent:hover{box-shadow:inset 0 0 0 1.5px var(--ink)}
.consent.on{box-shadow:inset 0 0 0 1.5px var(--ink);background:var(--ground)}
.consent input{appearance:none;-webkit-appearance:none;width:24px;height:24px;margin:0;border:1.5px solid var(--ink);border-radius:6px;background:#fff;display:grid;place-items:center;cursor:pointer;transition:background 200ms}
.consent input::after{content:"";width:6px;height:11px;border:solid #fff;border-width:0 2.5px 2.5px 0;transform:translateY(-1px) rotate(45deg) scale(0);transition:transform 320ms var(--spring)}
.consent input:checked{background:var(--ink)}
.consent input:checked::after{transform:translateY(-1px) rotate(45deg) scale(1)}
.consent span{font-size:14px;line-height:1.5}
.assure{margin-top:-6px;font-size:14px;line-height:1.45;color:var(--ink)}
.calm-path{display:grid;grid-template-columns:auto minmax(0,1fr);gap:14px;align-items:start}
.calm-mark{width:40px;height:40px;flex:none;fill:none;stroke:var(--ink);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.calm-path div{display:grid;gap:8px}

/* run panel: two honest counts, nothing else to read */
.runhead{display:flex;justify-content:space-between;align-items:flex-end;gap:12px}
.clock{font:500 12px/1 "DM Mono",monospace;color:var(--muted);white-space:nowrap}
.clock b{font-weight:500;font-size:20px;color:var(--ink);font-variant-numeric:tabular-nums}
.status{font-size:14px;font-weight:500}
.counts{display:grid;border-top:1.5px solid var(--ink)}
.cline{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:16px 2px;border-bottom:1px solid var(--hair);color:var(--muted);transition:color 300ms}
.cline.on,.cline.done{color:var(--ink)}
.cl-label{font-weight:600;font-size:16px}
.cl-num{font:500 14px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;white-space:nowrap}
.cl-num b{display:inline-block;font:800 28px/1 "Bricolage Grotesque",sans-serif;letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:inherit}
.cl-num b.uA{animation:tickUpA 360ms var(--spring)}
.cl-num b.uB{animation:tickUpB 360ms var(--spring)}
.cancelbox{display:grid;gap:8px;justify-items:start}
.caveat{font-size:12px;line-height:1.5;color:var(--muted);max-width:44ch}
.notice{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:start;padding:14px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px var(--hair)}
.notice strong{display:block;font-size:16px}
.notice p{margin-top:2px;font-size:14px;line-height:1.45}
.notice b.mono{font-weight:500}
.nmark{width:20px;height:20px;margin-top:2px}
.nmark.sq{background:var(--ink);border-radius:6px}
/* a rate limit is a wait, not a failure: ink clock, no red */
.nclock{width:20px;height:20px;margin-top:1px;fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* review panel */
.dochead{display:flex;align-items:flex-end;gap:14px}
.bignum{display:inline-block;font:800 72px/.8 "Bricolage Grotesque",sans-serif;letter-spacing:-.035em;font-variant-numeric:tabular-nums}
.bignum.uA{animation:tickUpA 360ms var(--spring)}
.bignum.uB{animation:tickUpB 360ms var(--spring)}
.bignum.dA{animation:tickDnA 360ms var(--spring)}
.bignum.dB{animation:tickDnB 360ms var(--spring)}
.docword{display:grid;gap:4px;padding-bottom:2px;min-width:0}
.docword strong{font:700 20px/1 "Bricolage Grotesque",sans-serif}
.docword span{font:500 12px/1.3 "DM Mono",monospace;color:var(--muted)}
.checkbar{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;padding:6px;border-radius:16px;background:var(--accent);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink);transition:background 320ms var(--settle)}
.checkbar.clear{background:transparent}
.cb-go{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;width:100%;min-height:48px;padding:4px 10px 4px 6px;border:0;border-radius:10px;background:transparent;color:inherit;text-align:left;cursor:pointer;transition:background 200ms}
.cb-go:hover{background:rgba(255,255,255,.5)}
.checkbar.clear .cb-go:hover{background:var(--mat)}
.cb-go .chev{width:16px;height:16px;transition:transform 320ms var(--spring)}
.cb-go:hover .chev{transform:translateX(3px)}
.cb-dia{position:relative;width:34px;height:34px;display:grid;place-items:center;color:#fff;font:800 16px/1 "Bricolage Grotesque",sans-serif;transition:color 200ms}
/* the reward: the ink diamond turns into the ✓ ring */
.cb-dia::before{content:"";position:absolute;inset:6px;background:var(--ink);border-radius:3px;transform:rotate(45deg);transition:transform 420ms var(--spring),border-radius 420ms var(--spring),background 200ms,box-shadow 200ms}
.cb-dia b,.cb-dia .ic{position:relative}
.cb-dia .ic{width:14px;height:14px;stroke-width:2.6}
.checkbar.clear .cb-dia{color:var(--ink)}
.checkbar.clear .cb-dia::before{background:transparent;border-radius:50%;transform:none;box-shadow:inset 0 0 0 1.5px var(--ink)}
.cb-text{min-width:0}
.cb-text strong{display:block;font-size:14px;font-weight:600}
.cb-text span{display:block;font:500 12px/1.4 "DM Mono",monospace;overflow-wrap:anywhere}
.cb-nav{display:flex;gap:4px;padding-right:4px}
.cb-nav button{width:32px;height:32px;border-radius:50%;border:1.5px solid var(--ink);background:transparent;color:var(--ink);display:grid;place-items:center;cursor:pointer;transition:background 200ms,transform 300ms var(--spring)}
.cb-nav button:hover{background:#fff}
.cb-nav button:active{transform:scale(.9)}
.cb-nav .ic{width:14px;height:14px;stroke-width:2.2}
.mbarbox{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:12px;padding:12px;border-radius:16px;box-shadow:inset 0 0 0 1px var(--hair)}
.mbarbox .cb-dia{color:var(--ink)}
.mbarbox .cb-dia::before{background:transparent;border-radius:50%;transform:none;box-shadow:inset 0 0 0 1.5px var(--ink)}
.mbarbox .cb-text strong{font-size:14px}
.mbarbox .cb-text span{font-family:"DM Sans",sans-serif;font-size:12px;color:var(--muted)}
.actions{position:sticky;top:0;z-index:2;display:grid;gap:10px;padding:2px 0 6px;background:var(--ground)}
.act-main{display:flex;gap:8px}
/* one size held back or filled (no text snap on the reward); two balanced 16px lines still fit the 48px pill */
.act-main .btn{flex:1;min-width:0;padding:4px 16px;white-space:normal;text-wrap:balance;line-height:1.15;text-align:center}
.again{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px}
.again .small{flex:1 1 160px}
.chips{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:minmax(0,1fr);border-top:1.5px solid var(--ink)}
.chips li{min-width:0;border-bottom:1px solid var(--hair)}
.chip{position:relative;width:100%;min-height:44px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;column-gap:12px;padding:5px 8px 5px 4px;border:0;border-radius:0;background:transparent;color:var(--ink);text-align:left;cursor:pointer;transition:background 160ms,box-shadow 160ms,border-radius 160ms}
.chip:hover,.chip.hl{background:#fff;box-shadow:inset 0 0 0 1.5px var(--ink);border-radius:6px}
.chip-num{min-width:36px;height:32px;padding:0 6px;display:grid;place-items:center;border-radius:6px;background:var(--c);color:var(--tk);box-shadow:0 0 0 1.5px var(--ink);font:800 20px/1 "Bricolage Grotesque",sans-serif;letter-spacing:-.025em;font-variant-numeric:tabular-nums;transition:transform 380ms var(--spring)}
.chip:hover .chip-num,.chip.hl .chip-num{transform:rotate(-6deg) scale(1.08)}
.chip-txt{display:flex;align-items:baseline;gap:10px;min-width:0}
/* every row names its document (its first text line): a one-tile island has no room for a label on the grid */
.chip-line{display:block;flex:1 1 auto;min-width:0;font-size:14px;font-weight:500;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chip-meta{flex:none;font:500 12px/1.2 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted)}
.chip-flag{position:relative;width:20px;height:20px;display:grid;place-items:center;color:var(--ink);font:800 12px/1 "Bricolage Grotesque",sans-serif}
.chip-flag::before{content:"";position:absolute;inset:3px;background:var(--accent);border-radius:2px;transform:rotate(45deg);box-shadow:0 0 0 1.5px var(--ink)}
.chip-flag b{position:relative}

/* ---------- export: the fingerprint of the split, then every island folded into its page stack ---------- */
.xstage{max-width:var(--gw)}
/* the fingerprint: one sliver per page in its document's colour, drawn left to right */
.fp{display:grid;gap:6px;padding:2px 0 0}
.fp-marks,.fp-bar,.fp-nums{display:grid;grid-template-columns:repeat(var(--fpn,48),minmax(0,1fr));column-gap:var(--fpg,2px)}
.fp-nums .xd{visibility:hidden}
.fp-marks{height:16px}
/* its own keyframes: it sits in its grid cell, so it pops in place (smarkIn carries the seam mark's centring translate) */
.fp-tick{justify-self:center;width:16px;height:16px;border-radius:50%;display:grid;place-items:center;background:var(--ground);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink);animation:fpTick 420ms var(--spring) var(--d,0ms) backwards}
.fp-tick.you{background:var(--ink);color:#fff;box-shadow:none}
.fp-tick .ic{width:10px;height:10px;stroke-width:2.6}
.fp-bar{height:56px}
.fp-s{display:block;min-width:0;border-radius:3px;background:var(--c);transform-origin:50% 100%;animation:fpDraw 260ms var(--settle) var(--d,0ms) backwards;transition:transform 320ms var(--spring) calc(var(--i) * 20ms)}
.fp.sunk .fp-s{transform:translateY(4px)}
/* truly centred on its span: a number wider than a one- or two-page span overflows both sides, not just the right */
.fp-nums span{min-width:0;display:flex;justify-content:center;white-space:nowrap;font:500 12px/1 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted)}
/* the stacks: a balanced, centred board (5 to a row: 5 + 4 for the sample) */
.stacks{list-style:none;margin:0;padding:24px 0 0;display:flex;flex-wrap:wrap;justify-content:center;gap:28px 20px}
.stack{position:relative;min-width:0;flex:0 0 calc((100% - 81px) / 5);display:grid;justify-items:center;align-content:start;gap:12px;text-align:center;container-type:inline-size}
.stacks .stack{flex-basis:calc((100% - (var(--per,5) - 1) * 20px - 1px) / var(--per,5))}
.sk-card{position:relative;z-index:0;display:block;width:min(100%,104px);aspect-ratio:.78}
.sk-card::before,.sk-card::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:6px;background:var(--c);box-shadow:inset 0 0 0 1px rgba(18,18,18,.4);transition:transform 420ms var(--spring)}
/* a stack fans its pages open under the pointer */
.stack:hover .sk-card::before{transform:translate(calc(var(--fan) * 1.8),calc(var(--fan) * 1.4)) rotate(5deg)}
.stack:hover .sk-card::after{transform:translate(var(--fan),var(--fan)) rotate(2.5deg)}
.sk-card::before{transform:translate(var(--fan),var(--fan)) rotate(2.5deg)}
.sk-card::after{transform:translate(calc(var(--fan) / 2),calc(var(--fan) / 2)) rotate(1.2deg)}
.stack.one .sk-card::before,.stack.one .sk-card::after{display:none}
.sk-face{position:absolute;inset:0;display:block;border-radius:6px;background:var(--c);box-shadow:inset 0 0 0 1px rgba(18,18,18,.4);overflow:hidden}
.sk-face .paper{transition:none}
.sk-card .stamp{animation:none}
.sk-meta{display:grid;justify-items:center;gap:3px;min-width:0;max-width:100%;margin-top:9px}
/* the document's first line in two balanced lines, clamped */
.sk-line{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;max-width:100%;font:600 12px/1.25 "DM Sans",sans-serif;white-space:normal;text-wrap:balance;overflow:hidden}
/* the file name is never cut: "02_pages-10-11.pdf" breaks to "02_" / "pages-10-11.pdf" only where it must */
.sk-file{display:flex;flex-wrap:wrap;justify-content:center;max-width:100%;font:500 12px/1.25 "DM Mono",monospace;color:var(--muted);white-space:nowrap}
/* a column narrower than "pages-10-11.pdf" (1024×768, 375, 360) also breaks before the range: "02_pages-" / "10-11.pdf" */
@container (width < 108px){.sk-file .nb{display:contents}}
.stack.man .sk-face{background:var(--ground);box-shadow:inset 0 0 0 1.5px var(--ink);display:grid;place-items:center}
.stack.man .sk-face .ic{width:34px;height:34px;stroke-width:1.5}
.sk-btn{padding:0;border:0;background:none;text-align:center;cursor:pointer;color:inherit;display:grid;justify-items:center;gap:12px;min-width:0;max-width:100%}
.sk-btn .sk-line{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1.5px}
.sk-btn:hover .sk-line{text-decoration-thickness:3px}
/* the flight: no fades — a stack is hidden for one frame while it is measured, then flies from its island */
.stack.pre .sk-card{visibility:hidden}
.stack.arc .sk-card{animation:skFly 620ms cubic-bezier(.3,.7,.25,1) calc(var(--i) * 60ms) both}
/* the stamp keeps the grid's size through the flight (counter-scaled, same clock), the sheets fan out mid-flight */
.stack.arc .sk-card .stamp{transform-origin:0 0;animation:skStamp 620ms cubic-bezier(.3,.7,.25,1) calc(var(--i) * 60ms) both}
.stack.arc .sk-card::before,.stack.arc .sk-card::after{animation:fanIn 380ms var(--spring) calc(var(--i) * 60ms + 300ms) backwards}
.stack.pop .sk-card{animation:stampA 480ms calc(var(--i) * 60ms + 120ms) both}
.stack.pre .sk-meta,.stack.pre .sk-btn{visibility:hidden}
.stack.arc .sk-meta{animation:fileIn 360ms var(--settle) calc(var(--i) * 60ms + 480ms) both}
/* manifest.json lands last, after every PDF */
.stack.late .sk-card{animation-delay:var(--md,1100ms)}
.stack.late .sk-meta{animation:fileIn 360ms var(--settle) calc(var(--md,1100ms) + 160ms) both}
.manifest{margin:24px 0 0;max-height:320px;overflow:auto;padding:14px;border-radius:16px;background:var(--ink);color:#F4F3EE;font:400 12px/1.55 "DM Mono",monospace;white-space:pre;animation:panelIn 360ms var(--settle) both}
/* the headline counts the PDFs as their stacks land */
.xn{display:inline-block;min-width:.62em;font-variant-numeric:tabular-nums}
.xn.uA{animation:tickUpA 360ms var(--spring)}
.xn.uB{animation:tickUpB 360ms var(--spring)}
.loader{display:inline-grid;grid-template-columns:repeat(4,6px);gap:2px}
.loader i{display:block;width:6px;height:6px;background:#fff;animation:blink 500ms ease-in-out infinite alternate;animation-delay:calc(var(--i) * 120ms)}
.confirmbox{display:grid;gap:10px;padding:14px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px var(--hair)}
.confirmbox p{font-weight:600}

/* ---------- phone: the floating pill, the bottom bar ---------- */
/* the pill lives outside the listbox (a button is not a valid option child), on a box laid exactly over its page:
   the cell recomputed from the grid's own columns, gap and padding (a margin's % resolves against the width) */
.fpslot{--py:12px;--cw:calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols));position:absolute;left:calc(var(--col) * (var(--cw) + var(--gap)));top:0;width:var(--cw);margin-top:calc(var(--py) + var(--row) * (var(--cw) / .78 + var(--gap)));aspect-ratio:.78;pointer-events:none}
.fpill{position:absolute;left:0;bottom:calc(100% + 8px);z-index:8;pointer-events:auto;display:inline-flex;align-items:center;gap:6px;height:44px;padding:0 14px 0 11px;border:0;border-radius:999px;background:var(--ink);color:#fff;font:600 14px/1 "DM Sans",sans-serif;white-space:nowrap;cursor:pointer;box-shadow:0 6px 0 -1px rgba(18,18,18,.22);transform-origin:16px 100%;animation:fpPop 320ms var(--spring) both}
.fpill .ic{width:14px;height:14px;stroke-width:2.2}
.fpill.join{background:#fff;color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ink),0 6px 0 -1px rgba(18,18,18,.22)}
.fpill:active{transform:scale(.94)}
.fpslot.rh .fpill{left:auto;right:0;transform-origin:calc(100% - 16px) 100%}
.mbar{display:none}
.mb-txt{flex:1;min-width:0;display:grid;gap:2px}
.mb-t{font-weight:600;font-size:14px}
.mb-s{font:500 12px/1.3 "DM Mono",monospace;font-variant-numeric:tabular-nums;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mb-flag{flex:none;display:inline-flex;align-items:center;gap:8px;height:48px;padding:0 12px 0 16px;border-radius:999px;border:1.5px solid var(--ink);background:var(--accent);color:var(--ink);font:800 16px/1 "Bricolage Grotesque",sans-serif;font-variant-numeric:tabular-nums;cursor:pointer}
.mb-flag i{width:10px;height:10px;background:var(--ink);transform:rotate(45deg)}
.mb-flag .ic{width:14px;height:14px}
.mbar .mb-btn{flex:1;min-width:0}
.mbar .btn.wait{background:transparent;color:var(--ink);box-shadow:4px 4px 0 0 transparent}

/* ---------- keyframes ---------- */
@keyframes breathe{0%,100%{transform:scale(1)}50%{transform:scale(.93)}}
@keyframes pingA{0%{opacity:0;transform:scale(.8)}30%{opacity:.9;transform:scale(1.06)}100%{opacity:0;transform:scale(1.16)}}
@keyframes pingB{0%{opacity:0;transform:scale(.8)}30%{opacity:.9;transform:scale(1.06)}100%{opacity:0;transform:scale(1.16)}}
@keyframes deal{from{opacity:0;transform:translateY(8px) scale(.6)}to{opacity:1;transform:none}}
@keyframes qsweep{0%,100%{opacity:.25}50%{opacity:.85}}
@keyframes scan{0%{transform:translateY(-2px);opacity:0}12%,88%{opacity:1}100%{transform:translateY(calc(100% - 2px));opacity:0}}
@keyframes sheen{0%{opacity:0;transform:translateX(-120%) skewX(-18deg)}15%{opacity:1}100%{opacity:0;transform:translateX(320%) skewX(-18deg)}}
@keyframes floodA{from{transform:translate(-50%,-50%) scale(0)}to{transform:translate(-50%,-50%) scale(1)}}
@keyframes floodB{from{transform:translate(-50%,-50%) scale(0)}to{transform:translate(-50%,-50%) scale(1)}}
@keyframes bumpA{0%{transform:scale(1)}35%{transform:scale(.92)}100%{transform:scale(1)}}
@keyframes bumpB{0%{transform:scale(1)}35%{transform:scale(.92)}100%{transform:scale(1)}}
@keyframes stampA{0%{opacity:0;transform:scale(1.9) rotate(-12deg);animation-timing-function:cubic-bezier(.55,0,1,.45)}45%{opacity:1;transform:scale(.94) rotate(1deg);animation-timing-function:cubic-bezier(.2,0,.2,1)}72%{transform:scale(1.03)}100%{opacity:1;transform:none}}
@keyframes stampB{0%{opacity:0;transform:scale(1.9) rotate(-12deg);animation-timing-function:cubic-bezier(.55,0,1,.45)}45%{opacity:1;transform:scale(.94) rotate(1deg);animation-timing-function:cubic-bezier(.2,0,.2,1)}72%{transform:scale(1.03)}100%{opacity:1;transform:none}}
@keyframes stampOut{from{opacity:1;transform:none}to{opacity:0;transform:scale(.4) rotate(8deg)}}
@keyframes renumA{from{transform:translateY(-7px);opacity:0}to{transform:none;opacity:1}}
@keyframes renumB{from{transform:translateY(-7px);opacity:0}to{transform:none;opacity:1}}
@keyframes dashOut{to{opacity:0;transform:translateY(7px)}}
@keyframes islIn{from{opacity:0;transform:translateX(var(--nx,0px)) translateY(4px)}}
@keyframes curIn{from{opacity:0;transform:scale(1.14)}to{opacity:1;transform:none}}
@keyframes blade{0%{transform:scaleY(0);opacity:1}40%{transform:scaleY(1);opacity:1}100%{transform:scaleY(1);opacity:0}}
@keyframes zip{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes ghOutA{to{opacity:0}}
@keyframes ghOutB{to{opacity:0}}
@keyframes zipFill{from{background-size:100% 0%,50% 100%,50% 100%}to{background-size:100% 100%,50% 100%,50% 100%}}
@keyframes detA{0%{transform:translateX(var(--nx,0px)) scale(1)}40%{transform:translateX(calc(var(--nx,0px) + 1px)) scale(.97)}100%{transform:translateX(var(--nx,0px)) scale(1)}}
@keyframes detB{0%{transform:translateX(var(--nx,0px)) scale(1)}40%{transform:translateX(calc(var(--nx,0px) - 1px)) scale(.97)}100%{transform:translateX(var(--nx,0px)) scale(1)}}
@keyframes pillIn{from{opacity:0;transform:translate(-50%,-50%) translate(var(--px,0px),var(--py,0px)) scale(.3)}}
@keyframes ajarIn{from{opacity:0;transform:translate(-50%,-50%) scale(.3)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@keyframes ajarBreath{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(.92)}}
@keyframes ajarDone{0%{transform:translate(-50%,-50%) scale(1)}30%{transform:translate(-50%,-50%) scale(1.16)}100%{opacity:0;transform:translate(-50%,-50%) scale(.4)}}
@keyframes smarkIn{from{opacity:0;transform:translate(-50%,-50%) scale(.3)}to{opacity:1;transform:translate(-50%,-50%)}}
@keyframes dpRel{0%{opacity:1;transform:translate(calc(var(--dx,0) * 1px),calc(var(--dy,0) * 1px)) translate(-50%,-50%) scale(.88)}35%{opacity:1;transform:translate(calc(var(--dx,0) * 1px),calc(var(--dy,0) * 1px)) translate(-50%,-50%) scale(1)}100%{opacity:0;transform:translate(calc(var(--dx,0) * 1px),calc(var(--dy,0) * 1px)) translate(-50%,-50%) scale(1)}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes fadeOut{from{opacity:1}to{opacity:0}}
@keyframes zoomIn{from{transform:translate(var(--fx),var(--fy)) scale(var(--fs))}to{transform:none}}
@keyframes zoomOut{from{transform:none}to{transform:translate(var(--fx),var(--fy)) scale(var(--fs))}}
@keyframes sheetUp{from{transform:translateY(100%)}to{transform:none}}
@keyframes sheetDown{from{transform:none}to{transform:translateY(100%)}}
@keyframes infoIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes popIn{from{opacity:0;transform:translateY(-6px) scale(.96)}to{opacity:1;transform:none}}
@keyframes panelIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes tickUpA{from{opacity:.2;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes tickUpB{from{opacity:.2;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes tickDnA{from{opacity:.2;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes tickDnB{from{opacity:.2;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes blink{from{opacity:.25}to{opacity:1}}
@keyframes toastA{from{opacity:0;transform:translateY(-10px) scale(.92)}to{opacity:1;transform:none}}
@keyframes toastB{from{opacity:0;transform:translateY(-10px) scale(.92)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(8px) scale(.96)}}
@keyframes fileIn{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}}
@keyframes skStamp{from{transform:scale(calc(1 / var(--fs,1)))}}
@keyframes fanIn{from{transform:none}}
@keyframes skFly{0%{transform:translate(var(--fx,0px),var(--fy,0px)) scale(var(--fs,1))}55%{transform:translate(calc(var(--fx,0px) * .35),calc(var(--fy,0px) * .35 - 24px)) scale(1.04) rotate(-3deg)}100%{transform:none}}
/* the slivers grow from the baseline */
@keyframes fpDraw{from{transform:scaleY(0)}}
@keyframes fpTick{from{opacity:0;transform:scale(.3)}}
@keyframes fpPop{from{opacity:0;transform:translateY(6px) scale(.6)}to{opacity:1;transform:none}}

/* ---------- touch, responsive, reduced motion ---------- */
@media (hover:none){
  .grid.review .seam{pointer-events:none}
}
@media (max-width:900px){
  .app{--gw:776px}
  .layout{grid-template-columns:minmax(0,1fr);gap:28px;max-width:none;padding:18px 20px 40px}
  .layout.s-run,.layout.s-review,.layout.s-export{padding-bottom:112px}
  .layout.s-upload .side,.layout.s-consent .side{order:-1}
  .side{position:static}
  .actions{position:static}
  .top{flex-wrap:wrap;gap:10px 20px;padding:10px 20px}
  .steps{order:3;flex-basis:100%;justify-content:flex-start}
  .mbar.on{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;align-items:center;gap:10px;padding:10px 16px calc(10px + env(safe-area-inset-bottom));background:var(--ground);box-shadow:0 -1px 0 var(--ink)}
  /* touch: the card's close is a 44px target */
  .xbtn{width:44px;height:44px}
  .scrim{position:fixed;inset:0;z-index:60;border-radius:0}
  .insp{position:fixed;left:0;right:0;bottom:0;top:auto;z-index:61;width:auto;max-height:88vh;overflow:auto;background:#fff;border-radius:16px 16px 0 0;box-shadow:0 -1.5px 0 var(--ink);transform:none;animation:sheetUp 360ms var(--settle) both}
  .insp.out{animation:sheetDown 260ms cubic-bezier(.55,0,.8,.2) both}
  .insp-bg{display:none}
  /* the sheet reads top-down: title and close first, then the pages, then the decision */
  .app .insp .insp-body{display:flex;flex-direction:column;gap:14px;padding:20px 20px calc(20px + env(safe-area-inset-bottom))}
  .insp-info{display:contents}
  .ihead{order:-1}
  .pcol{align-self:center}
  .toast{max-width:min(100%,440px)}
  .toast-dock{position:fixed;left:0;right:0;top:auto;bottom:calc(84px + env(safe-area-inset-bottom));height:auto;max-width:none;justify-content:center;padding:0 16px}
  /* the sheet and its scrim cover the bar: decision toasts (and their Undo) ride above them, at the top */
  .app.sheet-up .toast-dock{z-index:62;top:calc(12px + env(safe-area-inset-top));bottom:auto}
}
@supports (height:100svh){@media (max-width:900px){.insp{max-height:88svh}}}
@media (max-width:600px){
  .app{--gap:8px}
  .top{padding:10px 16px}
  .details{position:static}
  .details .pop{left:16px;right:16px;top:100%;width:auto;margin-top:6px}
  .conn-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .step-label{display:none}
  .step.cur .step-label{display:inline}
  .step + .step::before{width:14px;margin:0 6px 0 2px}
  .layout{padding:14px 16px 32px}
  .layout.s-run,.layout.s-review,.layout.s-export{padding-bottom:112px}
  .grid{padding:8px 0}
  .layout.s-upload .cell:nth-child(n+25){display:none}
  .cell.ed .bridge{display:block}
  .cell.e6 .bridge{display:none}
  .cell.vd .vbridge{transform:scaleY(0);transition:transform 160ms cubic-bezier(.5,0,.75,0),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
  .cell.v6 .vbridge{transform:none;transition:transform 240ms var(--settle) calc(var(--bd,0ms) + 120ms),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
  .cell.kd .corner{transform:scale(0);transition:transform 160ms cubic-bezier(.5,0,.75,0),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
  .cell.k6 .corner{transform:none;transition:transform 240ms var(--settle) calc(var(--bd,0ms) + 170ms),background-color 160ms linear calc(var(--bd,0ms) + 60ms)}
  .stamp{left:-5px;top:-6px;min-width:24px;height:20px;padding:0 4px;font-size:12px}
  /* phone: no labels, no % chips — a flagged gap is a small butter diamond with an ink ring, on the gap */
  .isl,.ajar{display:none}
  .seam.aj::before{content:"";position:absolute;left:50%;top:calc(50% - 12px);width:9px;height:9px;margin:-4.5px 0 0 -4.5px;border-radius:2px;background:var(--accent);box-shadow:0 0 0 1.5px var(--ink);transform:rotate(45deg)}
  .cell.rs > .seam.aj::before{left:calc(100% - 1.5px)}
  /* the first row's pill opens below its page: above it is the stage head */
  .fpslot{--py:8px}
  .fpslot.r0 .fpill{bottom:auto;top:calc(100% + 8px);transform-origin:16px 0}
  .fpslot.r0.rh .fpill{transform-origin:calc(100% - 16px) 0}
  /* no room in the margin (it would sit on the screen edge): the row's first page shows its own number tab */
  .rno{display:none}
  .grid.review .cell.rs .pno{opacity:1}
  .smark{width:12px;height:12px}
  .smark .ic,.smark.you .ic{width:8px;height:8px}
  .chip-txt{display:grid;gap:1px}
  .stage-head{grid-template-columns:minmax(0,1fr);grid-template-rows:auto;height:auto;row-gap:4px}
  .sh-title{white-space:normal;overflow-wrap:anywhere}
  .sh-sub{height:auto;min-height:24px}
  .readout{justify-self:start;text-align:left}
  .s-review .readout{min-height:17px}
  .h1{font-size:28px}
  .bignum{font-size:44px}
  .row > .btn,.row > .btn2{flex:1 1 100%}
  .btn{white-space:normal;text-align:center;line-height:1.2}
  .stacks{gap:24px 12px}
  .stack,.stacks .stack{flex-basis:calc((100% - 25px) / 3)}
  .layout.s-review .stage-head{grid-template-columns:minmax(0,1fr)}
  /* a number that would touch its neighbour's on the narrow bar is left to the stacks below */
  .fp-nums .xd{visibility:visible}
  .fp-nums .xp{visibility:hidden}
  .sk-card{width:min(100%,88px)}
  .fp-bar{height:40px}
  .fp-bar,.fp-marks,.fp-nums{column-gap:min(var(--fpg,2px),1px)}
}

/* ---------- real data: page shell, columns by page count, long PDFs scroll inside the stage ---------- */
.skip-link{position:absolute;left:-9999px;top:8px;z-index:200;padding:10px 14px;border-radius:999px;background:#121212;color:#fff;font:600 14px/1 "DM Sans",system-ui,sans-serif}
.skip-link:focus{left:16px}
.nojs{margin:24px;padding:14px 16px;border-radius:16px;background:#FFF1EF;box-shadow:inset 0 0 0 1.5px #B3261E;color:#8C1D18;font:400 16px/1.5 "DM Sans",system-ui,sans-serif}
.app main:focus{outline:none}
.grid-wrap{--cols:8}
.grid-wrap.c10{--cols:10}
.grid-wrap.c12{--cols:12;--gap:10px}
.grid-wrap.c10 .stamp{min-width:32px;height:28px;font-size:18px}
.grid-wrap.c12 .stamp{left:-6px;top:-7px;min-width:28px;height:24px;padding:0 4px;font-size:15px}
.grid-wrap.c12 .isl{font-size:11px}
/* phones: six columns and small stamps whatever the page count (after the column classes, so it wins) */
@media (max-width:600px){
  .app .grid-wrap[class]{--cols:6;--gap:8px}
  .grid-wrap.c10 .stamp,.grid-wrap.c12 .stamp{left:-5px;top:-6px;min-width:24px;height:20px;padding:0 4px;font-size:12px}
}
.grid-scroll{position:relative}
.grid-inner{position:relative}
@media (min-width:901px){
  .grid-wrap.tall .grid-scroll{max-height:calc(100vh - 176px);overflow-x:hidden;overflow-y:auto;margin:-12px -20px 0 -52px;padding:12px 20px 16px 52px;overscroll-behavior:contain;scrollbar-width:thin}
}
@supports (height:100svh){@media (min-width:901px){.grid-wrap.tall .grid-scroll{max-height:calc(100svh - 176px)}}}
/* the real page, drawn over its schematic once its bitmap is ready */
.thumb{position:absolute;inset:0;z-index:1;display:block;width:100%;height:100%;background:#fff;opacity:0;transition:opacity 320ms var(--settle)}
.thumb.on{opacity:1}
.conn.warn i{animation:none;box-shadow:inset 0 0 0 1.5px var(--ink),0 0 0 3px var(--accent)}
.authbox{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:14px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px var(--hair)}
.authbox.blocked{grid-template-columns:minmax(0,1fr);box-shadow:inset 0 0 0 1.5px var(--ink)}
.authtitle{font-size:16px;font-weight:600}
.authbox .small{margin-top:2px}
.upload-progress{padding:18px;border:1.5px solid var(--ink);border-radius:18px;background:var(--paper);box-shadow:4px 4px 0 var(--accent)}
.upload-progress-heading,.upload-progress-detail{display:flex;align-items:center;justify-content:space-between;gap:12px}
.upload-progress-heading p{margin:0;font-weight:600}.upload-progress-detail{margin-top:8px;font-size:12px;color:var(--muted)}
.upload-progress progress{appearance:none;display:block;width:100%;height:12px;margin-top:14px;border:1px solid var(--ink);border-radius:8px;overflow:hidden;background:var(--mat);accent-color:var(--accent)}
.upload-progress progress::-webkit-progress-bar{background:var(--mat)}.upload-progress progress::-webkit-progress-value{background:var(--accent);transition:width .15s ease-out}.upload-progress progress::-moz-progress-bar{background:var(--accent)}
.upload-progress progress:indeterminate{background:repeating-linear-gradient(120deg,var(--mat) 0 12px,var(--accent) 12px 24px)}
.upload-progress>.small{margin:12px 0 0}.creditbox{display:grid;gap:10px;padding:16px;border:1px solid var(--hair);border-radius:16px;background:var(--paper)}.creditbox p{margin:0}.creditbox .btn2{justify-self:start}
@media(prefers-reduced-motion:reduce){.upload-progress progress::-webkit-progress-value{transition:none}}
.btn.busy{cursor:progress}
/* a hovered document lifts as one: its name stays above the neighbouring lifted tiles */
.cell.lift:has(> .isl){z-index:3}

@media (prefers-reduced-motion:reduce){
  .app *,.app *::before,.app *::after{animation-duration:1ms !important;animation-delay:0ms !important;animation-iteration-count:1 !important;transition-duration:1ms !important;transition-delay:0ms !important}
  .cell.idle .edge,.scan,.grid.queued .cell.wait .edge,.sheen::before,.sheen::after,.ajar,.loader i,.conn i{animation:none !important}
  .shell{transform:none}
  .btn{--mx:0px !important;--my:0px !important}
  .tile{--nx:0px !important}
  .cell.wrun .sheen{background:rgba(18,18,18,.05)}
  .mark rect{transition:none}
  .brand:hover .mark .mk-b{transform:rotate(-11deg)}
  .brand:hover .mark .mk-f{transform:rotate(10deg)}
}

.account-credits{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px max(16px,calc((100% - var(--gw) - 460px) / 2));border-bottom:1px solid var(--hair);background:var(--paper)}.account-credits p{margin:0}.account-credits p+p{margin-top:4px}.account-credits .pill-btn{flex-shrink:0}
