/* ═══════════════════════════════════════════════════════════════════
   Article visuals: diagrams, row icons and interactive widgets.
   Kept in its own file so site.css stays untouched.
   Every colour resolves through a design token, so dark mode is free.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Figure wrapper ──────────────────────────────────────────────── */
.viz{margin:38px 0;border:1px solid color-mix(in oklab,var(--ac-2) 16%,var(--line));border-radius:20px;
  background:var(--bg-alt);overflow:hidden;position:relative}
.viz::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--g-ac)}
.viz-head{padding:20px 24px 0}
.viz-eyebrow{font-family:var(--font-m);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ac-ink);font-weight:700;display:block;margin-bottom:6px}
.viz-title{font-family:var(--font-b);font-size:18px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em;line-height:1.3}
.viz-canvas{padding:18px 24px 4px;overflow-x:auto}
.viz-canvas svg{display:block;width:100%;height:auto}
.viz-canvas.is-wide svg{min-width:540px}
.viz figcaption{padding:4px 24px 20px;font-size:14px;line-height:1.55;color:var(--ink-3)}
.viz figcaption strong{color:var(--ink-2);font-weight:600}
@media(max-width:640px){
  .viz-head{padding:16px 18px 0}
  .viz-canvas{padding:14px 18px 4px}
  .viz figcaption{padding:4px 18px 16px;font-size:13.5px}
}

/* Hero banner variant sits flush inside .article-hero-visual */
.article-hero-visual .viz{margin:0;border:0;border-radius:0;background:transparent}
.article-hero-visual .viz::before{display:none}
.article-hero-visual .viz-canvas{padding:18px 24px 6px;overflow-x:auto}
@media(max-width:640px){.article-hero-visual .viz-canvas{padding:14px 18px 4px}}

/* ── SVG colour vocabulary ───────────────────────────────────────── */
.viz .s-bg{fill:var(--bg)}
.viz .s-surface{fill:var(--bg-alt)}
.viz .s-tint{fill:var(--bg-tint)}
.viz .s-none{fill:none}
.viz .s-line{stroke:var(--line);fill:none}
.viz .s-line2{stroke:var(--ink-5);fill:none}
.viz .s-brand{stroke:var(--brand);fill:none}
.viz .s-brandf{fill:var(--brand)}
.viz .s-violet{stroke:var(--violet);fill:none}
.viz .s-violetf{fill:var(--violet)}
.viz .s-amberf{fill:var(--amber)}
.viz .s-amber{stroke:var(--amber);fill:none}
.viz .s-dangerf{fill:var(--danger)}
.viz .s-danger{stroke:var(--danger);fill:none}
.viz .s-okf{fill:var(--success)}
.viz .s-ok{stroke:var(--success);fill:none}
.viz .s-inkf{fill:var(--ink)}
.viz .s-ink3f{fill:var(--ink-3)}
.viz .s-ink5{stroke:var(--ink-5);fill:none}
.viz .s-dash{stroke-dasharray:5 4}
.viz .s-thin{stroke-width:1.25}
.viz .s-med{stroke-width:1.8}
.viz .s-thick{stroke-width:2.6}
.viz .s-round{stroke-linecap:round;stroke-linejoin:round}
.viz .s-soft{opacity:.5}
.viz .s-faint{opacity:.22}

/* ── SVG typography ──────────────────────────────────────────────── */
.viz text{font-family:var(--font-b);fill:var(--ink-2)}
.viz .t-lab{font-size:13px;font-weight:600;fill:var(--ink-2)}
.viz .t-sm{font-size:11.5px;font-weight:500;fill:var(--ink-3)}
.viz .t-mono{font-family:var(--font-m);font-size:12px;fill:var(--ink-3)}
.viz .t-num{font-family:var(--font-num);font-size:20px;font-weight:700;fill:var(--ink)}
.viz .t-big{font-family:var(--font-num);font-size:30px;font-weight:800;fill:var(--brand)}
.viz .t-head{font-size:14px;font-weight:700;fill:var(--ink)}
.viz .t-inv{fill:#fff}
.viz .t-mid{text-anchor:middle}
.viz .t-end{text-anchor:end}

/* ── Icons inside info-graphic rows ──────────────────────────────── */
.info-graphic .ig-list li{position:relative}
.info-graphic .ig-list li > .ig-ico{flex:none;width:28px;height:28px;border-radius:9px;
  display:grid;place-items:center;background:color-mix(in oklab,var(--ac-2) 10%,var(--bg));
  border:1px solid color-mix(in oklab,var(--ac-2) 24%,var(--line));
  color:var(--ac-ink);margin-right:2px}
.info-graphic .ig-list li > .ig-ico svg{width:14px;height:14px;display:block}
.info-graphic .ig-list li > span:not(.ig-v):not(.ig-ico){flex:1;min-width:0}

/* ── Process step icons ──────────────────────────────────────────── */
.process-step .pn{position:relative}
.process-step .pc h4 .pc-ico{display:inline-grid;place-items:center;width:20px;height:20px;
  vertical-align:-4px;margin-right:7px;color:var(--ac-ink)}
.process-step .pc h4 .pc-ico svg{width:16px;height:16px}

/* ── Copy button on inline code ──────────────────────────────────── */
.article-body .copyable{position:relative;display:inline-flex;align-items:center;gap:6px}
.article-body .copy-btn{border:1px solid var(--line);background:var(--bg);color:var(--ink-4);
  border-radius:6px;width:22px;height:22px;display:grid;place-items:center;cursor:pointer;
  transition:color .18s,border-color .18s,background .18s;flex:none;padding:0}
.article-body .copy-btn svg{width:12px;height:12px}
.article-body .copy-btn:hover{color:var(--ac-ink);border-color:var(--ac-2)}
.article-body .copy-btn.done{color:var(--success);border-color:var(--success)}

/* ── Interactive widgets ─────────────────────────────────────────── */
.widget{margin:38px 0;border:1px solid color-mix(in oklab,var(--ac-2) 18%,var(--line));border-radius:20px;background:var(--bg);
  overflow:hidden;box-shadow:0 16px 40px -30px color-mix(in oklab,var(--ac-2) 50%,transparent),var(--sh-1)}
.widget-head{padding:20px 24px 14px;border-bottom:1px solid color-mix(in oklab,var(--ac-2) 12%,var(--line));
  background:linear-gradient(135deg,color-mix(in oklab,var(--ac-2) 8%,var(--bg)) 0%,color-mix(in oklab,var(--ac-3) 4%,var(--bg)) 100%)}
.widget-head .w-eyebrow{font-family:var(--font-m);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ac-ink);font-weight:700;display:block;margin-bottom:6px}
.widget-head h4{font-family:var(--font-b);font-size:18px;font-weight:700;color:var(--ink);
  letter-spacing:-.01em;margin:0}
.widget-head p{font-size:13.5px;color:var(--ink-3);margin:6px 0 0;line-height:1.5}
.widget-body{padding:20px 24px 22px}
@media(max-width:640px){.widget-head{padding:16px 18px 12px}.widget-body{padding:16px 18px 18px}}

.w-row{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end}
.w-field{flex:1 1 150px;min-width:0}
.w-field label{display:block;font-family:var(--font-m);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-4);margin-bottom:6px}
.w-field input,.w-field select{width:100%;border:1px solid var(--line);background:var(--bg-alt);
  color:var(--ink);border-radius:10px;padding:11px 13px;font-family:var(--font-b);
  font-size:15px;outline:none;transition:border-color .18s,box-shadow .18s}
.w-field input:focus,.w-field select:focus{border-color:var(--ac-2);
  box-shadow:0 0 0 3px color-mix(in oklab,var(--ac-2) 16%,transparent)}
.w-field input[type=number]{font-family:var(--font-num);font-weight:600}

.w-out{margin-top:18px;border-top:1px solid var(--line-2);padding-top:16px}
.w-result{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:4px}
.w-result .w-val{font-family:var(--font-num);font-size:clamp(24px,4vw,32px);font-weight:800;
  color:var(--ac-ink);letter-spacing:-.02em}
.w-result .w-unit{font-family:var(--font-m);font-size:12px;color:var(--ink-4);
  letter-spacing:.08em;text-transform:uppercase}
.w-note{font-size:13.5px;color:var(--ink-3);line-height:1.55}
.w-note code{font-family:var(--font-m);font-size:12.5px;background:var(--bg-alt);
  border:1px solid var(--line);border-radius:5px;padding:1px 6px;color:var(--ink-2)}

.w-verdicts{display:grid;gap:8px;margin-top:14px}
.w-verdict{display:flex;align-items:center;gap:10px;padding:10px 13px;border-radius:11px;
  border:1px solid var(--line);background:var(--bg-alt);font-size:13.5px;color:var(--ink-2)}
.w-verdict .w-dot{width:9px;height:9px;border-radius:50%;flex:none}
.w-verdict .w-who{font-weight:600;color:var(--ink);flex:1;min-width:0}
.w-verdict .w-state{font-family:var(--font-m);font-size:11px;letter-spacing:.08em;
  text-transform:uppercase}
.w-verdict.ok .w-dot{background:var(--success)} .w-verdict.ok .w-state{color:var(--success)}
.w-verdict.warn .w-dot{background:var(--amber)} .w-verdict.warn .w-state{color:var(--gold)}
.w-verdict.bad .w-dot{background:var(--danger)} .w-verdict.bad .w-state{color:var(--danger)}

/* Segmented toggle used by the binding-edge demo */
.w-seg{display:inline-flex;border:1px solid var(--line);border-radius:11px;overflow:hidden;
  background:var(--bg-alt)}
.w-seg button{border:0;background:transparent;color:var(--ink-3);font-family:var(--font-b);
  font-size:14px;font-weight:600;padding:10px 18px;cursor:pointer;transition:background .18s,color .18s}
.w-seg button[aria-pressed=true]{background:var(--g-ac-deep);color:#fff}
.w-seg button:not([aria-pressed=true]):hover{color:var(--ink)}

.w-stage{margin-top:18px;border:1px solid var(--line);border-radius:14px;
  background:var(--bg-alt);padding:16px;overflow-x:auto}
.w-stage svg{display:block;width:100%;height:auto;min-width:300px}

@media(prefers-reduced-motion:reduce){
  .viz *,.widget *{transition:none!important;animation:none!important}
}

/* The widget stage draws with the same vocabulary, outside .viz. */
.w-stage .s-bg{fill:var(--bg)}
.w-stage .s-surface{fill:var(--bg-alt)}
.w-stage .s-tint{fill:var(--bg-tint)}
.w-stage .s-none{fill:none}
.w-stage .s-line{stroke:var(--line);fill:none}
.w-stage .s-line2{stroke:var(--ink-5);fill:none}
.w-stage .s-brand{stroke:var(--brand);fill:none}
.w-stage .s-brandf{fill:var(--brand)}
.w-stage .s-violet{stroke:var(--violet);fill:none}
.w-stage .s-violetf{fill:var(--violet)}
.w-stage .s-amberf{fill:var(--amber)}
.w-stage .s-amber{stroke:var(--amber);fill:none}
.w-stage .s-dangerf{fill:var(--danger)}
.w-stage .s-danger{stroke:var(--danger);fill:none}
.w-stage .s-okf{fill:var(--success)}
.w-stage .s-ok{stroke:var(--success);fill:none}
.w-stage .s-inkf{fill:var(--ink)}
.w-stage .s-ink3f{fill:var(--ink-3)}
.w-stage .s-ink5{stroke:var(--ink-5);fill:none}
.w-stage .s-dash{stroke-dasharray:5 4}
.w-stage .s-thin{stroke-width:1.25}
.w-stage .s-med{stroke-width:1.8}
.w-stage .s-thick{stroke-width:2.6}
.w-stage .s-round{stroke-linecap:round;stroke-linejoin:round}
.w-stage .s-soft{opacity:.5}
.w-stage .s-faint{opacity:.22}
.w-stage text{font-family:var(--font-b);fill:var(--ink-2)}
.w-stage .t-lab{font-size:13px;font-weight:600;fill:var(--ink-2)}
.w-stage .t-sm{font-size:11.5px;font-weight:500;fill:var(--ink-3)}
.w-stage .t-mono{font-family:var(--font-m);font-size:12px;fill:var(--ink-3)}
.w-stage .t-num{font-family:var(--font-num);font-size:20px;font-weight:700;fill:var(--ink)}
.w-stage .t-big{font-family:var(--font-num);font-size:30px;font-weight:800;fill:var(--brand)}
.w-stage .t-head{font-size:14px;font-weight:700;fill:var(--ink)}
.w-stage .t-inv{fill:#fff}
.w-stage .t-mid{text-anchor:middle}
.w-stage .t-end{text-anchor:end}

/* Grid items default to min-width:auto, which lets a wide diagram stretch the
   whole article column on narrow screens. Keep the overflow inside the canvas. */
.article-shell .article-body{min-width:0}
.article-body > .viz,
.article-body > .widget{max-width:100%}
.viz-canvas,.w-stage{max-width:100%}

/* ── Diagrams on phones ──────────────────────────────────────────
   article-viz.js re-stacks multi-panel diagrams vertically (.is-stacked)
   and marks one-piece drawings as a scrolling canvas (.is-scroll).
   Before the script runs, .is-wide keeps the old scroll behaviour. */
@media(max-width:640px){
  .viz-canvas.is-stacked{overflow:visible;padding-bottom:6px}
  .viz-canvas.is-stacked svg{min-width:0;display:block}
  .viz-canvas.is-scroll,.viz-canvas.is-wide:not(.is-stacked){scrollbar-width:thin;padding-bottom:10px}
  .viz-canvas.is-scroll svg,.viz-canvas.is-wide:not(.is-stacked) svg{min-width:580px}
  .viz-canvas.is-scroll:not([data-scroll=none]),.viz-canvas.is-wide:not(.is-stacked):not([data-scroll]){
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)}
  .viz-canvas[data-scroll=mid]{
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 28px,#000 calc(100% - 28px),transparent);
    mask-image:linear-gradient(90deg,transparent,#000 28px,#000 calc(100% - 28px),transparent)}
  .viz-canvas[data-scroll=end]{
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 28px);
    mask-image:linear-gradient(90deg,transparent,#000 28px)}
  .viz:has(.viz-canvas.is-scroll:not([data-scroll=none])) .viz-head::after,
  .viz:has(.viz-canvas.is-wide:not(.is-stacked):not([data-scroll])) .viz-head::after{
    content:"Swipe to see the whole diagram";
    display:inline-flex;align-items:center;gap:6px;margin-top:10px;
    font-family:var(--font-m);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
    color:var(--ac-ink);background:color-mix(in oklab,var(--ac-2) 9%,var(--bg));
    border:1px solid color-mix(in oklab,var(--ac-2) 22%,transparent);border-radius:99px;padding:4px 10px}
  .widget-body{padding:16px 16px 18px}
  .w-stage{padding:12px}
  .w-stage.is-stacked{overflow:visible}
  .w-stage.is-stacked svg{min-width:0}
}
