/* 가상 장치판 (vpanel.js). 색은 app.css 의 것을 그대로 쓴다: 입력 = 노란 LED, 출력 = 빨간 LED, 납작하게 */
.vtools{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.vvin{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}
.vpal{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:6px}
.vpal .chip{cursor:pointer}
.vwrap{overflow-x:auto;border:1px solid var(--line);border-radius:8px;background:var(--panel2);margin:10px 0 14px}
.vcanvas{position:relative;padding:10px}
.vcanvas.free{width:980px;min-height:300px;padding:0;margin:0 auto}
.vcanvas.free>.vdev,.vcanvas.free>.vboard{position:absolute}
.vcanvas.free>.vdev{width:200px}
.vcanvas.free>.vnone{position:absolute;left:10px;top:10px;width:300px;text-align:left;padding:8px}
.vcanvas.flow{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;align-items:start}
.vcanvas.flow>.vboard,.vcanvas.flow>.vnone{grid-column:1/-1}
.vwires{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;z-index:0}
.flow .vwires{display:none}
.vw{fill:none;stroke:#B9C2CA;stroke-width:2}
.vw.on.in{stroke:var(--lamp-in)} .vw.on.out{stroke:var(--lamp-out)}
.vw.rub{stroke:var(--accent);stroke-dasharray:5 4}

/* 보드 */
.vboard{background:var(--ink);color:#EEF2F5;border-radius:8px;padding:10px;z-index:1}
.vbt{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-bottom:8px;min-width:0}
.vboard .muted,.vboard .label{color:#A9B6C2}
.vbcols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
.vterms{display:flex;flex-direction:column;gap:4px;min-width:0}
.vterm{display:flex;align-items:center;gap:6px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);border-radius:5px;
  padding:4px 6px;color:inherit;cursor:pointer;min-height:30px;text-align:left;min-width:0}
.vterm .lamp{flex:none}
.vterm .nm{font-size:11.5px;color:#A9B6C2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.vterm.on .lamp.in{background:var(--lamp-in)} .vterm.on .lamp.out{background:var(--lamp-out)}
.vterm.virt{border-color:var(--lamp-in);box-shadow:inset 0 0 0 1px var(--lamp-in)}
.vterm.out{cursor:default}
.edit .vterm{cursor:crosshair}
.vbn:empty{display:none}
.vbn{margin-top:6px}
.flow .vterms{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.flow .vterms .label{grid-column:1/-1}
.flow .vterm .nm{display:none}
.flow .vterm{min-height:36px}
.vpic{display:block;width:100%;height:auto;margin-bottom:8px}
.vpic .ol{fill:#2B3A47;stroke:#8696A5;stroke-width:.5}
.vpic .art{fill:none;stroke:#C5CFD8;stroke-width:.25;stroke-linecap:round}
.vdot{fill:var(--lamp-off);stroke:rgba(0,0,0,.4);stroke-width:.2;cursor:pointer}
.vdot.on.in{fill:var(--lamp-in)} .vdot.on.out{fill:var(--lamp-out)}
.vmore{fill:#5B6B7A;stroke:rgba(0,0,0,.4);stroke-width:.2}

/* 장치 */
.vdev{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:8px 10px;display:flex;flex-direction:column;gap:8px;z-index:1;min-width:0}
.vdev.drag{border-color:var(--accent);z-index:3}
.vdh{display:flex;justify-content:space-between;align-items:baseline;gap:6px;min-width:0}
.vdh b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vdh .small{flex:none}
.edit .free .vdev{cursor:grab}
.vgrip{flex:none;align-self:center;color:var(--muted);cursor:grab;touch-action:none;padding:2px 2px 2px 0;font-size:15px;line-height:1;user-select:none}
.free .vbtn{width:64px;height:64px}
.free .vlamp,.free .vspin{width:40px;height:40px}
.free .vspin i{height:16px;transform-origin:50% 16px}
.vname{flex:1;min-width:0;border:1px solid var(--line);border-radius:5px;padding:3px 6px;background:var(--panel2)}
.vx{background:none;border:0;cursor:pointer;color:var(--muted);padding:2px 6px}
.vx:hover{color:var(--crit)}
.vedit{display:flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:12px}
.vedit select,.vedit input{border:1px solid var(--line);border-radius:5px;padding:2px 4px;background:var(--panel2);max-width:100%}
.vedit input{width:64px}
.vedit .btn{padding:2px 8px}
.vbody{display:flex;justify-content:center;align-items:center}
.vbody:empty{display:none}
.edit .vbody{opacity:.5;pointer-events:none}
.vpins{display:flex;flex-wrap:wrap;gap:4px}
.vpin{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:var(--panel2);border-radius:5px;padding:2px 6px;font-size:12px;cursor:default;min-height:26px}
.vpin.none{border-style:dashed;color:var(--muted)}
.vpin .u{color:var(--muted)}
.vpin .un{color:var(--muted);cursor:pointer;padding:0 3px;font-size:14px}
.vpin .un:hover{color:var(--crit)}
.edit .vpin{cursor:crosshair;touch-action:none}
.vpin.pick{border-color:var(--accent);border-style:solid;box-shadow:0 0 0 2px var(--accent-soft)}
.use .k-etc .vpin.in:not(.none){cursor:pointer}

.vbtn{-webkit-tap-highlight-color:transparent;width:84px;height:84px;border-radius:50%;border:3px solid #235F3C;background:var(--ok);color:#fff;font-weight:600;cursor:pointer;
  touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.vdev.p0 .vbtn{background:#235F3C;outline:3px solid var(--lamp-in);outline-offset:2px}
.vsw{width:64px;height:32px;border-radius:16px;border:1px solid rgba(0,0,0,.12);background:var(--lamp-off);position:relative;cursor:pointer;padding:0}
.vsw i{position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:#fff;transition:left .12s}
.vdev.p0 .vsw{background:var(--lamp-in)} .vdev.p0 .vsw i{left:35px}
.vestop{width:100%;min-height:56px;border-radius:8px;border:2px solid var(--crit);background:var(--crit);color:#fff;font-weight:600;cursor:pointer;padding:6px}
.vestop .t-on{display:none}
.vdev.p0 .vestop{background:var(--panel);color:var(--crit)}
.vdev.p0 .vestop .t-on{display:inline} .vdev.p0 .vestop .t-off{display:none}
.vsel{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;max-width:100%}
.vsel button{background:var(--panel);border:0;padding:8px 9px;cursor:pointer;color:var(--muted)}
.vsel button+button{border-left:1px solid var(--line)}
.vdev.p0 .vsel [data-v="l"],.vdev.p1 .vsel [data-v="r"],.vdev:not(.p0):not(.p1) .vsel [data-v="c"]{background:var(--accent-soft);color:var(--accent);font-weight:600}
.vlamp{width:48px;height:48px;border-radius:50%;background:var(--lamp-off);border:1px solid rgba(0,0,0,.12);transition:background .08s}
.vdev.p0 .vlamp{background:var(--lamp-out)}
.vcyl{position:relative;width:170px;max-width:100%;height:34px}
.vcyl .body{position:absolute;left:0;top:4px;width:90px;height:26px;background:#8693A0;border-radius:4px}
.vcyl .rod{position:absolute;left:86px;top:13px;height:8px;width:calc(10px + var(--pos,0) * 62px);background:var(--ink);transition:width .1s linear}
.vcyl .rod::after{content:"";position:absolute;right:-6px;top:-7px;width:8px;height:22px;background:var(--ink);border-radius:2px}
.vspin{width:48px;height:48px;border-radius:50%;border:2px solid #8693A0;position:relative}
.vspin i{position:absolute;left:50%;top:4px;width:4px;height:20px;margin-left:-2px;background:#8693A0;border-radius:2px;transform-origin:50% 20px}
.vdev.p0 .vspin{border-color:var(--lamp-out)}
.vdev.p0 .vspin i{background:var(--lamp-out);animation:vspin 1s linear infinite}
@keyframes vspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){ .vdev.p0 .vspin i{animation:none} .vcyl .rod,.vsw i{transition:none} }

.vnote{margin:8px 0 0;padding-left:18px;font-size:13px;color:var(--muted)}
.vnote li{margin-bottom:4px}
