/* Spot the Violation - sandbox.css
 * Wiring sandbox page (sandbox.html). Loads after css/app.css and reuses its tokens and components.
 * Sandbox-only tokens: framing, wall cavity, tape, the inspector's clipboard. Dark mode mirrors app.css.
 */

:root {
  --sbx-cavity: #e9dfc9;          /* OSB / sheathing seen between the studs */
  --sbx-fleck: rgba(120, 90, 40, 0.18);
  --sbx-wood: #dcb57e;
  --sbx-wood-edge: #a77d43;
  --sbx-grain: rgba(120, 78, 24, 0.28);
  --sbx-plate: #d2a76b;
  --sbx-joist: #c99a5b;
  --sbx-attic: #f1ece2;
  --sbx-label-halo: rgba(255, 255, 255, 0.92);
  --sbx-tape: #f4c430;
  --sbx-tape-ink: #2b2410;
  --sbx-hole: #3b2a14;
  --sbx-hole-rim: #f3d9b0;
  --sbx-paper: #fffdf6;
  --sbx-paper-line: rgba(47, 79, 127, 0.10);
  --sbx-clip: #8b939b;
  --sbx-stage: #e9ecef;
  --sbx-stage-dot: rgba(0, 0, 0, 0.06);
  --sbx-live: rgba(255, 166, 0, 0.55);
  --sbx-toast-accent: #ff9a5c;    /* the snackbar's Undo on the dark toast (the toast inverts the theme) */
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --sbx-cavity: #3a3428;
    --sbx-fleck: rgba(255, 230, 180, 0.08);
    --sbx-wood: #9a7547;
    --sbx-wood-edge: #6b4e2a;
    --sbx-grain: rgba(40, 24, 6, 0.4);
    --sbx-plate: #8c6a3f;
    --sbx-joist: #82623a;
    --sbx-attic: #2a2722;
    --sbx-label-halo: rgba(20, 22, 25, 0.9);
    --sbx-tape: #d8ab22;
    --sbx-hole: #120c05;
    --sbx-hole-rim: #c7a978;
    --sbx-paper: #20232a;
    --sbx-paper-line: rgba(169, 196, 240, 0.07);
    --sbx-clip: #6b737b;
    --sbx-stage: #171a1e;
    --sbx-stage-dot: rgba(255, 255, 255, 0.05);
    --sbx-live: rgba(255, 176, 30, 0.6);
    --sbx-toast-accent: #b8470a;
  }
}
:root[data-theme="dark"] {
  --sbx-cavity: #3a3428;
  --sbx-fleck: rgba(255, 230, 180, 0.08);
  --sbx-wood: #9a7547;
  --sbx-wood-edge: #6b4e2a;
  --sbx-grain: rgba(40, 24, 6, 0.4);
  --sbx-plate: #8c6a3f;
  --sbx-joist: #82623a;
  --sbx-attic: #2a2722;
  --sbx-label-halo: rgba(20, 22, 25, 0.9);
  --sbx-tape: #d8ab22;
  --sbx-hole: #120c05;
  --sbx-hole-rim: #c7a978;
  --sbx-paper: #20232a;
  --sbx-paper-line: rgba(169, 196, 240, 0.07);
  --sbx-clip: #6b737b;
  --sbx-stage: #171a1e;
  --sbx-stage-dot: rgba(255, 255, 255, 0.05);
  --sbx-live: rgba(255, 176, 30, 0.6);
  --sbx-toast-accent: #b8470a;
}

/* ---------- page ---------- */
.sbx-view { --maxw: 1440px; max-width: var(--maxw); padding-top: 16px; }
/* the site header and footer line up with the sandbox's wider column: brand, job card and footer text share x = 16 */
body.page-sandbox .site-header .wrap, body.page-sandbox .site-footer .wrap { max-width: 1440px; }
/* while the phone menu is open, the fixed dock goes under the header and its scrim (still visible; a tap outside the
   menu only closes it, as anywhere else on the page) */
body.page-sandbox:has(#site-nav.is-open) .sbx-dock, body.page-sandbox:has(#site-nav.is-open) #toast { z-index: 15; }
.sbx-view, .bx-dialog { -webkit-tap-highlight-color: transparent; }
body.has-dialog { overflow: hidden; }

/* ---------- job header ---------- */
.sbx-job { display: grid; gap: 8px; margin-bottom: 14px; padding: 14px 16px; }
/* the top row: the eyebrow, then Reset job and the job picker together at the right (the picker keeps its corner and
   its right-aligned popover); below 720 px the pair takes a row of its own under the eyebrow, Reset job at the left */
.sbx-job-top { display: flex; align-items: center; justify-content: space-between; gap: 6px 10px; flex-wrap: wrap; }
.sbx-job-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
@media (max-width: 719px) {
  .sbx-job-actions { flex-basis: 100%; justify-content: space-between; margin-left: 0; }
}
.sbx-eyebrow { margin: 0; }
.sbx-eyebrow .icon { width: 16px; height: 16px; }
.sbx-jobs-toggle { gap: 8px; }
.sbx-jobs-toggle .chev { width: 18px; height: 18px; transition: transform 0.15s; }
.sbx-jobs-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.sbx-jobs-count { font-weight: 600; color: var(--muted); font-size: 0.8rem; }
.sbx-job-title { margin: 2px 0 0; font-size: 1.45rem; }
.sbx-job-title:focus { outline: none; }
.sbx-job-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.sbx-job-meta .pill .icon { width: 1em; height: 1em; }
.sbx-job-body { display: grid; gap: 12px; margin-top: 4px; }
.sbx-job-text { min-width: 0; }
.sbx-job-intro { margin: 0 0 6px; max-width: 64em; }
.sbx-task { margin: 0; padding-left: 1.2rem; display: grid; gap: 2px; font-size: 0.95rem; }
.sbx-hints { border: 1px dashed var(--border-strong); border-radius: var(--radius); padding: 10px 12px; background: var(--surface-2); align-self: start; min-width: 0; }
.sbx-hints .section-title { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.sbx-hints .section-title .icon { width: 16px; height: 16px; color: var(--warn-text); }
.sbx-hint-list { margin: 0 0 8px; padding-left: 1.2rem; display: grid; gap: 4px; font-size: 0.92rem; }
@media (min-width: 900px) {
  .sbx-job-body { grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); align-items: start; }
}

/* the job picker: a popover right-aligned under its toggle, over the briefing; it scrolls inside when long */
.sbx-jobs-anchor { position: relative; }
.sbx-jobs {
  position: absolute; z-index: 30; top: calc(100% + 6px); right: 0; width: min(640px, calc(100vw - 32px)); max-height: 70vh; overflow: auto; overscroll-behavior: contain;
  padding: 10px; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.sbx-jobs[hidden] { display: none; }
.sbx-joblist { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }
.sbx-jobbtn {
  width: 100%; min-height: 52px; display: flex; align-items: center; gap: 10px; padding: 8px 10px; text-align: left;
  border: 1.5px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); cursor: pointer;
}
.sbx-jobbtn:hover { border-color: var(--accent); }
.sbx-jobbtn.is-current { border-color: var(--accent); background: var(--accent-soft); }
.sbx-jobnum { flex: none; width: 30px; height: 30px; border-radius: 50%; display: inline-grid; place-items: center; background: var(--surface-3); font-weight: 800; font-size: 0.85rem; }
.sbx-jobbtn.is-done .sbx-jobnum { background: var(--ok); color: #fff; }
.sbx-jobnum .icon { width: 16px; height: 16px; }
.sbx-jobtext { display: grid; min-width: 0; flex: 1; }
.sbx-jobname { font-weight: 700; line-height: 1.25; }
.sbx-jobsub { font-size: 0.78rem; color: var(--muted); }

/* ---------- three panels ---------- */
.sbx-layout { display: grid; gap: 14px; grid-template-columns: minmax(0, 1fr); grid-template-areas: "tools" "wall" "test" "lists"; align-items: start; }
.sbx-tools { grid-area: tools; display: grid; gap: 10px; padding: 12px; min-width: 0; }
.sbx-wall { grid-area: wall; padding: 10px; min-width: 0; }
.sbx-lists { grid-area: lists; padding: 12px; min-width: 0; display: grid; gap: 8px; }
.sbx-test { grid-area: test; min-width: 0; position: relative; }
.sbx-tools .section-title, .sbx-lists .section-title { margin: 0; }
@media (min-width: 1100px) {
  .sbx-layout {
    grid-template-columns: 228px minmax(0, 1fr) 330px;
    grid-template-areas: "tools wall test" "lists wall test";
    grid-template-rows: auto 1fr;
  }
  /* sticky beside the wall only while the whole card fits the window (JS sets .is-tall); results never scroll inside it */
  .sbx-test { position: sticky; top: 12px; }
  .sbx-test.is-tall { position: static; }
}

/* tools */
.sbx-toolseg { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.sbx-tool {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 52px; padding: 6px 4px;
  border: 1.5px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); cursor: pointer; font-weight: 700; font-size: 0.78rem; position: relative;
}
.sbx-tool:hover { border-color: var(--muted); }
.sbx-tool .icon { width: 20px; height: 20px; }
.sbx-tool[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); }
.sbx-tool-key { position: absolute; top: 3px; right: 3px; font-size: 0.62rem; min-width: 1.3em; padding: 0 3px; display: none; }
@media (hover: hover) and (pointer: fine) { .sbx-tool-key { display: inline-block; } }
@media (min-width: 1100px) {
  .sbx-toolseg { grid-template-columns: 1fr 1fr; }
}
/* cable types: single-choice option buttons (.opt-group), 2 x 2 in the sidebar */
.sbx-cabletypes { display: flex; flex-wrap: wrap; gap: 6px; }
@media (min-width: 1100px) { .sbx-cabletypes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sbx-cable-chip { gap: 6px; }
.sbx-history { gap: 6px; }
.sbx-history .btn { padding-left: 10px; padding-right: 10px; }
.sbx-history .icon, .sbx-reset .icon, .sbx-zoom .icon, .sbx-openbox .icon { width: 16px; height: 16px; }
.sbx-reset-confirm { padding: 10px 12px; }

/* swatches used in legends and chips */
.sbx-sw { display: inline-block; width: 22px; height: 9px; border-radius: 5px; flex: none; vertical-align: middle; border: 1.5px solid; position: relative; }
.sbx-sw.is-nm14 { background: #f2efe6; border-color: #7f796c; }
.sbx-sw.is-nm12 { background: #f4c63d; border-color: #8d6c0d; }
.sbx-sw.is-three, .sbx-sw.has-stripe { background-image: linear-gradient(transparent 3px, #c92a2a 3px, #c92a2a 4.5px, transparent 4.5px); }
.sbx-sw.is-three { background-color: #f2efe6; border-color: #7f796c; }
.sbx-sw.is-hole { width: 12px; height: 12px; border-radius: 50%; background: var(--sbx-hole); border: 2px solid var(--sbx-hole-rim); }
.sbx-sw.is-staple { width: 14px; height: 9px; border: 2.5px solid #6b7280; border-bottom: 0; border-radius: 7px 7px 0 0; background: none; }

/* lists */
.sbx-boxlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sbx-boxbtn {
  width: 100%; display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 6px 10px; text-align: left;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); cursor: pointer;
}
.sbx-boxbtn:hover { border-color: var(--accent); }
.sbx-boxbtn > .icon { color: var(--muted); }
.sbx-boxbtn-text { display: grid; min-width: 0; line-height: 1.25; }
.sbx-boxbtn-text span { font-size: 0.8rem; color: var(--muted); }
.sbx-cablelist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sbx-cableitem { border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 10px; background: var(--surface-2); display: grid; gap: 6px; min-width: 0; }
.sbx-cableitem-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* the cable's trash sits on the title's first line, however many lines the title takes */
.sbx-cableitem-head > .sbx-rm { align-self: flex-start; }
.sbx-cableitem-title { flex: 1; min-width: 0; font-size: 0.88rem; }
.sbx-rm { min-height: 36px; padding: 4px 8px; }
.sbx-rm .icon { width: 16px; height: 16px; }
.sbx-runs { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sbx-run { display: grid; gap: 4px; padding-top: 6px; border-top: 1px solid var(--border); font-size: 0.85rem; }
.sbx-run-title { font-weight: 700; }
.sbx-staples { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.sbx-staple-chip { min-height: 30px; padding: 3px 8px; font-size: 0.8rem; gap: 4px; }
.sbx-staple-chip .icon { width: 12px; height: 12px; }
.sbx-run-add { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.sbx-pos { width: 76px; min-height: 36px; }
.sbx-run-none { margin: 0; }
@media (min-width: 720px) and (max-width: 1099px) {
  .sbx-lists { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); column-gap: 16px; }
  .sbx-lists > .section-title:nth-of-type(1) { grid-column: 1; grid-row: 1; }
  .sbx-lists > .sbx-boxlist { grid-column: 1; grid-row: 2; align-self: start; }
  .sbx-lists > .section-title:nth-of-type(2) { grid-column: 2; grid-row: 1; }
  .sbx-lists > .sbx-cablelist { grid-column: 2; grid-row: 2; }
}

/* ---------- wall view ---------- */
.sbx-wall-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; padding: 2px 4px 0; }
.sbx-wall-head .section-title { margin: 0; }
.sbx-wall-scale { font-size: 0.78rem; color: var(--muted); }
.sbx-wall-status { margin: 4px 4px 8px; min-height: 1.5em; font-size: 0.9rem; font-weight: 600; color: var(--text); }
.sbx-wall-wrap { position: relative; border-radius: 8px; overflow: hidden; background: var(--sbx-attic); border: 1px solid var(--border); }
.sbx-wall-svg { display: block; width: 100%; height: auto; touch-action: manipulation; user-select: none; -webkit-user-select: none; }
.sbx-wall-wrap[data-tool="run"] .sbx-wall-svg, .sbx-wall-wrap[data-tool="staple"] .sbx-wall-svg { cursor: crosshair; }
.sbx-wall-wrap[data-tool="remove"] .sbx-wall-svg { cursor: not-allowed; }
.sbx-wall-wrap[data-tool="remove"] .sbx-cable-hit, .sbx-wall-wrap[data-tool="remove"] .sbx-staple { cursor: pointer; }
.sbx-wall-svg text { font-family: var(--font); }
.sbx-cavity { fill: var(--sbx-cavity); }
.sbx-cavity-fleck { stroke: var(--sbx-fleck); stroke-width: 1.2; fill: none; stroke-linecap: round; }
.sbx-attic { fill: var(--sbx-attic); }
.sbx-stud, .sbx-plate { fill: var(--sbx-wood); stroke: var(--sbx-wood-edge); stroke-width: 0.8; }
.sbx-plate { fill: var(--sbx-plate); }
.sbx-joist { fill: var(--sbx-joist); stroke: var(--sbx-wood-edge); stroke-width: 0.8; }
.sbx-grain { stroke: var(--sbx-grain); stroke-width: 0.7; fill: none; }
.sbx-band-label { font-size: 10px; font-weight: 700; fill: var(--muted); letter-spacing: 0.04em; text-transform: uppercase; }
.sbx-tape { fill: var(--sbx-tape); stroke: #8d6c0d; stroke-width: 1; }
.sbx-tape-tick { stroke: var(--sbx-tape-ink); stroke-width: 0.8; fill: none; }
.sbx-tape-stud { fill: #c92a2a; }
.sbx-tape-num { font-size: 9.5px; font-weight: 800; fill: var(--sbx-tape-ink); font-family: var(--mono); }
.sbx-hole { fill: var(--sbx-hole); }
.sbx-hole-rim { fill: var(--sbx-hole-rim); opacity: 0.9; }

.sbx-hit { fill: transparent; }
.sbx-box { cursor: pointer; outline: none; }
.sbx-box-ring { fill: none; stroke: transparent; stroke-width: 2.5; }
.sbx-box:hover .sbx-box-ring { stroke: var(--accent); stroke-dasharray: 4 3; }
.sbx-box:focus-visible .sbx-box-ring { stroke: var(--accent); stroke-width: 3; }
.sbx-box.is-from .sbx-box-ring { stroke: var(--accent); stroke-width: 3; stroke-dasharray: none; }
.sbx-boxshape.is-plastic { fill: #2f6fbd; stroke: #173f73; stroke-width: 1; }
.sbx-boxshape.is-metal { fill: #9aa1a9; stroke: #4d545b; stroke-width: 1; }
.sbx-mudring { fill: #c3c8cd; stroke: #6c737a; stroke-width: 0.8; }
.sbx-nailtab { fill: none; stroke: #173f73; stroke-width: 1.2; }
.sbx-panel-can { fill: #858c94; stroke: #3f454b; stroke-width: 1.2; }
.sbx-panel-dead { fill: #b8bec4; stroke: #6c737a; stroke-width: 0.8; }
.sbx-panel-slot { fill: #3a3f45; }
.sbx-panel-slot.is-used { fill: #e8590c; }
.sbx-panel-text { font-size: 10px; font-weight: 800; fill: #1c1e21; letter-spacing: 0.04em; text-transform: uppercase; }
.sbx-box-label { font-size: 10.5px; font-weight: 700; fill: var(--text); paint-order: stroke; stroke: var(--sbx-label-halo); stroke-width: 3.2px; stroke-linejoin: round; }
.sbx-icon-plate { fill: #f6f3ea; stroke: #8a8475; stroke-width: 0.6; }
.sbx-icon-face { fill: none; stroke: #5a554b; stroke-width: 0.9; }
.sbx-icon-btn { fill: #343a40; }
.sbx-icon-toggle { fill: #5a554b; }
.sbx-icon-num { font-size: 5px; font-weight: 800; fill: #2b2b2b; }
.sbx-icon-bulb { fill: #f8f9fa; stroke: #adb5bd; stroke-width: 1; }
.sbx-icon-bulb.is-on { fill: #ffd43b; stroke: #e8590c; }
.sbx-glow { fill: #ffd43b; opacity: 0.35; }

/* the drawn cable lets the pointer through: its hit stroke, in a layer under the boxes, takes the clicks */
.sbx-cable { outline: none; pointer-events: none; }
.sbx-cable-hit { fill: none; stroke: transparent; stroke-width: 14; stroke-linejoin: round; cursor: pointer; }
/* drawn feedback only: markers, badges, highlights and previews never catch a click meant for what is under them */
.sbx-marks, .sbx-preview { pointer-events: none; }
.sbx-cable-focus { fill: none; stroke: transparent; stroke-width: 9; stroke-linejoin: round; stroke-linecap: round; }
.sbx-cable:focus-visible .sbx-cable-focus { stroke: var(--accent); }
.sbx-staple { outline: none; }
.sbx-staple-hit { fill: transparent; }
.sbx-staple-focus { fill: none; stroke: transparent; stroke-width: 2.5; }
.sbx-staple:focus-visible .sbx-staple-focus { stroke: var(--accent); }
.sbx-staple-crown { fill: none; stroke: #4b5563; stroke-width: 2.2; stroke-linecap: round; }
.sbx-staple-legs { stroke: #374151; stroke-width: 1.6; stroke-linecap: round; }
.sbx-staple-crown.is-ghost, .sbx-staple-legs.is-ghost { stroke: var(--accent); }
.sbx-preview-path { fill: none; stroke: var(--accent); stroke-width: 3; stroke-dasharray: 7 5; stroke-linejoin: round; stroke-linecap: round; animation: sbx-march 0.8s linear infinite; }
.sbx-preview-path.is-free { stroke-width: 2; opacity: 0.8; }
.sbx-preview-text { font-size: 11px; font-weight: 800; fill: var(--accent-text); paint-order: stroke; stroke: var(--sbx-label-halo); stroke-width: 3.5px; }
.sbx-remove-ring { fill: rgba(224, 49, 49, 0.18); stroke: var(--bad); stroke-width: 2.4; }
.sbx-remove-path { fill: none; stroke: var(--bad); stroke-width: 7; stroke-opacity: 0.55; stroke-linejoin: round; stroke-linecap: round; }
@keyframes sbx-march { to { stroke-dashoffset: -24; } }

.sbx-mark { stroke: #fff; stroke-width: 1.6; }
.sbx-mark.is-bad { fill: var(--bad); }
.sbx-mark.is-warn { fill: var(--warn); }
.sbx-mark-pulse { fill: none; stroke-width: 2; animation: sbx-pulse 1.6s ease-out infinite; transform-box: fill-box; transform-origin: center; }
.sbx-mark-pulse.is-bad { stroke: var(--bad); }
.sbx-mark-pulse.is-warn { stroke: var(--warn); }
.sbx-mark-glyph { font-size: 9px; font-weight: 900; fill: #fff; pointer-events: none; font-variant-numeric: tabular-nums; }
.sbx-mark-glyph.is-warn { fill: #1d1d1d; }
.sbx-badge { stroke: #fff; stroke-width: 1.4; }
.sbx-badge.is-ok { fill: var(--ok); }
.sbx-badge.is-bad { fill: var(--bad); }
.sbx-badge-glyph { fill: none; stroke: #fff; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* a stale check's marks on the wall (the Test panel fades its own parts, keeping its buttons readable) */
.sbx-marks .is-stale { opacity: 0.45; }
/* a finding clicked in the Test panel: its spot flashes in the error red, never the accent of hover and selection,
   and the other cables step back */
.sbx-flash-ring { fill: none; stroke: var(--bad); stroke-width: 3.5; stroke-dasharray: 6 4; animation: sbx-march 0.6s linear infinite; }
.sbx-flash-path { fill: none; stroke: var(--bad); stroke-width: 9; stroke-opacity: 0.55; stroke-linejoin: round; stroke-linecap: round; animation: sbx-blink 0.9s ease-in-out infinite alternate; }
.sbx-cable.is-dim { opacity: 0.3; }
@keyframes sbx-pulse { from { transform: scale(0.8); opacity: 1; } to { transform: scale(1.7); opacity: 0; } }
@keyframes sbx-blink { from { stroke-opacity: 0.2; } to { stroke-opacity: 0.7; } }

.sbx-tip {
  position: absolute; z-index: 3; pointer-events: none; max-width: 260px; padding: 5px 9px; border-radius: 6px;
  background: rgba(20, 22, 25, 0.88); color: #fff; font-size: 0.78rem; font-weight: 600; line-height: 1.3; white-space: normal;
}
.sbx-legend { list-style: none; margin: 8px 4px 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 0.78rem; color: var(--muted); }
.sbx-legend li { display: inline-flex; align-items: center; gap: 6px; }
.sbx-legend li[hidden] { display: none; }
/* after a check: the wall's numbered finding dot and the green check on a device that tests correct */
.sbx-sw.is-finding, .sbx-sw.is-ok { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid #fff; display: inline-grid; place-items: center; color: #fff; font-style: normal; font-size: 10px; font-weight: 900; line-height: 1; box-shadow: 0 0 0 1px var(--border-strong); }
.sbx-sw.is-finding { background: var(--bad); }
.sbx-sw.is-ok { background: var(--ok); }
.sbx-sw.is-ok .icon { width: 11px; height: 11px; stroke-width: 3; }

/* ---------- test panel: the inspector's clipboard ---------- */
.sbx-test { padding-top: 14px; }
.sbx-clip {
  position: absolute; top: 2px; left: 50%; transform: translateX(-50%); width: 110px; height: 24px; z-index: 2;
  border-radius: 7px 7px 4px 4px; background: linear-gradient(var(--sbx-clip), #5d646b); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
}
.sbx-clip::after { content: ""; position: absolute; left: 50%; top: 5px; width: 34px; height: 8px; transform: translateX(-50%); border-radius: 4px; background: var(--bg); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.4); }
.sbx-test-paper {
  border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow); padding: 22px 14px 14px;
  background-color: var(--sbx-paper);
  background-image: repeating-linear-gradient(transparent 0 27px, var(--sbx-paper-line) 27px 28px);
  display: grid; gap: 10px;
}
.sbx-test-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; border-bottom: 2px solid var(--text); padding-bottom: 4px; }
.sbx-test-title { margin: 0; font-size: 1.15rem; letter-spacing: 0.02em; text-transform: uppercase; }
.sbx-test-sub { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }
.sbx-test-body { display: grid; gap: 8px; }
.sbx-test-row, .sbx-devrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; }
.sbx-test-label { display: grid; min-width: 0; line-height: 1.25; }
.sbx-test-label .small { font-size: 0.78rem; }
.sbx-devlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sbx-devrow { padding: 8px 0; border-top: 1px dashed var(--border-strong); flex-wrap: wrap; }
.sbx-devrow.is-tester { align-items: flex-start; }
.sbx-tester-wrap { display: grid; justify-items: end; gap: 4px; }
.sbx-tester { width: 128px; height: auto; display: block; }
.sbx-tester-name .icon { width: 1em; height: 1em; }
.sbx-bulb-wrap { display: inline-flex; align-items: center; gap: 8px; }
.sbx-bulb { width: 30px; height: 36px; color: var(--muted); }
.sbx-switch {
  display: inline-flex; align-items: center; gap: 8px; min-height: 40px; min-width: 92px; padding: 4px 10px 4px 4px; border-radius: 999px;
  border: 1.5px solid var(--border-strong); background: var(--surface-3); color: var(--text); cursor: pointer; font-weight: 800; font-size: 0.8rem; font-family: var(--mono);
}
.sbx-switch-knob { width: 30px; height: 30px; border-radius: 50%; background: var(--surface); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); transition: transform 0.15s; flex: none; }
.sbx-switch.is-on { background: var(--ok); border-color: var(--ok); color: #fff; }
.sbx-switch.is-on .sbx-switch-knob { transform: translateX(2px); }
.sbx-switch.is-ab.is-on { background: #3b82c4; border-color: #3b82c4; }
.sbx-fault { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: 8px; background: var(--bad); color: #fff; }
.sbx-fault .icon { width: 22px; height: 22px; flex: none; margin-top: 1px; }
.sbx-fault p { margin: 2px 0 0; font-size: 0.88rem; }
/* a GFCI tripped on purpose with its TEST button: a notice, not a fault */
.sbx-fault.is-test { background: var(--surface-2); color: var(--text); border: 1px solid var(--border-strong); }
.sbx-fault.is-test .icon { color: var(--bad); }
.sbx-devrow > .sbx-gfci-btn { margin-left: auto; align-self: center; min-width: 74px; font-weight: 800; letter-spacing: 0.04em; }
.sbx-devrow > .pill + .sbx-gfci-btn { margin-left: 8px; }
.sbx-gfci-btn.is-tripped { border-color: var(--bad); color: var(--bad); }
.sbx-note { display: flex; gap: 8px; align-items: flex-start; margin: 0; padding: 8px 10px; border-radius: 8px; background: var(--info-soft); color: var(--text); font-size: 0.85rem; }
.sbx-note .icon { color: var(--info-text); width: 18px; height: 18px; flex: none; }
.sbx-check { width: 100%; }
.sbx-results { display: grid; gap: 8px; }
.sbx-results-empty { margin: 0; }
.sbx-score { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--radius); border: 2px solid; }
.sbx-score:focus { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.sbx-score.is-complete, .sbx-score.is-clean { border-color: var(--ok); background: var(--ok-soft); }
.sbx-score.is-open { border-color: var(--bad); background: var(--bad-soft); }
/* a check made before the latest change: the verdict fades, its buttons stay usable */
.sbx-score.is-stale > .sbx-score-icon, .sbx-score.is-stale > .sbx-score-text { opacity: 0.6; }
.sbx-score-icon { width: 34px; height: 34px; border-radius: 50%; display: inline-grid; place-items: center; color: #fff; flex: none; }
.sbx-score.is-complete .sbx-score-icon, .sbx-score.is-clean .sbx-score-icon { background: var(--ok); }
.sbx-score.is-open .sbx-score-icon { background: var(--bad); }
.sbx-score-icon .icon { width: 20px; height: 20px; }
.sbx-score-text { display: grid; min-width: 0; }
.sbx-score-title { font-size: 1.15rem; }
.sbx-score.is-complete .sbx-score-title { color: var(--ok-text); }
.sbx-score.is-open .sbx-score-title { color: var(--bad-text); }
.sbx-score-sub { font-size: 0.8rem; color: var(--muted); font-family: var(--mono); }
/* "Job complete": the way forward (Next job, All jobs) under the verdict; Next is full width on a phone */
.sbx-score { flex-wrap: wrap; }
.sbx-score-text { flex: 1 1 0; }
.sbx-next-row { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* both full width at every width: Next job (the primary, trailing arrow) over the tertiary All jobs */
.sbx-next-job, .sbx-all-jobs { flex: 1 1 100%; min-height: 44px; justify-content: center; text-align: center; }
.sbx-stale-note { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; margin: 0; color: var(--warn-text); font-weight: 600; }
.sbx-stale-note .icon { width: 16px; height: 16px; }
.sbx-stale-note > span { flex: 1 1 12em; min-width: 0; }
.sbx-again { flex: none; min-height: 32px; padding: 3px 10px; }
/* a stale check's goals and findings fade with its verdict (their Open <box> buttons still work) */
.sbx-goals.is-stale, .sbx-findings.is-stale { opacity: 0.55; }
.sbx-res-h { margin: 6px 0 0; font-size: 0.75rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.sbx-res-h.is-violation { color: var(--bad-text); }
.sbx-res-h.is-warning { color: var(--warn-text); }
.sbx-goals { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sbx-goals li { display: flex; gap: 8px; align-items: flex-start; font-size: 0.9rem; }
.sbx-goal-mark { flex: none; width: 22px; height: 22px; border-radius: 50%; display: inline-grid; place-items: center; color: #fff; margin-top: 1px; }
.sbx-goals .is-pass .sbx-goal-mark { background: var(--ok); }
.sbx-goals .is-fail .sbx-goal-mark { background: var(--bad); }
.sbx-goal-mark .icon { width: 14px; height: 14px; }
.sbx-goal-detail { display: block; font-size: 0.8rem; color: var(--muted); }
.sbx-findings { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sbx-finding { display: grid; gap: 2px; }
.sbx-finding-btn {
  display: grid; gap: 4px; justify-items: start; width: 100%; text-align: left; padding: 8px 10px; cursor: pointer;
  border: 1px solid var(--border); border-left: 4px solid var(--border-strong); border-radius: 8px; background: var(--surface); color: var(--text); font-size: 0.88rem;
}
/* a finding's hover is its own severity color: findings never use the accent of hover and selection elsewhere */
.sbx-finding-btn:hover { border-color: var(--border-strong); }
.sbx-finding.is-violation .sbx-finding-btn:hover { border-color: var(--bad); }
.sbx-finding.is-warning .sbx-finding-btn:hover { border-color: var(--warn); }
.sbx-finding-btn[aria-disabled="true"] { cursor: default; }
.sbx-finding.is-violation .sbx-finding-btn { border-left-color: var(--bad); }
.sbx-finding.is-warning .sbx-finding-btn { border-left-color: var(--warn); }
.sbx-finding.is-tip .sbx-finding-btn { border-left-color: var(--info-text); }
.sbx-finding-top { display: flex; gap: 6px; align-items: flex-start; }
.sbx-sev .icon { width: 16px; height: 16px; margin-top: 2px; }
/* a violation's or warning's number, the same as on its wall marker */
.sbx-fnum { flex: none; display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; margin-top: 0; border-radius: 10px; background: var(--bad); color: #fff; font-size: 0.75rem; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
.sbx-finding.is-warning .sbx-fnum { background: var(--warn); color: #1d1d1d; }
.sbx-finding.is-violation .sbx-sev { color: var(--bad-text); }
.sbx-finding.is-warning .sbx-sev { color: var(--warn-text); }
.sbx-finding.is-tip .sbx-sev { color: var(--info-text); }
.sbx-finding-title { line-height: 1.3; }
.sbx-nec { display: inline-block; padding: 2px 7px; border-radius: 4px; background: var(--text); color: var(--surface); font-family: var(--mono); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.02em; }
.sbx-finding-detail { color: var(--text); line-height: 1.4; }
.sbx-finding-ref { font-size: 0.75rem; color: var(--muted); }
.sbx-openbox { justify-self: start; }
/* a failed goal: the boxes that still hold loose conductors, each with its Open <box> */
.sbx-loose { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sbx-loose li { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; justify-content: space-between; font-size: 0.9rem; }
.sbx-solution, .sbx-solution-note { padding: 10px 12px; border-radius: 8px; background: var(--warn-soft); display: grid; gap: 8px; justify-items: start; margin: 0; font-size: 0.88rem; }
.sbx-solution-note { display: flex; gap: 8px; align-items: flex-start; }
.sbx-solution-note .icon, .sbx-solution-btn .icon { width: 18px; height: 18px; flex: none; }
.sbx-solution p { margin: 0; }

/* ---------- box view dialog ---------- */
.bx-dialog {
  width: min(1120px, calc(100vw - 32px)); height: min(860px, calc(100vh - 32px)); max-width: none; max-height: none; padding: 0;
  border: 1px solid var(--border-strong); border-radius: 14px; background: var(--surface); color: var(--text); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; overflow: hidden;
}
.bx-dialog:not([open]) { display: none; }
.bx-dialog::backdrop { background: rgba(10, 12, 14, 0.62); }
.bx-head { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px 8px; border-bottom: 1px solid var(--border); }
.bx-head-text { flex: 1; min-width: 0; }
.bx-title { margin: 0; font-size: 1.15rem; }
.bx-sub { margin: 2px 0 0; font-size: 0.85rem; color: var(--muted); }
/* X: a borderless icon button, as big as Undo and Redo beside it, 12 px apart from that pair */
.bx-close { flex: none; width: 36px; height: 36px; margin-left: 12px; }
.bx-close .icon { width: 20px; height: 20px; }
@media (pointer: coarse) { .bx-close { width: 44px; height: 44px; } }
.bx-bar { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; padding: 8px 14px; border-bottom: 1px solid var(--border); background: var(--surface-2); }
.bx-group { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.bx-group-label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin-right: 2px; }
.bx-chip { min-height: 36px; }
.bx-chip.btn-sm { font-weight: 600; }
.bx-device-name { font-size: 0.92rem; }
.bx-seg button { min-height: 34px; padding: 5px 12px; }
.bx-status { padding: 6px 14px; min-height: 46px; border-bottom: 1px solid var(--border); display: flex; align-items: center; }
.bx-hint { margin: 0; font-size: 0.85rem; color: var(--muted); }
.bx-hint strong { color: var(--text); }
.bx-kbd-hint { display: none; }
@media (hover: hover) and (pointer: fine) { .bx-kbd-hint { display: inline; } .kbd.bx-kbd-hint { display: inline-block; } }
.bx-selrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; width: 100%; }
.bx-seltext { margin: 0; font-size: 0.88rem; flex: 1 1 260px; min-width: 0; }
.bx-swatch { display: inline-block; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(0, 0, 0, 0.45); flex: none; vertical-align: -3px; box-shadow: 0 0 0 1px var(--border-strong); }
.bx-acts { gap: 6px; }
.bx-acts .btn { min-height: 36px; }
.bx-pig-btn { gap: 6px; }
.bx-stage {
  flex: 1 1 auto; min-height: 0; position: relative; padding: 6px;
  background-color: var(--sbx-stage);
  background-image: radial-gradient(var(--sbx-stage-dot) 1px, transparent 1.2px);
  background-size: 16px 16px;
}
.bx-svg { display: block; width: 100%; height: 100%; touch-action: none; user-select: none; -webkit-user-select: none; }
.bx-svg text { font-family: var(--font); pointer-events: none; }
.bx-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; padding: 8px 14px 10px; border-top: 1px solid var(--border); }
.bx-fill { flex: 1 1 300px; min-width: 0; display: grid; gap: 4px; }
.bx-fill-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.bx-fill-label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.bx-fill-num { font-family: var(--mono); font-weight: 800; font-size: 0.9rem; }
.bx-fill-bar { height: 10px; border-radius: 5px; background: var(--surface-3); overflow: hidden; border: 1px solid var(--border); }
.bx-fill-bar > span { display: block; height: 100%; background: var(--ok); transition: width 0.2s; }
.bx-fill.is-over .bx-fill-bar > span { background: var(--bad); }
.bx-fill.is-over .bx-fill-num { color: var(--bad-text); }
.bx-fill-items { font-size: 0.8rem; }
.bx-fill-items summary { cursor: pointer; color: var(--muted); font-weight: 600; }
.bx-fill-items ul { margin: 4px 0 0; padding-left: 1.1rem; }
.bx-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 0.75rem; color: var(--muted); }
.bx-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.bx-screw-swatch { width: 12px; height: 12px; border-radius: 50%; display: inline-block; border: 1.5px solid rgba(0, 0, 0, 0.5); }
.bx-screw-swatch.is-brass { background: radial-gradient(circle at 35% 35%, #f6d37a, #b07f1c); }
.bx-screw-swatch.is-silver { background: radial-gradient(circle at 35% 35%, #fbfcfd, #9aa1a9); }
.bx-screw-swatch.is-green { background: radial-gradient(circle at 35% 35%, #6fdc87, #1f7a36); }
.bx-screw-swatch.is-black { background: radial-gradient(circle at 35% 35%, #777, #151515); box-shadow: 0 0 0 1px var(--border-strong); }
.bx-live-swatch { width: 18px; height: 8px; border-radius: 4px; background: #26272b; box-shadow: 0 0 0 3px var(--sbx-live); display: inline-block; }

/* drawing: box shell */
.bx-shell.is-plastic { fill: #2b66b1; stroke: #143a6b; stroke-width: 2.5; }
.bx-back.is-plastic { fill: #3d7cc6; }
.bx-shell.is-metal { fill: #8f969e; stroke: #474e55; stroke-width: 2.5; }
.bx-back.is-metal { fill: #b4bac0; }
.bx-shell.is-panel { fill: #7a8189; stroke: #3b4147; stroke-width: 2.5; }
.bx-back.is-panel { fill: #a3a9b0; }
.bx-rib { stroke: rgba(10, 30, 60, 0.35); stroke-width: 2; fill: none; }
.bx-ko { fill: none; stroke: rgba(40, 45, 50, 0.35); stroke-width: 2; }
.bx-mark-text { font-size: 12px; font-weight: 800; letter-spacing: 0.08em; fill: rgba(255, 255, 255, 0.55); }
.bx-back.is-metal ~ .bx-mark-text, .bx-shell.is-metal ~ .bx-mark-text { fill: rgba(30, 35, 40, 0.5); }
.bx-sheath { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.25)); }
.bx-clamp { fill: #c3c8cd; stroke: #5d646b; stroke-width: 1.5; }
.bx-clamp-screw { fill: #8d959c; stroke: #3f454b; }
.bx-ko-tab { fill: rgba(10, 30, 60, 0.35); stroke: rgba(10, 30, 60, 0.6); stroke-width: 1.5; }
.bx-label { font-size: 12px; font-weight: 800; fill: var(--text); paint-order: stroke; stroke: var(--sbx-stage); stroke-width: 4px; stroke-linejoin: round; letter-spacing: 0.02em; }
.bx-label-sm { font-size: 10.5px; fill: #e9f7ec; stroke: rgba(0, 0, 0, 0.55); }
.bx-entry-label { font-size: 12.5px; }
.bx-term-label { font-size: 11px; fill: var(--text); }
.bx-dev-text { font-size: 11.5px; font-weight: 800; fill: #3a3632; stroke: none; letter-spacing: 0.04em; }
.bx-dev-text.is-tiny { font-size: 9.5px; }
.bx-dev-text.is-light { fill: #f1f3f5; }
.bx-dev-text.is-warn { fill: #c62828; font-size: 12px; }
.bx-dev-text.is-on { fill: #b35c00; }
.bx-labels .bx-dev-text { paint-order: normal; }
.bx-empty-text { font-size: 15px; font-weight: 800; fill: rgba(255, 255, 255, 0.9); }
.bx-empty-text.is-sub { font-size: 12.5px; font-weight: 600; fill: rgba(255, 255, 255, 0.78); }
.bx-nodev { fill: none; stroke: var(--border-strong); stroke-width: 2; stroke-dasharray: 8 6; }
.bx-nodev ~ .bx-empty-text { fill: var(--muted); }
.bx-nodev-btn { cursor: pointer; outline: none; }
.bx-nodev-btn .bx-nodev { fill: transparent; }
.bx-nodev-btn:hover .bx-nodev { stroke: var(--muted); }
.bx-nodev-btn:focus-visible .bx-nodev { stroke: var(--accent); stroke-width: 3; }
.bx-washer { fill: rgba(0, 0, 0, 0.18); }
.bx-yoke { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3)); }
.bx-contact { stroke: #c92a2a; stroke-width: 3; stroke-linecap: round; fill: none; }
.bx-contact-dot { fill: #c92a2a; }
.bx-lead-tip { fill: #c97a3b; stroke: #6e3a12; stroke-width: 1.5; }
.bx-bar-hole { fill: #2b2f33; stroke: #111; }
.bx-tape-text { font-size: 13px; font-weight: 900; fill: #5c4300; letter-spacing: 0.08em; }
.bx-tape-text.is-sub { font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em; }
.bx-nut-count { font-size: 12px; font-weight: 900; fill: #ffffff; }
/* a wire nut's member count: a dark badge with a white edge, red past what one nut may hold */
.bx-nut-badge { fill: #24272b; stroke: #ffffff; stroke-width: 1.5; }
.bx-nut-badge.is-over { fill: #c62828; }
/* captions drawn on the stage itself (bar names, BREAKER SPACE, the breaker, BOND, hole numbers, LIGHT ON/OFF) follow
   the theme; text printed on a light device face keeps .bx-dev-text's dark ink */
.bx-stage-text { font-size: 11.5px; font-weight: 800; fill: var(--text); letter-spacing: 0.04em; paint-order: stroke; stroke: var(--sbx-stage); stroke-width: 3px; stroke-linejoin: round; }
.bx-stage-text.is-tiny { font-size: 9.5px; }
.bx-stage-text.is-warn { fill: var(--bad-text); font-size: 12px; }
.bx-stage-text.is-on { fill: var(--accent-text); }
.bx-hole-num { font-weight: 800; letter-spacing: 0; }
/* hole numbers are drawn over the wires, with a halo in the surface color (3 CSS px at any stage size), so a wire
   landed in a hole never hides its number */
.bx-stage-text.bx-hole-num { stroke: var(--surface); stroke-width: 3px; vector-effect: non-scaling-stroke; }
/* a landed end keeps its color letter on a small tag where the wire comes in */
.bx-end-tag { pointer-events: none; }

/* drawing: interaction states */
.bx-hit, .bx-term-hit, .bx-tab-hit { fill: transparent; }
.bx-end { cursor: grab; outline: none; }
.bx-svg.is-dragging, .bx-svg.is-dragging .bx-end { cursor: grabbing; }
.bx-end-shadow { fill: rgba(0, 0, 0, 0.28); }
.bx-end-letter { font-weight: 900; font-family: var(--font); }
/* Rings are drawn in CSS px (non-scaling strokes), so they keep their weight however small the drawing is. Each ring
   has a halo under it in the surface color: the pair reads on the light and dark stage and on every box back (blue
   plastic, metal, the panel can), 3:1 at least (S05). */
.bx-sel-ring, .bx-sel-halo, .bx-target-ring, .bx-target-halo { fill: none; stroke: transparent; pointer-events: none; vector-effect: non-scaling-stroke; }
.bx-sel-ring { stroke-width: 3.5px; }
.bx-end:hover .bx-sel-ring, .bx-nut:hover .bx-sel-ring { stroke: rgba(232, 89, 12, 0.55); }
.bx-end:focus-visible .bx-sel-ring, .bx-nut:focus-visible .bx-sel-ring { stroke: var(--accent); stroke-dasharray: 4 3; }
/* the selected end (or nut): a solid accent ring with a surface halo. Never dashed, never moving: dashes mean target */
.bx-end.is-selected .bx-sel-halo, .bx-nut.is-selected .bx-sel-halo { stroke: var(--surface); stroke-width: 9px; }
.bx-end.is-selected .bx-sel-ring, .bx-nut.is-selected .bx-sel-ring { stroke: var(--accent); stroke-width: 5px; stroke-dasharray: none; }
.bx-end.is-dragged .bx-end-body { stroke: var(--accent); stroke-width: 3; }
/* every legal target: marching ants, a 2 px dashed ring in the text color over a 4 px underlay in the surface color.
   Green is kept for passed goals; a target is not "correct", it is only somewhere the wire can go. */
.has-sel .is-target .bx-target-halo, .has-sel .bx-end.is-target .bx-sel-halo { stroke: var(--surface); stroke-width: 4px; }
.has-sel .is-target .bx-target-ring, .has-sel .bx-end.is-target .bx-sel-ring { stroke: var(--text); stroke-width: 2px; stroke-dasharray: 5 4; animation: bx-ants 1.6s linear infinite; }
@keyframes bx-ants { to { stroke-dashoffset: -18; } }
/* the target under the pointer or finger, and keyboard focus on a target: a solid 4 px ring, a 6 px underlay, a
   light fill (not the accent ring, which is the selected end's) */
.is-hot .bx-target-halo, .bx-end.is-hot .bx-sel-halo,
.has-sel .is-target:focus-visible .bx-target-halo, .has-sel .bx-end.is-target:focus-visible .bx-sel-halo { stroke: var(--surface) !important; stroke-width: 6px !important; fill: color-mix(in srgb, var(--surface) 35%, transparent) !important; }
.is-hot .bx-target-ring, .bx-end.is-hot .bx-sel-ring,
.has-sel .is-target:focus-visible .bx-target-ring, .has-sel .bx-end.is-target:focus-visible .bx-sel-ring { stroke: var(--text) !important; stroke-width: 4px !important; stroke-dasharray: none !important; animation: none !important; }
.is-hot-bad .bx-target-halo, .bx-end.is-hot-bad .bx-sel-halo { stroke: var(--surface) !important; stroke-width: 6px !important; }
.is-hot-bad .bx-target-ring, .bx-end.is-hot-bad .bx-sel-ring { stroke: var(--bad) !important; stroke-width: 4px !important; fill: rgba(224, 49, 49, 0.18) !important; stroke-dasharray: none !important; animation: none !important; }
.bx-term { cursor: pointer; outline: none; }
.bx-term:focus-visible .bx-target-halo { stroke: var(--surface); stroke-width: 6px; }
.bx-term:focus-visible .bx-target-ring { stroke: var(--text); stroke-width: 4px; }
.bx-term.is-passive { pointer-events: none; }
.has-sel .bx-term.is-blocked { opacity: 0.55; }
/* no breaker yet: the empty breaker space is a button that points at the breaker chips */
.bx-brkspace { cursor: pointer; outline: none; }
.bx-brkspace:hover .bx-target-ring { stroke: rgba(232, 89, 12, 0.55); stroke-width: 3px; }
.bx-brkspace:focus-visible .bx-target-halo { stroke: var(--surface); stroke-width: 6px; }
.bx-brkspace:focus-visible .bx-target-ring { stroke: var(--accent); stroke-width: 3px; }
.bx-brkspace-text { stroke: none; }
.bx-nut { cursor: pointer; outline: none; }
.bx-tab { cursor: pointer; outline: none; }
.bx-gfci-btn { cursor: pointer; }
.bx-gfci-btn:active .bx-gfci-face { transform: translateY(1.5px); }
.bx-tab-focus { fill: none; stroke: transparent; stroke-width: 2.5; }
.bx-tab:hover .bx-tab-focus { stroke: rgba(232, 89, 12, 0.6); }
.bx-tab:focus-visible .bx-tab-focus { stroke: var(--accent); stroke-width: 3; }
.bx-wire { pointer-events: none; }
/* dark theme: a black wire's edge is light, or it vanishes into the dark stage (#26272b on #171a1e is 1.2:1) until the
   live glow shows; the black swatch (the status line, the pigtail colors) gets a light ring for the same reason */
:root[data-theme="dark"] .bx-wire.is-c-black .bx-wire-edge { stroke: #8a9099; }
:root[data-theme="dark"] .bx-swatch.is-c-black { border-color: rgba(255, 255, 255, 0.55); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bx-wire.is-c-black .bx-wire-edge { stroke: #8a9099; }
  :root:not([data-theme="light"]) .bx-swatch.is-c-black { border-color: rgba(255, 255, 255, 0.55); }
}
.bx-wire-glow { fill: none; stroke: var(--sbx-live); stroke-linecap: round; stroke-linejoin: round; }
.bx-wire.is-fault .bx-wire-glow { stroke: rgba(224, 49, 49, 0.6); animation: sbx-blink 0.6s ease-in-out infinite alternate; }

/* phones: the box view is full screen */
@media (max-width: 719px) {
  .bx-dialog { width: 100vw; height: 100vh; height: 100dvh; max-width: 100vw; max-height: 100vh; max-height: 100dvh; margin: 0; border-radius: 0; border: 0; }
  .bx-head { padding: 8px 10px 6px; }
  .bx-title { font-size: 1.02rem; }
  .bx-sub { font-size: 0.78rem; }
  .bx-bar { padding: 6px 10px; gap: 6px 12px; }
  .bx-status { padding: 4px 10px; min-height: 40px; }
  .bx-hint { font-size: 0.8rem; }
  .bx-stage { padding: 2px; }
  .bx-foot { padding: 6px 10px calc(8px + env(safe-area-inset-bottom)); gap: 6px; }
  .bx-legend { display: none; }
  .sbx-job-title { font-size: 1.25rem; }
  .sbx-tool { min-height: 50px; font-size: 0.74rem; }
}
@media (max-width: 380px) {
  .bx-chip { padding-left: 9px; padding-right: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .sbx-preview-path, .sbx-mark-pulse, .sbx-flash-ring, .sbx-flash-path, .has-sel .is-target .bx-target-ring, .has-sel .bx-end.is-target .bx-sel-ring { animation: none; }
}

@media print {
  .sbx-tools, .sbx-lists, .bx-dialog { display: none !important; }
}

/* ---------- refinements ---------- */
.sbx-panel-bus { fill: #c9a227; opacity: 0.7; }
.sbx-brief > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; min-height: 36px; font-size: 0.78rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.sbx-brief > summary::-webkit-details-marker { display: none; }
.sbx-brief > summary .chev { width: 16px; height: 16px; transition: transform 0.15s; }
.sbx-brief[open] > summary .chev { transform: rotate(180deg); }
.sbx-brief .sbx-job-intro { font-size: 0.95rem; line-height: 1.45; }
.sbx-brief .sbx-task { font-size: 0.9rem; line-height: 1.4; }
.sbx-run-add { flex-wrap: nowrap; }
.sbx-pos { width: 64px; flex: none; padding-left: 6px; padding-right: 4px; }
.sbx-cableitem-title { font-size: 0.84rem; line-height: 1.3; }
.sbx-in { white-space: nowrap; }
.sbx-run-add .btn { flex: none; }
.sbx-joist { stroke: var(--sbx-wood-edge); stroke-width: 0.8; }
.sbx-joist-fill { fill: var(--sbx-joist); }
.sbx-joist-hatch { stroke: var(--sbx-wood-edge); stroke-width: 1.4; opacity: 0.55; }
.sbx-ceiling-line { fill: #9aa1a9; }
.bx-mark-text { font-size: 11px; }
.bx-head, .bx-bar, .bx-status, .bx-foot { flex: none; }
:root[data-theme="dark"] .sbx-staple-crown { stroke: #c4cad1; }
:root[data-theme="dark"] .sbx-staple-legs { stroke: #9aa1a9; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sbx-staple-crown { stroke: #c4cad1; }
  :root:not([data-theme="light"]) .sbx-staple-legs { stroke: #9aa1a9; }
}
@media (max-width: 719px) {
  .bx-bar .btn-sm, .bx-chip { min-height: 34px; padding: 4px 10px; font-size: 0.82rem; }
  .bx-group-label { font-size: 0.66rem; }
}
.sbx-box-label { font-size: var(--sbx-lbl, 10.5px); stroke-width: calc(var(--sbx-lbl, 10.5px) * 0.32); }
.sbx-wall-wrap.is-zoomed { overflow-x: auto; overscroll-behavior-x: contain; }
.sbx-wall-wrap.is-zoomed .sbx-wall-svg { max-width: none; }
.sbx-wall-head .sbx-wall-scale { margin-right: auto; }
.sbx-zoom[aria-pressed="true"] { border-color: var(--accent); color: var(--accent-text); }
@media (max-width: 479px) { .sbx-wall-scale { display: none; } .sbx-wall-head .section-title { margin-right: auto; } }
.sbx-switch-knob { background: #ffffff; }
.bx-tip-edge { stroke: #6e3a12; stroke-width: 5.2; stroke-linecap: round; fill: none; }
.bx-tip { stroke: #e0995a; stroke-width: 3.2; stroke-linecap: round; fill: none; }
.sbx-switch.is-tripped { background: var(--bad); border-color: var(--bad); color: #fff; }
.sbx-halves { display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end; }
.sbx-half { font-size: 0.72rem; font-weight: 700; }
.sbx-devnote { flex-basis: 100%; text-align: right; font-size: 0.78rem; }
.sbx-devrow > .pill { margin-left: auto; }
.sbx-devrow > .sbx-tester-wrap, .sbx-devrow > .sbx-halves, .sbx-devrow > .sbx-bulb-wrap, .sbx-devrow > .sbx-switch { margin-left: auto; }

/* ---------- review pass: weights that follow the drawn size of the wall (--sbx-k is set by the wall view) ---------- */
.sbx-preview-path { stroke-width: calc(3px * var(--sbx-k, 1)); }
.sbx-preview-path.is-free { stroke-width: calc(2px * var(--sbx-k, 1)); }
.sbx-remove-path { stroke-width: calc(7px * var(--sbx-k, 1)); }
.sbx-flash-path { stroke-width: calc(9px * var(--sbx-k, 1)); }
.sbx-flash-ring { stroke-width: calc(3.5px * var(--sbx-k, 1)); }
.sbx-mark { stroke-width: calc(1.6px * var(--sbx-k, 1)); }
.sbx-box:focus-visible .sbx-box-ring, .sbx-box.is-from .sbx-box-ring { stroke-width: calc(3px * var(--sbx-k, 1)); }
.sbx-preview-text { stroke-width: calc(3.5px * var(--sbx-k, 1)); }
/* empty-box text on a light metal or panel back needs dark ink */
.bx-back.is-metal ~ .bx-empty-text, .bx-back.is-panel ~ .bx-empty-text { fill: #1f2328; }
.bx-back.is-metal ~ .bx-empty-text.is-sub, .bx-back.is-panel ~ .bx-empty-text.is-sub { fill: #3d434a; }
/* hover feedback for everything clickable in the drawings (keyboard focus already has its own ring) */
@media (hover: hover) {
  /* hover is a quiet gray, so it never reads as the (accent) selection; only the Select tool selects. With Staple the
     same gray marks the cable a staple goes on where another runs beside it on the stud */
  .sbx-wall-wrap[data-tool="select"] .sbx-cable.is-hover:not(.is-selected) .sbx-cable-focus,
  .sbx-wall-wrap[data-tool="staple"] .sbx-cable.is-hover .sbx-cable-focus { stroke: color-mix(in srgb, var(--muted) 45%, transparent); }
  .sbx-wall-wrap[data-tool="select"] .sbx-staple:hover:not(.is-selected) .sbx-staple-focus { stroke: color-mix(in srgb, var(--muted) 70%, transparent); }
  .bx-term:not(.bx-bar-target):hover .bx-target-ring { stroke: rgba(232, 89, 12, 0.55); stroke-width: 3px; }
  .sbx-switch:not(:disabled):hover { border-color: var(--accent); }
  .sbx-finding-btn[aria-disabled="true"]:hover { border-color: var(--border); }
}
.sbx-switch:focus-visible { outline-offset: 3px; }
/* the breaker handle before a breaker is chosen: nothing to switch */
.sbx-switch:disabled { cursor: not-allowed; opacity: 0.6; border-style: dashed; }
/* the knob slides to the right when a toggle is on (it used to sit on the left in both states) */
.sbx-switch { justify-content: space-between; }
.sbx-switch.is-on { flex-direction: row-reverse; padding: 4px 4px 4px 12px; }
.sbx-switch.is-on .sbx-switch-knob { transform: none; }

/* ---------- getting started: running the first cable (the start prompt lives in the tool bar, .sbx-status-bar.is-start) ---------- */
/* while Run cable is active every box gets an outlined target the size of its tap area, so small boxes are easy to find */
.sbx-run-target { fill: color-mix(in srgb, var(--accent) 10%, transparent); stroke: var(--accent); stroke-width: calc(2.5px * var(--sbx-k, 1)); stroke-dasharray: 6 4; pointer-events: none; }
.sbx-run-target.is-from { fill: color-mix(in srgb, var(--accent) 22%, transparent); stroke-dasharray: none; stroke-width: calc(3.5px * var(--sbx-k, 1)); }
@media (prefers-reduced-motion: no-preference) {
  .sbx-run-target:not(.is-from) { animation: sbx-run-pulse 1.4s ease-in-out infinite; }
  @keyframes sbx-run-pulse { 0%, 100% { stroke-opacity: 1; } 50% { stroke-opacity: 0.35; } }
}
/* box view: the break-off tabs are checkboxes under "Tabs broken off", drawn neutral (a checkmark is a state, not
   the orange selection); 44 px tall on touch */
.bx-check { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 2px 8px 2px 4px; border-radius: 6px; font-size: 0.875rem; font-weight: 600; cursor: pointer; user-select: none; -webkit-user-select: none; }
.bx-check:hover { background: var(--surface-3); }
.bx-check-box { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--text); cursor: pointer; }
@media (max-width: 719px) {
  /* one row from 375 px: "TABS BROKEN OFF [ ] Hot (brass) [ ] Neutral (silver)" */
  .bx-tabs { gap: 4px; }
  .bx-tabs .bx-group-label { letter-spacing: 0.03em; margin-right: 0; }
  .bx-check { font-size: 0.78rem; gap: 4px; padding: 0 2px 0 0; }
  .bx-check-box { width: 16px; height: 16px; }
}
@media (max-width: 379px) {
  .bx-tabs .bx-group-label { font-size: 0.6rem; }
  .bx-check { font-size: 0.72rem; }
  .bx-check-box { width: 14px; height: 14px; }
}
@media (pointer: coarse) { .bx-check { min-height: 44px; } }

/* box view: "+ Run cable from here" ends the Device (or Breaker) row; it hands the box to the wall's Run cable tool */
.bx-run-from { gap: 6px; }
@media (min-width: 720px) { .bx-run-from { margin-left: 6px; } }
.bx-run-from .icon { width: 16px; height: 16px; }

/* ---------- novice pass: the tool bar above the wall ---------- */
/* The current hint and invisible copies of every other hint share one grid cell, so the bar is always as tall as the
   longest hint and switching tools never moves the wall. The button (Run cable / Cancel / Done) keeps its column even
   when it is hidden, and a min-width that fits its longest label, for the same reason. */
.sbx-status-bar { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 10px; margin: 4px 0 8px; padding: 8px 10px; background: var(--surface); border-radius: 8px; }
.sbx-status-bar > .sbx-wall-status, .sbx-status-sizers { grid-area: 1 / 1; }
.sbx-status-bar > .sbx-wall-status { margin: 0; min-height: 0; line-height: 1.4; }
.sbx-status-sizers { display: grid; visibility: hidden; pointer-events: none; }
.sbx-status-sizers > p { grid-area: 1 / 1; margin: 0; font-size: 0.9rem; font-weight: 600; line-height: 1.4; }
/* 9.5em: the widest label, the start prompt's "Run cable" with its icon, so the column has one width in every state */
.sbx-status-act { grid-area: 1 / 2; min-width: 9.5em; justify-content: center; white-space: nowrap; }
.sbx-status-act .icon { width: 16px; height: 16px; }
.sbx-status-act.is-idle { visibility: hidden; }
.sbx-status-probe { height: 0; }
/* an empty wall: the bar is the "Start here" prompt (an inset ring, not a border, so its size never changes) */
.sbx-status-bar.is-start { background: var(--accent-soft); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent); }
/* wide screens: the bar sticks to the top of the window while the wall scrolls under it */
@media (min-width: 720px) {
  .sbx-status-bar { position: sticky; top: 0; z-index: 5; }
  .sbx-status-bar.is-stuck { border-radius: 0 0 8px 8px; box-shadow: 0 8px 12px -10px rgba(0, 0, 0, 0.5); }
  .sbx-status-bar.is-start.is-stuck { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent), 0 8px 12px -10px rgba(0, 0, 0, 0.5); }
}
@media (max-width: 719px) {
  .sbx-status-bar > .sbx-wall-status, .sbx-status-sizers > p { font-size: 0.84rem; line-height: 1.35; }
  .sbx-status-act { min-width: 7.4em; padding-left: 8px; padding-right: 8px; }
}

/* Cables and staples: the distance field says which box it is measured from */
.sbx-run-add { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 6px; }
.sbx-run-add .sbx-in { white-space: normal; overflow-wrap: normal; line-height: 1.2; }
@media (min-width: 1100px) {
  /* the narrow sidebar: "in. from" over the box name, never a word broken in two */
  .sbx-run-add { grid-template-columns: auto minmax(min-content, 1fr) auto; gap: 4px; }
  .sbx-run-add .sbx-pos { width: 46px; }
  .sbx-run-add .sbx-in { font-size: 0.75rem; }
  .sbx-run-add .btn { white-space: nowrap; padding-left: 8px; padding-right: 8px; }
}

/* ---------- novice pass: box view ---------- */
/* The status line has a fixed height in every state (hint, selected wire, wire nut menu): selecting a wire never
   shrinks the stage, so the drawing does not move or rescale between a tap on a wire end and the tap on its target.
   The description gets two lines; the actions scroll sideways when they do not fit (a fade says there is more; a
   fallback, since on a phone they get a row of their own); Cancel sits outside them and is always in sight. */
.bx-status { height: 58px; min-height: 0; overflow: hidden; }
.bx-hint { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.bx-selrow { flex-wrap: nowrap; }
.bx-seltext { flex: 1 1 0; min-width: 140px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; line-height: 1.35; }
.bx-acts { flex: 0 1 auto; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin; padding: 1px; }
.bx-acts:empty { display: none; }
.bx-acts .btn { flex: none; }
.bx-acts.is-scroll { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); padding-right: 24px; }
.bx-sel-cancel { flex: none; }
.bx-next { color: var(--muted); }
.bx-next.is-miss { color: var(--bad-text); font-weight: 700; }
@media (max-width: 719px) {
  .bx-status { height: 88px; align-items: center; }
  .bx-hint { -webkit-line-clamp: 4; }
  /* Cancel sits beside the wire's name (as on a wire nut), so the actions get the whole second row: "Cap (wire nut)"
     and "Tape black (this end)" fit side by side from 360 px up without scrolling */
  .bx-selrow { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "text text cancel" "acts acts acts"; gap: 4px 8px; align-items: center; }
  /* the swatch gives its width to the text (the name starts with the color, and the selected end is ringed on the
     drawing) and Cancel is compact, so the wire and its screw fit the two lines beside it */
  .bx-selrow > .bx-swatch { display: none; }
  .bx-selrow > .bx-seltext { grid-area: text; min-width: 0; font-size: 0.82rem; }
  .bx-selrow > .bx-acts { grid-area: acts; max-width: 100%; }
  .bx-selrow > .bx-sel-cancel { grid-area: cancel; min-height: 32px; padding-left: 10px; padding-right: 10px; font-size: 0.8rem; }
  /* no actions: Cancel takes the actions' row, on its left, and the text keeps the whole first row */
  .bx-selrow > .bx-acts:empty + .bx-sel-cancel { grid-area: acts; justify-self: start; }
  .bx-acts .btn { min-height: 32px; padding-top: 3px; padding-bottom: 3px; }
}
/* the breaker handle: the Test panel's switch, a little smaller in the bar */
.bx-handle { min-height: 36px; min-width: 84px; }
.bx-handle .sbx-switch-knob { width: 26px; height: 26px; }
/* messages inside the box view: one compact toast over the foot (fill meter and legend), never over the drawing */
.bx-dialog .toast-region { position: absolute; bottom: calc(6px + env(safe-area-inset-bottom)); left: 50%; right: auto; transform: translateX(-50%); justify-items: center; max-width: min(560px, calc(100% - 32px)); }
.bx-dialog .toast { padding: 7px 12px; font-size: 0.82rem; }

/* ---------- messages: one toast at a time, the Undo snackbar, transient messages in the status lines ---------- */
/* Toasts are kept for rare events. On this page they sit bottom-center at every width (the drill page puts them in the
   corner), 560 px at most, above the phone dock when there is one (--sbx-dock-h). */
body.page-sandbox > .toast-region { left: 50%; right: auto; transform: translateX(-50%); justify-items: center; max-width: min(560px, calc(100vw - 32px)); bottom: calc(16px + env(safe-area-inset-bottom) + var(--sbx-dock-h, 0px)); }
/* the Undo snackbar: message and a text button in the accent color; it takes the pointer (hovering it holds it) */
.toast.has-action { display: flex; align-items: center; gap: 4px 12px; padding-top: 4px; padding-bottom: 4px; padding-right: 6px; pointer-events: auto; }
.toast-text { flex: 1 1 auto; min-width: 0; }
.toast-btn { flex: none; min-height: 36px; padding: 6px 12px; border: 0; border-radius: 6px; background: transparent; color: var(--sbx-toast-accent); font: inherit; font-weight: 800; letter-spacing: 0.03em; cursor: pointer; }
.toast-btn:hover { background: color-mix(in srgb, var(--sbx-toast-accent) 18%, transparent); }
.toast-btn:focus-visible { outline: 2px solid var(--sbx-toast-accent); outline-offset: 1px; }
@media (pointer: coarse) { .toast-btn { min-height: 44px; padding-left: 14px; padding-right: 14px; } }
.bx-dialog .toast.has-action { padding-top: 2px; padding-bottom: 2px; }

/* the wall's tool bar: a confirmation or correction replaces the hint for 4 s, tinted so the change is seen; the
   bar keeps its height (the sizers hold every message from 720 px up) */
.sbx-status-bar { transition: background-color 0.2s; }
.sbx-status-bar.is-flash-echo { background: var(--ok-soft); }
.sbx-status-bar.is-flash-hint, .sbx-status-bar.is-flash-pin { background: var(--warn-soft); }
.sbx-status-bar.is-flash-refusal { background: var(--bad-soft); }
.sbx-status-bar.is-flash > .sbx-wall-status { animation: marker-fade 0.2s ease-out both; }
.sbx-flash-act { margin-left: 8px; min-height: 32px; padding: 4px 10px; }
@media (max-width: 719px) {
  /* phones: the bar's reserve is already taller than any message, and growing it would push the wall down */
  .sbx-status-sizers > .is-flash-sizer { display: none; }
}

/* box view status line: a message over the hint, or in place of the selection's "next" text; on a narrow line the
   description, then the name, give way so the message fits its two lines */
.bx-status { transition: background-color 0.2s; }
.bx-status.is-flash-echo { background: var(--ok-soft); }
.bx-status.is-flash-hint, .bx-status.is-flash-pin { background: var(--warn-soft); }
.bx-status.is-flash-refusal { background: var(--bad-soft); }
.bx-flash { color: var(--text); font-weight: 600; }
.bx-flash.is-miss, .bx-next.is-miss { color: var(--bad-text); font-weight: 700; }
.bx-next.is-flash.is-echo { color: var(--text); font-weight: 600; }
.bx-seltext.is-tight .bx-seldesc { display: none; }
.bx-seltext.is-tighter .bx-selname { display: none; }
.bx-seltext.is-tightest { -webkit-line-clamp: 3; font-size: 0.75rem; line-height: 1.2; }
.bx-seltext.is-tightest .bx-next.is-miss { font-weight: 600; }
@media (max-width: 719px) {
  /* a phone gives a long message (the pigtail steps) the whole first row: the swatch goes, and Cancel moves down to
     the end of the actions' row while it shows */
  .bx-selrow:has(> .bx-seltext.is-tightest) > .bx-swatch { display: none; }
  .bx-selrow:not(.is-nut):has(> .bx-seltext.is-tightest) { grid-template-areas: "text text text" "acts acts cancel"; }
}
@media (max-width: 379px) { .bx-selrow > .bx-seltext { font-size: 0.78rem; } .bx-selrow > .bx-seltext.is-tightest { font-size: 0.72rem; } }
.bx-flash-act { flex: none; min-height: 32px; padding: 4px 10px; }
.bx-status > .bx-flash { flex: 1 1 auto; min-width: 0; }
.bx-status > .bx-flash-act { margin-left: 10px; }

/* box view header: Undo and Redo next to the close button (36 px with a mouse, 44 px on touch) */
.bx-hist { flex: none; width: 36px; height: 36px; }
.bx-hist .icon { width: 20px; height: 20px; }
.bx-hist[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }
.bx-hist[aria-disabled="true"]:hover { background: var(--surface); }
@media (pointer: coarse) { .bx-hist { width: 44px; height: 44px; } }

/* Reset job confirm: Cancel first, the red verb last, on one row */
.sbx-confirm-row { flex-wrap: nowrap; justify-content: flex-end; gap: 6px; }
.sbx-confirm-row .btn { white-space: nowrap; padding-left: 9px; padding-right: 9px; }

/* ---------- the wall on a phone: fixed-size labels and staples, the staple chooser ---------- */
/* box labels never take a click meant for a cable or another box under them (the box's own hit area opens it) */
.sbx-box-label { pointer-events: none; }
/* staples: outlined in the page's surface color so they show on a white or yellow sheath in both themes */
.sbx-staple-halo { fill: none; stroke: var(--surface); stroke-linecap: round; }
.sbx-wall-svg:focus { outline: none; }
.sbx-wall-svg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* tools show only what they act on: Run cable and Staple do not point at cables, Remove does not point at boxes */
.sbx-wall-wrap[data-tool="run"] .sbx-cable-hit, .sbx-wall-wrap[data-tool="staple"] .sbx-cable-hit { cursor: crosshair; }
.sbx-wall-wrap[data-tool="remove"] .sbx-box { cursor: not-allowed; }
.sbx-wall-wrap[data-tool="remove"] .sbx-box:hover .sbx-box-ring { stroke: transparent; }
.sbx-wall-host { position: relative; }
.sbx-chooser {
  position: absolute; z-index: 6; min-width: 220px; max-width: calc(100% - 8px); padding: 6px; display: grid; gap: 4px;
  background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.sbx-chooser-title { margin: 2px 6px 2px; font-size: 0.8rem; font-weight: 800; color: var(--muted); }
.sbx-chooser-row {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 10px; text-align: left; font: inherit; font-size: 0.9rem; font-weight: 700;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text); cursor: pointer;
}
.sbx-chooser-row:hover, .sbx-chooser-row:focus-visible { border-color: var(--accent); background: var(--accent-soft); }
.sbx-chooser-cancel { min-height: 44px; justify-self: stretch; }

/* ---------- the Select tool's selection: a cable or a staple ---------- */
.sbx-cable-sel { fill: none; stroke: var(--accent); stroke-linejoin: round; stroke-linecap: round; }
.sbx-staple-sel { fill: color-mix(in srgb, var(--accent) 14%, transparent); stroke: var(--accent); }
.sbx-wall-status .sbx-sw, .sbx-dock-text .sbx-sw, .sbx-status-sizers .sbx-sw { margin-right: 6px; vertical-align: -1px; }
.sbx-sel-del { margin-left: 8px; min-height: 32px; padding: 4px 10px; gap: 6px; }
.sbx-sel-del .icon { width: 15px; height: 15px; }
.sbx-status-bar.is-sel { background: var(--accent-soft); }

/* ---------- the phone dock: the wall's tool bar and the tools at the bottom of the screen (below 720 px) ---------- */
.sbx-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40; display: grid; gap: 4px;
  padding: 6px 10px calc(4px + env(safe-area-inset-bottom)); background: var(--surface); border-top: 1px solid var(--border-strong);
  box-shadow: 0 -6px 16px -12px rgba(0, 0, 0, 0.45);
}
/* the strip: always three lines tall (the staple hint with its 334.30 reference needs them at 390 px), the button at
   its right end; anything longer is cut with an ellipsis (the whole text is in its title and was announced) */
.sbx-dock-strip { display: flex; align-items: center; gap: 8px; height: 54px; padding: 0 2px 0 8px; border-radius: 8px; transition: background-color 0.2s; }
.sbx-dock-text {
  flex: 1 1 auto; min-width: 0; margin: 0; font-size: 0.8rem; font-weight: 600; line-height: 1.3; color: var(--text);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
@media (max-width: 379px) {
  .sbx-dock { padding-left: 6px; padding-right: 6px; }
  .sbx-dock-strip { padding-left: 6px; gap: 6px; }
  .sbx-dock-text { font-size: 0.75rem; }
}
.sbx-dock-acts { display: contents; }
.sbx-dock-acts .btn, .sbx-dock-act { flex: none; min-height: 40px; padding: 4px 10px; white-space: nowrap; }
.sbx-dock-acts .sbx-flash-act, .sbx-dock-acts .sbx-sel-del { margin-left: 0; }
.sbx-dock-act .icon { width: 16px; height: 16px; }
.sbx-dock-act.is-idle { display: none; }
.sbx-dock.is-start .sbx-dock-strip { background: var(--accent-soft); }
.sbx-dock.is-sel .sbx-dock-strip { background: var(--accent-soft); }
.sbx-dock.is-flash-echo .sbx-dock-strip { background: var(--ok-soft); }
.sbx-dock.is-flash-hint .sbx-dock-strip, .sbx-dock.is-flash-pin .sbx-dock-strip { background: var(--warn-soft); }
.sbx-dock.is-flash-refusal .sbx-dock-strip { background: var(--bad-soft); }
.sbx-dock.is-flash .sbx-dock-text { animation: marker-fade 0.2s ease-out both; }
/* the row: Select, Cable, Staple, Remove, then Undo and Redo; icon over an 11 px label, 44 px at least */
.sbx-dock-row { display: flex; align-items: stretch; gap: 4px; }
.sbx-dock-tools, .sbx-dock-history { display: flex; gap: 2px; }
.sbx-dock-tools { flex: 4 1 0; }
.sbx-dock-history { flex: 2 1 0; padding-left: 4px; border-left: 1px solid var(--border); }
.sbx-dock-btn {
  flex: 1 1 0; min-width: 44px; min-height: 50px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 4px 2px;
  border: 1.5px solid transparent; border-radius: 10px; background: transparent; color: var(--text); font: inherit; cursor: pointer;
}
.sbx-dock-btn .icon { width: 22px; height: 22px; }
.sbx-dock-label { font-size: 11px; font-weight: 700; line-height: 1.1; }
.sbx-dock-btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); }
.sbx-dock-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.sbx-dock-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* hidden from 720 px up, under an open dialog, and while a field has the phone's keyboard up (it would cover it) */
.sbx-dock.is-typing, body.has-dialog .sbx-dock { visibility: hidden; }
@media (min-width: 720px) { .sbx-dock { display: none; } }
@media (max-width: 719px) {
  /* the dock replaces the Tools card's tool row, Undo and Redo, and the wall's tool bar */
  .sbx-tools-title, .sbx-toolseg, .sbx-history, .sbx-status-bar { display: none; }
  /* what is left of the Tools card is one row: "CABLE" and the cable types after it */
  .sbx-tools { display: flex; align-items: center; gap: 10px; padding: 10px 12px; }
  .sbx-tools .sbx-cabletypes { flex: 1 1 0; min-width: 0; }
  /* the page keeps its foot clear of the dock; toasts and snackbars sit 8 px above it; scrolling into view stops above it */
  body.page-sandbox { padding-bottom: var(--sbx-dock-h, 0px); }
  html { scroll-padding-bottom: var(--sbx-dock-h, 0px); }
  body.page-sandbox > .toast-region { bottom: calc(var(--sbx-dock-h, 0px) + 8px); }
}
@media print { .sbx-dock { display: none !important; } }
@media (prefers-reduced-motion: reduce) { .sbx-dock.is-flash .sbx-dock-text, .sbx-status-bar.is-flash > .sbx-wall-status { animation: none; } }

/* ---------- box view: wire actions (Cap, Delete, tape on this end) and the wire nut's pigtail button ---------- */
/* "Disconnect [Del]": the key, a badge after the label, is shown with a mouse only */
.bx-acts .kbd.bx-kbd-hint { margin-left: -2px; font-weight: 600; line-height: 1.25; }
/* a capped end: a small wire nut of its own where the stripped tip would be */
.bx-cap { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35)); }
/* "Add black pigtail" is the likely color; "Other color" opens a popover over the drawing, never a row that scrolls */
.bx-pig-main { gap: 6px; }
@media (max-width: 719px) {
  /* phones: the nut's Cancel goes up beside its text, so "Add black pigtail" and "Other color" get the whole row */
  .bx-selrow.is-nut { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "text cancel" "acts acts"; }
}
.bx-pig-main .bx-swatch { width: 14px; height: 14px; border-color: rgba(255, 255, 255, 0.75); }
/* "Other color" ends with a chevron that turns over while its popover is open */
.bx-caret { width: 16px; height: 16px; transition: transform 0.15s; }
.bx-pig-more[aria-expanded="true"] .bx-caret { transform: rotate(180deg); }
.bx-pop { position: absolute; z-index: 20; min-width: 200px; margin: 0; padding: 6px; display: grid; gap: 2px; background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-radius: 10px; box-shadow: var(--shadow-lg); }
.bx-pop-title { margin: 2px 8px 4px; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.bx-pop-row { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 6px 12px; border: 0; border-radius: 6px; background: transparent; color: inherit; font: inherit; font-size: 0.92rem; font-weight: 600; text-align: left; cursor: pointer; }
.bx-pop-row:hover { background: var(--surface-2); }
.bx-pop-row:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }

/* ---------- box view: targets, feedback, sizes (S05, S13, S14, S17, ADD-budget, ADD-afci) ---------- */
/* the live readout while dragging ("Release to land on HOT 1 screw (brass)"): plain text; a spot that refuses says why */
.bx-next.is-live { color: var(--text); font-weight: 600; }
.bx-next.is-bad { color: var(--bad-text); font-weight: 600; }
/* Conductors 4 of 6 connected · 2 loose: on the Box fill line, amber while any end is loose */
/* never shrunk or cut: where the line has no room (the Over pill on a phone) the count wraps onto a line of its own */
.bx-conds { display: inline-flex; flex: none; align-items: baseline; gap: 6px; margin-left: auto; white-space: nowrap; }
.bx-conds-num { font-size: 0.85rem; font-weight: 700; }
.bx-conds.is-loose .bx-conds-num { color: var(--warn-text); }
.bx-conds.is-ok .bx-conds-num { color: var(--ok-text); }
.bx-conds-short { display: none; font-weight: 700; }
.bx-conds.is-loose .bx-conds-short { color: var(--warn-text); }
.bx-conds.is-ok .bx-conds-short { color: var(--ok-text); }
.bx-conds-row { flex: 1 1 100%; }
@media (min-width: 720px) {
  /* the fill line holds the count too; the legend beside it wraps onto two rows instead */
  .bx-fill { flex: 1 1 560px; }
  .bx-legend { flex: 1 1 300px; }
}
.bx-conds-row .bx-conds { margin-left: 0; }
/* the panel view's interim note (ADD-afci) and the task list's */
.bx-head-note { margin: 4px 0 0; padding: 4px 8px; border-radius: 6px; background: var(--info-soft); color: var(--text); font-size: 0.78rem; line-height: 1.35; }
/* below 720 px the panel's note is one line, "Real AFCI/GFCI breakers: white to LOAD NEUTRAL. Why?"; Why? opens the
   whole note under it (the link's padding widens its tap area without making the line taller) */
.bx-note-short { display: none; margin: 4px 0 0; padding: 3px 6px; border-radius: 6px; background: var(--info-soft); color: var(--text); font-size: 0.74rem; line-height: 1.35; }
.bx-note-why { font-weight: 700; padding: 4px 6px; margin: -4px -6px -4px 0; }
@media (max-width: 719px) {
  .bx-note-short:not([hidden]) { display: block; }
  .bx-head-note.is-folded { display: none; }
}
/* the panel's bar: the breaker chips, the Breaker handle and "+ Run cable from here" wrap in one row; on a phone the
   row's "Breaker" label goes (the chips name the breakers) and the handle's reads "Handle", so two rows hold them */
.bx-handle-group { display: inline-flex; align-items: center; gap: 6px; margin-left: 12px; }
@media (max-width: 719px) {
  .bx-dialog.is-panel-view .bx-brk-label, .bx-handle-word { display: none; }
  .bx-handle-group { margin-left: 0; }
  .bx-handle { min-width: 76px; }
}
.sbx-task-note { list-style: none; margin-left: -1.2rem; display: flex; gap: 6px; align-items: flex-start; padding: 6px 8px; border-radius: 6px; background: var(--info-soft); font-size: 0.85rem; line-height: 1.35; }
.sbx-task-note .icon { width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--info-text); }
/* "Choose a breaker first": the breaker chips pulse once */
@media (prefers-reduced-motion: no-preference) {
  .bx-chip.is-pulse { animation: bx-pulse-once 0.9s ease-out 1; }
  @keyframes bx-pulse-once { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 70%, transparent); } 100% { box-shadow: 0 0 0 10px transparent; } }
}
/* touch screens: every control in the box view and the sandbox's own buttons are 44 px at least */
@media (pointer: coarse) {
  .bx-bar .btn-sm, .bx-chip, .bx-acts .btn, .bx-sel-cancel, .bx-flash-act, .bx-seg button, .bx-handle,
  .sbx-undo, .sbx-redo, .sbx-reset, .sbx-hint-btn, .sbx-jobs-toggle, .sbx-start-btn, .sbx-status-act, .sbx-cable-chip, .sbx-switch, .sbx-zoom, .sbx-again { min-height: 44px; }
  .sbx-undo, .sbx-redo { min-width: 44px; }
  .bx-selrow > .bx-sel-cancel, .bx-acts .btn { min-height: 44px; padding-top: 4px; padding-bottom: 4px; }
  /* the dock strip's Cancel, Done and Delete: with no Escape key they are the only way out of a tool (the 54 px strip
     holds them, so the dock keeps its height) */
  .sbx-dock-act, .sbx-dock-acts .btn { min-height: 44px; }
  /* Open <box>: a whole 44 px target, set 6 px below the finding button it sits under (a tap a little high used to
     open the finding instead) */
  .sbx-openbox { min-height: 44px; }
  .sbx-brief > summary { min-height: 44px; }
  .sbx-finding > .sbx-openbox { margin-top: 6px; }
}
@media (max-width: 719px) {
  /* the box's description fits one line beside the header's buttons (the whole text is its title) */
  .bx-sub.is-desc { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .bx-head { padding-top: 6px; padding-bottom: 4px; }
  .bx-bar { padding-top: 4px; padding-bottom: 4px; row-gap: 4px; }
  .bx-bar .bx-group { row-gap: 4px; }
  .bx-conds .bx-fill-label, .bx-conds-num { display: none; }
  .bx-conds-short { display: block; font-size: 0.8rem; white-space: nowrap; }
  .bx-fill-top { column-gap: 6px; row-gap: 2px; flex-wrap: wrap; }
  .bx-fill-top > span { white-space: nowrap; flex: none; }
  .bx-fill { grid-template-columns: minmax(0, 1fr); }
  .bx-fill-top { min-width: 0; }
  /* the panel view: its instructions and the AFCI note get the whole width under the title and its buttons */
  .bx-dialog.is-panel-view .bx-head { flex-wrap: wrap; row-gap: 2px; }
  .bx-dialog.is-panel-view .bx-head-text { display: contents; }
  .bx-dialog.is-panel-view .bx-title { flex: 1 1 0; min-width: 0; align-self: center; }
  .bx-dialog.is-panel-view .bx-sub, .bx-dialog.is-panel-view .bx-head-note, .bx-dialog.is-panel-view .bx-note-short { flex: 1 1 100%; order: 5; }
  .bx-dialog.is-panel-view .bx-note-short { order: 6; }
  .bx-dialog.is-panel-view .bx-head-note { order: 7; font-size: 0.74rem; padding: 3px 6px; }
  .bx-fill-num { font-size: 0.82rem; }
}
@media (max-width: 719px) and (pointer: coarse) {
  /* the selection's two text lines over a row of 44 px buttons */
  .bx-status { height: 92px; }
}
@media (max-width: 379px) {
  /* the smallest phones: the fill line still holds the conductor count */
  .bx-fill-top .bx-fill-label { letter-spacing: 0.03em; }
  .bx-fill-num { font-size: 0.74rem; }
  .bx-conds-short { font-size: 0.76rem; }
}

/* ---------- findings (S15): a finding opened in the box view pulses red on what it names ---------- */
.bx-finding { pointer-events: none; }
.bx-finding-halo, .bx-finding-ring { fill: none; vector-effect: non-scaling-stroke; }
.bx-finding-halo { stroke: var(--surface); stroke-width: 8px; }
.bx-finding-ring { stroke: var(--bad); stroke-width: 4px; }
.bx-fill.is-finding { outline: 3px solid var(--bad); outline-offset: 3px; border-radius: 6px; }
@media (prefers-reduced-motion: no-preference) {
  .bx-finding-ring { animation: bx-finding-pulse 1.2s ease-in-out infinite; }
  .bx-fill.is-finding { animation: bx-finding-outline 1.2s ease-in-out infinite; }
  @keyframes bx-finding-pulse { 0%, 100% { stroke-opacity: 1; stroke-width: 4px; } 50% { stroke-opacity: 0.45; stroke-width: 6px; } }
  @keyframes bx-finding-outline { 0%, 100% { outline-color: var(--bad); } 50% { outline-color: color-mix(in srgb, var(--bad) 40%, transparent); } }
}
