/* ============ 网络拓扑编辑器 专有样式 ============ */
html, body { height: 100%; margin: 0; }
body { overflow: hidden; }
* { box-sizing: border-box; }

.app {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  height: 100vh;
  padding: 14px 18px 8px;
}

/* ---------- 头部 ---------- */
header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 12px; flex-shrink: 0; flex-wrap: wrap;
}
.logo { display: flex; align-items: center; gap: 12px; }
.logo-mark {
  width: 42px; height: 42px; border-radius: 12px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dim) 100%);
  display: grid; place-items: center; box-shadow: var(--glow);
  position: relative; overflow: hidden;
}
.logo-mark svg { position: relative; z-index: 1; }
.logo-text h1 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-size: 22px; font-weight: 800; letter-spacing: -.02em; line-height: 1; margin: 0;
}
.logo-text p {
  font-size: 11px; color: var(--fg-3); margin: 3px 0 0;
  font-family: 'JetBrains Mono', monospace; letter-spacing: .06em;
}
.header-hero { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; }
.header-hero h2 {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-size: clamp(18px, 2.4vw, 28px); font-weight: 800; line-height: 1.2;
  letter-spacing: -.02em; margin: 0; white-space: nowrap;
}
.header-hero h2 .accent {
  background: linear-gradient(120deg, var(--accent) 0%, var(--accent-2) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.header-stats {
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  font-family: 'JetBrains Mono', monospace; font-size: 12px; flex-shrink: 0;
}
.hero-label {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; background: var(--badge-bg, var(--bg-2));
  border: 1px solid var(--badge-border, var(--border)); border-radius: 100px;
  font-size: 10px; color: var(--accent); letter-spacing: .08em; text-transform: uppercase;
}
.hero-label::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.stat-group { display: flex; gap: 6px; }
.stat-pill {
  padding: 5px 10px; background: var(--bg-2); border: 1px solid var(--border);
  border-radius: 8px; color: var(--fg-2); font-size: 11px;
}

/* ---------- 主区域三栏 ---------- */
/* --pal-slot：图元库占位宽度（面板宽 + 右间距），即收起前画布列的左边界；
   工具条收起时用它做 margin-left 抵位，保证「盒子不动、画布向该侧延申」。
   --inspector-w：属性面板宽度（拖拽时会以内联变量覆盖），--insp-slot 由脚本实时写入。
   --panel-anim：面板收放动画的唯一时间来源，工具条与画布的 margin 过渡共用同一份，
   两侧位移才能严格抵消（避免「修好左边、右边抽动」这类不同步问题）。 */
.main {
  display: flex; flex: 1; min-height: 0; gap: 0; position: relative;
  --pal-slot: 260px; --inspector-w: 300px;
  --panel-anim: .2s cubic-bezier(.22,.8,.35,1);
}

.palette, .inspector {
  width: 248px; flex-shrink: 0; background: var(--bg-2);
  border: 1px solid var(--border); border-radius: 14px;
  display: flex; flex-direction: column; overflow: hidden;
}
.palette { margin-right: 12px; width: 248px; }
.inspector {
  position: relative; margin-left: 12px;
  width: var(--inspector-w, 300px); font-size: 12px;
}
/* 右侧属性面板可调宽度拖拽条 */
.insp-resizer {
  position: absolute; left: -7px; top: 0; width: 14px; height: 100%;
  cursor: col-resize; z-index: 6; touch-action: none;
}
.insp-resizer::after {
  content: ''; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 2px; height: 40px; border-radius: 2px; background: var(--border-light);
  transition: background .15s, height .15s;
}
.insp-resizer:hover::after, .insp-resizer.dragging::after { background: var(--accent); height: 72px; }
.palette-head, .inspector-head {
  padding: 12px 14px; font-size: 13px; font-weight: 600; color: var(--fg);
  border-bottom: 1px solid var(--border); flex-shrink: 0;
  font-family: 'Space Grotesk', sans-serif;
}
/* 图元库 / 属性面板头部：两端对齐，标题在左，收起/展开按钮在右 */
.palette-head, .inspector-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.palette-toggle, .inspector-toggle {
  flex: none; width: 30px; height: 30px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-4); color: var(--fg-2); cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.palette-toggle:hover, .inspector-toggle:hover { background: var(--bg-3); border-color: var(--border-light); color: var(--fg); }
.palette-toggle svg, .inspector-toggle svg { width: 16px; height: 16px; display: block; }
.palette-toggle .ic-expand, .inspector-toggle .ic-expand { display: none; }
.palette.collapsed .palette-toggle .ic-collapse,
.inspector.collapsed .inspector-toggle .ic-collapse { display: none; }
.palette.collapsed .palette-toggle .ic-expand,
.inspector.collapsed .inspector-toggle .ic-expand { display: block; }

/* 收起态：图元库缩成与工具栏等高的一条，置于左上角，画布占满其余空间 */
.palette.collapsed {
  position: absolute; top: 0; left: 0;
  width: 248px; height: 52px; margin: 0;
  z-index: 5; flex: none;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.palette.collapsed .palette-hint,
.palette.collapsed #paletteBody { display: none; }
.palette.collapsed .palette-head {
  height: 100%; padding: 0 12px; border-bottom: none;
}
/* 收起态：属性面板同理，缩成与工具栏等高的一条浮在右上角（宽度跟随可拖拽的 --inspector-w） */
.inspector.collapsed {
  position: absolute; top: 0; right: 0;
  width: var(--inspector-w, 300px); height: 52px; margin: 0;
  z-index: 5; flex: none;
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.inspector.collapsed .inspector-head {
  height: 100%; padding: 0 12px; border-bottom: none;
}
.inspector.collapsed .insp-resizer,
.inspector.collapsed #inspectorBody { display: none; }

/* 收起态工具栏抵位：画布列向该侧延申多少，工具栏就用 margin 推回多少，
   保证工具条「盒子」位置与宽度完全不变（padding 只是把内容推回来，盒子仍会移动并被盖住） */
.main.palette-collapsed .toolbar { margin-left: var(--pal-slot, 260px); }
.main.inspector-collapsed .toolbar { margin-right: var(--insp-slot, 312px); }
.palette-hint { padding: 8px 14px 4px; font-size: 11px; color: var(--fg-3); }
#paletteBody, #inspectorBody { overflow-y: auto; padding: 8px 10px 14px; flex: 1; }

/* 自定义滚动条：跟随明暗主题，图元库 / 属性面板共用 */
#paletteBody, #inspectorBody {
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: var(--border-light) transparent;
}
#paletteBody::-webkit-scrollbar, #inspectorBody::-webkit-scrollbar { width: 10px; height: 10px; }
#paletteBody::-webkit-scrollbar-track, #inspectorBody::-webkit-scrollbar-track { background: transparent; }
#paletteBody::-webkit-scrollbar-thumb, #inspectorBody::-webkit-scrollbar-thumb {
  background-color: var(--border-light);
  border-radius: 8px;
  border: 3px solid transparent;
  background-clip: content-box;                /* 留出边距，更像悬浮细条 */
}
#paletteBody::-webkit-scrollbar-thumb:hover, #inspectorBody::-webkit-scrollbar-thumb:hover {
  background-color: var(--fg-3);
}
/* 浅色主题：滑块加深以提升对比度 */
.light-theme #paletteBody, .light-theme #inspectorBody { scrollbar-color: var(--fg-3) transparent; }
.light-theme #paletteBody::-webkit-scrollbar-thumb, .light-theme #inspectorBody::-webkit-scrollbar-thumb { background-color: var(--fg-3); }
.light-theme #paletteBody::-webkit-scrollbar-thumb:hover, .light-theme #inspectorBody::-webkit-scrollbar-thumb:hover { background-color: var(--fg-2); }

/* 图元分类 */
.pal-cat { margin-top: 10px; }
.pal-cat-title {
  font-size: 11px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em;
  padding: 4px 4px 6px; font-family: 'JetBrains Mono', monospace;
}
.pal-items { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.pal-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 9px;
  background: var(--bg-3); border: 1px solid var(--border); border-radius: 9px;
  cursor: grab; user-select: none; transition: all .15s ease;
}
.pal-item:hover { border-color: var(--accent); background: var(--bg-4); }
.pal-item:active { cursor: grabbing; }
.pal-item svg { width: 20px; height: 20px; flex-shrink: 0; }
.pal-item span { font-size: 12px; color: var(--fg-2); line-height: 1.2; }
.pal-swatch { width: 16px; height: 16px; border-radius: 4px; flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(255,255,255,.35); }
.pal-group { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; }
.pal-custom { border-style: dashed; color: var(--accent); }
.pal-custom svg { stroke: var(--accent); }
.pal-custom:hover { background: var(--accent-alpha-10); border-color: var(--accent); }

/* ---------- 自定义分组弹窗 ---------- */
.modal-mask {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.45); backdrop-filter: blur(2px);
}
.modal-mask[hidden] { display: none; }
.modal {
  width: 320px; max-width: calc(100vw - 32px);
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 20px;
  box-shadow: 0 18px 50px rgba(0,0,0,.3);
  font-family: 'Space Grotesk','Noto Sans SC','Microsoft YaHei',sans-serif;
}
.light-theme .modal { box-shadow: 0 18px 50px rgba(0,0,0,.18); }
.modal-title { font-size: 15px; font-weight: 700; color: var(--fg); margin-bottom: 14px; }
.modal-sub { font-size: 12px; color: var(--fg-3); margin: 12px 0 8px; }
.swatch-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.swatch {
  height: 34px; border-radius: 8px; cursor: pointer;
  border: 2px solid transparent; transition: transform .1s ease;
  position: relative;
}
.swatch:hover { transform: translateY(-1px); }
.swatch.on { border-color: var(--fg); box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 4px var(--accent); }
.swatch.on::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 12px; height: 12px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 0 2px rgba(0,0,0,.25);
}
.modal-input {
  width: 100%; box-sizing: border-box; padding: 9px 11px;
  font-size: 13px; font-family: inherit; color: var(--fg);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; outline: none;
}
.modal-input:focus { border-color: var(--accent); }
.gm-custom-color { display: flex; align-items: center; gap: 10px; }
.gm-color {
  width: 42px; height: 34px; flex-shrink: 0; padding: 0;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); cursor: pointer; overflow: hidden;
}
.gm-color::-webkit-color-swatch-wrapper { padding: 2px; }
.gm-color::-webkit-color-swatch { border: none; border-radius: 5px; }
.gm-color::-moz-color-swatch { border: none; border-radius: 5px; }
.gm-hex { flex: 1; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* ---------- 画布列 ---------- */
/* 工具条与画布列的 margin 过渡都由 --panel-anim 统一提供时长与缓动（见 .main），
   两条 margin 都必须声明 —— 只声明一条会导致另一侧面板收起时补位瞬间跳变（抽动）。
   注意：这里是「成对抵消」的结构，工具条与画布两侧的 margin 位移之和必须恒为定值，
   所以任何一侧的过渡声明/时长都不能缺失或不同。 */
.canvas-col {
  flex: 1; display: flex; flex-direction: column; min-width: 0;
  transition: margin-left var(--panel-anim), margin-right var(--panel-anim);
}
/* JS 定位动画起点时用：只把「该侧」的 margin 过渡清零，另一侧（可能正在进行的）过渡不受影响 */
.canvas-col.instant-left  { transition: margin-left 0s, margin-right var(--panel-anim); }
.canvas-col.instant-right { transition: margin-right 0s, margin-left var(--panel-anim); }
.toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 10px; margin-bottom: 10px; flex-wrap: wrap; flex-shrink: 0;
  background: linear-gradient(180deg, var(--bg-2) 0%, var(--bg-3) 100%);
  border: 1px solid var(--border); border-radius: 14px;
  transition: margin-left var(--panel-anim), margin-right var(--panel-anim);
}
.toolbar-left, .toolbar-right { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.seg { display: inline-flex; background: var(--bg); border: 1px solid var(--border); border-radius: 9px; padding: 3px; gap: 2px; }
.seg button {
  padding: 6px 12px; background: transparent; border: none; color: var(--fg-2);
  font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 500;
  cursor: pointer; border-radius: 6px; transition: all .2s ease; min-width: 32px;
}
.seg button:hover { color: var(--fg); background: var(--bg-3); }
.seg button.zoom-val { min-width: 56px; text-align: center; color: var(--accent); background: var(--accent-alpha-10); cursor: pointer; }
.seg button.zoom-val:hover { background: var(--accent-alpha-10); }
.zoom-wrap { position: relative; display: inline-flex; }
.zoom-input {
  display: none; width: 56px; box-sizing: border-box; text-align: center;
  font: inherit; font-weight: 600; font-size: 12.5px; color: var(--accent);
  background: var(--accent-alpha-10); border: 1px solid var(--accent); border-radius: 6px; outline: none;
}
.zoom-wrap.editing .zoom-val { display: none; }
.zoom-wrap.editing .zoom-input { display: inline-block; }
.zoom-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  display: none; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 8px;
  background: var(--bg); border: 1px solid var(--border-light); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,.18); min-width: 168px;
}
.light-theme .zoom-pop { box-shadow: 0 8px 24px rgba(0,0,0,.12); }
.zoom-wrap.open .zoom-pop { display: grid; }
.zoom-pop button {
  padding: 6px 8px; font-family: 'Space Grotesk', sans-serif; font-size: 12px; font-weight: 600;
  color: var(--fg-2); background: var(--bg-4); border: 1px solid var(--border); border-radius: 6px;
  cursor: pointer; transition: all .12s;
}
.zoom-pop button:hover { color: var(--fg); background: var(--bg-3); border-color: var(--border-light); }
.zoom-pop button.active { color: var(--accent); background: var(--accent-alpha-10); border-color: var(--accent); }

.btn {
  padding: 7px 13px; border-radius: 8px; font-family: 'Space Grotesk', sans-serif;
  font-size: 12.5px; font-weight: 600; cursor: pointer; border: 1px solid var(--border);
  background: var(--bg-4); color: var(--fg); transition: all .15s ease;
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
}
.btn:hover { background: var(--bg-3); border-color: var(--border-light); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--accent); color: #001a10; border-color: var(--accent); }
.light-theme .btn.primary { color: #fff; }
.btn.primary:hover { box-shadow: 0 0 18px var(--accent-alpha-40); }
.btn.danger { color: var(--danger, #e24b4a); border-color: var(--border-light); }
.btn.icon { padding: 7px 10px; }
.btn.danger:hover { background: var(--danger, #e24b4a); color: #fff; border-color: var(--danger, #e24b4a); }
.btn.toggle.on { background: var(--accent-alpha-15); color: var(--accent); border-color: var(--accent-alpha-30-border, var(--accent)); }

.stage {
  position: relative; flex: 1; min-height: 0;
  border: 1px solid var(--border); border-radius: 14px;
  overflow: hidden; background: var(--bg);
  cursor: default;
}
.stage.tool-pan { cursor: grab; }
.stage.panning { cursor: grabbing; }
.stage.connecting { cursor: crosshair; }
.mode-grp { display: inline-flex; gap: 4px; }
.mode-grp .btn { padding: 7px 10px; }
.mode-grp .btn svg { display: block; }
.btn svg { display: block; }
.stage svg { display: block; width: 100%; height: 100%; touch-action: none; user-select: none; }
.stage-tip {
  position: absolute; right: 12px; bottom: 10px;
  font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--fg-3);
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 5px 10px; pointer-events: none; opacity: .85;
}

/* ---------- 节点 / 端口 / 连线（SVG 内） ---------- */
.node { cursor: move; }
.node rect.node-box { transition: stroke .15s ease, fill .15s ease; }
.node:hover rect.node-box { stroke: var(--accent); }
.node.selected rect.node-box { stroke: var(--accent); stroke-width: 1.8; }
.port {
  fill: var(--bg); stroke: var(--accent); stroke-width: 1.4;
  opacity: 0; transition: opacity .12s ease; cursor: crosshair;
}
.node:hover .port, .node.selected .port, .stage.connecting .port { opacity: 1; }
.port:hover { fill: var(--accent); r: 6; }
.edge-hit { stroke: transparent; fill: none; cursor: pointer; }
.edge.selected .edge-line { stroke: var(--accent); stroke-width: 2.2; }
.temp-edge { stroke: var(--accent); stroke-width: 2; fill: none; stroke-dasharray: 6 4; pointer-events: none; }
.marquee { fill: var(--accent-alpha-10); stroke: var(--accent); stroke-width: 1; stroke-dasharray: 4 3; pointer-events: none; }
.edge-endpoint { fill: var(--bg); stroke: var(--accent); stroke-width: 1.8; cursor: grab; pointer-events: all; transition: fill .12s ease; }
.edge-endpoint:hover { fill: var(--accent); }

/* 分组底框 / 标签 / 缩放把手 */
.group { cursor: move; }
.group-box { transition: stroke .15s ease; }
.group.selected .group-box { stroke-width: 3; }
.group-label { cursor: move; }
.ghandle {
  fill: var(--bg); stroke: var(--accent); stroke-width: 1.6;
  cursor: nwse-resize; pointer-events: all;
}
.ghandle[data-ghandle="1"], .ghandle[data-ghandle="5"] { cursor: ns-resize; }
.ghandle[data-ghandle="3"], .ghandle[data-ghandle="7"] { cursor: ew-resize; }
.ghandle:hover { fill: var(--accent); }

/* ---------- 属性面板 ---------- */
.insp-empty { padding: 24px 8px; color: var(--fg-3); font-size: 12px; text-align: center; line-height: 1.7; }
.insp-section { margin-bottom: 14px; }
.insp-section-title {
  font-size: 10.5px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .06em;
  font-family: 'JetBrains Mono', monospace; margin: 6px 2px 8px;
  border-left: 2px solid var(--accent); padding-left: 8px;
}
.field { margin-bottom: 9px; }
.field label { display: block; font-size: 11px; color: var(--fg-2); margin-bottom: 4px; }
.field input[type=text], .field input[type=number], .field select, .field textarea {
  width: 100%; padding: 7px 9px; border-radius: 8px;
  background: var(--bg); color: var(--fg); border: 1px solid var(--border);
  font-size: 12px; font-family: inherit; outline: none; transition: border-color .15s;
}
.field textarea { resize: vertical; min-height: 64px; font-family: 'JetBrains Mono', monospace; font-size: 11px; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.sublist { display: flex; flex-direction: column; gap: 6px; }
.subitem {
  display: flex; align-items: center; gap: 6px; padding: 6px;
  background: var(--bg-3); border: 1px solid var(--border); border-radius: 8px;
}
.subitem .subicon { width: 22px; height: 22px; flex-shrink: 0; }
.subitem input[type="text"] { flex: 1; min-width: 0; padding: 5px 7px; border-radius: 6px; background: var(--bg); color: var(--fg); border: 1px solid var(--border); font-size: 11px; }
.subitem input[type="text"].desc { font-size: 10.5px; color: var(--fg-2); }
.subbtns { display: flex; flex-direction: column; gap: 2px; }
.iconbtn {
  width: 22px; height: 22px; border-radius: 6px; border: 1px solid var(--border);
  background: var(--bg-4); color: var(--fg-2); cursor: pointer; font-size: 11px;
  display: grid; place-items: center; line-height: 1;
}
.iconbtn:hover { border-color: var(--accent); color: var(--accent); }
.iconbtn.del:hover { border-color: var(--danger, #e24b4a); color: var(--danger, #e24b4a); }
.insp-btn {
  width: 100%; padding: 8px; border-radius: 8px; border: 1px dashed var(--border-light);
  background: transparent; color: var(--fg-2); cursor: pointer; font-size: 11px; transition: all .15s;
  margin-top: 2px;
}
.insp-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-alpha-10); }
.insp-actions { display: flex; gap: 8px; margin-top: 4px; }
.insp-actions .btn { flex: 1; justify-content: center; padding: 8px; }
/* 规格标签右侧控件组：紧贴排列，把剩余横向空间全部让给文本框 */
.tagctl {
  position: relative;
  display: flex; align-items: center; gap: 4px;
  flex: 0 0 auto; margin-left: auto;
}
.chk { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--fg-2); }
.tagcolor {
  flex: 0 0 auto; width: 30px; height: 15px; flex-shrink: 0; padding: 0;
  border: 1px solid var(--border-light); border-radius: 5px;
  background: var(--bg); cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0,0,0,.05);
}
/* 取色器：脱离 flex 流，避免前后各吃掉一个 gap（原先色块右侧空出 12px） */
.tagcolor-picker {
  position: absolute; left: 0; top: 0;
  width: 1px; height: 1px; padding: 0; margin: 0; border: 0; opacity: 0;
  pointer-events: none;
}
.iconbtn.reset:hover { border-color: var(--accent); color: var(--accent); }
.chk input { width: 14px; height: 14px; padding: 0; margin: 0; border: 0; flex: 0 0 auto; background: var(--bg); }

/* 规格标签：聚焦文本框时在输入框下方浮出操作菜单（悬浮层，不占面板空间；仅作用于 tagsList，不影响 svcList） */
#tagsList .subitem { flex-direction: column; align-items: stretch; position: relative; }
#tagsList .tagrow { display: flex; align-items: center; gap: 6px; }
#tagsList .tagmenu {
  position: absolute; top: calc(100% + 2px); left: 6px; z-index: 50;
  display: none; flex-direction: column; gap: 4px; padding: 6px; min-width: 180px;
  background: var(--bg); border: 1px solid var(--border-light); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,.18);
}
.light-theme #tagsList .tagmenu { box-shadow: 0 8px 24px rgba(0,0,0,.12); }
/* 出场动画：像从文本输入框下方“抽屉”一样滑出 + 淡入，约 0.5s */
@keyframes tagmenuDrawer {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}
#tagsList .subitem.open .tagmenu { display: flex; animation: tagmenuDrawer .5s cubic-bezier(.22, .8, .35, 1) both; }
.tagact {
  width: 100%; text-align: left; padding: 6px 10px; font-family: inherit; font-size: 11px; font-weight: 600;
  color: var(--fg-2); background: var(--bg-4); border: 1px solid var(--border); border-radius: 6px; cursor: pointer;
  transition: all .12s;
}
.tagact:hover { color: var(--accent); background: var(--accent-alpha-10); border-color: var(--accent); }

/* ---------- 演示方案：激活组件高亮（1/2/3 + 编辑键） ---------- */
/* 三个方案号各自的主题色：按钮激活态与画布高亮统一使用，深浅主题各一套 */
:root {
  --demo-c1: #ff6b35;  /* 方案 1 */
  --demo-c2: #0aa5c9;  /* 方案 2 */
  --demo-c3: #8a5cf6;  /* 方案 3 */
  --demo-edit: #ffffff;  /* 编辑态预览高亮：中性白（不绑定任何方案号） */
  --demo-edit-fg: #131313;  /* 编辑键/高亮底上的前景文字色 */
}
.light-theme {
  --demo-c1: #c94d1e;
  --demo-c2: #0a7ea4;
  --demo-c3: #6d4ed4;
  --demo-edit: #26221c;  /* 浅色底上用深炭色，保证可辨 */
  --demo-edit-fg: #f5f0ea;
}
.toolbar-sep { width: 1px; height: 22px; background: var(--border); margin: 0 8px; flex: none; }
.demo-grp { display: inline-flex; align-items: center; gap: 3px; background: var(--bg); border: 1px solid var(--border); border-radius: 9px; padding: 3px; }
.demo-num {
  width: 26px; height: 24px; position: relative;
  display: grid; place-items: center;
  font-family: 'Space Grotesk', sans-serif; font-size: 12px; font-weight: 600;
  color: var(--dc, var(--fg-3)); background: transparent; border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; transition: all .12s;
}
#demoNum1 { --dc: var(--demo-c1); }
#demoNum2 { --dc: var(--demo-c2); }
#demoNum3 { --dc: var(--demo-c3); }
.demo-num:hover { color: var(--dc, var(--fg)); background: var(--bg-3); }
.demo-num.has::after { content: ''; position: absolute; left: 50%; bottom: 1px; transform: translateX(-50%); width: 3px; height: 3px; border-radius: 50%; background: var(--dc, var(--accent-2)); }
.demo-num.on { color: #fff; background: var(--dc, var(--accent-2)); border-color: var(--dc, var(--accent-2)); }
.demo-num.on::after { background: #fff; }
.demo-edit {
  width: 24px; height: 24px; display: grid; place-items: center;
  color: var(--fg-3); background: transparent; border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; transition: all .12s;
}
.demo-edit:hover { color: var(--fg); background: var(--bg-3); }
.demo-edit.on { color: var(--demo-edit-fg); background: var(--demo-edit); border-color: var(--demo-edit); box-shadow: 0 0 10px var(--demo-edit); }
.stage.demo-editing { cursor: crosshair; }
.stage.demo-editing .node { cursor: pointer; }
.stage.demo-editing .edge-hit { cursor: pointer; }

/* ---------- Toast ---------- */
.toast-stack { position: fixed; bottom: 22px; right: 22px; z-index: 200; display: flex; flex-direction: column; gap: 10px; pointer-events: none; }
.toast {
  background: var(--bg-3); border: 1px solid var(--border-light); border-radius: 10px;
  padding: 11px 15px; display: flex; align-items: center; gap: 10px;
  min-width: 220px; max-width: 360px; font-size: 13px; color: var(--fg);
  box-shadow: var(--toast-shadow, 0 8px 30px rgba(0,0,0,.3)); transform: translateX(120%); opacity: 0;
  transition: all .35s cubic-bezier(.4,0,.2,1); pointer-events: auto;
}
.toast.show { transform: translateX(0); opacity: 1; }
.toast.success { border-left: 3px solid var(--accent); }
.toast.error { border-left: 3px solid var(--danger, #e24b4a); }

footer {
  margin-top: 10px; padding-top: 8px; display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 10px; font-size: 12px; color: var(--fg-3);
  font-family: 'JetBrains Mono', monospace; flex-shrink: 0;
}
footer a { color: var(--fg-2); text-decoration: none; transition: color .15s; }
footer a:hover { color: var(--accent); }

@media (max-width: 1100px) {
  .palette { width: 200px; }
  /* 占位随之收窄，收起态工具条才能对齐 200 + 12 */
  .main { --pal-slot: 212px; --inspector-w: 240px; }
  /* 收起条宽度跟随面板宽度，避免收/展之间横向跳变 */
  .palette.collapsed { width: 200px; }
}
@media (max-width: 860px) {
  .palette, .inspector { display: none; }
  .header-hero { display: none; }
}
