/* Extra rules for the data-structure diagrams (js/viz/*.js). Colours come only from app.css tokens. */
.vx-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; }
.vx-row.nowrap { flex-wrap: nowrap; width: max-content; }
.vx-col { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 46px; }
.vx-ptr { font: 700 .72rem var(--font-mono); color: var(--focus); min-height: 1.15em; text-align: center; white-space: nowrap; }
.vx-ptr.alt { color: var(--bad); }
.vx-ptr.good { color: var(--ok); }
.cell.sm { min-width: 36px; height: 36px; font-size: .85rem; border-radius: 8px; padding: 0 6px; }
.cell.wide { justify-content: start; place-items: center start; padding: 0 10px; }

.vx-split { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.vx-split > * { flex: 1 1 220px; min-width: 0; }
.vx-split > .grow { flex: 2 1 300px; }
.vx-panel { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); padding: 10px; min-height: 64px; transition: border-color .2s, box-shadow .2s; }
.vx-panel h4 { margin: 0 0 8px; font: 700 .72rem var(--font-body); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.vx-panel.on { border-color: var(--focus); box-shadow: 0 0 0 2px color-mix(in srgb, var(--focus) 30%, transparent); }
.vx-empty { font: .8rem var(--font-mono); color: var(--muted); }

.vx-stack { display: flex; flex-direction: column-reverse; justify-content: flex-start; gap: 6px; width: 150px; min-height: 210px; padding: 6px; border: 2px solid var(--rule); border-top: 0; border-radius: 0 0 12px 12px; }
.vx-stack .cell { width: 100%; }
.vx-stack.auto { width: auto; min-width: 150px; min-height: 120px; }

.vx-code { font: .84rem/1.6 var(--font-mono); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); padding: 8px 0; margin: 0; overflow-x: auto; white-space: pre; }
.vx-code span { display: block; padding: 0 12px; border-left: 4px solid transparent; }
.vx-code span.on { background: color-mix(in srgb, var(--signal) 28%, var(--surface)); border-left-color: var(--signal); }

.vx-table { border-collapse: collapse; font: .82rem var(--font-mono); background: var(--surface); }
.vx-table caption { text-align: left; font: 700 .72rem var(--font-body); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); padding-bottom: 4px; }
.vx-table th, .vx-table td { border: 1px solid var(--rule); padding: 4px 8px; text-align: left; white-space: nowrap; }
.vx-table th { background: var(--surface-2); font-family: var(--font-body); }
.vx-table tr.hl td { background: color-mix(in srgb, var(--focus) 16%, var(--surface)); }
.vx-table tr.ok td { background: color-mix(in srgb, var(--ok) 16%, var(--surface)); }
.vx-table tr.bad td { background: color-mix(in srgb, var(--bad) 12%, var(--surface)); }
.vx-table td.null { color: var(--muted); font-style: italic; }
.vx-scroll { overflow-x: auto; max-width: 100%; }

.vx-stats { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.vx-seq { font: 700 .9rem var(--font-mono); margin-top: 8px; min-height: 1.4em; overflow-wrap: anywhere; }
.vx-calc { font: .85rem/1.5 var(--font-mono); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); padding: 8px 12px; margin-bottom: 10px; overflow-wrap: anywhere; }

.vx-svg { display: block; width: 100%; height: auto; max-width: 720px; margin: 0 auto; }
.vx-svg.fixed { width: auto; max-width: none; margin: 0; }
.vx-svg .node circle, .vx-svg .node rect { fill: var(--surface); stroke: var(--muted); stroke-width: 2.5; transition: fill .2s, stroke .2s, opacity .2s; }
.vx-svg .node text { font: 700 14px var(--font-mono); text-anchor: middle; dominant-baseline: central; }
.vx-svg .node.hl circle, .vx-svg .node.hl rect { stroke: var(--focus); fill: color-mix(in srgb, var(--focus) 18%, var(--surface)); }
.vx-svg .node.ok circle, .vx-svg .node.ok rect { stroke: var(--ok); fill: color-mix(in srgb, var(--ok) 20%, var(--surface)); }
.vx-svg .node.bad circle, .vx-svg .node.bad rect { stroke: var(--bad); fill: color-mix(in srgb, var(--bad) 16%, var(--surface)); }
.vx-svg .node.sig circle, .vx-svg .node.sig rect { stroke: var(--signal); fill: color-mix(in srgb, var(--signal) 35%, var(--surface)); }
.vx-svg .node.dim { opacity: .35; }
.vx-svg .node.pop { animation: pop-in .35s var(--ease-out); transform-box: fill-box; transform-origin: center; }
.vx-svg .edge { stroke: var(--muted); stroke-width: 2; fill: none; transition: stroke .2s, opacity .2s; }
.vx-svg .edge.hl { stroke: var(--focus); stroke-width: 3.5; }
.vx-svg .edge.ok { stroke: var(--ok); stroke-width: 3.5; }
.vx-svg .edge.bad { stroke: var(--bad); stroke-width: 3; stroke-dasharray: 6 4; }
.vx-svg .edge.dim { opacity: .3; }
.vx-svg .vx-arrow { fill: var(--muted); }
.vx-svg .vx-lbl { font: 700 11px var(--font-mono); fill: var(--muted); text-anchor: middle; }
.vx-svg .vx-lbl.ptr { fill: var(--focus); }
.vx-svg .vx-lbl.alt { fill: var(--bad); }
.vx-svg .vx-lbl.good { fill: var(--ok); }
.vx-svg .vx-lbl.start { text-anchor: start; }
.vx-svg .vx-lbl.end { text-anchor: end; }
.vx-svg .grid { stroke: var(--rule); stroke-width: 1; }
.vx-svg .curve { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.vx-svg .venn { stroke: none; fill: var(--surface); transition: fill .25s; }
.vx-svg .venn.on { fill: color-mix(in srgb, var(--sql) 45%, var(--surface)); }
.vx-svg .venn-line { fill: none; stroke: var(--ink); stroke-width: 2; }

.vx-legend { display: flex; flex-wrap: wrap; gap: 6px; }
.vx-legend .btn { min-height: 34px; padding: 4px 12px; font-size: .82rem; gap: 6px; display: inline-flex; align-items: center; }
.vx-legend .btn i { width: 12px; height: 12px; border-radius: 50%; background: var(--c); display: inline-block; }
.vx-legend .btn[aria-pressed="false"] { opacity: .5; }
.vx-legend .btn[aria-pressed="true"] { background: var(--surface); color: var(--ink); border-color: var(--c); }
.vx-range { width: min(260px, 100%); accent-color: var(--focus); }

.vx-bucket { display: flex; align-items: center; gap: 6px; padding: 4px 0; flex-wrap: nowrap; }
.vx-bucket + .vx-bucket { border-top: 1px dashed var(--rule); }
.vx-link { color: var(--muted); font: 700 .9rem var(--font-mono); }
.cell.txt { height: auto; min-height: 34px; padding: 4px 8px; font-size: .78rem; text-align: left; place-items: center start; overflow-wrap: anywhere; }
.vx-loop { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.vx-loop .vx-panel { display: flex; flex-direction: column; gap: 6px; }
.vx-svg.big .vx-lbl { font-size: 13px; }

/* ---------- shared polish: grouped inputs, fitted stages, centred content ---------- */
.viz-inputs:has(> .vx-group) { gap: 10px 22px; }
.vx-group { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.vx-group .btn, .vx-group .field { min-height: 36px; }
.vx-group .field-wrap { gap: 6px; }
.viz-stage.vx-fit { min-height: 0; }
.vx-center { width: max-content; max-width: none; margin-inline: auto; }
.vx-svg.fixed { margin: 0 auto; }
/* diagrams that size themselves to the stage do not need the phone min-width */
.viz-stage > svg.vx-free, .viz-stage > svg.vx-svg.fixed { min-width: 0; }
.vx-svg .vx-mover { transition: transform .4s var(--ease-out); }
.vx-svg .edge.vx-tween { transition: d .4s var(--ease-out), stroke .2s, opacity .2s; }

/* sorting: bars persist between frames so heights tween */
.bars .bar.is-swap { box-shadow: 0 0 0 2px var(--signal); }
@media (max-width: 600px) { .bars { gap: 3px; height: 200px; } .bar { min-width: 0; } .bar span { font-size: .62rem; } }
/* arrays of cells (binary search, queue): tighter on phones so more of the array is visible */
@media (max-width: 600px) {
  .vx-array { gap: 4px; }
  .vx-array .vx-col { min-width: 34px; }
  .vx-array .cell { min-width: 34px; height: 38px; padding: 0 4px; font-size: .85rem; border-radius: 8px; }
}
/* two-part stage: a fixed-width structure on the left and a notes panel, centred together */
.vx-duo { justify-content: center; }
.vx-duo > .vx-duo-a { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.vx-duo > .vx-duo-b { flex: 1 1 260px; max-width: 460px; display: flex; flex-direction: column; gap: 10px; }
.vx-duo .vx-panel p { line-height: 1.5; }
.btn.mono { font-family: var(--font-mono); }
.vx-stats.center { justify-content: center; }
/* linked list */
.vx-ll .vx-lbl { font-size: 13px; }
.vx-ll .node text { font-size: 15px; }
/* trees */
.vx-tree .node text { font-size: 14px; }
.vx-seq.center { text-align: center; }
.vx-seq:empty { display: none; }
/* graph */
.vx-graph .node text { font-size: 16px; }
.vx-graph .vx-lbl { font-size: 13px; }
.vx-graph-wrap { align-items: center; }
.vx-side { display: flex; flex-direction: column; gap: 8px; }
/* big-o */
.vx-bigo .vx-lbl { font-size: 12px; font-weight: 400; }
.vx-bigo .vx-lbl.axis { font-family: var(--font-body); font-weight: 700; }
.vx-nval { font: 700 .85rem var(--font-mono); min-width: 2ch; }
.vx-legend .btn.small { min-height: 32px; }
.vx-duo > .vx-duo-b.wide { max-width: none; flex: 1 1 300px; min-width: 0; }
/* sql joins */
.vx-sqltop { align-items: center; }
.vx-venn .vx-lbl { font-size: 12px; font-family: var(--font-body); }
.vx-table caption { white-space: nowrap; }
/* event loop: code on top at full width, the five areas below */
.vx-evloop { display: grid; gap: 12px; }
.vx-evloop .vx-code { font-size: .86rem; }
.vx-evloop .vx-loop { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.vx-evloop .vx-panel { min-height: 92px; }
@media (max-width: 600px) {
  .vx-evloop .vx-code { font-size: .76rem; }
  .vx-evloop .vx-loop { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .vx-evloop .vx-panel { min-height: 72px; padding: 8px; }
  .vx-evloop .vx-panel:last-child { grid-column: 1 / -1; }
}
