:root { --bg:#090b0d; --panel:#101316; --line:#2a3036; --text:#eff2ed; --muted:#899199; --dim:#596168; --acid:#c8ff31; --cyan:#63d8ff; --danger:#ff6577; --shadow:0 18px 55px rgba(0,0,0,.38); color-scheme:dark; }
* { box-sizing:border-box; } html,body { margin:0; min-height:100%; background:var(--bg); color:var(--text); font-family:Inter,ui-sans-serif,system-ui,"Microsoft YaHei",sans-serif; } body { height:100vh; overflow:hidden; display:grid; grid-template-rows:58px minmax(0,1fr) 176px; } button,input,textarea,select { font:inherit; }
.canvas-topbar { display:flex; align-items:center; gap:9px; padding:8px 14px; border-bottom:1px solid var(--line); background:rgba(10,12,14,.97); z-index:20; }.canvas-brand { display:flex; align-items:center; gap:9px; min-width:190px; color:var(--text); text-decoration:none; }.canvas-brand b { display:block; font-size:11px; letter-spacing:.11em; }.canvas-brand small { display:block; color:var(--dim); font-size:7px; letter-spacing:.15em; margin-top:2px; }.brand-grid { width:27px; height:27px; display:grid; grid-template-columns:1fr 1fr; gap:2px; transform:rotate(45deg); }.brand-grid i { border:1px solid var(--acid); }.brand-grid i:first-child { background:var(--acid); }
.canvas-picker { display:flex; align-items:center; gap:7px; margin-right:auto; }.canvas-picker span { color:var(--dim); font-size:8px; letter-spacing:.1em; }.canvas-picker select { min-width:220px; max-width:360px; border:1px solid var(--line); border-radius:7px; background:#0c0f11; color:var(--text); padding:7px 30px 7px 9px; }.button,.icon-button { min-height:34px; border:1px solid var(--line); border-radius:7px; background:#12161a; color:var(--muted); padding:7px 11px; text-decoration:none; font-size:9px; cursor:pointer; white-space:nowrap; }.button:hover,.icon-button:hover { border-color:#48515a; color:var(--text); }.button.primary { color:#101407; background:var(--acid); border-color:var(--acid); font-weight:800; }.icon-button { width:34px; padding:0; font-size:15px; }.save-state { display:flex; align-items:center; gap:6px; color:var(--dim); font-size:8px; }.save-state i { width:6px; height:6px; border-radius:50%; background:var(--acid); box-shadow:0 0 10px var(--acid); }.save-state.saving i { background:var(--cyan); }.save-state.error i { background:var(--danger); }
.canvas-shell { min-height:0; display:grid; grid-template-columns:198px minmax(0,1fr) 278px; }.node-palette,.inspector { min-width:0; background:var(--panel); z-index:5; overflow:auto; }.node-palette { border-right:1px solid var(--line); }.inspector { border-left:1px solid var(--line); }.panel-heading,.dock-heading { min-height:52px; display:flex; align-items:center; gap:7px; padding:11px 13px; border-bottom:1px solid var(--line); }.panel-heading span,.dock-heading span { color:var(--acid); font:7px ui-monospace,monospace; letter-spacing:.15em; }.panel-heading strong,.dock-heading strong { font-size:10px; }.dock-heading i { margin-left:auto; color:var(--dim); font:7px ui-monospace,monospace; }
.node-buttons { padding:8px; display:grid; gap:5px; }.node-buttons button { display:grid; grid-template-columns:31px 1fr; align-items:center; gap:8px; width:100%; border:1px solid transparent; border-radius:8px; background:transparent; color:var(--text); padding:8px; text-align:left; cursor:pointer; }.node-buttons button:hover { border-color:var(--line); background:rgba(255,255,255,.025); }.node-buttons i { width:31px; height:31px; display:grid; place-items:center; border:1px solid var(--line); border-radius:7px; color:var(--cyan); font-style:normal; font-size:9px; }.node-buttons strong { display:block; font-size:9px; }.node-buttons small { display:block; margin-top:3px; color:var(--dim); font-size:7px; }.connection-help { margin:8px; padding:10px; border-top:1px solid var(--line); color:var(--dim); font-size:8px; line-height:1.55; }.connection-help span { color:var(--muted); }.connection-help p { margin:6px 0 9px; }.connection-help div { padding:7px; border-radius:6px; background:#0b0e10; color:var(--cyan); }
.canvas-viewport { position:relative; min-width:0; overflow:hidden; cursor:grab; background-color:#0b0e11; background-image:radial-gradient(circle,rgba(170,185,195,.19) 1px,transparent 1px); background-size:22px 22px; }.canvas-viewport.panning { cursor:grabbing; }.canvas-world { position:absolute; inset:0; transform-origin:0 0; will-change:transform; }.edge-layer { position:absolute; inset:0; width:100%; height:100%; pointer-events:none; z-index:1; overflow:visible; }.edge-path { fill:none; stroke:#53606a; stroke-width:1.4; }.edge-path.active { stroke:var(--cyan); stroke-width:2; filter:drop-shadow(0 0 4px rgba(99,216,255,.35)); }
.flow-node { position:absolute; z-index:2; border:1px solid #343b42; border-radius:10px; background:rgba(17,21,24,.98); box-shadow:var(--shadow); overflow:visible; user-select:none; }.flow-node.selected { border-color:var(--acid); box-shadow:0 0 0 1px rgba(200,255,49,.13),var(--shadow); }.flow-node.connectable { border-color:var(--cyan); }.flow-node.group { z-index:0; background:rgba(99,216,255,.025); border-style:dashed; box-shadow:none; }.node-header { height:38px; display:flex; align-items:center; gap:7px; padding:7px 10px; border-bottom:1px solid var(--line); cursor:move; }.node-kind { width:22px; height:22px; display:grid; place-items:center; border-radius:5px; background:rgba(99,216,255,.1); color:var(--cyan); font-size:8px; }.node-header strong { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:9px; }.node-header small { margin-left:auto; color:var(--dim); font:7px ui-monospace,monospace; }.node-body { height:calc(100% - 38px); padding:10px; overflow:hidden; color:var(--muted); font-size:8px; line-height:1.55; }.node-body p { margin:0; display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical; overflow:hidden; white-space:pre-line; }.node-body footer { position:absolute; left:10px; right:10px; bottom:8px; display:flex; justify-content:space-between; color:var(--dim); font:7px ui-monospace,monospace; }.port { position:absolute; top:50%; width:13px; height:13px; padding:0; border:2px solid #0b0e11; border-radius:50%; background:#77838d; transform:translateY(-50%); cursor:crosshair; z-index:5; }.port.input { left:-7px; }.port.output { right:-7px; background:var(--cyan); }.port:hover,.port.pending { box-shadow:0 0 0 4px rgba(99,216,255,.16); }.port:disabled { opacity:.2; cursor:not-allowed; }.viewport-hud,.canvas-hint { position:absolute; z-index:4; border:1px solid var(--line); background:rgba(10,13,15,.86); color:var(--dim); font:7px ui-monospace,monospace; }.viewport-hud { left:12px; bottom:12px; display:flex; gap:12px; padding:7px 9px; }.canvas-hint { right:12px; bottom:12px; padding:7px 9px; }
.inspector-content { padding:11px; }.empty-inspector { padding:50px 15px; color:var(--dim); text-align:center; font-size:9px; line-height:1.6; }.node-form { display:grid; gap:10px; }.node-form .type-label { display:flex; justify-content:space-between; padding:8px; border:1px solid var(--line); color:var(--cyan); font:8px ui-monospace,monospace; }.node-form label { display:grid; gap:5px; }.node-form label span { color:var(--dim); font-size:7px; letter-spacing:.08em; }.node-form input,.node-form textarea,.node-form select { width:100%; border:1px solid var(--line); border-radius:6px; outline:0; background:#0b0e11; color:var(--text); padding:8px; font-size:9px; resize:vertical; }.node-form input:focus,.node-form textarea:focus,.node-form select:focus { border-color:#4a565f; }.form-row { display:grid; grid-template-columns:1fr 1fr; gap:7px; }.inspector-actions { display:grid; grid-template-columns:1fr 1fr; gap:6px; margin-top:5px; }.danger-button { color:var(--danger); border-color:rgba(255,101,119,.25); }
.bottom-dock { min-height:0; display:grid; grid-template-columns:.9fr 1.2fr 1fr; border-top:1px solid var(--line); background:#0d1012; }.dock-panel { min-width:0; overflow:hidden; border-right:1px solid var(--line); }.dock-panel:last-child { border-right:0; }.dock-heading { min-height:38px; padding:7px 11px; }.dock-list { height:137px; overflow:auto; padding:5px 8px; }.dock-empty { padding:20px; text-align:center; color:var(--dim); font-size:8px; }.dock-item { display:grid; grid-template-columns:auto 1fr auto; gap:8px; align-items:center; padding:7px; border-bottom:1px solid rgba(42,48,54,.65); }.dock-item .badge { min-width:44px; color:var(--cyan); font:7px ui-monospace,monospace; }.dock-item strong { display:block; font-size:8px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }.dock-item small { display:block; margin-top:2px; color:var(--dim); font-size:7px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }.dock-item button { border:0; background:transparent; color:var(--muted); font-size:7px; cursor:pointer; }.dock-item button:hover { color:var(--acid); }.status-failed { color:var(--danger)!important; }.status-submitted { color:var(--acid)!important; }.status-ready { color:#ffc95f!important; }.toast { position:fixed; left:50%; bottom:190px; z-index:50; transform:translate(-50%,15px); opacity:0; pointer-events:none; border:1px solid var(--line); border-radius:8px; background:#161a1d; padding:10px 15px; color:var(--text); font-size:9px; box-shadow:var(--shadow); transition:.2s; }.toast.show { opacity:1; transform:translate(-50%,0); }.toast.error { border-color:rgba(255,101,119,.45); color:#ffabb5; }
@media (max-width:1000px) { .canvas-shell { grid-template-columns:170px minmax(0,1fr); }.inspector { position:fixed; top:58px; right:0; bottom:176px; width:280px; transform:translateX(calc(100% - 3px)); transition:.2s; }.inspector:hover,.inspector:focus-within { transform:none; }.canvas-topbar .button:not(.primary),.save-state { display:none; } }

/* 端口磁吸与线段断开交互 */
.edge-group { pointer-events:none; }
.edge-hit { fill:none; stroke:transparent; stroke-width:18; pointer-events:stroke; cursor:crosshair; }
.edge-cut { opacity:0; pointer-events:all; cursor:pointer; transition:opacity .14s ease; }
.edge-group:hover .edge-cut,.edge-cut:focus { opacity:1; outline:0; }
.edge-cut circle { fill:#12171b; stroke:var(--cyan); stroke-width:1.5; }
.edge-cut text { fill:var(--cyan); font:700 16px system-ui,sans-serif; text-anchor:middle; dominant-baseline:middle; }
.edge-preview { fill:none; stroke:var(--acid); stroke-width:2; stroke-dasharray:6 5; opacity:.9; pointer-events:none; filter:drop-shadow(0 0 4px rgba(200,255,49,.25)); }
.port { width:28px; height:28px; padding:0; border:0; background:transparent; appearance:none; }
.port::before { content:""; position:absolute; inset:6px; border:2px solid #77838d; border-radius:50%; background:#11161a; transition:transform .14s ease, border-color .14s ease, box-shadow .14s ease; }
.port::after { content:"+"; position:absolute; inset:0; display:grid; place-items:center; color:#a9b4ba; font:700 13px/1 system-ui,sans-serif; opacity:.86; }
.port.input { left:-14px; }.port.output { right:-14px; background:transparent; }.port.output::before { border-color:var(--cyan); }
.port:hover::before,.port.pending::before,.port.snap::before { transform:scale(1.18); border-color:var(--acid); box-shadow:0 0 0 4px rgba(200,255,49,.15),0 0 12px rgba(200,255,49,.35); }
.port:hover::after,.port.pending::after,.port.snap::after { color:var(--acid); }.port:disabled { opacity:.2; cursor:not-allowed; }.port:disabled::before { transform:none; box-shadow:none; }

/* Xcine 风格的操控节奏与轻量动效 */
.hidden { display:none!important; }
.canvas-viewport.space-pan { cursor:grab; }.canvas-viewport.space-pan.panning { cursor:grabbing; }
.flow-node { transform-origin:center; transition:border-color .16s ease,box-shadow .18s ease,filter .18s ease,transform .16s cubic-bezier(.2,.8,.2,1); }
.flow-node:hover { border-color:#46515a; filter:brightness(1.035); }.flow-node.selected { transform:translateY(-1px); }.flow-node.dragging { z-index:8; cursor:grabbing; transform:scale(1.012); transition:none; box-shadow:0 24px 70px rgba(0,0,0,.5),0 0 0 1px rgba(200,255,49,.22); }
.node-header:active { cursor:grabbing; }
.edge-path { stroke-linecap:round; stroke-linejoin:round; transition:stroke .15s ease,stroke-width .15s ease,opacity .15s ease; }
.edge-group:hover .edge-path { stroke:var(--cyan); stroke-width:2.2; filter:drop-shadow(0 0 5px rgba(99,216,255,.35)); }
.edge-cut { transform-box:fill-box; transform-origin:center; }.edge-group:hover .edge-cut { animation:cut-pop .18s cubic-bezier(.2,.9,.25,1.2) both; }
.edge-cut .scissor-icon { fill:none; stroke:var(--cyan); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; }
.edge-new .edge-path { stroke:var(--acid); stroke-width:2.2; stroke-dasharray:9 7; animation:edge-arrive .52s ease-out both; }
.edge-preview { stroke-dasharray:8 7; animation:edge-flow .65s linear infinite; }
.edge-preview-head { fill:#11161a; stroke:var(--acid); stroke-width:2; transition:r .14s ease,filter .14s ease; }.edge-preview-head.snapped { r:6px; filter:drop-shadow(0 0 6px rgba(200,255,49,.8)); }
.quick-node-menu { position:absolute; z-index:15; width:218px; max-height:330px; overflow:auto; padding:7px; border:1px solid #374149; border-radius:11px; background:rgba(17,21,24,.97); box-shadow:0 24px 70px rgba(0,0,0,.48); backdrop-filter:blur(16px); animation:menu-in .16s cubic-bezier(.2,.85,.25,1) both; }
.quick-node-menu header { display:flex; justify-content:space-between; align-items:center; padding:5px 7px 8px; color:var(--muted); font-size:8px; }.quick-node-menu kbd { border:1px solid var(--line); border-radius:4px; padding:2px 4px; color:var(--dim); font:7px ui-monospace,monospace; }
.quick-node-menu button { width:100%; display:grid; grid-template-columns:28px 1fr; align-items:center; gap:8px; border:0; border-radius:7px; background:transparent; color:var(--text); padding:7px; text-align:left; cursor:pointer; }.quick-node-menu button:hover,.quick-node-menu button:focus { outline:0; background:rgba(99,216,255,.08); }.quick-node-menu button i { width:27px; height:27px; display:grid; place-items:center; border:1px solid #34414a; border-radius:6px; color:var(--cyan); font-style:normal; font-size:8px; }.quick-node-menu strong { display:block; font-size:9px; }.quick-node-menu small { display:block; margin-top:2px; color:var(--dim); font-size:7px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
@keyframes edge-flow { to { stroke-dashoffset:-30; } }
@keyframes edge-arrive { 0% { stroke-dashoffset:38; opacity:.15; } 100% { stroke-dashoffset:0; opacity:1; } }
@keyframes cut-pop { 0% { opacity:0; transform:scale(.65); } 100% { opacity:1; transform:scale(1); } }
@keyframes menu-in { 0% { opacity:0; transform:translateY(6px) scale(.97); } 100% { opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce) { .flow-node,.edge-path,.edge-cut,.quick-node-menu { transition:none!important; animation:none!important; }.edge-preview,.edge-new .edge-path { animation:none!important; } }
