:root {
  --bg:#0d1117; --panel:#161b22; --border:#30363d; --text:#e6edf3; --muted:#8b949e;
  --blue:#58a6ff; --green:#3fb950; --orange:#d29922; --purple:#bc8cff; --red:#f85149;
}
* { box-sizing:border-box; }
body { font-family:-apple-system,"Segoe UI","Microsoft YaHei",sans-serif; background:var(--bg); color:var(--text); margin:0; padding:20px; }
.container { max-width:1020px; margin:0 auto; }

header { display:flex; align-items:center; gap:14px; padding:12px 16px; background:var(--panel); border:1px solid var(--border); border-radius:8px; margin-bottom:14px; flex-wrap:wrap; }
header h1 { font-size:1em; margin:0; }
.status { display:flex; align-items:center; gap:8px; font-size:13px; }
.dot { width:8px; height:8px; border-radius:50%; background:var(--muted); }
.dot.connected { background:var(--green); }
.sys-info { display:flex; gap:14px; color:var(--muted); font-size:12px; margin-left:auto; }
.sys-info b { color:var(--text); }

.btn { padding:6px 14px; border:1px solid var(--border); border-radius:6px; background:#21262d; color:var(--text); cursor:pointer; font-size:13px; }
.btn:hover { border-color:var(--blue); }
.btn.primary { background:#238636; border-color:#2ea043; }
.btn.danger { background:#da3633; border-color:var(--red); }
.btn.small { padding:4px 10px; font-size:12px; }

.canvas-wrap { background:var(--panel); border:1px solid var(--border); border-radius:10px; margin-bottom:14px; }
.canvas-title { font-size:12px; color:var(--muted); padding:10px 14px 0; }
#canvas { position:relative; width:1000px; height:520px; margin:0 auto; }
svg.lines { position:absolute; top:0; left:0; z-index:0; }

.node { position:absolute; width:190px; background:#0d1117; border-radius:8px; padding:10px; z-index:1; }
.node .head { display:flex; align-items:center; gap:6px; margin-bottom:7px; cursor:move; }
.node .nt { font-size:12px; font-weight:600; }
.node .wave { margin-bottom:7px; text-align:center; }
.node .wave svg { width:72px; height:30px; }
.node .f { margin-bottom:7px; }
.node .f label { display:block; font-size:10px; color:var(--muted); margin-bottom:2px; }
.node .f select, .node .f input { width:100%; padding:4px 6px; background:#161b22; color:var(--text); border:1px solid var(--border); border-radius:4px; font-size:11px; }
.node .ratio { display:flex; align-items:center; gap:5px; }
.node .ratio input { flex:1; min-width:0; }
.node .ratio select { width:auto; flex-shrink:0; }
.node .count { margin-top:6px; font-size:13px; color:var(--muted); border-top:1px dashed var(--border); padding-top:5px; }
.node .count b { color:var(--blue); font-size:16px; font-variant-numeric:tabular-nums; }
.node.qei { border:2px solid var(--blue); }
.node.qei .nt { color:var(--blue); }
.node.gear { border:2px solid var(--orange); }
.node.gear .nt { color:var(--orange); }
.node.qeo { border:2px solid var(--green); }
.node.qeo .nt { color:var(--green); }

/* 连线端口 */
.port { position:absolute; width:18px; height:18px; border-radius:50%; background:#0d1117; border:2px solid var(--blue); cursor:crosshair; z-index:2; }
.port.out { right:-10px; top:50%; transform:translateY(-50%); border-color:var(--blue); }
.port.in { left:-10px; top:50%; transform:translateY(-50%); border-color:var(--green); }
.port:hover { background:var(--blue); }

footer { display:flex; gap:12px; padding:14px; background:var(--panel); border:1px solid var(--border); border-radius:8px; flex-wrap:wrap; align-items:center; }

.toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%); background:#238636; color:#fff; padding:10px 20px; border-radius:6px; opacity:0; transition:opacity .3s; z-index:10; }
.toast.show { opacity:1; }
.toast.err { background:#da3633; }
