/* ═══════════════════════════════════════
   繁星智绘 · 无限画布（对标 LibTV 节点工作流）
   主题沿用站点 token：黑白极简 + 品牌紫
   ═══════════════════════════════════════ */
:root{
  --bg:#F5F5F7; --card:#FFFFFF; --ink:#1C1C1E; --sub:#6E6E73; --faint:#86868B;
  --brand:#1C1C1E; --brand-light:#F2F2F5; --grad:linear-gradient(135deg,#2E2E33,#48484D);
  --brand-p:#7335F2; --brand-light-p:#F1EBFF; --grad-p:linear-gradient(135deg,#7D5CFF,#B06EFF);
  --line:rgba(0,0,0,.08); --radius:20px;
  --shadow:0 8px 30px rgba(0,0,0,.06);
  --ok:#16A34A; --warn:#F59E0B; --err:#EF4444;
  /* 节点类型色 */
  --c-text:#64748B;   --c-text-bg:#F1F5F9;
  --c-image:#7D5CFF;  --c-image-bg:#F1EBFF;
  --c-video:#0EA5E9;  --c-video-bg:#E0F2FE;
  --c-script:#F59E0B; --c-script-bg:#FEF3C7;
  --c-llm:#10B981;    --c-llm-bg:#D1FAE5;
  --c-upload:#EC4899; --c-upload-bg:#FCE7F3;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{
  font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Noto Sans SC","Microsoft YaHei",sans-serif;
  background:var(--bg); color:var(--ink); -webkit-font-smoothing:antialiased;
  overflow:hidden; /* 画布页整屏，禁用 body 滚动 */
  display:flex; flex-direction:column;   /* 顶栏 + 三栏主体 */
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
input,textarea,select{font-family:inherit;outline:none;color:inherit}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:rgba(0,0,0,.16);border-radius:8px}
::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.28)}
::-webkit-scrollbar-track{background:transparent}

/* ══════════ 顶栏 ══════════ */
.cnv-top{
  height:56px; background:rgba(255,255,255,.9); backdrop-filter:blur(20px);
  -webkit-backdrop-filter:blur(20px); border-bottom:1px solid var(--line);
  display:flex; align-items:center; gap:14px; padding:0 16px; flex:none; z-index:60;
  position:relative;
}
.cnv-back{
  display:flex; align-items:center; gap:6px; font-size:13px; color:var(--sub);
  padding:7px 12px; border-radius:10px; transition:all .18s; white-space:nowrap;
}
.cnv-back:hover{background:var(--brand-light); color:var(--ink)}
.cnv-back svg{width:15px;height:15px}
.cnv-title{
  flex:1; min-width:0; max-width:340px; font-size:14px; font-weight:600;
  padding:8px 12px; border:1px solid transparent; border-radius:10px;
  background:transparent; transition:all .18s;
}
.cnv-title:hover{border-color:var(--line)}
.cnv-title:focus{border-color:var(--brand-p); background:#fff}
.cnv-savestate{font-size:12px; color:var(--faint); white-space:nowrap; min-width:76px}
.cnv-savestate.saving{color:var(--warn)}
.cnv-savestate.saved{color:var(--ok)}
.cnv-savestate.error{color:var(--err)}
.cnv-top-actions{display:flex; align-items:center; gap:8px; margin-left:auto}
.cnv-credits{
  display:flex;align-items:center;gap:5px;background:var(--brand-light);
  padding:0 11px;height:28px;border-radius:14px;font-size:12px;font-weight:600;white-space:nowrap;
}
.cnv-credits svg{width:13px;height:13px}
.btn{
  padding:8px 15px; border-radius:10px; font-size:13px; font-weight:500;
  background:var(--brand-light); color:var(--ink); transition:all .18s; white-space:nowrap;
}
.btn:hover{background:#E5E5EA}
.btn-grad{background:var(--grad); color:#fff}
.btn-grad:hover{opacity:.86}
.btn-purple{background:var(--grad-p); color:#fff}
.btn-purple:hover{opacity:.88}
.btn:disabled{opacity:.45; cursor:not-allowed}
.btn-sm{padding:6px 11px; font-size:12px; border-radius:9px}
.btn-icon{
  width:30px;height:30px;border-radius:9px;display:flex;align-items:center;justify-content:center;
  background:var(--brand-light); transition:all .18s;
}
.btn-icon:hover{background:#E5E5EA}
.btn-icon svg{width:15px;height:15px}

/* ══════════ 主体三栏 ══════════ */
.cnv-body{flex:1; display:flex; min-height:0; position:relative}

/* ── 左侧工具栏 ── */
.cnv-rail{
  width:76px; flex:none; background:rgba(255,255,255,.9); backdrop-filter:blur(20px);
  -webkit-backdrop-filter:blur(20px); border-right:1px solid var(--line);
  display:flex; flex-direction:column; align-items:center; gap:4px; padding:12px 0; z-index:50;
}
.rail-btn{
  width:56px; padding:9px 0; border-radius:12px; display:flex; flex-direction:column;
  align-items:center; gap:4px; font-size:11px; color:var(--sub); transition:all .16s; position:relative;
}
.rail-btn svg{width:19px;height:19px}
.rail-btn:hover{background:var(--brand-light); color:var(--ink)}
.rail-btn.active{background:var(--brand-light-p); color:var(--brand-p); font-weight:600}
.rail-sep{width:34px; height:1px; background:var(--line); margin:7px 0}
.rail-head{font-size:9px; color:var(--sub); letter-spacing:2px; margin:2px 0; opacity:.75; user-select:none}
.rail-tip{
  position:absolute; left:64px; top:50%; transform:translateY(-50%);
  background:var(--ink); color:#fff; font-size:12px; padding:6px 10px; border-radius:8px;
  white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .16s; z-index:70; font-weight:400;
}
.rail-btn:hover .rail-tip{opacity:1}
/* 上传入口：主色高亮，避免被淹没在工具栏里 */
.rail-accent{
  background:var(--brand-light-p); color:var(--brand-p); font-weight:600;
  box-shadow:inset 0 0 0 1px rgba(124,58,237,.18);
}
.rail-accent:hover{background:var(--grad-p); color:#fff}
.rail-accent:hover svg{color:#fff}

/* 顶栏上传按钮：全站唯一的主色实心入口 */
.btn-upload{
  background:var(--grad-p); color:#fff; display:inline-flex; align-items:center; gap:5px;
  font-weight:600; box-shadow:0 2px 8px rgba(124,58,237,.28);
}
.btn-upload:hover{opacity:.9; box-shadow:0 4px 14px rgba(124,58,237,.36)}
.btn-upload svg{color:#fff}

/* 空画布提示里的可点击上传按钮 */
.cnv-hint-btn{
  pointer-events:auto; display:inline-flex; align-items:center; gap:6px;
  padding:9px 18px; border-radius:11px; background:var(--grad-p); color:#fff;
  font-size:13px; font-weight:600; box-shadow:0 4px 16px rgba(124,58,237,.3);
  transition:transform .16s, box-shadow .16s; margin-top:2px;
}
.cnv-hint-btn:hover{transform:translateY(-1px); box-shadow:0 6px 20px rgba(124,58,237,.4)}
.cnv-hint-btn svg{color:#fff}

/* ── 画布视口 ── */
.cnv-viewport{
  flex:1; position:relative; overflow:hidden; background:#FBFBFD; min-width:0;
  cursor:default;
}
.cnv-viewport.panning{cursor:grabbing}
.cnv-viewport.space-ready{cursor:grab}
.cnv-viewport.linking{cursor:crosshair}
/* 网格背景：随视口平移/缩放同步 */
.cnv-grid{
  position:absolute; inset:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(0,0,0,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.045) 1px, transparent 1px);
  background-size:24px 24px;
}
.cnv-world{
  position:absolute; top:0; left:0; width:0; height:0;
  transform-origin:0 0; will-change:transform;
}
/* 节点层：SVG 连线在下，节点在上（DOM 顺序即层叠顺序） */
.cnv-nodes{position:absolute; top:0; left:0; width:0; height:0}
.cnv-edges{position:absolute; top:0; left:0; overflow:visible; pointer-events:none}
.cnv-edges path{fill:none; stroke-linecap:round}
.edge-hit{stroke:transparent; stroke-width:18; pointer-events:stroke; cursor:pointer}
.edge-line{stroke:#B8B8C0; stroke-width:2; pointer-events:none; transition:stroke .16s}
.edge-line.active{stroke:var(--brand-p); stroke-width:2.5}
.edge-line.dim{stroke:#D8D8DE}
.edge-dot{fill:var(--brand-p); pointer-events:none}
.edge-temp{stroke:var(--brand-p); stroke-width:2.5; stroke-dasharray:6 5; pointer-events:none}

/* ── 节点 ── */
.node{
  position:absolute; width:300px; background:var(--card); border-radius:14px;
  box-shadow:0 2px 10px rgba(0,0,0,.07), 0 0 0 1px rgba(0,0,0,.05);
  transition:box-shadow .16s; user-select:none;
}
.node:hover{box-shadow:0 4px 16px rgba(0,0,0,.1), 0 0 0 1px rgba(0,0,0,.08)}
.node.selected{
  box-shadow:0 6px 22px rgba(125,92,255,.22), 0 0 0 2px var(--brand-p);
}
.node.running{box-shadow:0 6px 22px rgba(245,158,11,.26), 0 0 0 2px var(--warn)}
.node.failed{box-shadow:0 6px 22px rgba(239,68,68,.2), 0 0 0 2px var(--err)}
.node-head{
  display:flex; align-items:center; gap:8px; padding:10px 12px;
  border-bottom:1px solid var(--line); cursor:grab; border-radius:14px 14px 0 0;
  background:var(--card);
}
.node.dragging .node-head{cursor:grabbing}
.node-type{
  width:22px;height:22px;border-radius:7px;display:flex;align-items:center;justify-content:center;
  flex:none;
}
.node-type svg{width:13px;height:13px}
/* 标题默认不吃鼠标事件：整条 head 都可拖动节点，双击标题才进入编辑 */
.node-title{
  flex:1; min-width:0; font-size:13px; font-weight:600; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  padding:2px 4px; border-radius:6px; border:1px solid transparent; background:transparent;
  pointer-events:none;
}
.node-title.editing{pointer-events:auto; cursor:text}
.node-title:focus{border-color:var(--line); background:#fff; cursor:text}
.node-badge{
  font-size:10px; font-weight:600; padding:2px 7px; border-radius:6px;
  background:var(--brand-light); color:var(--sub); flex:none;
}
.node-badge.ok{background:#DCFCE7; color:#15803D}
.node-badge.run{background:#FEF3C7; color:#B45309}
.node-badge.err{background:#FEE2E2; color:#B91C1C}
.node-del{
  width:20px;height:20px;border-radius:6px;display:flex;align-items:center;justify-content:center;
  color:var(--faint); flex:none; opacity:0; transition:all .16s;
}
.node:hover .node-del{opacity:1}
.node-del:hover{background:#FEE2E2; color:#DC2626}
.node-del svg{width:12px;height:12px}
.node-body{padding:11px 12px 12px; display:flex; flex-direction:column; gap:9px}

/* 类型配色 */
.node[data-type="text"]   .node-type{background:var(--c-text-bg);  color:var(--c-text)}
.node[data-type="script"] .node-type{background:var(--c-script-bg);color:var(--c-script)}
.node[data-type="image"]  .node-type{background:var(--c-image-bg); color:var(--c-image)}
.node[data-type="video"]  .node-type{background:var(--c-video-bg); color:var(--c-video)}

/* 表单控件 */
.fld{display:flex; flex-direction:column; gap:5px}
.fld-lab{font-size:11px; color:var(--sub); font-weight:500; display:flex; align-items:center; gap:5px}
.fld-lab .auto{
  font-size:10px; background:var(--brand-light-p); color:var(--brand-p);
  padding:1px 6px; border-radius:5px; font-weight:600;
}
.ta{
  width:100%; min-height:66px; resize:vertical; padding:9px 11px; font-size:12.5px; line-height:1.6;
  border:1px solid var(--line); border-radius:10px; background:#FBFBFD; transition:all .16s;
}
.ta:focus{border-color:var(--brand-p); background:#fff; box-shadow:0 0 0 3px rgba(125,92,255,.1)}
.ta.locked{background:#F7F7FA; color:var(--sub); cursor:not-allowed}
.row{display:flex; gap:8px}
.row>*{flex:1; min-width:0}
select.sel, input.inp{
  width:100%; padding:7px 9px; font-size:12px; border:1px solid var(--line);
  border-radius:9px; background:#FBFBFD; transition:all .16s; cursor:pointer;
}
input.inp{cursor:text}
select.sel:focus, input.inp:focus{border-color:var(--brand-p); background:#fff}
.gen-btn{
  width:100%; padding:10px; border-radius:10px; font-size:13px; font-weight:600;
  background:var(--grad-p); color:#fff; transition:all .18s;
  display:flex; align-items:center; justify-content:center; gap:6px;
}
.gen-btn:hover{opacity:.88}
.gen-btn:disabled{opacity:.5; cursor:not-allowed}
.gen-btn .spin{
  width:13px;height:13px;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  border-radius:50%; animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
.cost-hint{font-size:11px; color:var(--faint); text-align:center}
.cost-hint b{color:var(--brand-p); font-weight:600}

/* 结果区 */
.res{
  border:1px solid var(--line); border-radius:10px; overflow:hidden; background:#FAFAFC;
  position:relative;
}
.res-img-wrap{display:grid; gap:2px; background:var(--line)}
.res-img-wrap.n1{grid-template-columns:1fr}
.res-img-wrap.n2{grid-template-columns:1fr 1fr}
.res-img-wrap.n3, .res-img-wrap.n4{grid-template-columns:1fr 1fr}
.res-img{
  width:100%; aspect-ratio:1/1; object-fit:cover; display:block; background:#EEEEF2; cursor:zoom-in;
}
.res-img:hover{opacity:.92}
.res-video{width:100%; display:block; background:#000; max-height:220px}
.res-bar{
  display:flex; align-items:center; gap:6px; padding:6px 8px; border-top:1px solid var(--line);
  background:#fff;
}
.res-bar .sp{flex:1}
.res-act{
  font-size:11px; padding:4px 9px; border-radius:7px; background:var(--brand-light);
  color:var(--ink); transition:all .16s; white-space:nowrap;
}
.res-act:hover{background:#E5E5EA}
.res-act.p{background:var(--brand-light-p); color:var(--brand-p)}
.res-act.p:hover{background:#E4D9FF}
.prog{height:3px; background:var(--line); border-radius:2px; overflow:hidden}
.prog i{display:block; height:100%; background:var(--grad-p); border-radius:2px; transition:width .4s}
.err-box{
  font-size:11.5px; line-height:1.6; color:#B91C1C; background:#FEF2F2;
  border:1px solid #FECACA; border-radius:9px; padding:8px 10px; word-break:break-word;
}
.empty-res{
  font-size:12px; color:var(--faint); text-align:center; padding:22px 10px; line-height:1.7;
  border:1px dashed var(--line); border-radius:10px;
}
.empty-res svg{width:26px;height:26px;opacity:.35;margin-bottom:6px}
.empty-res .spin{
  width:16px;height:16px;border:2px solid var(--line);border-top-color:var(--brand-p);
  border-radius:50%; animation:spin .7s linear infinite;
}

/* 对话节点 */
.ta-sm{min-height:48px; font-size:12px}
.gen-btn.llm{background:linear-gradient(135deg,#10B981,#34D399)}
.upstream-peek{
  margin-top:6px; padding:7px 9px; border-radius:8px; background:#F4FBF7;
  border:1px dashed #A7F3D0; font-size:11px; line-height:1.6; color:#6B7280;
  max-height:64px; overflow:hidden; word-break:break-word;
}
.reply-box{
  padding:10px 11px; font-size:12px; line-height:1.7; color:var(--ink);
  background:#fff; max-height:190px; overflow:auto; white-space:pre-wrap; word-break:break-word;
}
.reply-box::-webkit-scrollbar{width:6px}
.reply-box::-webkit-scrollbar-thumb{background:var(--line); border-radius:3px}

/* 本地素材节点（图片 / 视频 / 音频） */
.node[data-type="upload"] .node-type{background:var(--c-upload-bg); color:var(--c-upload)}
.up-zone{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding:24px 12px; text-align:center; cursor:pointer;
  border:1.5px dashed #F9A8D4; border-radius:11px; background:#FFF7FB; transition:all .18s;
}
.up-zone:hover{background:#FDF2F8; border-color:var(--c-upload)}
.up-zone svg{width:30px; height:30px; color:var(--c-upload); opacity:.75; margin-bottom:8px}
.up-zone.busy{cursor:default; background:#FFF7FB}
/* 视频 / 音频节点的拖拽区按类型着色 */
.node[data-type="uploadv"] .up-zone{border-color:#7DD3FC; background:#F0F9FF}
.node[data-type="uploadv"] .up-zone svg{color:#0284C7}
.node[data-type="uploadv"] .up-zone:hover{background:#E0F2FE; border-color:#38BDF8}
.node[data-type="uploada"] .up-zone{border-color:#5EEAD4; background:#F0FDFA}
.node[data-type="uploada"] .up-zone svg{color:#0D9488}
.node[data-type="uploada"] .up-zone:hover{background:#CCFBF1; border-color:#2DD4BF}
.up-zone .spin{
  width:18px; height:18px; border:2px solid #FBCFE8; border-top-color:var(--c-upload);
  border-radius:50%; animation:spin .7s linear infinite;
}
.up-list{
  display:flex; flex-direction:column; gap:6px;
  border:1px solid var(--line); border-radius:10px; padding:6px; background:#FAFAFC;
}
.up-item{display:flex; align-items:center; gap:9px; padding:4px; border-radius:8px; transition:background .16s}
.up-item:hover{background:#F2F2F5}
.up-thumb{
  width:42px; height:42px; flex:none; object-fit:cover; border-radius:7px;
  background:#EEEEF2; cursor:zoom-in; border:1px solid var(--line);
}
.up-thumb:hover{opacity:.9}
.up-meta{flex:1; min-width:0}
.up-name{
  font-size:12px; font-weight:500; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.up-size{font-size:10.5px; color:var(--faint); margin-top:1px}
.up-del{
  width:22px; height:22px; flex:none; border-radius:6px; display:flex;
  align-items:center; justify-content:center; color:var(--faint); transition:all .16s;
}
/* 占位预览：文件刚拖进来、服务端还没返回时的本地 blob 预览 */
.up-item.pending{opacity:.62; position:relative}
.up-pending{
  position:absolute; top:6px; right:26px; display:flex; align-items:center; gap:4px;
  padding:2px 7px; border-radius:20px; background:rgba(17,17,26,.82); color:#fff;
  font-size:10px; font-weight:600; white-space:nowrap; pointer-events:none;
}
.up-pending .spin{
  width:9px; height:9px; border:1.6px solid rgba(255,255,255,.35); border-top-color:#fff;
  border-radius:50%; animation:spin .7s linear infinite;
}
/* 视频节点：参考视频 / 参考音频投放区 */
.ref-drop.drop-in{outline:2.5px dashed #0EA5E9; outline-offset:2px; background:#F0F9FF; border-radius:9px}
.ref-drop.drop-bad{outline:2.5px dashed #EF4444; outline-offset:2px; background:#FEF2F2; border-radius:9px}
.ref-list{display:flex; flex-direction:column; gap:5px}
.ref-linked{
  font-size:11.5px; color:var(--sub); background:var(--brand-light);
  border:1px dashed var(--line); border-radius:8px; padding:7px 9px;
}
.ref-warn{
  font-size:11.5px; color:#B91C1C; background:#FEF2F2;
  border:1px solid #FECACA; border-radius:8px; padding:7px 9px; line-height:1.5;
}
.ref-item{display:flex; align-items:center; gap:8px; padding:4px; border-radius:8px; transition:background .16s}
.ref-item:hover{background:#F2F2F5}
.ref-thumb{
  width:44px; height:44px; flex:0 0 44px; border-radius:7px; object-fit:cover;
  background:#0F172A; border:1px solid var(--line);
}
.ref-thumb.aud{
  display:flex; align-items:center; justify-content:center;
  background:#F0FDFA; color:#14B8A6; border-color:#99F6E4;
}
.ref-thumb.aud svg{width:20px; height:20px}

.up-del:hover{background:#FEE2E2; color:#DC2626}
.up-del svg{width:11px; height:11px}

/* 拖拽反馈 */
.node.drop-in{box-shadow:0 0 0 2.5px var(--c-upload), 0 10px 34px rgba(236,72,153,.22)}
.node.drop-in .up-zone{background:#FDF2F8; border-color:var(--c-upload)}
/* 拖入的文件类型与当前节点不一致 → 将在旁边新建对应类型的节点 */
.node.drop-new{box-shadow:0 0 0 2.5px #7D5CFF, 0 10px 34px rgba(125,92,255,.2)}
.node.drop-new .up-zone{background:#F5F1FF; border-color:#7D5CFF}
.cnv-viewport.drop-canvas::after{
  content:"松开鼠标，自动创建素材节点";
  position:absolute; inset:14px; z-index:40; pointer-events:none;
  display:flex; align-items:center; justify-content:center;
  font-size:14px; font-weight:600; color:var(--c-upload);
  border:2.5px dashed var(--c-upload); border-radius:16px;
  background:rgba(253,242,248,.72); backdrop-filter:blur(2px);
}

/* 视频 / 音频节点：播放器预览 */
.media-item{flex-wrap:wrap; row-gap:5px; padding:6px}
.media-prev{
  flex:0 0 100%; width:100%; height:124px; display:block;
  background:#000; border-radius:8px; object-fit:contain;
}
.audio-thumb{
  width:42px; height:42px; flex:none; border-radius:7px; display:flex;
  align-items:center; justify-content:center;
  background:#CCFBF1; color:#0F766E; border:1px solid #99F6E4;
}
.audio-thumb svg{width:20px; height:20px}
.media-audio{
  flex:0 0 100%; width:100%; height:32px; display:block; margin-top:1px;
}

/* 顶栏「上传素材」下拉 */
.up-menu{min-width:196px}
.up-menu-tip{
  padding:8px 11px 4px; margin-top:4px; border-top:1px solid var(--line);
  font-size:11px; color:var(--faint); text-align:center;
}

/* 端口 */
.port{
  position:absolute; width:13px; height:13px; border-radius:50%;
  background:#fff; border:2.5px solid #B8B8C0; top:22px; transition:all .16s; z-index:3;
}
.port:hover{transform:scale(1.3); border-color:var(--brand-p)}
.port.in{left:-7px}
.port.out{right:-7px}
.port.connected{border-color:var(--brand-p); background:var(--brand-p)}
.port.hot{border-color:var(--brand-p); background:var(--brand-p); transform:scale(1.35)}
.port.drop-ok{border-color:var(--ok); background:var(--ok); transform:scale(1.35)}
.port.drop-bad{border-color:var(--err); background:var(--err); transform:scale(1.2)}
.node.linked-in .port.in.hot{border-color:var(--ok); background:var(--ok)}

/* 脚本节点 */
.script-scenes{display:flex; flex-direction:column; gap:6px}
.scene{
  display:flex; gap:7px; align-items:flex-start; font-size:12px; line-height:1.6;
  padding:7px 9px; background:#FFFBEB; border:1px solid #FDE68A; border-radius:8px;
}
.scene i{
  font-style:normal; font-size:10px; font-weight:700; color:#B45309; background:#FDE68A;
  padding:1px 6px; border-radius:5px; flex:none; margin-top:1px;
}
.scene span{flex:1; word-break:break-word}
.scene-pick{
  font-size:10px; padding:2px 7px; border-radius:5px; background:#FDE68A; color:#92400E;
  flex:none; transition:all .16s;
}
.scene-pick:hover{background:#FCD34D}

/* ── 右侧属性面板 ── */
.cnv-panel{
  width:284px; flex:none; background:rgba(255,255,255,.94); backdrop-filter:blur(20px);
  -webkit-backdrop-filter:blur(20px); border-left:1px solid var(--line);
  display:flex; flex-direction:column; z-index:50; overflow:hidden;
}
.panel-head{
  padding:13px 15px; border-bottom:1px solid var(--line); display:flex;
  align-items:center; justify-content:space-between; flex:none;
}
.panel-head h3{font-size:13px; font-weight:600}
.panel-body{flex:1; overflow-y:auto; padding:14px 15px}
.panel-empty{
  flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:9px; padding:28px 18px; text-align:center; color:var(--faint); font-size:12.5px; line-height:1.7;
}
.panel-empty svg{width:32px;height:32px;opacity:.3}
.hint-list{text-align:left; font-size:12px; line-height:2; color:var(--sub); width:100%}
.hint-list b{color:var(--ink); font-weight:600}
.kbd{
  display:inline-block; padding:1px 6px; border:1px solid var(--line); border-radius:5px;
  background:var(--brand-light); font-size:11px; font-family:ui-monospace,Menlo,monospace;
}

/* ── 底部控制条 ── */
.cnv-bottom{
  position:absolute; left:88px; bottom:16px; display:flex; align-items:center; gap:6px;
  background:rgba(255,255,255,.94); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border:1px solid var(--line); border-radius:12px; padding:5px 7px; box-shadow:var(--shadow); z-index:40;
}
.zoom-val{
  font-size:12px; font-weight:600; min-width:44px; text-align:center; color:var(--sub);
  font-variant-numeric:tabular-nums;
}
.cnv-mini{
  position:absolute; right:298px; bottom:16px; width:172px; height:112px;
  background:rgba(255,255,255,.94); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border:1px solid var(--line); border-radius:11px; overflow:hidden; box-shadow:var(--shadow); z-index:40;
}
.cnv-mini canvas{width:100%; height:100%; display:block; cursor:pointer}

/* ── 画布内空态提示 ── */
.cnv-hint{
  position:absolute; inset:0; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:10px; pointer-events:none; color:var(--faint);
  font-size:14px; text-align:center; line-height:1.8;
}
.cnv-hint svg{width:44px;height:44px;opacity:.25}

/* ── 双击建节点的浮层菜单 ── */
.node-menu{
  position:fixed; z-index:200; background:#fff; border:1px solid var(--line);
  border-radius:13px; box-shadow:0 12px 40px rgba(0,0,0,.16); padding:6px; min-width:184px;
  animation:menuIn .14s ease;
}
@keyframes menuIn{from{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:none}}
.node-menu .mi{
  display:flex; align-items:center; gap:9px; width:100%; padding:9px 11px; border-radius:9px;
  font-size:13px; transition:background .14s; text-align:left;
}
.node-menu .mi:hover{background:var(--brand-light)}
.node-menu .mi .ic{
  width:24px;height:24px;border-radius:7px;display:flex;align-items:center;justify-content:center;flex:none;
}
.node-menu .mi .ic svg{width:14px;height:14px}
.node-menu .mi small{display:block; font-size:11px; color:var(--faint); font-weight:400; margin-top:1px}

/* ── 项目列表抽屉 ── */
.drawer-mask{
  position:fixed; inset:0; background:rgba(0,0,0,.32); z-index:300;
  animation:fadeIn .18s ease; display:flex; justify-content:flex-end;
}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.drawer{
  width:430px; max-width:92vw; background:#fff; height:100%; display:flex;
  flex-direction:column; animation:slideIn .22s cubic-bezier(.32,.72,0,1);
}
@keyframes slideIn{from{transform:translateX(100%)}to{transform:none}}
.drawer-head{
  padding:16px 18px; border-bottom:1px solid var(--line); display:flex;
  align-items:center; justify-content:space-between; flex:none;
}
.drawer-head h3{font-size:15px; font-weight:600}
.drawer-body{flex:1; overflow-y:auto; padding:12px 14px; display:flex; flex-direction:column; gap:9px}
.proj-card{
  display:flex; gap:11px; padding:11px; border:1px solid var(--line); border-radius:12px;
  transition:all .16s; cursor:pointer; align-items:center;
}
.proj-card:hover{border-color:var(--brand-p); background:#FCFAFF}
.proj-card.cur{border-color:var(--brand-p); background:var(--brand-light-p)}
.proj-thumb{
  width:60px;height:60px;border-radius:9px;background:var(--brand-light);flex:none;
  display:flex;align-items:center;justify-content:center;overflow:hidden;color:var(--faint);
}
.proj-thumb img{width:100%;height:100%;object-fit:cover}
.proj-thumb svg{width:20px;height:20px;opacity:.4}
.proj-meta{flex:1; min-width:0}
.proj-meta .t{font-size:13.5px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.proj-meta .d{font-size:11.5px; color:var(--faint); margin-top:3px}
.proj-acts{display:flex; gap:5px; flex:none}
.drawer-foot{padding:13px 16px; border-top:1px solid var(--line); flex:none}

/* ── Toast / 图片灯箱 ── */
#toast{
  position:fixed; left:50%; bottom:40px; transform:translateX(-50%) translateY(20px);
  background:var(--ink); color:#fff; padding:11px 20px; border-radius:11px; font-size:13.5px;
  opacity:0; pointer-events:none; transition:all .26s; z-index:9999; max-width:80vw; text-align:center;
}
#toast.show{opacity:1; transform:translateX(-50%) translateY(0)}
.lightbox{
  position:fixed; inset:0; background:rgba(0,0,0,.9); z-index:9998; display:flex;
  align-items:center; justify-content:center; cursor:zoom-out; padding:40px;
}
.lightbox img{max-width:100%; max-height:100%; object-fit:contain; border-radius:8px}
.lightbox .lb-act{
  position:absolute; bottom:26px; left:50%; transform:translateX(-50%); display:flex; gap:10px;
}
.lightbox .lb-act button{
  background:rgba(255,255,255,.16); color:#fff; padding:9px 18px; border-radius:10px;
  font-size:13px; backdrop-filter:blur(10px);
}
.lightbox .lb-act button:hover{background:rgba(255,255,255,.28)}

@media(max-width:1180px){
  .cnv-mini{display:none}
  .cnv-panel{width:250px}
}
@media(max-width:820px){
  .cnv-rail{width:60px}
  .rail-btn{width:46px; font-size:10px}
  .cnv-panel{display:none}
  .cnv-bottom{left:70px}
}
