/* /lab/inference: hand-annotated sketch of one request through LLM inference.
   Uses the palette and type from styles.css. No gradients, no glow. */
.lab-head{margin-bottom:1.5rem}
.lab-title{font-size:clamp(2rem,6vw,var(--s4));letter-spacing:-.012em;line-height:1.08;margin-bottom:1rem}
.lab-note{font:400 var(--s-1)/1.45 var(--sans);color:var(--ink);border-left:2px solid var(--accent);padding-left:.75rem;margin:1.25rem 0 .6rem}
.lab-legend code,.inf-cap code{font-size:.86em;background:none;padding:0}

.inf{margin:0 0 3rem}
.inf-steps{list-style:none;padding:0;margin:0;counter-reset:none}
.inf-step{margin:0 0 2.25rem;padding-top:1.5rem;border-top:1px solid var(--rule)}
.inf-fig{margin:0}
.inf-svg{display:block;width:100%;max-width:34rem;height:auto;margin:0 0 .75rem;overflow:visible}
.inf-cap{font-size:var(--s-1);line-height:1.5;color:var(--ink-2);max-width:34rem}
.inf-n{display:inline-block;min-width:1.4em;font:600 var(--s0)/1 var(--serif);color:var(--accent);font-variant-numeric:lining-nums}
.inf-t{color:var(--ink);font-weight:600}

/* SVG ink */
.inf-svg path{fill:none;stroke-linecap:round;stroke-linejoin:round}
.inf-svg .s-ink{stroke:var(--ink);stroke-width:1.2}
.inf-svg .f-soft{fill:var(--paper-2)}
.inf-svg .s-thin{stroke:var(--ink-2);stroke-width:1}
.inf-svg .s-faint{stroke:var(--rule);stroke-width:1}
.inf-svg .s-faint-box{stroke:var(--ink-2);stroke-width:.8;stroke-dasharray:2 3}
.inf-svg .s-cut{stroke:var(--accent);stroke-width:1.4;stroke-dasharray:4 4}
.inf-svg .s-arrow{stroke:var(--accent);stroke-width:1.5}
.inf-svg .s-arrow-thin{stroke:var(--accent);stroke-width:1}
.inf-svg .s-arrow-ink{stroke:var(--ink-2);stroke-width:1.3}
.inf-svg .s-acc-thin{stroke:var(--accent);stroke-width:1.2}
.inf-svg .s-tick{stroke:var(--rule);stroke-width:1}
.inf-svg .f-acc{fill:var(--accent);stroke:none}
.inf-svg .f-kv{fill:var(--accent);fill-opacity:.28;stroke:var(--accent);stroke-width:.8}
.inf-svg .f-new{fill-opacity:.6}
.inf-svg .pkt{fill:var(--accent);opacity:0}
.inf-svg text{fill:var(--ink)}
.inf-svg .t-label{font:400 13px var(--sans);fill:var(--ink-2)}
.inf-svg .t-ink{font:500 13px var(--sans);fill:var(--ink)}
.inf-svg .t-mono{font:400 12px var(--mono);fill:var(--ink-2)}
.inf-svg .t-mono-ink{font:400 12.5px var(--mono);fill:var(--ink)}
.inf-svg .t-serif{font:400 15px var(--serif);fill:var(--ink)}
.inf-svg .t-hand{font:500 19px var(--hand);fill:var(--accent)}
.inf-svg .t-knock{fill:var(--ink);paint-order:stroke;stroke:var(--paper-2);stroke-width:4px;stroke-linejoin:round}

/* Controls: only shown once JS takes over. */
.inf-controls{margin:.25rem 0 0;max-width:34rem}
.inf-buttons{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.75rem}
.inf-btn,.inf-dot{font:500 var(--s-1)/1 var(--sans);color:var(--ink);background:transparent;border:1px solid var(--ink-2);border-radius:2px;cursor:pointer;min-height:44px}
.inf-btn{padding:.6rem 1rem;min-width:4.75rem}
.inf-btn:hover,.inf-dot:hover{background:var(--paper-2);border-color:var(--ink)}
.inf-btn[aria-disabled=true]{color:var(--ink-2);border-style:dashed;cursor:default;background:transparent}
.inf-play{border-color:var(--accent);color:var(--accent)}
.inf-count{font:400 var(--s-1)/1.4 var(--sans);color:var(--ink-2);margin:0 0 0 auto;font-variant-numeric:lining-nums tabular-nums}
.inf-index{list-style:none;display:flex;flex-wrap:wrap;gap:.4rem;padding:0;margin:0}
.inf-index li{margin:0}
.inf-dot{width:44px;padding:0;font-variant-numeric:lining-nums}
.inf-dot[aria-current=step]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.inf-btn:focus-visible,.inf-dot:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Stepped mode: JS shows one panel at a time. */
.inf.is-stepped .inf-step{display:none;border-top:0;padding-top:0;margin-bottom:1rem}
.inf.is-stepped .inf-step.is-current{display:block}
.inf.is-stepped .inf-cap{min-height:6.2em}

/* Motion: only in stepped mode with motion allowed. Base styles above are the final state,
   so reduced motion and no JS both show complete panels. */
.inf.is-animated .is-current .a-in{animation:inf-in .5s ease-out both}
.inf.is-animated .is-current .a-draw{stroke-dasharray:1;animation:inf-draw .8s ease-out both}
.inf.is-animated .is-current .a-grow{transform-box:fill-box;transform-origin:0 50%;animation:inf-grow .6s ease-out both}
.inf.is-animated .is-current .pkt-r{animation:inf-r 1s ease-in-out both}
.inf.is-animated .is-current .pkt-l{animation:inf-l 1s ease-in-out both}
.inf.is-animated .is-current .s-cut.a-draw{stroke-dasharray:4 4;animation:inf-in .5s ease-out both}
.inf.is-animated .is-current .d0{animation-delay:0s}
.inf.is-animated .is-current .d1{animation-delay:.25s}
.inf.is-animated .is-current .d2{animation-delay:.5s}
.inf.is-animated .is-current .d3{animation-delay:.75s}
.inf.is-animated .is-current .d4{animation-delay:1s}
.inf.is-animated .is-current .d5{animation-delay:1.25s}
.inf.is-animated .is-current .d6{animation-delay:1.5s}
.inf.is-animated .is-current .d7{animation-delay:1.75s}
.inf.is-animated .is-current .d8{animation-delay:2s}
.inf.is-animated .is-current .d9{animation-delay:2.25s}
.inf.is-animated .is-current .r1{animation-delay:.9s}
.inf.is-animated .is-current .r2{animation-delay:2.2s}
@keyframes inf-in{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}
@keyframes inf-draw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@keyframes inf-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes inf-r{0%{opacity:0;transform:translateX(0)}15%{opacity:1}85%{opacity:1}100%{opacity:0;transform:translateX(94px)}}
@keyframes inf-l{0%{opacity:0;transform:translateX(0)}15%{opacity:1}85%{opacity:1}100%{opacity:0;transform:translateX(-94px)}}

@media (min-width:1040px){
  .inf.col-text,.lab-head.col-text{grid-column:2/4}
  .inf-svg{max-width:36rem}
  .inf-controls,.inf-cap{max-width:36rem}
}
@media (prefers-reduced-motion:reduce){.inf .a-in,.inf .a-draw,.inf .a-grow,.inf .pkt{animation:none!important}}
@media print{.inf-controls{display:none!important}.inf .inf-step{display:block!important;break-inside:avoid}}

/* /lab/kv-cache */
.kv{margin:0 0 3rem}
.kv fieldset{border:0;padding:0;margin:0 0 1.25rem}
.kv-field{display:grid;grid-template-columns:1fr auto;align-items:baseline;gap:.15rem 1rem;margin-bottom:1rem}
.kv-field label,.kv-label{font:400 var(--s-1)/1.4 var(--sans);color:var(--ink)}
.kv-out{font:400 .9rem/1.4 var(--mono);color:var(--ink);font-variant-numeric:tabular-nums}
.kv-field input[type=range]{grid-column:1/-1;width:100%;min-height:44px;accent-color:var(--accent);margin:0}
.kv-prec{display:flex;flex-wrap:wrap;gap:.25rem 1.25rem;align-items:center}
.kv-prec .kv-label{flex-basis:100%}
.kv-radio{display:inline-flex;align-items:center;gap:.4rem;min-height:44px;font:400 var(--s-1)/1 var(--sans);color:var(--ink);cursor:pointer}
.kv-radio input{width:1.1rem;height:1.1rem;accent-color:var(--accent);margin:0}
.kv-gpus{margin:0 0 1rem}
.kv-gpu{margin:0 0 .6rem}
.kv-gpu-h{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.25rem 1rem;font:400 var(--s-1)/1.4 var(--sans);color:var(--ink-2);margin-bottom:.25rem}
.kv-gpu-n{color:var(--ink);font-weight:600}
.kv-gpu-t{font-family:var(--mono);font-size:.8rem}
.kv-bar{display:block;width:100%;height:30px}
.kv-r-frame{fill:var(--paper);stroke:var(--ink);stroke-width:1;vector-effect:non-scaling-stroke}
.kv-r-weights{fill:var(--ink-2)}
.kv-r-reserve{fill:var(--rule)}
.kv-r-kv{fill:var(--accent)}
.kv-r-unusable{fill:var(--paper-2);stroke:var(--ink-2);stroke-dasharray:3 3;stroke-width:1;vector-effect:non-scaling-stroke}
.kv-legend{list-style:none;display:flex;flex-wrap:wrap;gap:.2rem 1rem;padding:0;margin:.4rem 0 0;font:400 .8rem/1.4 var(--sans);color:var(--ink-2)}
.kv-legend li{margin:0;display:inline-flex;align-items:center;gap:.35rem}
.kv-sw{display:inline-block;width:.9rem;height:.9rem;border:1px solid var(--ink-2)}
.kv-sw-weights{background:var(--ink-2)}.kv-sw-reserve{background:var(--rule)}.kv-sw-kv{background:var(--accent);border-color:var(--accent)}.kv-sw-free{background:var(--paper)}.kv-sw-unusable{background:var(--paper-2);border-style:dashed}
.kv-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));gap:.6rem 1.5rem;margin:1.25rem 0;padding:.9rem 0;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.kv-stats div{margin:0}
.kv-stats dt{font:400 .8rem/1.3 var(--sans);color:var(--ink-2)}
.kv-stats dd{margin:0;font:400 .95rem/1.4 var(--mono);color:var(--ink);font-variant-numeric:tabular-nums}
.kv-status{min-height:3.5rem;margin:0 0 1rem}
.kv-ok{font:400 var(--s-1)/1.4 var(--sans);color:var(--ink);border-left:2px solid var(--ink-2);padding-left:.75rem;margin:0}
.kv-oom{background:var(--con-bg);color:var(--con-ink);border-radius:3px;padding:.8rem 1rem}
.kv-oom-line{font:400 1rem/1.4 var(--mono);color:var(--con-hi);margin:0 0 .35rem}
.kv-oom-note{font:400 var(--s-1)/1.45 var(--sans);color:var(--con-ink);margin:0}
.kv-oom-note a{color:var(--con-hi)}
.kv-chart{margin:1.25rem 0 1.5rem}
.kv-chart-t{font:600 var(--s-1)/1.4 var(--sans);color:var(--ink);margin-bottom:.25rem}
.kv-svg{display:block;width:100%;max-width:36rem;height:auto;overflow:visible}
.kv-axis,.kv-tick{fill:none;stroke:var(--ink);stroke-width:1.2}
.kv-curve{fill:none;stroke:var(--accent);stroke-width:2;stroke-linejoin:round}
.kv-capline{fill:none;stroke:var(--accent);stroke-width:1.2;stroke-dasharray:4 4}
.kv-dot{fill:var(--paper);stroke:var(--accent);stroke-width:2}
.kv-svg text{fill:var(--ink-2);font:400 12px var(--sans)}
.kv-svg .kv-tm{font:400 11px var(--mono)}
.kv-svg .kv-cap-t{fill:var(--accent);font:600 12px var(--sans)}
.kv-svg .kv-hand{fill:var(--accent);font:500 17px var(--hand)}
.kv-svg .kv-you{fill:var(--ink);font:500 12px var(--sans)}
.kv-svg [hidden]{display:none}
.kv-assume{border-top:1px solid var(--rule);padding-top:1rem;margin:0 0 1.25rem}
.kv-h2,.dbg-h2{font-size:var(--s0);font-weight:600;margin:0 0 .6rem}
.kv-formula{font:400 var(--s-1)/1.5 var(--sans);margin-bottom:.4rem}
.kv-formula code{font-size:.85rem}
.kv-assume ul{padding-left:1.1rem}
.kv-table{border-collapse:collapse;width:100%;font:400 .82rem/1.4 var(--sans);margin:.5rem 0 0}
.kv-table caption{text-align:left;font-weight:600;color:var(--ink);padding-bottom:.35rem}
.kv-table th,.kv-table td{border-bottom:1px solid var(--rule);padding:.35rem .5rem .35rem 0;text-align:left;vertical-align:top}
.kv-table td{font-family:var(--mono);font-size:.8rem;font-variant-numeric:tabular-nums}
.kv-table th{color:var(--ink-2);font-weight:400}

/* /lab/debug */
.dbg{margin:0 0 3rem}
.dbg-choices{list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:.45rem;padding:0;margin:0 0 .6rem}
.dbg-choices li{margin:0}
.dbg-choice{width:100%;display:flex;justify-content:space-between;align-items:center;gap:.5rem;font:500 var(--s-1)/1.25 var(--sans);color:var(--ink);background:transparent;border:1px solid var(--ink-2);border-radius:2px;padding:.6rem .8rem;min-height:44px;cursor:pointer;text-align:left}
.dbg-choice:hover{background:var(--paper-2);border-color:var(--ink)}
.dbg-choice.is-done{border-style:dashed;color:var(--ink-2)}
.dbg-v{font:500 1rem/1 var(--hand);color:var(--accent)}
.dbg-count{margin:0 0 1rem}
.dbg-step{padding-top:1.25rem;margin:0 0 1.5rem;border-top:1px solid var(--rule)}
.dbg-step:focus,.dbg-root:focus{outline:none}
.dbg-step:focus-visible,.dbg-root:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.dbg-step-h{font-size:var(--s0);display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .5rem}
.dbg-num{font:600 var(--s0)/1 var(--serif);color:var(--accent);font-variant-numeric:lining-nums}
.dbg-verdict{font:500 .78rem/1.3 var(--sans);color:var(--ink-2);border:1px solid var(--ink-2);border-radius:2px;padding:.05rem .4rem}
.dbg-verdict-cause{color:var(--accent);border-color:var(--accent)}
.dbg-panel{margin:.4rem 0 .75rem;padding:.75rem .9rem;background:var(--paper-2);border-left:2px solid var(--ink-2)}
.dbg-panel-h{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.25rem 1rem;font:400 .78rem/1.4 var(--sans);color:var(--ink-2);margin-bottom:.4rem}
.dbg-panel-h code{color:var(--ink)}
.dbg-tag{font:500 1rem/1 var(--hand);color:var(--accent)}
.dbg-spark{display:block;width:100%;max-width:28rem;height:auto}
.dbg-grid{stroke:var(--rule);stroke-width:1;fill:none}
.dbg-deploy{stroke:var(--accent);stroke-width:1;stroke-dasharray:3 3;fill:none}
.dbg-line{stroke:var(--ink);stroke-width:1.6;fill:none;stroke-linejoin:round}
.dbg-spark text{fill:var(--ink-2);font:400 10px var(--mono)}
.dbg-vals{font:400 .82rem/1.5 var(--sans);color:var(--ink-2);margin:.35rem 0 0}
.dbg-vals code{color:var(--ink)}
.dbg-log{margin:.25rem 0 0;font-size:.78rem;white-space:pre-wrap}
.dbg-add{color:var(--accent)}
.dbg-del{color:var(--ink-2);text-decoration:line-through}
.dbg-table{border-collapse:collapse;font:400 .82rem/1.4 var(--sans);margin:0 0 .5rem;width:100%;max-width:28rem}
.dbg-table th,.dbg-table td{text-align:left;padding:.3rem .6rem .3rem 0;border-bottom:1px solid var(--rule)}
.dbg-table td{font-family:var(--mono);font-variant-numeric:tabular-nums}
.dbg-table thead th{color:var(--ink-2);font-weight:400}
.dbg-note{font-size:var(--s-1);line-height:1.55}
.dbg-note-h{font-weight:600}
.dbg-root-gate{margin:0 0 1.5rem}
.dbg-root{border-top:2px solid var(--accent);padding-top:1.1rem;margin:0 0 1.5rem}
.dbg-hand{font:500 1.35rem/1 var(--hand);color:var(--accent);margin-left:.4rem;font-weight:500}
.dbg-sub{font-size:var(--s-1);font-family:var(--sans);font-weight:600;margin:1rem 0 .3rem}
.dbg-root p,.dbg-root li{font-size:var(--s-1);line-height:1.55}
.dbg-skeptic{margin-top:1.5rem}
.dbg-actions{margin:1rem 0}
@media (min-width:1040px){.kv.col-text,.dbg.col-text{grid-column:2/4}.kv>*,.dbg>*{max-width:40rem}}
