:root{--area-hv:var(--sig-hv); 
  --paper:#F7F5F0; --ink:#1B2A41; --ink-soft:#4A5A72;
  /* IC bodies share the external blocks' surface — same fill, readable ink,
     no dark chip. Defined ONCE against --paper/--ink, so they follow whichever
     theme is active and can never drift apart from the external blocks. An IC
     still reads as an IC: solid outline + drop shadow, where an external block
     is a dashed soft outline. */
  --epoxy:var(--paper); --epoxy-edge:var(--ink); --silk:var(--ink);
  --probe:#FFC53D; --probe-deep:#B8860B;
  --copper:#B0793C; --copper-soft:#C9A06B; --grid:rgba(43,42,38,.07); --hv:#C43E1C;
  --panel:#FFFFFF; --line:#DEDACC; --ok:#3D7A46; --warn:#A8890B;
  --vellum:#F6EFDC; --field-bg:#FDFCF9;
  --btn-hover:#EFECE2; --primary-hover:#2A3D5C; --danger-hover:#FBEAE4;
  --overlay:rgba(27,42,65,.45);
  /* Signal-category palette — color + dash pattern differentiate nets instead of
     line/arrow size (every wire renders at the same weight, same arrowhead). */
  --sig-hv:#C43E1C; --sig-power:#C46A12; --sig-control:#2A63C4; --sig-logic:#1B8E86;
  --sig-analog:#3D7A46; --sig-switching:#8A4FC4; --sig-other:#767F8C;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Consolas,monospace;
  --sans:'IBM Plex Sans',system-ui,-apple-system,sans-serif;
}
:root[data-theme="dark"]{
  --paper:#1B2027; --ink:#E7ECF3; --ink-soft:#8D99AC;
  --probe:#FFC53D; --probe-deep:#D9A227;
  --copper:#D3A06C; --copper-soft:#B98A57; --grid:rgba(232,230,225,.06); --hv:#FF7A5C;
  --panel:#20262E; --line:#39424C; --ok:#5FBE6D; --warn:#F2C932;
  --vellum:#2E2A1E; --field-bg:#161B21;
  --btn-hover:#2A323C; --primary-hover:#C7CEDA; --danger-hover:#3A2620;
  --overlay:rgba(0,0,0,.55);
  --sig-hv:#FF7A5C; --sig-power:#F2A23D; --sig-control:#5B9BFF; --sig-logic:#3ED6C7;
  --sig-analog:#5FBE6D; --sig-switching:#BE93F5; --sig-other:#8D99AC;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{font-family:var(--sans);color:var(--ink);background:var(--paper);display:flex;flex-direction:column;overflow:hidden;transition:background .15s,color .15s}

/* ---------- top bar ---------- */
/* The header keeps ONE fixed height and ONE fixed button row, whatever the
   system title turns out to be: min-height pins the bar, the buttons never
   shrink or wrap, and the title alone absorbs the difference by ellipsizing
   (the full text stays available in its hover tooltip). */
header{display:flex;align-items:center;gap:14px;padding:10px 16px;border-bottom:2px solid var(--ink);background:var(--paper);flex-shrink:0;min-height:62px}
header button{flex-shrink:0;white-space:nowrap}
.brand-logo{height:40px;width:auto;border-radius:4px;flex-shrink:0;display:block}
/* flex:1 1 auto + min-width:0 — the title claims the leftover room when it is
   long and gives it back to the spacer when it is short, so the buttons stay
   right-aligned and full-size either way. */
.brand{display:flex;flex-direction:column;line-height:1.15;min-width:0;flex:1 1 auto}
.brand .eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--ink-soft);text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brand h1{font-family:var(--mono);font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.spacer{flex:1}
button{font-family:var(--mono);font-size:12px;font-weight:500;border:1.5px solid var(--ink);background:var(--paper);color:var(--ink);padding:7px 12px;cursor:pointer;border-radius:3px;transition:background .12s,transform .06s}
button:hover{background:var(--btn-hover)}
button:active{transform:translateY(1px)}
button.primary{background:var(--ink);color:var(--paper)}
button.primary:hover{background:var(--primary-hover)}
button.danger{border-color:var(--hv);color:var(--hv)}
button.danger:hover{background:var(--danger-hover)}
button:focus-visible{outline:2px solid var(--probe);outline-offset:2px}
button:disabled{opacity:.35;cursor:default;pointer-events:none}
#btnUndo,#btnRedo{font-size:15px;padding:5px 10px;line-height:1}
.linklike{background:none;border:none;padding:0;font:inherit;color:var(--ink-soft);text-decoration:underline;text-decoration-color:var(--copper);cursor:pointer}
.linklike:hover{color:var(--ink)}

/* ---------- layout ---------- */
main{flex:1;display:flex;min-height:0}
#canvasWrap{flex:1;position:relative;min-width:0;background:var(--paper)}
svg#board{position:absolute;inset:0;width:100%;height:100%;display:block;cursor:grab;touch-action:none}
svg#board.panning{cursor:grabbing}
svg#board.linking{cursor:crosshair}
/* Net trace armed: everything the traced net does not touch recedes — faded
   and desaturated, EDA cross-probe style — so the lit path reads instantly.
   Dimmed elements stay clickable (selecting one re-scopes or ends the trace). */
svg#board .dim{opacity:.22;filter:saturate(.35)}

.breadcrumb{position:absolute;top:12px;left:12px;z-index:5;display:flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:11.5px;background:var(--panel);border:1.5px solid var(--line);
  border-radius:3px;padding:5px 10px;pointer-events:none;user-select:none}
.breadcrumb .crumb-link{pointer-events:auto;background:none;border:none;padding:0;font:inherit;
  color:var(--ink-soft);text-decoration:underline;text-decoration-color:var(--copper);cursor:pointer}
.breadcrumb .crumb-link:hover{color:var(--ink)}
.breadcrumb .crumb-sep{color:var(--line)}
.breadcrumb .crumb-current{color:var(--ink);font-weight:600}

aside#inspector{width:340px;flex-shrink:0;border-left:2px solid var(--ink);background:var(--panel);display:flex;flex-direction:column;min-height:0;
  position:relative;overflow:hidden;transition:width .22s ease}
/* Unpinned + idle: the panel folds away completely so the diagram gets the room. */
aside#inspector.collapsed{width:0 !important;border-left-width:0}
aside#inspector.resizing{transition:none}
#inspector .head{padding:12px 40px 12px 16px;border-bottom:1px solid var(--line)}
/* Inner content is pinned to the panel's chosen width (JS keeps --inspw in
   sync), so folding away slides the text out instead of re-wrapping it. */
#inspector .head,#inspector .body{min-width:var(--inspw,340px)}
/* the peer-review tick in the inspector head — grey until the block has been
   reviewed, green once it has, matching the one drawn on the block */
.peertick{background:none;border:none;padding:0 0 0 6px;margin:0;cursor:pointer;color:var(--ink-soft);
  opacity:.6;vertical-align:-3px;line-height:0}
.peertick svg{width:14px;height:14px;display:block}
.peertick:hover{opacity:1}
.peertick.on{color:var(--ok);opacity:1}
#inspector .head .eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--ink-soft);text-transform:uppercase}
#inspector .head h2{font-family:var(--mono);font-size:15px;font-weight:600;margin-top:2px;word-break:break-word}
#inspector .body{flex:1;overflow-y:auto;padding:14px 16px;font-size:13px}
#inspector .body p{color:var(--ink-soft);line-height:1.5;margin-bottom:10px}
/* Altium-style thumbtack, top-right of the panel: upright = pinned (always
   visible), tilted = unpinned (the panel auto-hides to maximize the canvas). */
#inspPin{position:absolute;top:8px;right:8px;width:26px;height:26px;padding:3px;border:1px solid transparent;
  background:none;border-radius:4px;cursor:pointer;color:var(--ink-soft);z-index:2;line-height:0}
#inspPin:hover{border-color:var(--line);background:var(--btn-hover);color:var(--ink)}
#inspPin svg{width:18px;height:18px;transition:transform .18s ease}
#inspPin.pinned{color:var(--copper)}
#inspPin:not(.pinned) svg{transform:rotate(48deg)}
/* Drag strip on the panel's left edge — resize the panel horizontally. */
#inspResize{position:absolute;left:0;top:0;bottom:0;width:7px;cursor:ew-resize;z-index:2}
#inspResize:hover,#inspResize.active{background:linear-gradient(90deg,var(--copper),transparent)}
/* Collapse/expand handle, always visible (pin or no pin): a slim block sat
   on the divider's midpoint, splitting it into two line segments. Chevron
   points right while the panel is out (click = fold it away); the block
   stays at the screen edge, mirrored, while the panel is hidden. */
#inspHandle{position:absolute;right:-8px;top:50%;transform:translateY(-50%);width:16px;height:52px;
  display:flex;align-items:center;justify-content:center;padding:0;
  border:1.5px solid var(--ink);border-radius:5px;background:var(--panel);color:var(--ink-soft);
  cursor:pointer;z-index:6;line-height:0}
#inspHandle:hover{color:var(--ink);background:var(--btn-hover)}
#inspHandle svg{width:11px;height:38px}
#inspHandle.folded{right:0;border-radius:5px 0 0 5px;border-right:none}
#inspHandle.folded svg{transform:scaleX(-1)}
.kv{margin-bottom:10px}
.kv label{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-soft);margin-bottom:3px}
.kv .val{line-height:1.45;word-break:break-word}
.kv .val a{color:var(--ink);text-decoration-color:var(--copper)}
input[type=text],textarea,select{width:100%;font-family:var(--mono);font-size:12px;padding:6px 8px;border:1.5px solid var(--line);border-radius:3px;background:var(--field-bg);color:var(--ink)}
input[type=text]:focus,textarea:focus,select:focus{outline:2px solid var(--probe);border-color:var(--ink)}
textarea{resize:vertical;min-height:52px;font-family:var(--sans)}
.row{display:flex;gap:8px}
.row>*{flex:1}
.btnrow{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}

/* ---------- net list ---------- */
.netcard{border:1.5px solid var(--line);border-left:4px solid var(--sig-other);border-radius:3px;padding:8px 10px;margin-bottom:8px;background:var(--field-bg)}
.netcard.cat-hv{border-left-color:var(--sig-hv)}
/* a net on a connection that ILLEGALLY crosses isolation areas stays warning
   yellow whatever its level/category — the error owns the color until fixed */
.netcard.err{border-left-color:var(--warn);border-color:var(--warn)}
.netcard.cat-power{border-left-color:var(--sig-power)}
.netcard.cat-control{border-left-color:var(--sig-control)}
.netcard.cat-logic{border-left-color:var(--sig-logic)}
.netcard.cat-analog{border-left-color:var(--sig-analog)}
.netcard.cat-switching{border-left-color:var(--sig-switching)}
.netcard .nettop{display:flex;align-items:center;gap:6px}
.netcard .netname{font-family:var(--mono);font-size:12px;font-weight:600;flex:1;word-break:break-all}
.netcard .nettype{font-family:var(--mono);font-size:10px;color:var(--ink-soft)}
.netcard .netdesc{font-size:11.5px;color:var(--ink-soft);line-height:1.4;margin-top:4px}
.netcard .x{border:none;background:none;color:var(--hv);font-size:14px;padding:0 4px;cursor:pointer}
/* "✎" next to the "✕": flips the card into edit mode (name + description). */
.netcard .pen{border:none;background:none;color:var(--ink-soft);font-size:13px;padding:0 2px;cursor:pointer}
.netcard .pen:hover{color:var(--probe)}
.netcard.editing{background:var(--panel)}
.netcard .netdom{font-family:var(--mono);font-size:9px;font-weight:700;letter-spacing:.04em;line-height:1;
  padding:2px 6px;border-radius:8px;cursor:pointer;border:1.2px solid var(--ink-soft);
  background:var(--paper);color:var(--ink-soft);flex-shrink:0}
.netcard .netdom.hv{border-color:var(--sig-hv);color:var(--sig-hv)}
.netcard .netdom:hover{background:var(--btn-hover)}
/* Net cards double as trace toggles: click one to light the whole net up
   across the diagram (see traceSets in app.js); click again to switch off. */
.netcard.traceable{cursor:pointer}
.netcard.traceable:hover{border-color:var(--copper)}
.netcard.on{outline:2px solid var(--probe);outline-offset:1px}
.addnet{border:1.5px dashed var(--line);border-radius:3px;padding:10px;margin-top:6px}
.addnet .kv{margin-bottom:6px}

/* ---------- footer / status ---------- */
footer{display:flex;align-items:center;gap:10px;padding:6px 16px;border-top:1px solid var(--line);font-family:var(--mono);font-size:11px;color:var(--ink-soft);flex-shrink:0;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:10px;border:1px solid var(--line);background:var(--field-bg)}
.chip.warn{border-color:var(--warn);color:var(--warn)}
.chip.ok{border-color:var(--ok);color:var(--ok)}
.dot{width:7px;height:7px;border-radius:50%;background:currentColor}

/* ---------- signal legend (floats over the canvas, top-right) ---------- */
#legend{position:absolute;top:12px;right:12px;z-index:5;display:flex;align-items:center;justify-content:flex-end;
  gap:10px;flex-wrap:wrap;max-width:min(60%,560px);font-family:var(--mono);
  background:var(--panel);border:1.5px solid var(--line);border-radius:3px;padding:6px 10px;
  pointer-events:none;user-select:none}
#legend .litem{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;color:var(--ink-soft)}
#legend .lswatch{width:16px;height:0;border-top-width:2.5px;border-top-style:solid;display:inline-block}

/* ---------- Project Options: the PDF-export sub-window ---------- */
fieldset.subpane{border:1.5px solid var(--line);border-radius:3px;padding:10px 12px 4px;margin:12px 0 10px}
fieldset.subpane legend{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-soft);padding:0 6px}

/* ---------- empty sheet: the "+" card that opens Import ----------
   Shown only while nothing is loaded (renderEmptyState toggles [hidden]).
   It floats over the middle of the canvas and is the sheet's only offer:
   a diagram exists because the user imported one. */
#emptyState{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:5;
  display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;
  background:var(--panel);border:1.5px solid var(--line);border-radius:6px;padding:28px 40px}
#emptyState[hidden]{display:none}
/* Two side-by-side choices: import ("+") and start-from-scratch (blank page),
   each with a small caption underneath. */
#emptyState .es-actions{display:flex;gap:26px;align-items:flex-start}
#emptyState .es-choice{display:flex;flex-direction:column;align-items:center;gap:7px}
#emptyState .es-cap{margin:0;font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--ink-soft)}
#emptyAdd,#emptyBlank{width:76px;height:76px;padding:0;display:flex;align-items:center;justify-content:center;
  border:2px dashed var(--ink-soft);border-radius:8px;background:var(--field-bg);color:var(--ink-soft);
  cursor:pointer;line-height:0;transition:color .12s,border-color .12s,background .12s}
#emptyAdd:hover,#emptyBlank:hover{color:var(--probe);border-color:var(--probe);background:var(--btn-hover)}
#emptyAdd svg,#emptyBlank svg{width:40px;height:40px}
#emptyState .es-title{margin:0;font-family:var(--mono);font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink)}
#emptyState .es-hint{margin:0;font-size:12px;color:var(--ink-soft);max-width:34ch;line-height:1.5}

/* ---------- view controls (bottom-right of the sheet) ----------
   Icons only — zoom out, zoom in, fit — each naming itself on hover via its
   native title tooltip. */
#viewTools{position:absolute;right:12px;bottom:12px;z-index:6;display:flex;flex-direction:column;
  border:1.5px solid var(--line);border-radius:5px;background:var(--panel);overflow:hidden}
#viewTools button{width:30px;height:30px;padding:0;display:flex;align-items:center;justify-content:center;
  border:none;border-bottom:1px solid var(--line);border-radius:0;background:transparent;
  color:var(--ink-soft);cursor:pointer;line-height:0}
#viewTools button:last-child{border-bottom:none}
#viewTools button:hover{color:var(--ink);background:var(--btn-hover)}
#viewTools button:disabled{opacity:.4;cursor:default;background:transparent;color:var(--ink-soft)}
#viewTools svg{width:17px;height:17px}

/* ---------- LV|HV flip switch (barrier blocks) ----------
   `label.switch` (not just .switch): the generic `.kv label` block rule would
   otherwise out-rank the flex display and collapse the knob onto the text. */
label.switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none;margin:2px 0 0;
  font-family:var(--mono);font-size:11px;letter-spacing:0;text-transform:none;color:var(--ink-soft)}
label.switch input{position:absolute;opacity:0;pointer-events:none}
label.switch .knob{display:inline-block;width:34px;height:18px;border-radius:10px;border:1.5px solid var(--ink);
  background:var(--field-bg);position:relative;transition:background .15s;flex-shrink:0}
label.switch .knob::after{content:'';position:absolute;top:1.5px;left:2px;width:12px;height:12px;border-radius:50%;
  background:var(--ink);transition:left .15s}
label.switch input:checked + .knob{background:var(--probe)}
label.switch input:checked + .knob::after{left:17px}
label.switch .swlabel{font-family:var(--mono);font-size:11px;color:var(--ink-soft)}

/* ---------- part search — DigiKey + Mouser (Add IC modal) ---------- */
.dksearch{border:1.5px dashed var(--line);border-radius:3px;padding:10px;margin-bottom:14px}
.dksearch .row{align-items:flex-end}
.dksearch .row input{min-width:0}
.dkresults{max-height:220px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}
.dkrow{display:grid;grid-template-columns:auto auto 1fr;grid-template-areas:"pn src man" "desc desc desc" "stock stock price";
  gap:1px 10px;text-align:left;width:100%;padding:6px 9px;border:1.5px solid var(--line);border-radius:3px;
  background:var(--field-bg);cursor:pointer;transition:border-color .12s,background .12s}
.dkrow:hover{border-color:var(--copper)}
.dkrow.on{border-color:var(--probe);background:var(--btn-hover)}
.dkrow .dkpn,.dkchosen .dkpn{grid-area:pn;font-family:var(--mono);font-size:12px;font-weight:600;color:var(--ink)}
/* Which house the row came from — the one field that tells the two apart. */
.dkrow .dksrc,.dkchosen .dksrc{grid-area:src;justify-self:start;align-self:center;font-family:var(--mono);
  font-size:8.5px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:var(--ink-soft);
  border:1px solid var(--line);border-radius:3px;padding:0 4px;line-height:1.6}
.dkrow .dkman,.dkchosen .dkman{grid-area:man;font-family:var(--mono);font-size:10px;color:var(--ink-soft);text-align:right;align-self:center}
.dkrow .dkdesc,.dkchosen .dkdesc{grid-area:desc;font-size:11px;color:var(--ink-soft);line-height:1.35}
.dkrow .dkstock,.dkchosen .dkstock{grid-area:stock;font-family:var(--mono);font-size:10.5px;color:var(--ok)}
/* a picked part with nothing in stock reads as a warning, not as a fact */
.dkchosen .dkstock.nostock{color:var(--warn);font-weight:600}
.dkrow .dkprice,.dkchosen .dkprice{grid-area:price;font-family:var(--mono);font-size:10.5px;font-weight:600;color:var(--ink);text-align:right}
/* The block's CHOSEN part, shown under "Select IC" exactly like a search
   result — green border says "done", where the amber hint said "pending". */
.dkchosen{position:relative;display:grid;grid-template-columns:auto auto 1fr;grid-template-areas:"pn src man" "desc desc desc" "stock stock price";
  gap:2px 10px;border:1.5px solid var(--ok);border-radius:3px;background:var(--field-bg);
  padding:7px 9px 7px 26px;margin:-2px 0 12px}
/* "✕" top-left of the card: drop the part, the warnings come back. */
.dkchosen .x{position:absolute;top:4px;left:4px;width:17px;height:17px;padding:0;line-height:1;
  font-size:10px;border:1px solid var(--line);border-radius:3px;background:var(--panel);color:var(--ink-soft)}
.dkchosen .x:hover{border-color:var(--hv);color:var(--hv);background:var(--danger-hover)}
/* Scoped to the panel: the generic "#inspector .body p" rule out-ranks a bare
   .icwarn, which used to paint this warning the same grey as body copy. */
#inspector .body p.icwarn,.icwarn{color:var(--warn);font-family:var(--mono);font-size:11px;line-height:1.5;margin:-2px 0 12px}
/* A pending selection colors its own call to action — same amber as the
   block outline and the group tag, so the three read as one warning. */
button.warn{border-color:var(--warn);color:var(--warn)}
button.warn:hover{background:var(--danger-hover);border-color:var(--warn)}

/* The "+" under each FROM/TO column: hidden until the column is hovered or
   one of its boxes is selected. Alone in an EMPTY column it idles translucent
   (the only hint the column exists) and solidifies on hover. */
.pcol .portaladd{opacity:0;pointer-events:none;transition:opacity .15s}
.pcol .portaladd.lone{opacity:.35;pointer-events:auto}
.pcol:hover .portaladd,.pcol.selon .portaladd{opacity:1;pointer-events:auto}
/* the ground "+" follows the same norm as the FROM/TO one: out of the way
   until the block is hovered or selected */
/* The "+" stays clickable even while invisible: its transparent hit rect below
   the block is what lets an approach from UNDER the port reveal it (hovering
   the rect makes the whole .node :hover, since the "+" is one of its children). */
#nodesG .node .gndadd{opacity:0;transition:opacity .15s}
#nodesG .node:hover .gndadd,#nodesG .node.selon .gndadd,#nodesG .node .gndadd:hover{opacity:1}

/* Issues panel: warn chips in the status bar are clickable, and each listed
   issue is a full-width button that jumps to (and spotlights) the culprit. */
button.chip{cursor:pointer;font:inherit}
button.chip.warn:hover{border-color:var(--warn);background:var(--danger-hover)}
.issue{display:block;width:100%;text-align:left;font-size:11.5px;line-height:1.4;
  border:1.5px solid var(--line);border-left:4px solid var(--warn);border-radius:3px;
  background:var(--field-bg);padding:6px 9px;margin-bottom:6px;cursor:pointer}
.issue:hover{border-color:var(--warn)}
/* the entry currently spotlighted on the canvas — the list stays open while
   you walk it, so it has to say where you are */
.issue.on{border-color:var(--warn);background:var(--danger-hover);border-left-width:6px}
/* Isolation Barriers: an area's color is fixed by its position in the list, so
   the swatch is a round READING of it, never a control. */
.isoswatch{display:inline-block;width:22px;height:22px;border-radius:50%;
  border:1.5px solid var(--line);flex-shrink:0;align-self:center;margin-bottom:1px}
.issue b{font-family:var(--mono);font-size:11.5px}

/* Auto IC Selection progress log inside the modal */
.ailog{font-family:var(--mono);font-size:11px;line-height:1.8;max-height:300px;overflow-y:auto;color:var(--ink-soft)}

/* IC cost breakdown table (System panel → total → modal) */
.costtbl{width:100%;border-collapse:collapse;font-size:11.5px}
.costtbl th{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);
  text-align:left;padding:4px 8px;border-bottom:1.5px solid var(--line)}
.costtbl td{padding:4px 8px;border-bottom:1px solid var(--line)}
.costtbl .num{text-align:right;font-family:var(--mono)}
.costtbl tr.dim td{color:var(--ink-soft);opacity:.65}
/* a BOM row that needs attention — no part yet, or no stock — is warning
   yellow end to end */
.costtbl tr.warnrow td{background:color-mix(in srgb, var(--warn) 16%, transparent);color:var(--warn);font-weight:500}
.costtbl tr.warnrow td:first-child{box-shadow:inset 3px 0 0 var(--warn)}
.costtbl tfoot td{border-top:2px solid var(--ink);border-bottom:none;font-weight:600}

/* ---------- modal ---------- */
.overlay{position:fixed;inset:0;background:var(--overlay);display:none;align-items:center;justify-content:center;z-index:40}
.overlay.open{display:flex}
.modal{background:var(--panel);border:2px solid var(--ink);border-radius:4px;width:min(680px,92vw);max-height:88vh;display:flex;flex-direction:column}
.modal .mhead{padding:12px 16px;border-bottom:1px solid var(--line);display:flex;align-items:center}
.modal .mhead h3{font-family:var(--mono);font-size:14px}
.modal .mbody{padding:14px 16px;overflow-y:auto;font-size:13px}
.modal .mfoot{padding:12px 16px;border-top:1px solid var(--line);display:flex;gap:8px;justify-content:flex-end}
.modal textarea{min-height:150px}
.tabs{display:flex;gap:0;margin-bottom:12px;border-bottom:1.5px solid var(--line)}
.tabs button{border:none;border-bottom:3px solid transparent;border-radius:0;background:none;padding:8px 12px}
.tabs button.on{border-bottom-color:var(--probe);font-weight:600}
.hint{font-size:11.5px;color:var(--ink-soft);line-height:1.45;margin:6px 0 10px}
pre.out{font-family:var(--mono);font-size:11px;background:var(--field-bg);border:1.5px solid var(--line);border-radius:3px;padding:10px;max-height:240px;overflow:auto;white-space:pre-wrap;word-break:break-all}
.toast{position:fixed;left:50%;bottom:52px;transform:translateX(-50%);background:var(--ink);color:var(--paper);font-family:var(--mono);font-size:12px;padding:8px 14px;border-radius:3px;opacity:0;pointer-events:none;transition:opacity .18s;z-index:60}
.toast.show{opacity:1}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
@media (max-width:860px){aside#inspector{width:280px}.brand h1{max-width:30vw}}
