/* PCBNet integration styles — follows the playground's dark GitHub palette. */

/* ── Semantic state colors (A3) ─────────────────────────────────────────────
   One source of truth for ok/warn/error, so the badges (#2), diff (#25),
   pre-flight (#34), console, and stock chips all agree. `-fg` is the readable
   text/icon color (slightly brighter than the base token for contrast on dark
   surfaces); `-bg` is the soft fill behind chips. */
:root {
  --ok-fg:   #3fb950;  --ok-bg:   rgba(46, 164, 79, 0.16);
  --warn-fg: #e0a92a;  --warn-bg: rgba(210, 153, 34, 0.18);
  --err-fg:  #f0605e;  --err-bg:  rgba(229, 72, 77, 0.18);
}

/* ── Accessibility: visible keyboard focus (D1) ─────────────────────────────
   Keyboard users had almost no visible focus. One consistent :focus-visible
   ring across every interactive control — shell buttons/tabs and PCBNet's own
   chips, dialog controls, and links. :focus-visible (not :focus) so a mouse
   click doesn't leave a lingering ring, only keyboard/AT navigation does. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.ws-tab:focus-visible,
.tool-btn:focus-visible,
.dock-tab:focus-visible,
.con-tab:focus-visible,
.pcb-cmdk-item:focus-visible,
.sim-probe:focus-visible,
.ws-tab-badge:focus-visible,
.pcb-explain-q:focus-visible,
.pcb-bom-tr[data-refs]:focus-visible {
  outline: 2px solid var(--blue, #388bfd);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Schematic editor overlay (Circuit tab) */
.pcb-schematic {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 5;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* Component hover feedback (on the invisible fat hit-rect) */
.pcb-schematic g[data-comp]:hover .pcb-hit {
  fill: rgba(56, 139, 253, .07);
  stroke: rgba(56, 139, 253, .35);
  stroke-width: 1;
}
/* Pins grow slightly on hover so wiring targets are obvious */
.pcb-schematic [data-pin] { transition: r .08s; }
.pcb-schematic [data-pin]:hover { r: 6; }

/* PCB layout view (Layout tab) */
.pcb-layout-view {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
  position: relative;
  /* Matches the backend's board-SVG background (pcb_layout.py) so the viewport
     and the artifact are seamless. Stays dark in the light theme by design: the
     board SVG is rendered server-side on dark green, and a light surround would
     just frame it badly. */
  background: var(--board-bg, #02060d);
  cursor: grab;
}

.pcb-layout-view:active { cursor: grabbing; }

.pcb-layout-inner {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.pcb-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--dim, #7d8590);
  font-size: 12px;
  line-height: 1.7;
  pointer-events: none;
}

/* Empty state: the secondary "import a circuit file" route, kept visually
   quieter than the prompt chips so it reads as the alternative, not the path. */
.pcb-hero-alt {
  margin-top: 14px;
  font-size: 11.5px;
  color: var(--dim, #7d8590);
}
.pcb-hero-import {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--blue, #388bfd);
  cursor: pointer;
  text-decoration: underline;
}
.pcb-hero-import:hover { color: var(--bright, #f0f6fc); }
.pcb-hero-dim { opacity: .75; }

/* Dropping a circuit .json onto the schematic imports it. The inset ring says
   "this surface will accept the file" without moving anything. */
.pcb-drop-target {
  outline: 2px dashed var(--blue, #388bfd);
  outline-offset: -6px;
}

/* Honest dock menus (File/Edit/View/Simulate/Insert/Help). An action that
   cannot apply yet is shown disabled rather than hidden, so the menu keeps a
   stable shape and teaches what will become possible once a circuit exists. */
.pcb-menu .ctx-item.disabled {
  opacity: .45;
  cursor: default;
}
.pcb-menu .ctx-item.disabled:hover {
  background: none;
  color: inherit;
  padding-left: 10px;   /* cancel the stock hover indent */
}
.pcb-menu-hint {
  flex-shrink: 0;
  margin-left: 12px;
  font-size: 10px;
  color: var(--dim);
}

/* C2 — the no-simulation empty state, overlaid on each plot cell. Sits above
   the blank canvas but below the cell header, so the header's zoom/expand
   tools stay reachable. Padded so the text never collides with the header. */
.pcb-sim-empty {
  top: 26px;
  z-index: 1;
  padding: 0 12px;
}

/* Checks console lines reuse .con-line; a couple of extra severities */
.con-line.ok  { color: var(--ok-fg); }
.con-line.wrn { color: var(--warn-fg); }

/* ── Checks grouped by severity ─────────────────────────────────────
   Findings are bucketed ERRORS / WARNINGS rather than ERC / DRC, so the
   things that block fabrication are always at the top of the panel. */
.chk-hdr {
  font-weight: 700; letter-spacing: .04em;
  margin-top: 2px; padding-bottom: 2px;
  border-bottom: 1px solid var(--bord, #30363d);
}
/* Plain-language cue for what the group means — the count alone does not say
   whether a user must act. */
.chk-hint {
  float: right; font-weight: 400; font-size: 10px;
  opacity: .75; text-transform: none; letter-spacing: 0;
}
/* Which checker produced a finding, now that grouping is by severity. */
.chk-src { opacity: .6; }
.chk-ran { padding-top: 4px; border-top: 1px solid var(--bord, #30363d); }

/* ── Errors / Warnings console tabs ─────────────────────────────────
   Counts live on the tab itself so the bar says whether anything needs
   attention without opening a panel. No badge means nothing found. */
.con-tab-count {
  display: inline-block; margin-left: 5px;
  min-width: 15px; padding: 0 4px;
  border-radius: 7px; font-size: 9.5px; font-weight: 700;
  line-height: 15px; text-align: center; vertical-align: 1px;
}
.con-tab-count.err { background: var(--red, #f85149); color: #fff; }
.con-tab-count.wrn { background: var(--warn-fg, #d29922); color: #1c1300; }
/* A tab holding errors stays legible even when not the active tab. */
.con-tab.has-err { color: var(--red, #f85149); }
.con-tab.has-wrn { color: var(--warn-fg, #d29922); }

/* #24 — the AI-assumptions card, attached to the AI message that produced it. */
.pcb-assumptions {
  margin: 6px 0 2px;
  border: 1px solid var(--border2, #30363d);
  border-radius: 6px;
  background: rgba(57, 197, 207, 0.06);
  overflow: hidden;
}
.pcb-assumptions-hdr {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 5px 8px;
  border: none;
  background: transparent;
  color: var(--netlbl, #39c5cf);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  text-align: left;
}
.pcb-assumptions-caret { transition: transform 0.12s ease; display: inline-block; }
.pcb-assumptions:not(.open) .pcb-assumptions-caret { transform: rotate(-90deg); }
.pcb-assumptions-list {
  margin: 0;
  padding: 0 10px 8px 24px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text, #c9d1d9);
  /* The body sets user-select:none globally; re-enable it here so the text
     can be highlighted and copied, with an I-beam cursor to signal that. */
  user-select: text;
  -webkit-user-select: text;
  cursor: text;
}
.pcb-assumptions:not(.open) .pcb-assumptions-list { display: none; }
.pcb-assumptions-list li { margin: 2px 0; }

/* A contradicted assumption re-tints the card: this is the one case where it
   reports a fault rather than a decision, so it should not read as calm. */
.pcb-assumptions.has-bad {
  border-color: var(--red, #f85149);
  background: rgba(248, 81, 73, 0.06);
}
.pcb-assumptions.has-bad .pcb-assumptions-hdr { color: var(--red, #f85149); }

/* Per-assumption verification state. The icon carries the state; colour alone
   would not survive a colour-blind reader or a monochrome screenshot. */
.pcb-assumptions-list li.pcb-asm {
  list-style: none;
  margin-left: -14px;               /* pull back level with the plain <li> */
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 0 6px;
}
.pcb-asm-icon { font-weight: 700; line-height: 1.5; }
.pcb-asm.ok  .pcb-asm-icon { color: var(--green, #3fb950); }
.pcb-asm.bad .pcb-asm-icon { color: var(--red, #f85149); }
.pcb-asm.unk .pcb-asm-icon { color: var(--muted, #8b949e); }
/* An unverified claim is dimmed, never hidden: silence would read as checked. */
.pcb-asm.unk .pcb-asm-text { color: var(--muted, #8b949e); }
.pcb-asm-why {
  grid-column: 2;
  margin: 1px 0 3px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--red, #f85149);
}
.pcb-asm.unk .pcb-asm-why { color: var(--muted, #8b949e); }

/* Click-to-locate chips, matching the affordance the ERC list already offers. */
.pcb-asm-refs { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: 4px; }
.pcb-asm-ref {
  border: 1px solid var(--border2, #30363d);
  border-radius: 4px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 10px;
  padding: 0 4px;
  cursor: pointer;
}
.pcb-asm-ref:hover { border-color: var(--netlbl, #39c5cf); color: var(--netlbl, #39c5cf); }

/* How many claims were actually recomputed. Without this, "no errors" reads as
   "all verified" -- the conflation this whole feature exists to prevent. */
.pcb-asm-summary {
  padding: 0 10px 8px 24px;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--muted, #8b949e);
}
.pcb-assumptions:not(.open) .pcb-asm-summary { display: none; }

/* #3 — the "next best action" bar: a slim, dismissible status line across the
   top of the workspace. Calm and informational, not an alert. */
.pcb-nextstep {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  width: 100%;
  padding: 5px 10px;
  font-size: 12px;
  color: var(--text, #c9d1d9);
  background: var(--surf2, #161b22);
  border-bottom: 1px solid var(--border2, #30363d);
  box-shadow: inset 3px 0 0 var(--blue, #3b82f6);
  animation: pcb-nextstep-in 180ms ease-out;
}
/* B4 — the bar slides down from the top edge rather than appearing abruptly.
   Only on first insert: renderNextStep reuses the element for a new hint, so
   re-running the animation on every text change would be a distraction. */
@keyframes pcb-nextstep-in {
  from { opacity: 0; transform: translateY(-100%); }
  to   { opacity: 1; transform: translateY(0); }
}
.pcb-nextstep-icon { color: var(--blue, #3b82f6); font-weight: 700; flex-shrink: 0; }
.pcb-nextstep-text { flex: 1 1 auto; line-height: 1.4; }
.pcb-nextstep-x {
  flex-shrink: 0;
  width: 18px; height: 18px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--dim, #7d8590);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.pcb-nextstep-x:hover { background: var(--surf3, #21262d); color: var(--bright, #f0f6fc); }

/* #6 — explain-this-check: the "?" toggle and its collapsible what/why/fix panel. */
.pcb-explain-q {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px; height: 14px;
  margin-left: 4px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  user-select: none;
}
.pcb-explain-q:hover,
.pcb-explain-q.active { opacity: 1; }

/* "Fix this" — hands one ERC finding to the assistant. Styled as an action
   rather than a help affordance, so it reads differently from the "?" beside
   it: this one changes the design, the "?" only explains it. */
.pcb-fix {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  border: 1px solid currentColor;
  border-radius: 9px;
  font-size: 9.5px;
  font-weight: 600;
  line-height: 14px;
  cursor: pointer;
  opacity: .75;
  user-select: none;
  white-space: nowrap;
}
.pcb-fix::before { content: '✦ '; }
/* `background: currentColor` cannot be combined with setting `color` in the
   same rule — currentColor would resolve to the new value and the pill would
   fill with the text colour. Brighten instead: unambiguous, and it reads as
   active in both themes. */
.pcb-fix:hover, .pcb-fix:focus-visible {
  opacity: 1;
  background: rgba(127, 127, 127, .18);
}
.pcb-explain {
  display: none;
  margin: 2px 0 4px 18px;
  padding: 6px 8px;
  border-left: 2px solid var(--border2, #30363d);
  background: rgba(127, 156, 186, 0.07);
  white-space: normal;
  line-height: 1.55;
}
.pcb-explain.open { display: block; }
.pcb-explain-row { display: block; }
.pcb-explain-row b {
  display: inline-block;
  min-width: 34px;
  color: var(--blue, #3b82f6);
  font-weight: 700;
}

/* #2 — ERC/DRC status badge on the workspace tab strip (Circuit=ERC, Layout=DRC).
   Colour is paired with a glyph (✖ ⚠ ✓) so it never relies on colour alone. */
.ws-tab-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 0 5px;
  height: 15px;
  border-radius: 7px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  flex-shrink: 0;
}
.ws-tab-badge.err { background: var(--err-bg);  color: var(--err-fg); }
.ws-tab-badge.wrn { background: var(--warn-bg); color: var(--warn-fg); }
.ws-tab-badge.ok  { background: var(--ok-bg);   color: var(--ok-fg); }
/* A4 — the badge opens the Checks console (see setTabBadge), so it carries the
   same hover affordance as every other interactive control. It was the one
   interactive element left with a focus ring but no hover feedback. */
.ws-tab-badge { cursor: pointer; }
.ws-tab-badge:hover { filter: brightness(1.25); }

/* B3 — a badge whose state changed gets a single scale-pop, so a count going
   0 → 3 catches the eye instead of changing silently. Applied by JS only when
   the text actually differs (see setTabBadge), never on an idle re-render. */
@keyframes pcb-badge-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.35); }
  100% { transform: scale(1); }
}
.ws-tab-badge.pcb-pop { animation: pcb-badge-pop 260ms ease-out; }

/* #64 — the guarantees footnote: a calm, bordered aside, not another finding. */
.con-line.pcb-guarantees {
  margin-top: 4px;
  padding: 6px 8px;
  border-left: 2px solid #3b82f6;
  background: rgba(59, 130, 246, 0.06);
  white-space: normal;
  line-height: 1.6;
}

/* Chat bubbles: keep newlines readable for AI answers, and re-enable text
   selection (the stock body rule sets user-select:none globally). */
#chatMessages .chat-bubble {
  white-space: normal; word-break: break-word;
  user-select: text; -webkit-user-select: text; cursor: text;
}

/* Per-message Copy button (shown on hover of an AI message) */
#chatMessages .chat-msg { position: relative; }
.chat-copy {
  position: absolute; top: 2px; right: 2px;
  background: var(--surf3, #21262d);
  border: 1px solid var(--border2, #30363d);
  color: var(--dim, #7d8590);
  border-radius: 5px; padding: 1px 7px;
  font-size: 10px; cursor: pointer;
  opacity: 0; transition: opacity .12s, color .12s, border-color .12s;
}
#chatMessages .chat-msg:hover .chat-copy { opacity: 1; }
.chat-copy:hover { color: var(--bright, #fff); border-color: var(--blue, #388bfd); }
.chat-copy.copied { color: var(--ok-fg); border-color: var(--ok-fg); opacity: 1; }

/* Chat in-flight / result states */
.chat-send:disabled { opacity: .35; cursor: default; }
.chat-send:disabled:hover { background: var(--blue2, #1f6feb); }
.chat-status { font-size: 11px; color: var(--dim, #7d8590); margin-top: 6px; }
.chat-cancel, .pcb-retry {
  margin-top: 6px;
  background: transparent;
  border: 1px solid var(--border2, #30363d);
  color: var(--dim, #7d8590);
  border-radius: 5px;
  padding: 2px 9px;
  font-size: 11px;
  cursor: pointer;
  transition: color .12s, border-color .12s;
}
.chat-cancel:hover { color: #f85149; border-color: #f85149; }
.pcb-retry:hover  { color: var(--bright, #fff); border-color: var(--blue, #388bfd); }
.chat-meta { font-size: 10px; color: var(--dim, #7d8590); margin-top: 3px; }
#chatMessages .chat-bubble code {
  background: rgba(110, 118, 129, .22);
  padding: 1px 4px;
  border-radius: 4px;
  font-family: 'SF Mono', Consolas, monospace;
  font-size: 11px;
}

/* ── Dialogs ────────────────────────────────────────────────────── */
/* Shared open animation for every modal (export, pre-flight #34, diff #25,
   BOM, command palette #12) so they all feel like one system (A2) and fade
   in rather than pop (B1). Respects prefers-reduced-motion below. */
@keyframes pcb-dialog-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pcb-card-in {
  from { opacity: 0; transform: translateY(6px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.pcb-exp-overlay {
  position: fixed; inset: 0; z-index: 950;
  background: rgba(0,0,0,.55); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  animation: pcb-dialog-in .12s ease-out;
}
.pcb-exp-card {
  background: var(--surf, #0d1117); border: 1px solid var(--border2, #30363d);
  border-radius: 12px; padding: 22px; width: 440px; max-width: 92vw;
  box-shadow: 0 20px 60px rgba(0,0,0,.7);
  animation: pcb-card-in .15s cubic-bezier(.16,1,.3,1);
}
/* Import preview — wider than a plain confirm because it is showing evidence,
   not asking a yes/no. */
.pcb-exp-card.pcb-imp { width: 520px; }
.pcb-imp-file {
  font-family: ui-monospace, monospace; font-size: 12px;
  color: var(--bright, #e6edf3);
  background: var(--surf2, #161b22); border: 1px solid var(--border, #21262d);
  border-radius: 6px; padding: 7px 10px; margin-bottom: 12px;
  overflow-wrap: anywhere;
}
.pcb-imp-tbl { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.pcb-imp-tbl th {
  text-align: left; font-weight: 400; font-size: 11px;
  color: var(--dim, #7d8590); padding: 3px 0; width: 40%;
}
.pcb-imp-tbl td {
  text-align: right; font-size: 12px; font-family: ui-monospace, monospace;
  color: var(--bright, #e6edf3); padding: 3px 0;
}
.pcb-imp-note {
  font-size: 11px; line-height: 1.5; color: var(--text, #c9d1d9);
  background: var(--surf2, #161b22);
  border-left: 2px solid var(--border2, #30363d);
  border-radius: 0 6px 6px 0; padding: 8px 10px; margin-bottom: 8px;
}
.pcb-imp-note.wrn { border-left-color: var(--amber, #d29922); }
.pcb-imp-note.err { border-left-color: var(--red, #f85149); }
.pcb-imp-note b { color: var(--bright, #e6edf3); }
/* Three buttons do not fit the two-button footer at narrow widths. */
.pcb-imp .pcb-exp-foot { flex-wrap: wrap; }

.pcb-exp-title { font-size: 14px; font-weight: 700; color: var(--bright, #e6edf3); }
.pcb-exp-sub { font-size: 11px; color: var(--dim, #7d8590); margin: 2px 0 16px; }
.pcb-exp-name { display: block; font-size: 11px; color: var(--dim, #7d8590); margin-bottom: 14px; }
.pcb-exp-name input {
  display: block; width: 100%; box-sizing: border-box; margin-top: 5px;
  background: var(--surf2, #161b22); border: 1px solid var(--border2, #30363d);
  border-radius: 6px; color: var(--bright, #e6edf3); padding: 7px 10px;
  font-size: 13px; outline: none;
}
.pcb-exp-name input:focus { border-color: var(--blue, #388bfd); }
.pcb-exp-list { border: 1px solid var(--border, #21262d); border-radius: 8px; padding: 4px; margin-bottom: 16px; }
.pcb-exp-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 8px; border-radius: 6px; cursor: pointer;
}
.pcb-exp-row:hover { background: rgba(56,139,253,.07); }
.pcb-exp-row.disabled { cursor: default; opacity: .5; }
.pcb-exp-row.disabled:hover { background: none; }
.pcb-exp-row input { accent-color: #388bfd; width: 13px; height: 13px; flex-shrink: 0; }
.pcb-exp-label { font-size: 12px; color: var(--bright, #e6edf3); flex-shrink: 0; }
.pcb-exp-ext { font-size: 10px; color: var(--dim, #7d8590); margin-left: 6px; }
.pcb-exp-desc { font-size: 10px; color: var(--dim, #7d8590); margin-left: auto; }
/* #12 — the command palette (Ctrl/⌘-K). */
.pcb-cmdk-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 12vh;
  background: rgba(1, 4, 9, 0.55);
  animation: pcb-dialog-in .12s ease-out;
}
.pcb-cmdk {
  width: min(560px, 92vw);
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  border-radius: 10px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  animation: pcb-card-in .15s cubic-bezier(.16,1,.3,1);
}
.pcb-cmdk-input {
  width: 100%;
  box-sizing: border-box;
  padding: 13px 16px;
  border: none;
  border-bottom: 1px solid var(--border2, #30363d);
  background: transparent;
  color: var(--bright, #f0f6fc);
  font-size: 14px;
  outline: none;
}
.pcb-cmdk-list { list-style: none; margin: 0; padding: 6px; max-height: 46vh; overflow-y: auto; }
.pcb-cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
}
.pcb-cmdk-item.active { background: var(--surf3, #21262d); }
.pcb-cmdk-group {
  flex-shrink: 0;
  min-width: 74px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--blue, #3b82f6);
}
.pcb-cmdk-label { flex: 1 1 auto; color: var(--text, #c9d1d9); }
.pcb-cmdk-hint { flex-shrink: 0; font-size: 11px; color: var(--dim, #7d8590); }
.pcb-cmdk-empty { padding: 14px; text-align: center; color: var(--dim, #7d8590); font-size: 13px; }
.pcb-cmdk-foot {
  display: flex; gap: 14px;
  padding: 7px 14px;
  border-top: 1px solid var(--border2, #30363d);
  font-size: 11px;
  color: var(--dim, #7d8590);
}

/* #25 — the diff-before-apply confirm list. */
.pcb-diff-list {
  list-style: none;
  margin: 10px 0 14px;
  padding: 0;
  font-size: 12.5px;
  line-height: 1.9;
}
.pcb-diff-list li { display: flex; align-items: baseline; gap: 6px; }
.pcb-diff-add { color: var(--ok-fg); }
.pcb-diff-rem { color: var(--err-fg); }
.pcb-diff-chg { color: var(--warn-fg); }

/* #34 — the pre-flight "ready to fab?" summary list. */
.pcb-preflight-list {
  list-style: none;
  margin: 10px 0 14px;
  padding: 0;
  font-size: 12.5px;
  line-height: 1.9;
}
.pcb-preflight-list li { display: flex; align-items: center; gap: 6px; }
.pcb-preflight-list li.ok  { color: var(--ok-fg); }
.pcb-preflight-list li.wrn { color: var(--warn-fg); }
.pcb-preflight-list li.err { color: var(--err-fg); font-weight: 600; }

.pcb-exp-foot { display: flex; justify-content: flex-end; gap: 8px; }
.pcb-exp-cancel, .pcb-exp-go {
  border-radius: 6px; padding: 7px 16px; font-size: 12px; cursor: pointer;
  border: 1px solid var(--border2, #30363d);
}
.pcb-exp-cancel { background: none; color: var(--dim, #7d8590); }
.pcb-exp-go { background: var(--blue2, #1f6feb); border-color: var(--blue2, #1f6feb); color: #fff; }
.pcb-exp-go:hover { background: var(--blue, #388bfd); }
.pcb-exp-price {
  /* C4 — sits in the same footer row as .pcb-exp-cancel/.pcb-exp-go, so it
     carries their exact metrics (was 7px 14px, visibly narrower side by side). */
  border-radius: 6px; padding: 7px 16px; font-size: 12px; cursor: pointer;
  border: 1px solid var(--border2, #30363d); background: none;
  color: var(--bright, #e6edf3); margin-right: auto;   /* push it to the left */
}
.pcb-exp-price:hover { background: rgba(56,139,253,.10); }
.pcb-exp-price:disabled { opacity: .6; cursor: default; }

/* ── BOM pricing panel ──────────────────────────────────────────── */
.pcb-bom-card { max-width: 640px; width: min(640px, 92vw); }
.pcb-bom-banner {
  font-size: 11px; color: var(--dim, #7d8590); line-height: 1.5;
  background: rgba(56,139,253,.06); border: 1px solid var(--border, #21262d);
  border-radius: 6px; padding: 8px 10px; margin-bottom: 12px;
}
.pcb-bom-banner code {
  font-family: ui-monospace, monospace; font-size: 10px;
  background: rgba(110,118,129,.2); padding: 1px 4px; border-radius: 3px;
}
.pcb-bom-tablewrap { max-height: 46vh; overflow: auto; border: 1px solid var(--border, #21262d); border-radius: 8px; }
.pcb-bom-table { width: 100%; border-collapse: collapse; font-size: 11px; }
.pcb-bom-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--panel, #161b22); color: var(--dim, #7d8590);
  font-weight: 600; text-align: left; padding: 7px 8px;
  border-bottom: 1px solid var(--border, #21262d); white-space: nowrap;
}
.pcb-bom-table td { padding: 7px 8px; border-bottom: 1px solid var(--border, #21262d); vertical-align: top; }
.pcb-bom-tr:last-child td { border-bottom: none; }
.pcb-bom-num { text-align: right; white-space: nowrap; }
.pcb-bom-name { color: var(--bright, #e6edf3); }
.pcb-bom-fp { color: var(--dim, #7d8590); font-size: 10px; }
.pcb-bom-refs { color: var(--dim, #7d8590); font-size: 10px; margin-top: 2px; }
.pcb-bom-mpn a { color: var(--blue, #388bfd); text-decoration: none; }
.pcb-bom-mpn a:hover { text-decoration: underline; }
.pcb-bom-mfr { color: var(--dim, #7d8590); font-size: 10px; margin-top: 2px; }
.pcb-bom-alt {
  display: inline-block; margin-left: 6px; font-size: 9px; color: var(--dim, #7d8590);
  background: rgba(110,118,129,.18); padding: 0 5px; border-radius: 8px;
}
.pcb-bom-ext { color: var(--bright, #e6edf3); font-weight: 600; }
.pcb-bom-low { color: var(--warn-fg); }         /* stock below required qty */
.pcb-bom-na td { opacity: .7; }
.pcb-bom-why { color: var(--dim, #7d8590); font-style: italic; }
.pcb-bom-total { text-align: right; font-size: 12px; color: var(--bright, #e6edf3); margin: 12px 2px 4px; }
.pcb-bom-total-sub { color: var(--dim, #7d8590); font-size: 10px; font-weight: 400; }

/* ── PCBNet-first shell ─────────────────────────────────────────────
   The AI chat is the product's entry point: give it more room by default. */
:root { --rightdock-w: 320px; }

/* Left dock hosts the PCBNet parts palette; the stock Blocks/Components/
   Projects/Libraries panels are mock content (hidden by pcbnet.js). */
body.pcbnet .left-dock { width: 190px; min-width: 150px; }
body.pcbnet .left-dock .dock-panel:not(.pcb-pal) { display: none !important; }

/* ── Parts palette ──────────────────────────────────────────────── */
.pcb-pal { display: none; flex-direction: column; flex: 1; overflow: hidden; }
.pcb-pal.active { display: flex; }
.pcb-pal-scroll { flex: 1; overflow-y: auto; padding: 6px 6px 12px; }
.pcb-pal-group { margin-bottom: 8px; }
.pcb-pal-hdr {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--dim, #7d8590);
  padding: 6px 4px 4px;
}
.pcb-pal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
.pcb-pal-item {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 3px 4px;
  border: 1px solid transparent; border-radius: 6px;
  cursor: grab; background: var(--surf2, #161b22);
  transition: border-color .1s, background .1s;
}
.pcb-pal-item:hover { border-color: var(--blue, #388bfd); background: rgba(56,139,253,.08); }
.pcb-pal-item:active { cursor: grabbing; }
.pcb-pal-svg { width: 34px; height: 40px; }

/* E1 — the palette thumbnails are the one place a schematic symbol is drawn on
   a THEMED surface rather than on the dark sheet. palPreview() bakes the
   dark-sheet colours (COL.sym, a near-white) into the SVG strings, which
   vanishes on a light tile. Override stroke/fill here rather than threading a
   colour parameter through ~30 symbol builders; the schematic sheet itself is
   untouched and stays dark. `svg *` beats the element's own presentation
   attribute, which is exactly what we need. */
:root[data-theme="light"] .pcb-pal-svg *,
:root[data-theme="light"] .pcb-connect-btn svg * {
  stroke: var(--text);
}
:root[data-theme="light"] .pcb-pal-svg [fill]:not([fill="none"]) {
  fill: var(--text);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .pcb-pal-svg * { stroke: var(--text); }
  :root:not([data-theme]) .pcb-pal-svg [fill]:not([fill="none"]) { fill: var(--text); }
}
.pcb-pal-item span {
  font-size: 9.5px; color: var(--text, #c9d1d9); text-align: center;
  line-height: 1.1; word-break: break-word;
}

/* ── Symbol search results ──────────────────────────────────────────
   Results from the library index sit below the curated tiles and are
   deliberately distinguishable from them: a curated part has real symbol
   graphics and a verified pin map, a searched one is an honest labelled box. */
.pcb-pal-found { border-top: 1px solid var(--bord, #30363d); margin-top: 8px; padding-top: 2px; }
.pcb-pal-sym { border-style: dashed; border-color: var(--bord, #30363d); }
.pcb-pal-sym:hover { border-style: solid; }
.pcb-pal-lib {
  font-size: 8.5px; font-style: normal; color: var(--dim, #7d8590);
  text-align: center; line-height: 1; word-break: break-word;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Browse-only: the backend cannot validate parts from this source yet. */
.pcb-pal-ro { opacity: .55; cursor: not-allowed; }
.pcb-pal-ro:hover { border-color: var(--wrn, #d29922); background: rgba(210,153,34,.06); }
.pcb-pal-note {
  font-size: 10px; color: var(--dim, #7d8590);
  padding: 6px 4px; line-height: 1.35;
}
.pcb-pal-warn { color: var(--wrn, #d29922); }

/* ── The ROOT-E mark ──────────────────────────────────────────────────────
   A node with a signal leaving it, in the same visual language as the ROOTE
   logo's routed net. It replaces a "✦" that was, recognisably, Gemini's
   sparkle — borrowing another product's mark makes this look like a wrapper
   around someone else's model rather than a tool with its own engine.

   It is alive on purpose, and the motion is *diagnostic* rather than
   decorative: idle it breathes slowly, and `.thinking` speeds the pulse and
   runs the signal outward, so the same mark tells you whether ROOT-E is
   waiting or working. That is a state the UI otherwise only reports in a
   toast that has usually gone by the time you look. */
.roote-mark {
  width: 13px; height: 13px;
  flex-shrink: 0;
  vertical-align: -2px;
  overflow: visible;
}
.roote-mark .rm-core { fill: currentColor; transform-origin: 6px 8.5px; }
.roote-mark .rm-ring {
  fill: none; stroke: currentColor; stroke-width: 1.4;
  transform-origin: 6px 8.5px; opacity: .55;
}
.roote-mark .rm-trace {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Idle: a slow breath. Present enough to read as live, slow enough that it
   never competes with the canvas for attention. */
@keyframes roote-breathe {
  0%, 100% { transform: scale(1);    opacity: .55; }
  50%      { transform: scale(1.28); opacity: .9; }
}
.roote-mark .rm-ring { animation: roote-breathe 2.8s ease-in-out infinite; }

/* Working: the ring pulses at ~3x and the signal actually travels down the
   trace. A user who fires a request and looks away can tell at a glance
   whether it is still running. */
@keyframes roote-pulse {
  0%   { stroke-dashoffset: 12; opacity: .25; }
  60%  { opacity: 1; }
  100% { stroke-dashoffset: 0;  opacity: .25; }
}
.thinking .roote-mark .rm-ring { animation-duration: .9s; }
.thinking .roote-mark .rm-trace {
  stroke-dasharray: 6 6;
  animation: roote-pulse .9s linear infinite;
}

/* Respect a user who has asked the OS for less motion. An animated mark is a
   nicety; motion sickness is not. The mark still reads as a mark without it. */
@media (prefers-reduced-motion: reduce) {
  .roote-mark .rm-ring,
  .roote-mark .rm-trace { animation: none !important; }
}

/* "ROOT-E: connect parts" button at the top of the parts palette */
.pcb-connect-btn {
  display: block;
  width: calc(100% - 12px);
  margin: 0 6px 6px;
  padding: 7px 8px;
  border: 1px solid rgba(137, 87, 229, .5);
  border-radius: 6px;
  background: rgba(137, 87, 229, .12);
  color: var(--bright, #e6edf3);
  font-size: 11px; font-weight: 600;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.pcb-connect-btn:hover { background: rgba(137, 87, 229, .22); border-color: var(--purple, #8957e5); }
.pcb-connect-btn:disabled { opacity: .4; cursor: default; }
/* The label and the mark are one line, centred together. Without this the mark
   sits on the text baseline and reads as a bullet rather than an icon. */
.pcb-connect-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
/* Disabled means "nothing to connect yet". A mark still breathing there claims
   ROOT-E is doing something when it is not. */
.pcb-connect-btn:disabled .roote-mark .rm-ring { animation: none; }

/* Empty-state hero on the Circuit canvas (shown until a circuit exists) */
.pcb-hero {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
  z-index: 4;              /* under the schematic overlay (z 5) */
  pointer-events: none;    /* only the chips are interactive */
}
.pcb-hero-icon  { font-size: 44px; opacity: .3; }
.pcb-hero-title { font-size: 17px; font-weight: 600; color: var(--bright, #e6edf3); }
.pcb-hero-sub   { font-size: 12px; color: var(--dim, #7d8590); max-width: 400px; line-height: 1.6; }
.pcb-hero-chips {
  display: flex; gap: 8px; margin-top: 6px;
  flex-wrap: wrap; justify-content: center;
  pointer-events: auto;
}
.pcb-chip {
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  color: var(--text, #c9d1d9);
  border-radius: 14px;
  padding: 6px 12px;
  font-size: 12px;
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
}
.pcb-chip:hover {
  border-color: var(--blue, #388bfd);
  color: var(--bright, #fff);
  background: rgba(56, 139, 253, .1);
}

/* ── Simulation tab: AI-recommended analyses strip ───────────────────────── */
.pcb-sim-recs {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 16px 0 16px;
}
.pcb-rec-title {
  font-size: 11px; color: var(--dim, #7d8590); white-space: nowrap;
}
/* Why there are no suggestions right now. Deliberately quiet — it is
   information, not a fault — but present, because a panel that hides itself
   when empty reads as a feature that was removed. */
.pcb-rec-note {
  font-size: 11px; color: var(--dim, #7d8590);
  line-height: 1.5;
}
.pcb-rec-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  color: var(--text, #c9d1d9);
  border-radius: 14px;
  padding: 4px 10px;
  font-size: 11px;
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
}
.pcb-rec-chip:hover {
  border-color: var(--purple, #a371f7);
  color: var(--bright, #fff);
  background: rgba(163, 113, 247, .1);
}
.pcb-rec-type {
  font-size: 9px; color: var(--dim, #7d8590);
  border: 1px solid var(--border2, #30363d);
  border-radius: 8px; padding: 1px 6px;
}

/* Run button while a simulation is in flight (acts as Stop) */
.run-btn.pcb-running {
  background: rgba(248, 81, 73, .15);
  border-color: var(--red, #f85149);
  color: var(--red, #f85149);
}
.run-btn.pcb-running:hover {
  background: rgba(248, 81, 73, .28);
}

/* ── Layout tab: the board toolbar ───────────────────────────────────────────
   One flex row, not four absolutely-positioned buttons. The old layout gave
   each button its own `right:` offset (14px / 168px / 285px), so adding a
   control meant computing another magic number and renaming one broke the
   spacing silently. */
/* The board's actions, docked in the main toolbar beside ROOT-E and shown only
   on the Layout tab. In the flow of the bar rather than floating over the
   board: an overlay is laid out as if nothing else exists, which is what let
   the old version collide with the search box and the 3D toggle, and it
   covered the very thing it was acting on. */
.pcb-board-tools {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Fallback for a host page with no `.toolbar` (a stripped embed): keep the
   old floating behaviour so the controls exist rather than disappearing. */
.pcb-board-tools-float {
  position: absolute;
  top: 12px; right: 14px;
  z-index: 6;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: calc(100% - 90px);
}
.pcb-tool-btn {
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  color: var(--text, #c9d1d9);
  border-radius: var(--r, 5px);
  /* Sized to the 38px toolbar it now sits in. The old 7px/14px padding was
     drawn for a floating chip over the board, where nothing constrained the
     height; in the bar it made the row taller than every neighbouring
     control. */
  height: 28px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .12s, color .12s, background .12s;
}
/* Docked in the toolbar the buttons sit on the bar's own surface, so the chip
   background and border only earn their keep in the floating fallback. */
.toolbar .pcb-tool-btn {
  background: transparent;
  border-color: transparent;
  color: var(--dim, #8b949e);
}
.toolbar .pcb-tool-btn:hover:not(:disabled) {
  background: var(--surf2);
  border-color: var(--border2);
  color: var(--bright, #f0f6fc);
}
.pcb-tool-btn:hover:not(:disabled) {
  border-color: var(--green, #3fb950);
  color: var(--bright, #fff);
}
.pcb-tool-btn:disabled { opacity: .45; cursor: default; }
/* Undo/redo are glyphs, so they get a square footprint instead of a label's. */
.pcb-icon-btn {
  padding: 7px 10px;
  font-size: 14px;
  line-height: 1;
  min-width: 32px;
}
/* The non-destructive update, highlighted only while it is the answer to
   something — a permanently-lit call to action stops being one. */
.pcb-update-btn.pcb-suggested {
  border-color: var(--amber, #d29922);
  color: var(--bright, #fff);
  background: rgba(210, 153, 34, .16);
}
.pcb-genlayout-btn:hover:not(:disabled) {
  background: rgba(63, 185, 80, .12);
}
.pcb-genlayout-btn:disabled {
  opacity: .6;
  cursor: wait;
}

/* Board editing. Off by default. */
.pcb-edit-btn.on {
  border-color: var(--green, #3fb950);
  color: var(--bright, #fff);
  background: rgba(63, 185, 80, .18);
}

/* In edit mode a part is a drag handle, so say so with the cursor. */
.pcb-editing .pcb-xform g[data-ref] { cursor: grab; }
.pcb-editing .pcb-xform g[data-ref].pcb-dragging { cursor: grabbing; }
/* No transition on the dragged group: it is transformed per pointermove and
   any easing would make it lag the cursor. */
.pcb-xform g[data-ref].pcb-dragging { opacity: .85; }

.pcb-xform g[data-ref].pcb-selected {
  filter: drop-shadow(0 0 3px var(--green, #3fb950));
}
/* A lock has to be visible, or "why won't this move?" becomes a bug report. */
.pcb-editing .pcb-xform g[data-ref].pcb-locked {
  filter: drop-shadow(0 0 2px var(--amber, #d29922));
}
.pcb-editing .pcb-xform g[data-ref].pcb-locked { cursor: not-allowed; }

/* Hand routing. */
.pcb-route-btn.on {
  border-color: var(--green, #3fb950);
  color: var(--bright, #fff);
  background: rgba(63, 185, 80, .18);
}

/* While routing, a pad is a target and copper is rippable. */
.pcb-routing .pcb-xform { cursor: crosshair; }
.pcb-routing .pcb-xform [data-pad] { cursor: cell; }
.pcb-routing .pcb-xform [data-trace] { cursor: pointer; }

/* ── Staleness banner ─────────────────────────────────────────────────────
   The board no longer matches the schematic. This used to surface only as a
   409 when you tried to export — i.e. at the fab door. Sits under the toolbar
   so it cannot cover it. */
.pcb-board-banner {
  position: absolute;
  top: 56px; left: 14px; right: 14px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 12px;
  color: var(--text, #c9d1d9);
  background: rgba(210, 153, 34, .14);
  border: 1px solid var(--amber, #d29922);
  backdrop-filter: blur(2px);
}
.pcb-banner-icon { color: var(--amber, #d29922); font-size: 14px; flex: none; }
.pcb-banner-text { flex: 1 1 auto; line-height: 1.45; }
.pcb-banner-text strong { color: var(--bright, #fff); }
.pcb-banner-act {
  flex: none;
  background: var(--amber, #d29922);
  border: 1px solid var(--amber, #d29922);
  color: #1c1400;
  border-radius: 5px;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.pcb-banner-act:hover { filter: brightness(1.1); }
.pcb-banner-dismiss {
  flex: none;
  background: none;
  border: none;
  color: var(--muted, #8b949e);
  font-size: 13px;
  cursor: pointer;
  padding: 2px 4px;
}
.pcb-banner-dismiss:hover { color: var(--bright, #fff); }

/* A yes/no question with an optional third way out (confirmDialog). */
.pcb-confirm-body {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text, #c9d1d9);
  margin: 10px 0 4px;
}
.pcb-confirm-alt {
  background: var(--surf2, #161b22);
  border: 1px solid var(--amber, #d29922);
  color: var(--amber, #d29922);
  border-radius: 5px;
  padding: 6px 14px;
  font-size: 12px;
  cursor: pointer;
}
.pcb-confirm-alt:hover { color: var(--bright, #fff); background: rgba(210, 153, 34, .16); }

/* The leg being drawn. Dashed so it reads as not-yet-real copper. */
.pcb-route-preview {
  stroke: var(--green, #3fb950);
  stroke-dasharray: 4 3;
  opacity: .95;
  pointer-events: none;
}
.pcb-xform [data-trace].pcb-trace-selected {
  stroke: var(--red, #f85149);
  filter: drop-shadow(0 0 3px var(--red, #f85149));
}

/* 2D / 3D toggle — top-left of the Layout tab. */
.pcb-3d-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;   /* we handle drag/wheel ourselves */
}
.pcb-3d-toggle {
  position: absolute;
  top: 12px; left: 14px;
  z-index: 6;
  min-width: 40px;
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  color: var(--text, #c9d1d9);
  border-radius: 6px;
  padding: 7px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
}
.pcb-3d-toggle:hover {
  border-color: var(--blue, #388bfd);
  color: var(--bright, #fff);
  background: rgba(56, 139, 253, .12);
}
.pcb-3d-toggle.on {
  border-color: var(--blue, #388bfd);
  background: rgba(56, 139, 253, .18);
  color: var(--bright, #fff);
}

/* ── net highlight + click-to-locate ──────────────────────────────────────── */

/* Clickable component refs in the Checks panel. */
.pcb-loc {
  color: var(--blue);
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.pcb-loc:hover { color: var(--teal); border-bottom-style: solid; }

/* Locate pulse: a ring that fades out, so the eye lands on the part. */
.pcb-pulse {
  animation: pcb-pulse-ring 1.4s ease-out forwards;
  pointer-events: none;
}
@keyframes pcb-pulse-ring {
  0%   { opacity: 0;   stroke-width: 1; }
  15%  { opacity: 1;   stroke-width: 3; }
  100% { opacity: 0;   stroke-width: 1; }
}

/* Net labels invite a click once they do something. */
.pcb-schematic [data-net] { transition: font-size .08s; }
.pcb-schematic [data-net]:hover { text-decoration: underline; }

/* #1 — board copper is click-to-cross-probe: signal it with a pointer cursor. */
/* B2 — cross-probe highlight glides instead of snapping (opacity + glow).
   Applied to board copper and footprint groups; the highlight itself is set
   as inline opacity/filter by applyPcbHighlight(). */
#pcbLayoutInner [data-net] { cursor: pointer; transition: opacity .12s ease, filter .12s ease; }

/* #1 — a BOM row with known designators cross-probes to its net on click. */
.pcb-bom-tr[data-refs] { cursor: pointer; }
.pcb-bom-tr[data-refs]:hover { background: var(--surf3, #21262d); }
/* #15 — a BOM row highlighted from a board click (board → BOM direction). */
.pcb-bom-tr.pcb-bom-hi { background: rgba(240, 180, 41, 0.15); box-shadow: inset 3px 0 0 var(--yellow, #f0b429); }

/* #15 — board footprints are click-to-spotlight (iBOM). */
#pcbLayoutInner g[data-ref] { cursor: pointer; transition: opacity .12s ease, filter .12s ease; }

/* #16 — layer visibility: hiding a layer hides its data-layer elements. */
#pcbLayoutInner.hide-copper   [data-layer="copper"],
#pcbLayoutInner.hide-silk     [data-layer="silk"],
#pcbLayoutInner.hide-pad      [data-layer="pad"],
#pcbLayoutInner.hide-via      [data-layer="via"],
#pcbLayoutInner.hide-ratsnest [data-layer="ratsnest"] { display: none; }

/* §3.0a — per *copper layer* visibility, which is a different question from
   the categories above: "hide all copper" vs "show me In1 alone". Traces carry
   data-cu (the copper layer index) as well as data-layer="copper", so the two
   compose. Eight covers any stack the router can produce. */
#pcbLayoutInner.hide-cu0 [data-cu="0"],
#pcbLayoutInner.hide-cu1 [data-cu="1"],
#pcbLayoutInner.hide-cu2 [data-cu="2"],
#pcbLayoutInner.hide-cu3 [data-cu="3"],
#pcbLayoutInner.hide-cu4 [data-cu="4"],
#pcbLayoutInner.hide-cu5 [data-cu="5"],
#pcbLayoutInner.hide-cu6 [data-cu="6"],
#pcbLayoutInner.hide-cu7 [data-cu="7"] { display: none; }

/* The copper-layer strip sits above the category strip. Each button wears its
   own layer's colour, matching the SVG legend and the 3D view. */
.pcb-cu-toggles {
  position: absolute;
  left: 14px; bottom: 46px;
  z-index: 6;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  max-width: calc(100% - 28px);
}
.pcb-cu-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  color: var(--muted, #8b949e);
  border-radius: 5px;
  padding: 4px 9px;
  font-size: 11px;
  cursor: pointer;
  transition: color .12s, border-color .12s, opacity .12s;
  opacity: .55;
}
.pcb-cu-btn .pcb-cu-swatch {
  width: 9px; height: 9px;
  border-radius: 2px;
  flex: none;
}
.pcb-cu-btn.on { opacity: 1; color: var(--bright, #fff); }
.pcb-cu-btn:hover:not(:disabled) { border-color: var(--text, #c9d1d9); }
.pcb-cu-btn:disabled { opacity: .3; cursor: default; }
/* Says why the row is inert, so a dead control is never just dead. */
.pcb-cu-note {
  align-self: center;
  font-size: 11px;
  color: var(--muted, #8b949e);
  font-style: italic;
  cursor: help;
}
/* "Only this layer" — the isolate action, which is what people actually want
   most of the time and is otherwise four clicks on a four-layer board. */
.pcb-cu-solo {
  background: none;
  border: none;
  color: var(--muted, #8b949e);
  font-size: 11px;
  cursor: pointer;
  padding: 4px 6px;
  text-decoration: underline;
}
.pcb-cu-solo:hover { color: var(--bright, #fff); }

/* #8 — "what is this?" part hover tip. */
.pcb-part-tip {
  position: fixed;
  z-index: 1100;
  display: none;
  max-width: 260px;
  padding: 8px 10px;
  background: var(--surf2, #161b22);
  border: 1px solid var(--border2, #30363d);
  border-radius: 7px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  font-size: 12px;
  line-height: 1.45;
  pointer-events: none;   /* never intercept the mouse */
}
.pcb-part-tip-head { font-weight: 700; color: var(--bright, #f0f6fc); margin-bottom: 2px; }
.pcb-part-tip-role { color: var(--text, #c9d1d9); }
.pcb-part-tip-typ  { color: var(--dim, #7d8590); margin-top: 3px; }
.pcb-part-tip-warn { color: var(--warn-fg); margin-top: 4px; }
/* #27 — provenance line ("where did this part come from?"). */
.pcb-part-tip-origin { color: var(--teal, #39c5cf); margin-top: 5px; font-size: 11px; }

/* #17 — board search box (top-center of the Layout tab), clear of the 3D
   toggle (top-left) and Generate button (top-right). */
/* #17 — board search. Top-right of the board, where nothing else lives now
   that the board actions have moved into the main toolbar.
   It used to be centred at `top: 12px`, the same band the floating tools
   occupied, and collided with them below ~1300px. The offset still comes from
   `--board-tools-h` so the floating fallback (a host page with no toolbar)
   keeps working; docked, that variable resolves to the small default and the
   search simply sits at the top. */
.pcb-board-search {
  position: absolute;
  top: var(--board-tools-h, 12px);
  right: 14px;
  z-index: 20;
  display: flex; align-items: center;
  background: rgba(13, 17, 23, 0.85);
  border: 1px solid var(--border2, #30363d);
  border-radius: 7px;
  backdrop-filter: blur(3px);
  /* Never wider than the space it has; the input shrinks with it. */
  max-width: calc(100% - 80px);
}
.pcb-board-search:focus-within { border-color: var(--blue, #388bfd); }
.pcb-board-search-input {
  width: 180px;
  /* Shrinks on a narrow board instead of forcing the box wider than the
     space between the 3D toggle and the tools. */
  min-width: 0;
  border: none; background: transparent;
  color: var(--text, #c9d1d9);
  font-size: 12px;
  padding: 6px 8px;
  outline: none;
}
.pcb-board-search-clear {
  border: none; background: transparent;
  color: var(--dim, #7d8590);
  font-size: 15px; line-height: 1;
  padding: 0 8px; cursor: pointer;
}
.pcb-board-search-clear:hover { color: var(--bright, #f0f6fc); }

/* #16 — the layer-toggle control (bottom-left of the Layout tab). */
.pcb-layer-toggles {
  position: absolute;
  left: 10px; bottom: 10px;
  z-index: 20;
  display: flex; flex-wrap: wrap; gap: 4px;
  max-width: 60%;
}
.pcb-layer-btn {
  padding: 3px 9px;
  border: 1px solid var(--border2, #30363d);
  border-radius: 12px;
  background: rgba(13, 17, 23, 0.82);
  color: var(--dim, #7d8590);
  font-size: 11px;
  cursor: pointer;
  backdrop-filter: blur(3px);
  transition: color .1s, border-color .1s, background .1s;
}
.pcb-layer-btn:hover { color: var(--text, #c9d1d9); }
/* "on" = layer visible; lit in blue. Off = dimmed with a strikethrough cue so
   state isn't color-alone. */
.pcb-layer-btn.on { color: var(--blue, #388bfd); border-color: var(--blue, #388bfd); }
.pcb-layer-btn:not(.on) { text-decoration: line-through; opacity: 0.7; }

/* #1 — sim → schematic: clickable net chips in the simulation stats bar. */
/* C1 — cap the probe strip so a many-net circuit can't blow out the stats bar:
   it scrolls horizontally past a sensible width instead of wrapping tall. */
.sim-probes {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: min(52vw, 620px);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  padding-bottom: 1px;
}
.sim-probes-label { color: var(--dim, #7d8590); margin-right: 2px; flex-shrink: 0; }
.sim-probe { flex-shrink: 0; }
.sim-probe {
  padding: 1px 7px;
  border: 1px solid var(--border2, #30363d);
  border-radius: 10px;
  background: transparent;
  color: var(--netlbl, #39c5cf);
  font-size: 11px;
  cursor: pointer;
  white-space: nowrap;
}
.sim-probe:hover { background: var(--surf3, #21262d); color: var(--bright, #f0f6fc); }

/* Respect a reduced-motion preference: keep the ring, drop the animation. */
@media (prefers-reduced-motion: reduce) {
  .pcb-pulse { animation: none; opacity: 1; }
  /* B1/A2 — dialogs appear instantly (no fade/scale) when motion is reduced. */
  .pcb-exp-overlay, .pcb-exp-card,
  .pcb-cmdk-overlay, .pcb-cmdk { animation: none; }
  /* B2 — cross-probe highlight snaps instead of gliding. */
  #pcbLayoutInner [data-net], #pcbLayoutInner g[data-ref] { transition: none; }
  /* B3/B4 — the badge pop and the next-step slide are pure emphasis; the
     badge's colour+glyph and the bar itself still convey the state. */
  .ws-tab-badge.pcb-pop { animation: none; }
  .pcb-nextstep { animation: none; }
}

/* Shortcut list (truthful replacement for the stock mock dialog). */
.pcb-keys { max-height: 46vh; overflow-y: auto; margin: 4px 0 10px; }
.pcb-key-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 2px;
  font-size: 11.5px;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}
.pcb-key-row:last-child { border-bottom: none; }
.pcb-key-row kbd {
  flex: none;
  min-width: 118px;
  background: var(--bg);
  border: 1px solid var(--border2);
  border-radius: 4px;
  padding: 2px 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--bright);
  text-align: center;
}

/* #5 — visible undo history in the status bar. Names the edit that Ctrl+Z
   would reverse; clicking it is the same as undo. Hidden entirely when the
   history is empty, so it never implies state that isn't there. */
.sb-history {
  color: var(--muted, #8b949e);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sb-history:hover { color: var(--blue, #388bfd); }

/* ── Board shape picker ──────────────────────────────────────────────────────
   The form behind the Layout tab's "Shape" button. A plain field list rather
   than a preview canvas: the shapes on offer (rectangle, rounded rectangle,
   circle) are ones a width and a height already describe completely, and the
   board itself is the preview once Generate Layout runs. */
.pcb-shape-body { margin: 12px 0 4px; }
.pcb-shape-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 9px;
  font-size: 12px; color: var(--text, #c9d1d9);
}
.pcb-shape-row select,
.pcb-shape-row input[type="number"] {
  background: var(--surf2, #161b22); border: 1px solid var(--border, #21262d);
  color: var(--bright, #e6edf3); border-radius: 5px;
  padding: 5px 8px; font-size: 12px; font-family: inherit;
}
.pcb-shape-row select { flex: 1 1 auto; max-width: 60%; }
.pcb-shape-row input[type="number"] { width: 96px; text-align: right; }
.pcb-shape-dims {
  border-top: 1px solid var(--border, #21262d);
  margin-top: 12px; padding-top: 12px;
}
.pcb-shape-check {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text, #c9d1d9);
  margin: 2px 0 10px; cursor: pointer;
}
/* The one thing about a fixed shape that surprises people: it does not grow. */
.pcb-shape-note {
  font-size: 11px; line-height: 1.5; color: var(--dim, #8b949e);
  border-left: 2px solid var(--border2, #30363d); padding-left: 9px;
}
/* Carries the current shape as its label, so it is wider than an icon button
   and must not be squeezed when the toolbar wraps. */
.pcb-shape-btn { white-space: nowrap; }
