/* Las variables de color (tema base + acento) viven en css/theme.css */
*{box-sizing:border-box}
html,body{height:100%;margin:0}
body{
  background:var(--bg); color:var(--text);
  font:15px/1.45 var(--sans);
  display:flex;flex-direction:column;overflow:hidden;
  background-image:var(--body-glow);
}
button,input,select{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;box-shadow:0 0 0 4px rgba(var(--accent-rgb),.2)}
kbd{font:500 11px var(--mono);padding:0 5px;border:1px solid currentColor;border-radius:4px;opacity:.55;margin-left:4px}

/* `z-index` > `#toolbar` (30): el header crea contexto de apilamiento por
   su `backdrop-filter`, así que sin un z-index propio el desplegable de
   idioma (que cuelga de aquí) quedaría tapado por la barra y sus menús. */
header{display:flex;align-items:center;gap:14px;padding:10px 16px;background:var(--glass-2);backdrop-filter:blur(var(--blur-2));-webkit-backdrop-filter:blur(var(--blur-2));border-bottom:1px solid var(--glass-border);box-shadow:var(--glass-specular);position:relative;z-index:40;flex:none}
header::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:1px;background:linear-gradient(90deg,transparent,rgba(var(--accent-rgb),.5),transparent)}
header .mark{width:26px;height:26px;flex:none;filter:drop-shadow(0 0 8px rgba(var(--accent-rgb),.6))}
header h1{font-size:18px;font-weight:600;margin:0;letter-spacing:.02em;background:linear-gradient(90deg,var(--head-grad-a),var(--head-grad-b));-webkit-background-clip:text;background-clip:text;color:transparent}
header nav{margin-left:auto;display:flex;gap:4px}
header nav a{color:var(--text-dim);text-decoration:none;padding:6px 14px;border-radius:8px;font-size:13px;font-weight:500;transition:all .2s}
header nav a:hover{color:var(--accent);background:rgba(var(--accent-rgb),.06)}
header nav a[aria-current]{background:linear-gradient(180deg,rgba(var(--accent-rgb),.18),rgba(var(--accent-rgb),.08));color:var(--accent);box-shadow:inset 0 0 0 1px rgba(var(--accent-rgb),.35), 0 0 20px rgba(var(--accent-rgb),.15)}

main{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr)}
#editor{display:flex;flex-direction:column;min-width:0;min-height:0}

/* `position` + `z-index`: los menús desplegables (.dd-pop, en
   css/theme.css) cuelgan de la barra y se dibujan por encima del
   lienzo. Sin esto, el lienzo —que sí está posicionado— los taparía,
   porque la barra es estática y pinta antes que los posicionados. */
#toolbar{position:relative;z-index:30;display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 12px;background:var(--glass-1);backdrop-filter:blur(var(--blur-1));-webkit-backdrop-filter:blur(var(--blur-1));border-bottom:1px solid var(--glass-border);font-size:13px}
#toolbar .sep{width:1px;height:22px;background:var(--border);margin:0 6px}
#toolbar .lab{color:var(--text-mute);font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-right:2px;font-weight:500}
.tool{display:inline-flex;align-items:center;gap:8px;padding:6px 12px;background:transparent;border:1px solid transparent;border-radius:8px;cursor:pointer;color:var(--text-dim);font-size:13px;font-weight:500;transition:all .18s ease}
.tool:hover{background:rgba(var(--accent-rgb),.06);color:var(--accent);border-color:rgba(var(--accent-rgb),.2);box-shadow:0 0 12px rgba(var(--accent-rgb),.1)}
.tool.on{background:linear-gradient(180deg,rgba(var(--accent-rgb),.18),rgba(var(--accent-rgb),.08));color:var(--accent);border-color:rgba(var(--accent-rgb),.4);box-shadow:0 0 16px rgba(var(--accent-rgb),.2), inset 0 1px 0 rgba(var(--hair-rgb),.08)}
.tool.warn-armed{background:linear-gradient(180deg,rgba(var(--err-rgb),.25),rgba(var(--err-rgb),.1));color:var(--err);border-color:rgba(var(--err-rgb),.5);box-shadow:0 0 16px rgba(var(--err-rgb),.3)}
.step{width:32px;justify-content:center;padding:6px 0;border-color:var(--border)}
.check{display:inline-flex;align-items:center;gap:8px;cursor:pointer;padding:6px 8px;color:var(--text-dim);font-size:13px;font-weight:500}
.check:hover{color:var(--text)}
.check input{width:16px;height:16px;accent-color:var(--accent);background:var(--surface);cursor:pointer}
#balance{width:80px;accent-color:var(--accent);filter:drop-shadow(0 0 4px rgba(var(--accent-rgb),.4))}
#balanceVal{font-family:var(--mono);font-size:12px;color:var(--accent);min-width:38px;text-align:right;text-shadow:0 0 6px rgba(var(--accent-rgb),.5)}

#canvasWrap{flex:1;min-height:0;overflow:hidden;position:relative;background:var(--stage-bg)}
#canvasInner{position:absolute;top:0;left:0;padding:120px 160px;will-change:transform;transform-origin:0 0}
#svg{display:block;overflow:visible}

/* La barra de estado es la única línea de información de la vista: arriba
   el estado del tablero, abajo la ayuda (o la explicación del aislamiento).
   Las dos filas se recortan con puntos suspensivos antes que desbordar. */
#statusbar{
  display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;
  column-gap:10px;row-gap:1px;padding:6px 12px;
  background:var(--glass-1);backdrop-filter:blur(var(--blur-1));-webkit-backdrop-filter:blur(var(--blur-1));
  border-top:1px solid var(--glass-border);font-size:12.5px;color:var(--text-dim)
}
#statusbar b{color:var(--accent);text-shadow:0 0 8px rgba(var(--accent-rgb),.6);font-weight:600}
/* El resumen va en el mismo tono que la ayuda (el contraste de `--text-mute`
   se queda corto para 11,5 px): la jerarquía la marcan el tamaño y las
   cifras en acento. */
#statusbar #summary{grid-column:1;grid-row:1;font-size:11.5px;color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#statusbar #statusText{grid-column:1;grid-row:2;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#statusbar .sb-close{grid-column:2;grid-row:1 / span 2;align-self:center}
/* El botón × de la barra de estado (.sb-close) vive en css/theme.css:
   lo comparten la protoboard y el esquema. */

.notice{
  position:absolute;top:14px;right:14px;padding:10px 30px 10px 14px;
  background:linear-gradient(180deg, rgba(var(--warn-rgb),.22), rgba(var(--warn-rgb),.08));
  border:1px solid rgba(var(--warn-rgb),.5);color:var(--warn);border-radius:10px;
  font-size:12.5px;font-weight:500;line-height:1.35;
  box-shadow:0 0 24px rgba(var(--warn-rgb),.2), inset 0 1px 0 rgba(var(--hair-rgb),.05);
  z-index:8;max-width:290px;display:none;
  backdrop-filter:blur(var(--blur-1));-webkit-backdrop-filter:blur(var(--blur-1));
}
.notice b{color:#ffcb6b;font-weight:700}
.notice .sub{font-size:11px;color:#d9a44d;margin-top:3px;display:block;line-height:1.3}
.notice-close{
  position:absolute;top:4px;right:4px;
  width:20px;height:20px;
  display:inline-flex;align-items:center;justify-content:center;
  padding:0;border:1px solid transparent;border-radius:5px;
  background:transparent;color:inherit;
  cursor:pointer;font:700 14px/1 var(--mono);
  opacity:.75;transition:all .15s ease;
}
.notice-close:hover{opacity:1;background:rgba(var(--warn-rgb),.18);border-color:rgba(var(--warn-rgb),.4)}

/* Aviso de «no hay circuito» (2D y 3D). Es informativo, no un problema:
   mismo componente que el aviso de varias fuentes, en tono neutro. */
#emptyNotice{
  max-width:340px;
  background:var(--glass-2);
  border-color:var(--glass-border-hi);
  color:var(--text-dim);
  box-shadow:var(--glass-shadow), var(--glass-specular);
}
#emptyNotice b{color:var(--accent-ink)}
#emptyNotice .sub{color:var(--text-mute)}
#emptyNotice .notice-close:hover{background:rgba(var(--accent-rgb),.12);border-color:rgba(var(--accent-rgb),.35);color:var(--accent)}

/* El widget de zoom (#zoomWidget, cuatro lupas) vive en css/theme.css:
   es idéntico en las dos protoboards y en el esquema. */

/* Guía de ensamblaje paso a paso */
#guideBar{
  position:absolute;bottom:14px;left:50%;transform:translateX(-50%);
  display:none;align-items:center;gap:6px;
  padding:8px 12px;
  background:var(--glass-3);
  backdrop-filter:blur(var(--blur-2));-webkit-backdrop-filter:blur(var(--blur-2));
  border:1px solid rgba(var(--accent-rgb),.35);
  border-radius:12px;
  box-shadow:var(--glass-shadow), var(--glass-specular), 0 0 18px rgba(var(--accent-rgb),.12);
  z-index:20;user-select:none;
}
#guideBar.on{display:flex}
#guideBar button{
  min-width:30px;height:30px;padding:0 10px;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  background:transparent;border:1px solid var(--border-hi);border-radius:8px;
  color:var(--text-dim);cursor:pointer;
  font:500 13px var(--mono);line-height:1;
  transition:all .15s ease;
}
#guideBar button:hover:not(:disabled){background:rgba(var(--accent-rgb),.08);color:var(--accent);border-color:rgba(var(--accent-rgb),.3);box-shadow:0 0 10px rgba(var(--accent-rgb),.15)}
#guideBar button:disabled{opacity:.35;cursor:default}
#guideBar button:active:not(:disabled){transform:scale(.94)}
#guideBar .g-step{font:600 12px var(--mono);color:var(--accent);min-width:86px;text-align:center;text-shadow:0 0 8px rgba(var(--accent-rgb),.5)}
#guideBar .g-label{font:500 12px var(--sans);color:var(--text-dim);flex:0 0 auto;max-width:min(760px,50vw);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#guideBar .g-exit{border-color:rgba(var(--err-rgb),.4);color:var(--err)}
#guideBar .g-exit:hover:not(:disabled){background:rgba(var(--err-rgb),.08);border-color:rgba(var(--err-rgb),.6);color:var(--err);box-shadow:0 0 10px rgba(var(--err-rgb),.2)}
.guide-new{animation:glowPulse 1.4s ease-in-out infinite}
.guide-new .jumper{stroke-width:3.5}
.guide-new .ic-body,.guide-new .res-body,.guide-new .led-body,.guide-new .diode-body,.guide-new .pot-body,.guide-new .sw-body,.guide-new .to92-body,.guide-new .to220-body,.guide-new .cap-body,.guide-new .cap-el-body,.guide-new .ind-body,.guide-new .ldr-body,.guide-new .buzzer-body,.guide-new .motor-body,.guide-new .pcb-body,.guide-new .mcu-board{stroke:var(--accent);stroke-width:2;filter:drop-shadow(0 0 6px var(--accent))}
.mcu-pin-reveal .wire-lead {
  color: var(--accent);
  stroke: var(--accent) !important;
  stroke-width: 4 !important;
  animation: glowPulse 1.4s ease-in-out infinite;
}
.mcu-pin-reveal .jumper-dot {
  filter: drop-shadow(0 0 5px var(--accent)) drop-shadow(0 0 12px var(--accent));
}
.toast{position:fixed;bottom:60px;left:50%;transform:translateX(-50%);padding:10px 18px;background:var(--glass-3);border:1px solid rgba(var(--accent-rgb),.4);color:var(--accent);border-radius:10px;font-size:13.5px;font-weight:500;box-shadow:0 0 24px rgba(var(--accent-rgb),.2);z-index:100;opacity:0;pointer-events:none;transition:opacity .25s ease}
.toast.show{opacity:1}
.toast.err{border-color:rgba(var(--err-rgb),.5);color:var(--err);box-shadow:0 0 24px rgba(var(--err-rgb),.25)}

.bd{fill:#efece3;stroke:#c3bdab;stroke-width:1.5;transition:opacity .3s ease}
.trench{fill:#d8d3c5;stroke:#c3bdab;stroke-width:1;transition:opacity .3s ease}
.stripe{stroke-width:2.5;stroke-linecap:round;transition:opacity .3s ease}
.stripe.plus{stroke:#d64545}
.stripe.minus{stroke:#2f6bd6}
.lbl{font:500 11px var(--mono);fill:#7d8b9a;text-anchor:middle;pointer-events:none;user-select:none;transition:opacity .3s ease}
.lbl.plus{fill:#d64545;font-size:15px}
.lbl.minus{fill:#2f6bd6;font-size:15px}
.bar{fill:rgba(47,107,255,.2);stroke:var(--accent);stroke-width:1.5;pointer-events:none;transition:opacity .3s ease}
.hole{fill:#2f3d4b;pointer-events:none;transition:opacity .3s ease}
.hole.on{fill:var(--accent)}
.hole.cur{fill:#fff;stroke:var(--accent);stroke-width:2.5}

.wire-lead{stroke-width:2.8;stroke-linecap:round;stroke-linejoin:round;fill:none;pointer-events:none;transition:opacity .3s ease}
.pin-lead{stroke:#a8b3be;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;fill:none;transition:opacity .3s ease}
.diode-lead{stroke:#c8ccd4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none;transition:opacity .3s ease}
.res-body{fill:#e2c08d;stroke:#8c6d3f;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.led-body{fill:rgba(230,45,45,0.85);stroke:#b31414;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.diode-body{fill:#141414;stroke:#000;stroke-width:1;transition:opacity .3s ease, filter .3s ease}
.diode-band{fill:#e8e8e8;stroke:#999;stroke-width:.4}
.pot-body{fill:#c9b8e0;stroke:#6c4f9c;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.sw-body{fill:#c8d6e5;stroke:#4b6078;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.sw-dome{fill:#4b6078;opacity:.45}
.ic-body{fill:#1a1f2a;stroke:#4b6078;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.ic-notch{fill:#efece3;stroke:none}
.ic-dot{fill:#d8d3c5;stroke:none}
.ic-label{font:700 9px var(--mono);fill:#8b95a8;pointer-events:none;user-select:none;letter-spacing:.05em;transition:opacity .3s ease}
.ic-type{font:600 6.5px var(--mono);fill:#5a6472;pointer-events:none;user-select:none;letter-spacing:.04em;transition:opacity .3s ease}
.pcb-body{fill:#0e4d92;stroke:#0a3a6e;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.pcb-lbl{font:700 8px var(--mono);fill:#e6edf3;pointer-events:none;user-select:none;letter-spacing:.04em;transition:opacity .3s ease}
.pcb-ref{font:700 7px var(--mono);fill:#9fd4ff;pointer-events:none;user-select:none;letter-spacing:.04em;transition:opacity .3s ease}
.term-block{fill:#2e7d32;stroke:#1b4d20;stroke-width:1;transition:opacity .3s ease}
.term-screw{fill:#cfd8dc;stroke:#78909c;stroke-width:.8}
.pcb-header{fill:#1a1a1a;stroke:#000;stroke-width:.8}
.mcu-board{fill:#00878f;stroke:#00666d;stroke-width:1.5;transition:opacity .3s ease, filter .3s ease}
.mcu-header{fill:#1a1a1a;stroke:#000;stroke-width:.8}
.mcu-lbl{font:700 8px var(--mono);fill:#e6edf3;pointer-events:none;user-select:none;letter-spacing:.06em;transition:opacity .3s ease}
.mcu-ref{font:700 7px var(--mono);fill:#9fd4ff;pointer-events:none;user-select:none;letter-spacing:.04em;transition:opacity .3s ease}
.mcu-usb{fill:#c8ccd4;stroke:#8a9099;stroke-width:1}
.mcu-pin{fill:#e6edf3;stroke:#4b6078;stroke-width:1;transition:opacity .3s ease}
.mcu-pin-lbl{font:600 6.5px var(--mono);fill:#5a6472;pointer-events:none;user-select:none;letter-spacing:.03em}
.comp-lbl{font:600 9px var(--mono);fill:#4b6078;pointer-events:none;user-select:none;transition:opacity .3s ease}

.cap-body{fill:#e0a458;stroke:#8a5a2b;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.cap-el-body{fill:#2b3a67;stroke:#16213f;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.cap-el-stripe{fill:#c9d4f0;transition:opacity .3s ease}
.cap-el-sign{font:700 8px var(--mono);fill:#e6edf3;pointer-events:none;user-select:none}
.ind-body{fill:#7fb069;stroke:#4a6b3a;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.zener-body{fill:#c84c2c;stroke:#7a2a14;stroke-width:1;transition:opacity .3s ease, filter .3s ease}
.zener-band{fill:#2a2a2a;stroke:#000;stroke-width:.4}
.buzzer-body{fill:#15181d;stroke:#000;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.buzzer-hole{fill:#0a0e14;stroke:rgba(255,255,255,.18);stroke-width:.8}
.ldr-body{fill:#d9c9a0;stroke:#8a7a52;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.ldr-zig{fill:none;stroke:#c0392b;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.motor-body{fill:#9aa3ad;stroke:#5c626b;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.motor-cap{fill:#6d757f;stroke:#4b5158;stroke-width:1}
.motor-shaft{stroke:#cfd6dd;stroke-width:2;stroke-linecap:round}
.motor-lbl{font:700 7px var(--mono);fill:#2c3138;pointer-events:none;user-select:none}


.to92-body{fill:#1a1a1a;stroke:#0a0a0a;stroke-width:1.2;transition:opacity .3s ease, filter .3s ease}
.to92-shine{stroke:rgba(255,255,255,.14);stroke-width:1.2;fill:none;transition:opacity .3s ease}
.to92-label{font:700 8px var(--mono);fill:#8a8a8a;pointer-events:none;user-select:none;letter-spacing:.06em}
.to92-ref{font:600 9px var(--mono);fill:#4b6078;pointer-events:none;user-select:none}
.pin-lbl{font:600 7px var(--mono);fill:#5a6472;pointer-events:none;user-select:none;letter-spacing:.04em}

.to220-body{fill:#1a1a1a;stroke:#0a0a0a;stroke-width:1.4;transition:opacity .3s ease, filter .3s ease}
.to220-tab{fill:#c8ccd4;stroke:#8a9099;stroke-width:1;transition:opacity .3s ease}
.to220-hole{fill:#0d1220;stroke:#8a9099;stroke-width:.8;transition:opacity .3s ease}
.to220-bevel{fill:rgba(255,255,255,.14);transition:opacity .3s ease}
.to220-shine{fill:rgba(255,255,255,.18);transition:opacity .3s ease}
.to220-ref{font:600 8px var(--mono);fill:#8a8a8a;pointer-events:none;user-select:none;letter-spacing:.04em}

.psu-body{fill:#c8ccd4;stroke:#5c626b;stroke-width:1.5;cursor:grab;transition:all .2s ease}
.psu-body:hover{stroke:var(--accent);filter:drop-shadow(0 0 6px rgba(var(--accent-rgb),.4))}
[data-battery].dragging .psu-body{cursor:grabbing;stroke:var(--accent);stroke-width:2}
.psu-screen{fill:#0a0e14;stroke:#3a3f47;stroke-width:1}
.psu-label{font:700 18px var(--mono);fill:#ff4455;pointer-events:none;user-select:none}
.psu-ref{font:500 9px var(--mono);fill:#5a6472;pointer-events:none;user-select:none}

.sw-base2{fill:#1a1a1a;stroke:#0a0a0a;stroke-width:1;transition:opacity .3s ease}
.sw-rocker{fill:#2a2a2a;stroke:#000;stroke-width:.8;transition:opacity .3s ease}
.sw-mark{font:700 6px var(--mono);fill:#8a8a8a;pointer-events:none;user-select:none}

.jumper-group{cursor:pointer;transition:opacity .3s ease}
.jumper{fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;opacity:.95;transition:all .3s ease}
.jumper-cable{fill:none;stroke-width:2.8;stroke-linecap:round;stroke-linejoin:round;opacity:1;transition:all .3s ease}
.jumper-dot{stroke:#fff;stroke-width:1.5;transition:all .3s ease}

.jumper-flow{fill:none;stroke:#ffffff;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:4 12;animation:flow 1.1s linear infinite;pointer-events:none;mix-blend-mode:screen;filter:drop-shadow(0 0 2px #fff) drop-shadow(0 0 6px currentColor)}
@keyframes flow{ to { stroke-dashoffset:-32; } }

svg.has-selection .bd,
svg.has-selection .trench,
svg.has-selection .stripe,
svg.has-selection .lbl,
svg.has-selection .hole,
svg.has-selection .bar,
svg.has-selection [data-comp],
svg.has-selection [data-jumper]:not(.jumper-hot){opacity:.15}
svg.has-selection [data-comp].comp-hot{opacity:1}
svg.has-selection [data-comp].comp-clicked{opacity:1;filter:drop-shadow(0 0 3px #fff) drop-shadow(0 0 9px var(--accent)) drop-shadow(0 0 18px var(--accent))}
svg.has-selection [data-comp].comp-clicked .comp-lbl,
svg.has-selection [data-comp].comp-clicked .pin-lbl,
svg.has-selection [data-comp].comp-clicked .to92-ref,
svg.has-selection [data-comp].comp-clicked .to220-ref,
svg.has-selection [data-comp].comp-clicked .ic-label,
svg.has-selection [data-comp].comp-clicked .ic-type,
svg.has-selection [data-comp].comp-clicked .pcb-lbl,
svg.has-selection [data-comp].comp-clicked .pcb-ref,
svg.has-selection [data-comp].comp-clicked .mcu-lbl{fill:#fff}
svg.has-selection [data-comp].comp-hot .res-body,
svg.has-selection [data-comp].comp-hot .led-body,
svg.has-selection [data-comp].comp-hot .diode-body,
svg.has-selection [data-comp].comp-hot .diode-band,
svg.has-selection [data-comp].comp-hot .diode-lead,
svg.has-selection [data-comp].comp-hot .pot-body,
svg.has-selection [data-comp].comp-hot .sw-body,
svg.has-selection [data-comp].comp-hot .ic-body,
svg.has-selection [data-comp].comp-hot .ic-notch,
svg.has-selection [data-comp].comp-hot .ic-dot,
svg.has-selection [data-comp].comp-hot .ic-label,
svg.has-selection [data-comp].comp-hot .ic-type,
svg.has-selection [data-comp].comp-hot .pcb-body,
svg.has-selection [data-comp].comp-hot .pcb-lbl,
svg.has-selection [data-comp].comp-hot .pcb-ref,
svg.has-selection [data-comp].comp-hot .term-block,
svg.has-selection [data-comp].comp-hot .term-screw,
svg.has-selection [data-comp].comp-hot .pcb-header,
svg.has-selection [data-comp].comp-hot .mcu-board,
svg.has-selection [data-comp].comp-hot .mcu-header,
svg.has-selection [data-comp].comp-hot .mcu-lbl,
svg.has-selection [data-comp].comp-hot .bat-body,
svg.has-selection [data-comp].comp-hot .bat-cap,
svg.has-selection [data-comp].comp-hot .bat-term-pos,
svg.has-selection [data-comp].comp-hot .bat-term-neg,
svg.has-selection [data-comp].comp-hot .bat-term-inner-pos,
svg.has-selection [data-comp].comp-hot .bat-term-inner-neg,
svg.has-selection [data-comp].comp-hot .psu-body,
svg.has-selection [data-comp].comp-hot .psu-screen,
svg.has-selection [data-comp].comp-hot .jumper-dot,
svg.has-selection [data-comp].comp-hot .sw-base2,
svg.has-selection [data-comp].comp-hot .sw-rocker,
svg.has-selection [data-comp].comp-hot .to92-body,
svg.has-selection [data-comp].comp-hot .to92-shine,
svg.has-selection [data-comp].comp-hot .to220-body,
svg.has-selection [data-comp].comp-hot .to220-tab,
svg.has-selection [data-comp].comp-hot .to220-hole,
svg.has-selection [data-comp].comp-hot .to220-shine,
svg.has-selection [data-comp].comp-hot .to220-bevel,
svg.has-selection [data-comp].comp-hot .cap-body,
svg.has-selection [data-comp].comp-hot .cap-el-body,
svg.has-selection [data-comp].comp-hot .cap-el-stripe,
svg.has-selection [data-comp].comp-hot .cap-el-sign,
svg.has-selection [data-comp].comp-hot .ind-body,
svg.has-selection [data-comp].comp-hot .zener-body,
svg.has-selection [data-comp].comp-hot .zener-band,
svg.has-selection [data-comp].comp-hot .buzzer-body,
svg.has-selection [data-comp].comp-hot .buzzer-hole,
svg.has-selection [data-comp].comp-hot .ldr-body,
svg.has-selection [data-comp].comp-hot .ldr-zig,
svg.has-selection [data-comp].comp-hot .motor-body,
svg.has-selection [data-comp].comp-hot .motor-cap,
svg.has-selection [data-comp].comp-hot .motor-shaft,
svg.has-selection [data-comp].comp-hot .motor-lbl,
svg.has-selection [data-comp].comp-hot .pin-lead,
svg.has-selection [data-comp].comp-hot .wire-lead{filter:drop-shadow(0 0 5px var(--glow, rgba(var(--accent-rgb),.75))) drop-shadow(0 0 12px var(--glow, rgba(var(--accent-rgb),.45)))}
.nethl{fill:var(--c);opacity:.18;stroke:var(--c);stroke-width:1.5;stroke-opacity:.6;pointer-events:none;animation:nethlIn .34s ease-out}
@keyframes nethlIn{from{opacity:0;stroke-opacity:0}}
svg.has-selection [data-jumper].jumper-hot{opacity:1}
svg.has-selection [data-jumper].jumper-hot .jumper,
svg.has-selection [data-jumper].jumper-hot .jumper-cable{stroke-width:3.4;animation:glowPulse 2s ease-in-out infinite}
svg.has-selection [data-jumper].jumper-hot .jumper-dot{filter:drop-shadow(0 0 5px currentColor) drop-shadow(0 0 10px currentColor)}
@keyframes glowPulse{0%,100%{filter:drop-shadow(0 0 4px currentColor) drop-shadow(0 0 10px currentColor) drop-shadow(0 0 20px currentColor)}50%{filter:drop-shadow(0 0 6px currentColor) drop-shadow(0 0 14px currentColor) drop-shadow(0 0 28px currentColor)}}

/* ---------- Resaltado: nada entra ni sale de golpe ----------
   El apagado del tablero, el encendido de la red y el resaltado del
   elemento elegido comparten curva, así que el cambio se lee como un
   movimiento y no como un parpadeo. */
#svg [data-comp]{transition:opacity .3s ease, filter .3s ease}
/* Sin nada seleccionado el ratón enciende suavemente lo que hay debajo. */
svg:not(.has-selection) [data-comp]:hover{filter:drop-shadow(0 0 4px rgba(var(--accent-rgb),.6)) drop-shadow(0 0 10px rgba(var(--accent-rgb),.35))}
svg:not(.has-selection) [data-jumper]:hover{filter:drop-shadow(0 0 4px currentColor) drop-shadow(0 0 9px currentColor)}
/* El elemento elegido late y da un pequeño estirón al entrar: es lo único
   que se mueve, así que la vista va sola a él. */
svg.has-selection [data-comp].comp-clicked{
  transform-box:fill-box;transform-origin:center;
  animation:clickedGlow 1.8s ease-in-out infinite, clickedPop .42s cubic-bezier(.2,1.4,.4,1);
}
@keyframes clickedGlow{
  0%,100%{filter:drop-shadow(0 0 3px #fff) drop-shadow(0 0 8px var(--accent)) drop-shadow(0 0 16px var(--accent))}
  50%{filter:drop-shadow(0 0 4px #fff) drop-shadow(0 0 13px var(--accent)) drop-shadow(0 0 28px var(--accent))}
}
@keyframes clickedPop{0%{transform:scale(1)}28%{transform:scale(1.055)}100%{transform:scale(1)}}
/* El flujo de la red va más rápido mientras la red está aislada. */
svg.has-selection [data-jumper].jumper-hot .jumper-flow{stroke-width:3;animation-duration:.5s}
/* Quien pide menos movimiento, no lo recibe: el resaltado se queda,
   pero quieto. */
@media (prefers-reduced-motion:reduce){
  #svg [data-comp],.jumper-group,.jumper,.jumper-cable,.jumper-flow,.nethl{transition:none;animation:none}
  svg.has-selection [data-comp].comp-clicked,
  svg.has-selection [data-jumper].jumper-hot .jumper,
  svg.has-selection [data-jumper].jumper-hot .jumper-cable{animation:none}
}

.bat-body{fill:#0d1015;stroke:#3a3f47;stroke-width:1.5;transition:all .2s ease;cursor:grab}
.bat-body:hover{stroke:var(--accent);filter:drop-shadow(0 0 6px rgba(var(--accent-rgb),.4))}
[data-battery].dragging .bat-body{cursor:grabbing;stroke:var(--accent);stroke-width:2;filter:drop-shadow(0 0 12px rgba(var(--accent-rgb),.7))}
[data-battery].dragging{opacity:.96}
.bat-cap{fill:#b8bcc4;stroke:#6a6f78;stroke-width:1;transition:opacity .3s ease}
.bat-term-pos{fill:#d94040;stroke:#6b1a1a;stroke-width:1.5}
.bat-term-neg{fill:#1a1a1a;stroke:#4a4a4a;stroke-width:1.5}
.bat-term-inner-pos{fill:#b83030}
.bat-term-inner-neg{fill:#2a2a2a}
.bat-lbl-9v{font:700 14px var(--mono);fill:#e6edf3;pointer-events:none;user-select:none}
.bat-lbl-ref{font:500 9px var(--mono);fill:#5a6472;pointer-events:none;user-select:none}
.bat-term-sign{font:700 9px var(--mono);pointer-events:none;user-select:none}

/* Signo de polaridad del componente seleccionado. Se dibuja con un
   contorno oscuro debajo del relleno (`paint-order`), así que se lee
   igual sobre la placa clara, sobre el vidrio y sobre las tiras de
   color del resaltado. */
.pol-mark{
  font:700 14px var(--mono);pointer-events:none;user-select:none;
  paint-order:stroke;stroke:#0a0e14;stroke-width:4px;stroke-linejoin:round;
}
.pol-mark.pol-plus{fill:#ff8a8a}
.pol-mark.pol-minus{fill:#9fd4ff}

/* ============================================================
   Vidrio y material propios de la protoboard
   ------------------------------------------------------------
   Va al final a propósito: misma especificidad que las reglas de
   arriba, así que estas ganan. Los componentes compartidos con el
   esquema (.tool, kbd, pre, campos, checkboxes, scrollbars) viven
   en css/theme.css.
   ============================================================ */
/* La placa es pan: se mantiene el crema físico, solo se calienta un
   punto para que case con el sustrato. */
.bd{fill:#efe9dc;stroke:#c9bfa8}
.trench{fill:#dbd3c1;stroke:#c9bfa8}
.hole{fill:#3a3128}
.lbl{fill:#8a8172}
.lbl.plus{fill:#d64545}
.lbl.minus{fill:#2f6bd6}
/* Aviso flotante: cristal ámbar */
.notice{
  background:linear-gradient(180deg, rgba(var(--warn-rgb),.20), rgba(var(--warn-rgb),.09));
  backdrop-filter:blur(var(--blur-2));
  -webkit-backdrop-filter:blur(var(--blur-2));
  box-shadow:var(--glass-shadow), var(--glass-specular), 0 0 24px rgba(var(--warn-rgb),.18);
}
.notice b{color:#ffd489}
.notice .sub{color:#e0b366}
@media (max-width:980px){body{overflow:auto}main{grid-template-columns:1fr}#canvasWrap{height:62vh;flex:none}#editor{border-right:0}}
