/* Shared interactive visual kit (issue 142); drawn by visual.js from the site's colour tokens. */
.visual { margin: 1.25rem 0; padding: 1rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-panel); max-width: 100%; min-width: 0; }
.visual figcaption { color: var(--color-muted); font-size: var(--type-sm); margin-top: .5rem; }
.visual-plot { position: relative; width: 100%; cursor: crosshair; touch-action: pan-y; user-select: none; -webkit-user-select: none; border-radius: var(--radius-sm); }
.visual-plot:focus-visible { outline: 3px solid var(--color-link); outline-offset: 4px; }
.visual-plot.is-dragging { cursor: grabbing; }
.visual-plot svg { display: block; overflow: visible; }
.visual-readout { margin-top: .5rem; font-family: var(--font-label); font-size: var(--type-sm); font-variant-numeric: tabular-nums; color: var(--color-text); overflow-wrap: anywhere; min-height: 1.5em; }
.visual-tick, .visual-band-label { fill: var(--color-muted); font: 12px var(--font-label); }
.visual-band-label.is-active { fill: var(--color-text); font-weight: 700; }
.visual-grid { stroke: var(--line); stroke-width: 1; }
.visual-axis { stroke: var(--color-border); stroke-width: 1; }
.visual-line { fill: none; stroke: var(--color-link); stroke-width: 2.5; stroke-linejoin: round; }
.visual-line.is-muted { stroke: var(--color-muted); stroke-width: 1.5; stroke-dasharray: 5 4; }
.visual-area { fill: var(--color-link); opacity: .12; }
.visual-guide { stroke: var(--color-link); stroke-width: 1; stroke-dasharray: 3 3; }
.visual-guide.is-hover { stroke: var(--color-muted); }
.visual-ghost { fill: var(--color-muted); }
.visual-handle { fill: var(--color-accent); stroke: var(--color-text); stroke-width: 2; }
.visual-dot { fill: var(--color-surface); stroke: var(--color-text); stroke-width: 2; }
.visual-dot-label { fill: var(--color-text); font: 600 12px var(--font-label); }
.visual-band { fill: var(--color-surface-raised); stroke: var(--color-bg); stroke-width: 2; }
.visual-band.is-active { fill: var(--color-accent); opacity: .55; }
.visual-bar-edge { fill: none; stroke: var(--color-border); stroke-width: 1; }
.visual-marker { fill: var(--color-text); stroke: var(--color-bg); stroke-width: 2; }
.visual-waterfall { --wf-blocked: color-mix(in srgb, var(--color-muted) 40%, transparent); --wf-dns: var(--color-border); --wf-connect: var(--color-muted); --wf-send: color-mix(in srgb, var(--color-link) 45%, var(--color-bg)); --wf-wait: var(--color-link); --wf-receive: var(--color-text); }
.visual-waterfall .visual-plot { max-height: 32rem; overflow-y: auto; cursor: pointer; }
.visual-row { fill: transparent; }
.visual-row.is-hover { fill: var(--color-text); opacity: .07; }
.visual-row.is-selected { fill: var(--color-link); opacity: .2; }
.visual-bar { fill: var(--color-surface-raised); stroke: var(--color-border); stroke-width: .5; }
.visual-bar.is-muted { stroke-dasharray: 3 2; }
.visual-phase, .visual-swatch { pointer-events: none; }
.visual-phase-blocked { fill: var(--wf-blocked); background: var(--wf-blocked); }
.visual-phase-dns { fill: var(--wf-dns); background: var(--wf-dns); }
.visual-phase-connect { fill: var(--wf-connect); background: var(--wf-connect); }
.visual-phase-send { fill: var(--wf-send); background: var(--wf-send); }
.visual-phase-wait { fill: var(--wf-wait); background: var(--wf-wait); }
.visual-phase-receive { fill: var(--wf-receive); background: var(--wf-receive); }
.visual-legend { list-style: none; display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin: .5rem 0 0; padding: 0; color: var(--color-muted); font-size: var(--type-sm); }
.visual-legend:empty { display: none; }
.visual-swatch { display: inline-block; width: .8em; height: .8em; border-radius: 2px; margin-right: .35em; vertical-align: -.05em; }
.visual-entropy { --en-high: var(--color-accent); --en-mid: color-mix(in srgb, var(--color-link) 55%, var(--color-muted)); --en-text: var(--color-link); --en-low: var(--color-muted); }
.visual-entropy .visual-plot { cursor: pointer; }
.visual-col { fill: transparent; pointer-events: none; }
.visual-col.is-hover { fill: var(--color-text); opacity: .1; }
.visual-col.is-selected { fill: var(--color-text); opacity: .4; }
.visual-entropy .visual-bar { stroke: none; pointer-events: none; }
.visual-entropy .visual-bar.is-high, .visual-entropy-high { fill: var(--en-high); background: var(--en-high); }
.visual-entropy .visual-bar.is-mid, .visual-entropy-mid { fill: var(--en-mid); background: var(--en-mid); }
.visual-entropy .visual-bar.is-text, .visual-entropy-text { fill: var(--en-text); background: var(--en-text); }
.visual-entropy .visual-bar.is-low, .visual-entropy-low { fill: var(--en-low); background: var(--en-low); }
/* :root too, so a page can colour its own legend or rows to match the strip. */
:root, .visual-strip { --st-k0: var(--color-link); --st-k1: #f2c46d; --st-k2: #7fd6c2; --st-k3: #e59bd1; --st-k4: #ff8a7a; --st-k5: var(--color-muted); }
.visual-strip .visual-plot { cursor: pointer; }
.visual-strip-bed { fill: var(--color-bg); stroke: var(--line); stroke-width: 1; }
.visual-strip .visual-bar { stroke: none; pointer-events: none; }
.visual-strip .visual-col.is-selected { fill: var(--color-text); opacity: .45; }
.visual-strip .visual-bar.visual-strip-k0, .visual-strip-k0 { fill: var(--st-k0); background: var(--st-k0); }
.visual-strip .visual-bar.visual-strip-k1, .visual-strip-k1 { fill: var(--st-k1); background: var(--st-k1); }
.visual-strip .visual-bar.visual-strip-k2, .visual-strip-k2 { fill: var(--st-k2); background: var(--st-k2); }
.visual-strip .visual-bar.visual-strip-k3, .visual-strip-k3 { fill: var(--st-k3); background: var(--st-k3); }
.visual-strip .visual-bar.visual-strip-k4, .visual-strip-k4 { fill: var(--st-k4); background: var(--st-k4); }
.visual-strip .visual-bar.visual-strip-k5, .visual-strip-k5 { fill: var(--st-k5); background: var(--st-k5); }
/* groups: one bar per group with its count (141d APK inspector). */
.visual-groups .visual-plot { cursor: pointer; }
.visual-group-label { fill: var(--color-text); font: 13px var(--font-label); }
.visual-group-label.is-empty { fill: var(--color-muted); }
.visual-group-label.is-active { font-weight: 700; }
.visual-group-track { fill: var(--color-bg); stroke: var(--line); stroke-width: 1; }
.visual-groups .visual-bar.visual-group-bar { fill: var(--color-link); stroke: none; pointer-events: none; }
.visual-group-count { fill: var(--color-text); }
/* blocks: a file's parts as one proportional ribbon (141e binary inspector); same palette as the strip. */
.visual-blocks .visual-plot { cursor: pointer; }
.visual-blocks .visual-bar { stroke: var(--color-surface); stroke-width: 1; pointer-events: none; }
.visual-blocks .visual-bar.visual-blocks-k0, .visual-blocks-k0 { fill: var(--st-k0); background: var(--st-k0); }
.visual-blocks .visual-bar.visual-blocks-k1, .visual-blocks-k1 { fill: var(--st-k1); background: var(--st-k1); }
.visual-blocks .visual-bar.visual-blocks-k2, .visual-blocks-k2 { fill: var(--st-k2); background: var(--st-k2); }
.visual-blocks .visual-bar.visual-blocks-k3, .visual-blocks-k3 { fill: var(--st-k3); background: var(--st-k3); }
.visual-blocks .visual-bar.visual-blocks-k4, .visual-blocks-k4 { fill: var(--st-k4); background: var(--st-k4); }
.visual-blocks .visual-bar.visual-blocks-k5, .visual-blocks-k5 { fill: var(--st-k5); background: var(--st-k5); }
.visual-blocks .visual-bar.visual-blocks-km, .visual-blocks-km { fill: color-mix(in srgb, var(--color-muted) 55%, var(--color-surface)); background: color-mix(in srgb, var(--color-muted) 55%, var(--color-surface)); }
.visual-part-label { fill: var(--color-bg); font: 600 12px var(--font-label); pointer-events: none; }
.visual-part-mark { pointer-events: none; }
.visual-part-mark.is-hover rect { fill: var(--color-text); opacity: .18; }
.visual-part-mark.is-selected rect { fill: none; stroke: var(--color-text); stroke-width: 2.5; }
/* tree: a collapsible tree of counted nodes as HTML rows (141f HAR to OpenAPI; meant for 141h's type tree too). */
.visual-tree .visual-plot { max-height: 30rem; overflow-y: auto; cursor: pointer; border: 1px solid var(--line); background: var(--color-bg); }
.visual-tree-row { position: relative; display: flex; align-items: center; gap: .4rem; box-sizing: border-box; padding-right: .6rem; font: 13px var(--font-label); color: var(--color-text); white-space: nowrap; min-width: 0; }
.visual-tree-row > * { position: relative; }
.visual-tree-row > .visual-tree-fill { position: absolute; top: 4px; bottom: 4px; background: var(--color-link); opacity: .11; border-radius: 2px; pointer-events: none; }
.visual-tree-row.is-hover { background: color-mix(in srgb, var(--color-text) 8%, transparent); }
.visual-tree-row.is-selected { background: color-mix(in srgb, var(--color-link) 24%, transparent); box-shadow: inset 3px 0 0 var(--color-link); }
.visual-tree-twisty { flex: none; width: 1rem; height: 1rem; }
.visual-tree-twisty.has-kids::before { content: ""; position: absolute; left: .3rem; top: .2rem; border-left: 7px solid var(--color-muted); border-top: 5px solid transparent; border-bottom: 5px solid transparent; transition: transform .1s; }
.visual-tree-twisty.is-open::before { transform: rotate(90deg); }
.visual-tree-badge { flex: none; padding: 0 .35rem; border-radius: 3px; font-size: 11px; font-weight: 700; line-height: 1.6; color: var(--color-bg); }
.visual-tree-dot { flex: none; width: .6rem; height: .6rem; border-radius: 50%; }
.visual-tree-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.visual-tree-row.is-selected .visual-tree-label { font-weight: 700; }
.visual-tree-count { flex: none; color: var(--color-muted); font-variant-numeric: tabular-nums; }
.visual-tree-empty { margin: 0; padding: .75rem; color: var(--color-muted); text-align: center; }
.visual-tree-k0 { background: var(--st-k0); }
.visual-tree-k1 { background: var(--st-k1); }
.visual-tree-k2 { background: var(--st-k2); }
.visual-tree-k3 { background: var(--st-k3); }
.visual-tree-k4 { background: var(--st-k4); }
.visual-tree-k5 { background: var(--st-k5); }
.visual-tree-km { background: color-mix(in srgb, var(--color-muted) 55%, var(--color-surface)); }
/* compare: before/after of the visitor's own picture with a draggable divider (142d upscaler, background remover). */
.visual figcaption { font-weight: 400; }
.visual-compare { --cmp-a: color-mix(in srgb, var(--color-text) 14%, var(--color-bg)); --cmp-b: var(--color-bg); }
.visual-compare .visual-plot { cursor: ew-resize; overflow: hidden; }
.visual-compare .visual-plot.is-zoomed { overflow: auto; cursor: grab; touch-action: none; overscroll-behavior: contain; border: 1px solid var(--line); background: var(--color-bg); }
.visual-compare .visual-plot.is-panning { cursor: grabbing; }
.visual-compare-stage { position: relative; margin: 0 auto; overflow: hidden; }
.visual-compare-stage.is-checker { background: repeating-conic-gradient(var(--cmp-a) 0 25%, var(--cmp-b) 0 50%) 0 0 / 20px 20px; }
.visual-compare-before, .visual-compare-after { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; -webkit-user-drag: none; }
.visual-compare-divider { position: absolute; top: 0; bottom: 0; width: 24px; margin-left: -12px; cursor: ew-resize; }
.visual-compare-divider::after { content: ""; position: absolute; top: 0; bottom: 0; left: 11px; width: 2px; background: var(--color-bg); box-shadow: 0 0 0 1px var(--color-text); }
.visual-compare-handle { position: absolute; width: 34px; height: 34px; margin: -17px 0 0 -17px; border-radius: 50%; background: var(--color-accent); border: 2px solid var(--color-text); box-shadow: 0 1px 4px rgba(0, 0, 0, .35); cursor: ew-resize; }
.visual-compare-handle::before, .visual-compare-handle::after { content: ""; position: absolute; top: 10px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.visual-compare-handle::before { left: 5px; border-right: 7px solid var(--color-text); }
.visual-compare-handle::after { right: 5px; border-left: 7px solid var(--color-text); }
.visual-compare-tag { position: absolute; padding: 0 .4rem; border-radius: 3px; background: color-mix(in srgb, var(--color-bg) 82%, transparent); color: var(--color-text); font: 600 12px/1.6 var(--font-label); white-space: nowrap; pointer-events: none; }
.visual-compare-tag.is-after { transform: translateX(-100%); }
.visual-compare-empty { margin: 0; padding: 2.5rem 1rem; border: 1px dashed var(--color-border); border-radius: var(--radius-sm); color: var(--color-muted); text-align: center; }
.visual-toolbar { display: flex; justify-content: flex-end; margin-bottom: .5rem; }
.visual-toolbar[hidden] { display: none; }
