/* ============================================================
   node.css — 新拟态 (Soft UI) 节点设计系统 2026
   ============================================================ */

/* === 1. 节点基础外壳 === */
.node {
    position: absolute;
    --node-type-color: var(--type-text);
    --node-radius: var(--node-shell-radius);
    --node-padding: 14px;
    --node-gap: 10px;
    background: var(--node-shell-bg);
    border: var(--node-shell-border);
    border-radius: var(--node-radius);
    box-shadow: var(--node-shell-shadow);
    padding: 0;
    cursor: move;
    transition: box-shadow var(--duration-normal) var(--ease-out),
                transform var(--duration-normal) var(--ease-out);
    z-index: 10;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    overflow: visible;
}
.node:hover, .node:focus-within { z-index: 40; }
.node:hover {
    box-shadow: var(--node-shell-hover-shadow);
    transform: var(--node-shell-hover-transform);
}
.node.model-dropdown-open { z-index: 120; }
.node-type-group {
    z-index: 1 !important;
    background: transparent;
    border: none;
    box-shadow: none;
    cursor: move;
}
.node-type-group:hover,
.node-type-group.selected {
    z-index: 2 !important;
    transform: none;
    box-shadow: none;
}
.node-type-group.selected {
    border-color: transparent;
}

.node.selected {
    border-color: var(--node-selected-border);
    box-shadow: var(--node-selected-shadow);
    transform: var(--node-selected-transform);
}
.node.node-health-issue {
    border-color: var(--danger) !important;
    box-shadow: var(--neu-shadow), 0 0 0 3px color-mix(in srgb, var(--danger) 18%, transparent) !important;
}
.node-health-overlay {
    position: absolute;
    inset: 0;
    z-index: 18;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 14px;
    border-radius: inherit;
    background: var(--node-health-bg);
    color: var(--node-health-text);
    text-align: center;
    pointer-events: none;
    box-sizing: border-box;
}
.node-health-overlay strong { font-size: 14px; letter-spacing: 0.03em; }
.node-health-overlay span { max-width: 90%; font-size: 12px; line-height: 1.45; word-break: break-word; }

/* 统一选中状态 */
.node-type-img.selected,
.node-type-image.selected,
.node-type-preview.selected,
.node-type-compare.selected {
    border-color: var(--accent) !important;
}

/* 节点内框架 */
.node-frame {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--node-gap);
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    padding: var(--node-padding);
    border-radius: inherit;
    background: transparent;
    box-sizing: border-box;
    overflow: hidden;
}
.node-frame > * { position: relative; z-index: 1; }
.node-frame-body {
    display: flex;
    flex-direction: column;
    gap: var(--node-gap);
    min-width: 0;
    min-height: 0;
    flex: 1 1 auto;
}

/* 节点类型色彩条 — 顶部 3px 色带 */
.node-frame::before {
    content: '';
    position: absolute;
    top: 0; left: 12px; right: 12px;
    height: var(--node-stripe-height);
    border-radius: var(--node-stripe-radius);
    background: var(--node-type-color);
    opacity: 0.85;
    pointer-events: none;
    z-index: 2;
}

/* 各类型节点色彩 */
.node-frame-input { --node-type-color: var(--type-ai); }
.node-frame-doubao { --node-type-color: var(--type-ai); }
.node-frame-chat { --node-type-color: var(--type-chat); }
.node-frame-text { --node-type-color: var(--type-text); }
.node-frame-tip { --node-type-color: var(--type-compare); }
.node-frame-control { --node-type-color: var(--type-parallel); }
.node-frame-media { --node-type-color: var(--type-preview); }
.node-frame-compare { --node-type-color: var(--type-compare); }

/* 图片处理节点 token 默认值：放在 :root，确保外挂主题可通过 html[data-theme] 覆盖。 */
:root {
    --processor-accent: var(--type-image-processor, var(--accent, #2440ED));
    --processor-accent-soft: color-mix(in srgb, var(--processor-accent) 10%, transparent);
    --processor-accent-track: color-mix(in srgb, var(--processor-accent) 12%, var(--node-neu-surface));
    --processor-panel-bg: var(--node-neu-surface);
    --processor-panel-shadow: var(--neu-inset);
    --processor-card-bg: var(--node-neu-surface);
    --processor-card-shadow: var(--neu-inset);
    --processor-control-bg: var(--node-neu-surface);
    --processor-control-shadow: var(--neu-inset);
    --processor-control-raised-shadow: var(--neu-shadow);
    --processor-control-hover-shadow: var(--neu-shadow-hover);
    --processor-text: var(--text);
    --processor-text-soft: var(--text-soft);
    --processor-text-muted: var(--text-muted);
    --processor-divider: color-mix(in srgb, var(--text-muted) 12%, transparent);
    --processor-popup-bg: var(--surface);
    --processor-popup-border: 1px solid rgba(203,213,225,0.45);
    --processor-popup-shadow: 0 10px 28px rgba(15,23,42,0.14), 8px 8px 20px rgba(163,177,198,0.24), -8px -8px 20px rgba(255,255,255,0.55);
    --processor-option-hover-bg: color-mix(in srgb, var(--processor-accent) 8%, transparent);
    --processor-option-active-bg: color-mix(in srgb, var(--processor-accent) 10%, transparent);
    --processor-save-divider: color-mix(in srgb, var(--text-muted) 14%, transparent);
    --processor-save-hover-bg: color-mix(in srgb, var(--processor-accent) 8%, transparent);
    --processor-danger-soft: color-mix(in srgb, var(--danger) 10%, transparent);
    --processor-badge-bg: rgba(15, 23, 42, 0.58);
    --processor-badge-text: #fff;
}
.node-type-imageProcessor {
    --node-type-color: var(--processor-accent, var(--type-image-processor, var(--accent, #2440ED)));
    min-width: 360px;
}
.node-shell-image-processor .node-frame-body { min-height: 0; flex: 1; display: flex; overflow: visible; }
.node-shell-image-processor .node-frame { overflow: visible; }
.image-processor-body { gap: 10px; }
.proc-status-strip {
    padding: 6px 12px;
    border-radius: 10px;
    background: var(--processor-card-bg);
    box-shadow: var(--processor-card-shadow);
    color: var(--processor-text-soft);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: normal;
    word-break: break-all;
    text-align: center;
    line-height: 1.5;
}
.proc-compare-text {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 9px 10px;
    border-radius: 10px;
    background: var(--processor-card-bg);
    box-shadow: var(--processor-card-shadow);
}
.proc-compare-line {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: 11px;
    color: var(--processor-text-soft);
    line-height: 1.45;
    min-width: 0;
}
.proc-compare-tag {
    flex: 0 0 auto;
    height: 18px;
    padding: 0 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 5px;
    font-size: 9px;
    font-weight: 800;
    background: var(--processor-text-muted);
    color: var(--processor-badge-text);
    white-space: nowrap;
    margin-top: 1px;
}
.proc-compare-tag.out { background: var(--processor-accent); }
.proc-compare-desc {
    flex: 1 1 0;
    min-width: 0;
    white-space: normal;
    overflow: visible;
    word-break: break-all;
    font-weight: 700;
}
.proc-compare-line-out .proc-compare-desc { color: var(--processor-accent); }

.group-node-card {
    width: 100%;
    height: 100%;
    border-radius: 28px;
    border: 1px solid color-mix(in srgb, var(--type-preview) 28%, rgba(203, 213, 225, 0.52));
    background:
        linear-gradient(135deg, rgba(255,255,255,0.68), rgba(248,250,252,0.40)),
        color-mix(in srgb, var(--type-preview) 5%, transparent);
    box-shadow: 0 22px 55px rgba(15, 23, 42, 0.08), inset 0 1px 0 rgba(255,255,255,0.72);
    backdrop-filter: blur(10px);
    box-sizing: border-box;
    pointer-events: auto;
    overflow: hidden;
}
.group-node-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image: radial-gradient(circle at 10px 10px, color-mix(in srgb, var(--type-preview) 22%, transparent) 1.2px, transparent 1.2px);
    background-size: 28px 28px;
    opacity: 0.24;
    pointer-events: none;
}
.group-node-title-large {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(100% + 12px);
    z-index: 8;
    width: auto;
    max-width: 100%;
    min-height: calc(var(--group-title-size, 34px) * 1.2 + 16px);
    padding: 8px 24px;
    border-radius: 18px;
    border: 1px solid color-mix(in srgb, var(--type-preview) 28%, rgba(203, 213, 225, 0.52));
    background:
        linear-gradient(135deg, rgba(255,255,255,0.68), rgba(248,250,252,0.40)),
        color-mix(in srgb, var(--type-preview) 5%, transparent);
    box-shadow: 0 22px 55px rgba(15, 23, 42, 0.08), inset 0 1px 0 rgba(255,255,255,0.72);
    backdrop-filter: blur(10px);
    color: color-mix(in srgb, var(--type-preview) 38%, var(--text));
    font-size: var(--group-title-size, 34px);
    font-weight: 950;
    line-height: 1.15;
    letter-spacing: -0.02em;
    text-align: center;
    white-space: var(--group-title-wrap, nowrap);
    word-break: break-all;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: text;
    user-select: text;
    pointer-events: auto;
    box-sizing: border-box;
}
.group-node-title-large.stretch {
    text-align: justify;
    text-align-last: justify;
    text-justify: inter-character;
}
.group-node-title-large.editing {
    outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
    cursor: text;
    user-select: text;
}

.node-type-tip {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}
.node-type-tip:hover {
    box-shadow: none;
}
.node-type-tip.selected {
    border-color: transparent;
    box-shadow: none;
}
.tip-node-title-large {
    position: absolute;
    inset: 0;
    z-index: 8;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 8px 18px;
    border-radius: 16px;
    border: 1px solid color-mix(in srgb, var(--node-type-color) 30%, rgba(203, 213, 225, 0.52));
    background:
        linear-gradient(135deg, rgba(255,255,255,0.70), rgba(248,250,252,0.46)),
        color-mix(in srgb, var(--node-type-color) 6%, var(--node-neu-surface));
    box-shadow: var(--neu-shadow);
    color: color-mix(in srgb, var(--node-type-color) 42%, var(--text));
    font-size: var(--tip-title-size, 28px);
    font-weight: 900;
    line-height: 1.15;
    text-align: center;
    white-space: pre;
    word-break: keep-all;
    overflow: visible;
    cursor: pointer;
    user-select: none;
    box-sizing: border-box;
}
.tip-node-title-large.editing {
    outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
    cursor: text;
    user-select: text;
}

.group-node-header {
    position: absolute;
    left: 22px;
    top: 18px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    max-width: calc(100% - 40px);
    min-height: 30px;
    padding: 0 12px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--node-neu-bg) 82%, rgba(255,255,255,0.72));
    border: 1px solid rgba(203, 213, 225, 0.38);
    box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08), inset 0 1px 0 rgba(255,255,255,0.68);
    color: var(--text);
    box-sizing: border-box;
}
.group-node-dot {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: var(--type-preview);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--type-preview) 14%, transparent);
    flex: 0 0 auto;
}
.group-node-count {
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 750;
    white-space: nowrap;
}
.node-type-group.selected .group-node-card {
    border-color: color-mix(in srgb, var(--accent) 55%, rgba(203, 213, 225, 0.52));
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.10), 0 0 0 2px color-mix(in srgb, var(--accent) 24%, transparent), inset 0 1px 0 rgba(255,255,255,0.76);
}

/* Resize 手柄 */
.node-resize-handle {
    position: absolute;
    z-index: 200;
    width: 18px;
    height: 18px;
    background: transparent;
    opacity: 0;
    transition: opacity var(--duration-fast);
    pointer-events: auto;
}
.node:hover .node-resize-handle { opacity: 1; }
.resize-handle-nw { left: -8px; top: -8px; cursor: nwse-resize; }
.resize-handle-ne { right: -8px; top: -8px; cursor: nesw-resize; }
.resize-handle-se { right: -8px; bottom: -8px; cursor: nwse-resize; }
.resize-handle-sw { left: -8px; bottom: -8px; cursor: nesw-resize; }

/* 拖拽 / 框选性能优化 */
body.dragging-nodes .node,
body.selecting-canvas .node,
body.selecting-canvas .node:hover,
body.selecting-canvas .node.selected {
    transition: none !important;
    transform: none !important;
}
body.dragging-nodes .edge-group .edge-visual { transition: none !important; }
body.dragging-nodes .node-ai-prompt,
body.dragging-nodes .prompt-ref-token,
body.dragging-nodes #prompt-ref-tooltip { pointer-events: none !important; }
body.selecting-canvas .node,
body.selecting-canvas .node * {
    pointer-events: none !important;
}
body.selecting-canvas .node:hover {
    box-shadow: var(--neu-shadow) !important;
}
body.selecting-canvas .node.selected {
    box-shadow:
        var(--neu-shadow-active),
        0 0 0 2.5px var(--accent),
        0 0 24px color-mix(in srgb, var(--accent) 25%, transparent) !important;
}

/* 自动高度测量 */
.node-measuring { height: auto !important; overflow: visible !important; }
.node-measuring .ai-node-body,
.node-measuring .chat-container,
.node-measuring .node-content-text {
    height: auto !important; max-height: none !important;
    overflow: visible !important; flex: 0 0 auto !important;
}
.node-measuring .ai-panel,
.node-measuring .ai-connected-info,
.node-measuring .ai-ref-section,
.node-measuring .ai-config-section,
.node-measuring .node-ai-btn { flex-shrink: 0 !important; }

/* 节点类型 class */
.node-type-img, .node-type-image, .node-type-preview { overflow: visible !important; }
.node-type-compare { overflow: visible !important; }
.node-type-compare .port { z-index: 80; }

/* === 2. 节点 Header 统一组件 === */
.node-frame-header {
    min-height: 36px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 0 0 8px;
    border-bottom: 1px solid rgba(203, 213, 225, 0.35);
}
.node-frame-header-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}
.node-frame-title-row {
    display: flex;
    align-items: center;
    min-width: 0;
}
/* 隐藏旧的 meta/icon 元素 */
.node-frame-icon, .node-frame-meta, .node-frame-subtle { display: none !important; }

.node-frame-title {
    min-width: 0;
    font-size: 13px;
    font-weight: 750;
    color: var(--text);
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: 0.01em;
}
/* 类型色圆点 — 已移除 */
.node-frame-title::before {
    display: none;
}

/* 徽章区域 */
.node-frame-badges {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    flex: 0 0 auto;
    flex-wrap: nowrap;
    min-width: 0;
}
.node-status-badge {
    display: inline-flex;
    align-items: center;
    min-height: 22px;
    padding: 0 9px;
    border-radius: 999px;
    border: none;
    background: var(--model-search-bg);
    box-shadow: var(--control-shadow);
    color: var(--text-muted);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.03em;
    white-space: nowrap;
}
.node-status-badge.tone-neutral { color: var(--text-muted); }
.node-status-badge.tone-info { color: var(--type-preview); background: color-mix(in srgb, var(--type-preview) 10%, var(--node-neu-surface)); }
.node-status-badge.tone-success { color: var(--success); background: color-mix(in srgb, var(--success) 10%, var(--node-neu-surface)); }
.node-status-badge.tone-warning { color: var(--type-compare); background: color-mix(in srgb, var(--type-compare) 10%, var(--node-neu-surface)); }
.node-status-badge.tone-danger { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, var(--node-neu-surface)); }

/* 上游文本节点提示 badge */
.node-upstream-text-badge {
    color: var(--type-text, #7c3aed);
    background: color-mix(in srgb, var(--type-text, #7c3aed) 10%, var(--node-neu-surface));
    cursor: default;
}

/* 空状态 */
.node-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 100%;
    padding: 18px;
    border-radius: 14px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    color: var(--text-soft);
    box-sizing: border-box;
}
.node-empty-title { font-size: 14px; font-weight: 700; color: var(--text); line-height: 1.3; }
.node-empty-desc { max-width: 280px; font-size: 12px; color: var(--text-muted); line-height: 1.55; }
.parallel-connected-info {
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-soft, #475569);
    font-weight: 600;
}
.parallel-task-count {
    margin-top: 2px;
    font-size: 11px;
    color: var(--accent, #2563eb);
    font-weight: 700;
}

/* === 3. 节点内容区域通用样式 === */

/* 节点内统一滚动条 — 与对话节点一致的细滚动条 */
.node-content-text::-webkit-scrollbar,
.node-ai-prompt::-webkit-scrollbar,
.ai-node-body::-webkit-scrollbar,
.chat-list::-webkit-scrollbar { width: 4px; }
.node-content-text::-webkit-scrollbar-track,
.node-ai-prompt::-webkit-scrollbar-track,
.ai-node-body::-webkit-scrollbar-track,
.chat-list::-webkit-scrollbar-track { background: transparent; }
.node-content-text::-webkit-scrollbar-thumb,
.node-ai-prompt::-webkit-scrollbar-thumb,
.ai-node-body::-webkit-scrollbar-thumb,
.chat-list::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }

.node-content-text {
    margin-top: 0;
    font-size: var(--node-text-font-size, 13px);
    color: var(--text-soft);
    line-height: 1.6;
    outline: none;
    word-wrap: break-word;
    white-space: pre-wrap;
    cursor: text;
    padding: 10px 12px;
    border-radius: 12px;
    border: none;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
}
.node-content-text:focus {
    background: var(--surface);
    box-shadow: var(--neu-inset-deep), 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}
.node-text-editor { min-height: 160px; }
.tip-node-editor {
    flex: 1 1 auto;
    min-height: 88px;
    width: 100%;
    margin: 0;
    padding: 2px 4px;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--text-soft);
    font-size: var(--node-text-font-size, 13px);
    line-height: 1.6;
    outline: none;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-y: auto;
    overflow-x: hidden;
    cursor: text;
    box-sizing: border-box;
}
.preview-text-result { margin-top: var(--preview-gap, 8px); }

/* 状态色调 */
.state-tone-info { color: var(--type-preview); }
.state-tone-warning { color: var(--type-compare); }
.state-tone-danger { color: var(--danger); }

/* Placeholder */
.node-content-text[data-placeholder]:empty::before,
.tip-node-editor[data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    pointer-events: none;
    font-style: italic;
    opacity: 0.7;
}

/* AI 提示词输入框 */
.node-ai-prompt {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    margin-top: 0;
    resize: none;
    border: none;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    border-radius: 12px;
    padding: 12px 14px;
    font-size: var(--node-prompt-font-size, 13px);
    font-family: inherit;
    outline: none;
    transition: box-shadow var(--duration-normal), background var(--duration-normal);
    color: var(--text-soft);
    flex: 0 0 auto;
    min-height: 96px;
    max-height: 220px;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-y: auto;
    overflow-x: hidden;
    cursor: text;
    display: block;
    position: relative;
    isolation: isolate;
}
.node-ai-prompt:focus {
    background: var(--surface);
    box-shadow: var(--neu-inset-deep), 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}
.node-ai-prompt[data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    pointer-events: none;
    font-style: italic;
    opacity: 0.7;
}

/* 提示词引用 Token */
.prompt-ref-token {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin: 0 2px;
    vertical-align: baseline;
    contenteditable: false;
}
.prompt-ref-label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 20px;
    padding: 0 7px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 12%, var(--node-neu-surface));
    box-shadow: var(--neu-inset);
    color: var(--accent);
    font-size: 11px;
    font-weight: 600;
    user-select: none;
}

/* === 4. 连接端口 === */
.port {
    position: absolute;
    width: 14px;
    height: 14px;
    background: var(--node-port-bg);
    box-shadow: var(--node-port-shadow);
    border-radius: 50%;
    top: 50%;
    transform: translateY(-50%);
    cursor: crosshair;
    border: var(--node-port-border);
    z-index: 80;
    opacity: 0.5;
    transition: opacity var(--duration-fast), transform var(--duration-fast), box-shadow var(--duration-fast);
    pointer-events: auto;
}
.node:hover .port, .node.selected .port {
    opacity: 1;
    transform: translateY(-50%) scale(1.1);
}
.port:hover {
    background: var(--accent);
    border-color: var(--accent);
    transform: translateY(-50%) scale(1.4) !important;
    opacity: 1;
    box-shadow: var(--neu-shadow), 0 0 12px color-mix(in srgb, var(--accent) 40%, transparent);
}
.port.input { left: -9px; }
.port.output { right: -9px; }

/* Shift / Alt 按住时选中节点端点放大突出 */
.node.ports-highlighted .port {
    opacity: 1;
    width: 50px;
    height: 50px;
    border-width: 4px;
    transform: translateY(-50%) scale(1);
    box-shadow: var(--neu-shadow), 0 0 0 3px color-mix(in srgb, var(--node-type-color) 20%, transparent),
                0 0 16px color-mix(in srgb, var(--node-type-color) 30%, transparent);
    background: color-mix(in srgb, var(--node-type-color) 10%, var(--node-neu-surface));
    transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.node.ports-highlighted .port.input { left: -27px; }
.node.ports-highlighted .port.output { right: -27px; }
.node.ports-highlighted .port:hover {
    transform: translateY(-50%) scale(1.1) !important;
    background: var(--accent);
    border-color: var(--accent);
    box-shadow: var(--neu-shadow), 0 0 0 4px color-mix(in srgb, var(--accent) 25%, transparent),
                0 0 20px color-mix(in srgb, var(--accent) 40%, transparent);
}

/* === 5. 文本节点 === */
/* 文本节点最简洁，仅标题 + 内容区 */
/* 样式已由通用 .node-content-text 覆盖 */

/* === 6. 图片节点 & 7. 预览节点 — 统一媒体展示系统 === */
/*
 * 设计原则：
 * 1. 只有一个裁切层（.media-img-frame / .preview-img-container）
 * 2. 其他所有中间层全部透传（overflow:visible, padding:0, border-radius:0）
 * 3. 图片本身不设圆角，由唯一裁切层负责
 * 4. JS 尺寸计算只需关心：node-frame padding + header + gap
 */

/* --- 媒体节点通用 --- */
.node-shell-media {
    --media-radius: 10px;      /* 图片展示区圆角 */
    --media-padding: 0px;      /* 图片区域内边距（0=图片贴边） */
}
.node-shell-media .node-frame { padding: 12px; gap: 8px; }
.node-shell-media .node-frame-header { margin-bottom: 0; min-height: 34px; }
.node-shell-media .node-frame-body { gap: 0; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.node-type-preview .node-shell-media .node-frame-body { overflow: visible; }
.node-type-preview .node-frame-body:has(> .preview-regenerate-btn) {
    gap: 8px;
}
.node-type-preview .node-frame-body:has(> .preview-regenerate-btn) > .preview-body {
    flex: 0 0 auto;
}

/* --- 图片节点 --- */
.node-type-image .node-frame-body,
.node-type-img .node-frame-body { flex: 1 1 auto; min-height: 0; }

/* 图片区域外壳 — 纯透传 */
.full-img-area {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 0;
    overflow: visible;
}
.media-node-body {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 0;
    overflow: visible;
    display: flex;
    align-items: stretch;
    justify-content: center;
    cursor: move;
}

/* 图片外框 — 唯一裁切层 */
.media-img-frame {
    width: 100%;
    height: 100%;
    min-height: 0;
    overflow: hidden;
    border-radius: var(--media-radius);
    padding: var(--media-padding);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    box-sizing: border-box;
}

/* 图片本身 — 无圆角，由容器裁切 */
.full-img-area img, .node-content-image {
    width: 100%;
    height: 100%;
    min-height: 0;
    object-fit: cover;
    display: block;
    cursor: pointer;
    pointer-events: auto;
    background: transparent;
    border-radius: 0;
}
.node-content-image { cursor: move; }

/* 图片节点的“更换图片”按钮：复用 .preview-regenerate-btn 的胶囊视觉 */
.node-shell-media.has-image-replace { overflow: visible; }
.node-shell-media.has-image-replace .node-frame-body {
    gap: 8px;
    overflow: visible;
}
.node-shell-media.has-image-replace .node-frame-body > .full-img-area {
    flex: 1 1 auto;
    min-height: 0;
}
.image-replace-btn {
    flex: 0 0 auto;
    position: relative;
    z-index: 3;
    width: 100%;
    height: 36px;
    margin: 0;
    padding: 0 12px;
    border: none;
    border-radius: 10px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
    cursor: pointer;
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast), background var(--duration-normal), color var(--duration-fast);
}
.image-replace-btn svg {
    flex-shrink: 0;
    opacity: 0.75;
    transition: transform 0.3s var(--ease-out), opacity var(--duration-fast);
}
.image-replace-btn:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
    background: var(--image-edit-active-bg);
    color: var(--accent);
}
.image-replace-btn:hover svg {
    opacity: 1;
    transform: rotate(-180deg);
}
.image-replace-btn:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}

/* 分辨率徽章 */
.media-resolution {
    display: inline-flex;
    align-items: center;
    min-height: 22px;
    padding: 0 8px;
    border-radius: 999px;
    color: var(--type-preview);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.media-resolution.muted { color: var(--text-muted); }
.preview-resolution {
    gap: 6px;
    max-width: 100%;
}
.preview-resolution-count {
    color: var(--text-muted);
    font-weight: 800;
}
.preview-resolution-error {
    display: inline-flex;
    align-items: center;
    height: 17px;
    padding: 0 6px;
    border-radius: 999px;
    color: var(--danger);
    background: color-mix(in srgb, var(--danger) 12%, transparent);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 10px;
    font-weight: 750;
    letter-spacing: 0;
}

/* 图片空状态 */
.full-img-area .img-empty-state {
    width: 100%; height: 100%;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 8px;
    color: var(--text-muted);
    font-size: 12px;
    border-radius: var(--media-radius);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    box-sizing: border-box;
}
.img-empty-icon { font-size: 24px; line-height: 1; }
.full-img-area .img-quality-badge {
    position: absolute;
    left: 14px; bottom: 14px;
    z-index: 12;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    color: var(--type-compare);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    pointer-events: none;
}
.img-overlay-top { display: none; }
.img-meta-bar { display: none; }

/* --- 预览节点 --- */
.preview-empty {
    color: var(--text-muted);
    font-size: 12px;
    text-align: center;
    border-radius: var(--media-radius);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 14px;
    gap: 6px;
    box-sizing: border-box;
}
.preview-empty ul {
    margin: 0; padding-left: 16px;
    text-align: left; color: var(--danger);
    font-size: 11px; word-break: break-all;
}
.node-type-preview .preview-empty { margin: 0; }

.node-type-preview .node-frame-body > .preview-body + .preview-regenerate-btn {
    margin-top: 0 !important;
}

/* 再次生成按钮 — 新拟态风格，参考 .node-ai-btn */
.preview-regenerate-btn {
    flex: 0 0 auto;
    position: relative;
    z-index: 3;
    width: 100%;
    height: 36px;
    margin-top: 0 !important;
    margin-bottom: 4px;
    padding: 0 12px;
    border: none;
    border-radius: 10px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
    cursor: pointer;
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast), background var(--duration-normal), color var(--duration-fast);
}
.preview-regenerate-btn svg {
    flex-shrink: 0;
    opacity: 0.75;
    transition: transform 0.3s var(--ease-out), opacity var(--duration-fast);
}
.preview-regenerate-btn:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
    background: var(--image-edit-active-bg);
    color: var(--accent);
}
.preview-regenerate-btn:hover svg {
    opacity: 1;
    transform: rotate(-60deg);
}
.preview-regenerate-btn:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}
.preview-stop-btn {
    background: color-mix(in srgb, var(--danger) 12%, var(--node-neu-surface));
    color: var(--danger);
}
.preview-stop-btn:hover {
    background: color-mix(in srgb, var(--danger) 18%, var(--node-neu-surface));
    color: var(--danger);
}

/* 拆散按钮 — 悬浮在节点顶部外面，hover 时显示 */
.preview-split-btn {
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%) translateY(-100%);
    z-index: 12;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    height: 24px;
    padding: 0 10px;
    border: none;
    border-radius: 12px;
    background: var(--surface-elevated, #fff);
    box-shadow: 0 1px 6px rgba(0,0,0,0.1), 0 0.5px 2px rgba(0,0,0,0.06);
    color: var(--text-muted);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    cursor: pointer;
    pointer-events: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s ease,
                box-shadow 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.preview-split-btn svg {
    flex-shrink: 0;
    opacity: 0.5;
    transition: opacity 0.15s ease;
}
.node-type-preview:hover > .preview-split-btn,
.node:hover > .text-split-btn {
    opacity: 1;
    visibility: visible;
}
.preview-split-btn:hover {
    color: var(--type-preview);
    box-shadow: 0 2px 10px rgba(0,0,0,0.13), 0 1px 3px rgba(0,0,0,0.08);
    transform: translateX(-50%) translateY(-100%) scale(1.04);
}
.preview-split-btn:hover svg {
    opacity: 0.9;
}
.preview-split-btn:active {
    transform: translateX(-50%) translateY(-100%) scale(0.97);
    opacity: 0.85;
}

/* 预览内容区 — flex 撑满，不裁切子元素 */
.preview-body {
    width: 100%;
    flex: 1 1 auto;
    min-height: 0;
    box-sizing: border-box;
    padding: 0;
    overflow: visible;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    cursor: move;
}

/* 预览图片外框 — 纯透传（Grid 模式下由 container 裁切） */
.preview-img-frame {
    width: 100%;
    height: 100%;
    min-height: 0;
    overflow: visible;
    border-radius: 0;
    padding: 0;
    background: transparent;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Grid 布局容器 — 全部透传，不裁切 */
.preview-grid {
    display: flex;
    flex-direction: column;
    gap: var(--preview-gap, 8px);
    margin: 0;
    flex: 0 0 auto;
    overflow: visible;
    padding: 0;
    justify-content: flex-start;
    box-sizing: border-box;
    width: fit-content;
    min-height: 0;
    align-items: center;
    max-width: 100%;
}
.preview-grid-fit { flex: 0 0 auto; overflow: visible; width: fit-content; max-width: 100%; }
.preview-grid-row {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    width: fit-content;
    max-width: 100%;
    overflow: visible;
    gap: var(--preview-gap, 8px);
}

/* 预览图片容器 — 唯一裁切层 */
.preview-img-container, .img-node-wrapper {
    position: relative;
    width: 100%; height: auto;
    min-height: 0;
    overflow: hidden;
    border-radius: var(--media-radius);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    flex: 0 0 auto;
}
.preview-focus-main .preview-img-container,
.img-node-wrapper { height: 100%; }
/* ===== 通用占位格子（生成中/未能生成）— 预览节点和历史面板共用 ===== */
.placeholder-cell-inner {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 750;
}
.placeholder-cell-inner .svg-icon { width: 22px; height: 22px; }
/* 生成中变体 */
.placeholder-pending {
    border: 1px dashed color-mix(in srgb, var(--accent) 34%, rgba(148, 163, 184, 0.55));
    background:
        linear-gradient(135deg, color-mix(in srgb, var(--accent) 8%, transparent), rgba(248, 250, 252, 0.74)),
        var(--node-neu-surface);
}
.placeholder-pending .placeholder-cell-inner {
    color: color-mix(in srgb, var(--accent) 72%, var(--text));
}
/* 未能生成变体 */
.placeholder-failed {
    border: 1px dashed color-mix(in srgb, var(--danger) 34%, rgba(148, 163, 184, 0.55));
    background:
        linear-gradient(135deg, color-mix(in srgb, var(--danger) 6%, transparent), rgba(248, 250, 252, 0.74)),
        var(--node-neu-surface);
}
.placeholder-failed .placeholder-cell-inner {
    color: color-mix(in srgb, var(--danger) 65%, var(--text-muted));
    font-size: 11px;
    font-weight: 650;
}
.placeholder-failed .placeholder-cell-inner .svg-icon { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.5; }

/* 预览图片 — 无圆角，由容器裁切 */
.preview-img {
    width: 100%;
    height: 100%;
    min-height: 0;
    object-fit: cover;
    display: block;
    cursor: pointer;
    pointer-events: auto;
    background: transparent;
    border-radius: 0;
}
/* Focus 主图用 contain */
.preview-focus-main .preview-img {
    object-fit: contain;
}

.preview-feather-control {
    margin-top: 10px;
    padding: 9px 10px;
    border-radius: 14px;
    border: var(--preview-feather-border);
    background: var(--preview-feather-bg);
    box-shadow: var(--preview-feather-shadow);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 8px 6px;
    width: 100%;
    max-width: none;
    min-width: 0;
    box-sizing: border-box;
    color: var(--preview-feather-text);
    font-size: 11px;
}
.preview-feather-label {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-weight: 800;
    color: var(--preview-feather-label-text);
}
.preview-feather-label span { flex: 0 0 auto; white-space: nowrap; }
.preview-feather-slider {
    flex: 1 1 auto;
    min-width: 34px;
    height: 4px;
    accent-color: var(--preview-feather-accent);
}
.preview-feather-value {
    min-width: 30px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 850;
    color: var(--preview-feather-accent);
}
.preview-feather-reset {
    border: 0;
    border-radius: 999px;
    padding: 4px 7px;
    background: var(--preview-feather-reset-bg);
    color: var(--preview-feather-accent);
    font-size: 11px;
    font-weight: 850;
    cursor: pointer;
}
.preview-feather-reset:hover:not(:disabled) { background: var(--preview-feather-reset-hover-bg); }
.preview-feather-hint {
    grid-column: 1 / -1;
    min-width: 0;
    color: var(--preview-feather-hint-text);
    font-size: 10px;
    line-height: 1.25;
}
.preview-feather-control.disabled {
    opacity: var(--preview-feather-disabled-opacity);
}
.preview-feather-control.disabled .preview-feather-slider,
.preview-feather-control.disabled .preview-feather-reset {
    cursor: not-allowed;
}
.preview-feather-visual {
    position: absolute;
    z-index: 5;
    pointer-events: none;
    opacity: 0;
    border: 2px solid var(--preview-feather-visual-border);
    box-shadow: var(--preview-feather-visual-shadow);
    transition: opacity 0.16s ease;
}
.preview-feather-visualizing .preview-feather-visual,
.preview-img-container:hover .preview-feather-visual {
    opacity: 1;
}
.preview-feather-visual-label {
    position: absolute;
    left: 6px;
    top: 6px;
    padding: 3px 6px;
    border-radius: 999px;
    background: var(--preview-feather-visual-label-bg);
    color: var(--preview-feather-visual-label-text);
    font-size: 10px;
    font-weight: 900;
    line-height: 1;
    white-space: nowrap;
}

/* Focus 模式 — 主图占满全部内容区 */
.preview-focus {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    padding: 0; box-sizing: border-box;
    align-items: stretch;
    width: 100%;
}
.preview-focus-main {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    width: 100%;
    justify-content: center;
    overflow: hidden;
    border-radius: var(--media-radius);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    box-sizing: border-box;
}
.preview-focus-main .preview-img-container {
    width: 100%;
    height: 100%;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
}

/* === 缩略图悬浮面板 === */
/* === 缩略图底部面板 — Focus 模式常驻显示 === */
.preview-thumb-panel {
    position: absolute;
    left: 50%;
    top: calc(100% + 10px);
    transform: translateX(-50%);
    display: none;
    flex-direction: column;
    gap: 0;
    padding: 0;
    width: max-content;
    max-width: min(92vw, 720px);
    border-radius: 16px;
    background: var(--node-neu-bg);
    border: 1px solid rgba(203, 213, 225, 0.35);
    box-shadow: 0 10px 24px rgba(15, 23, 42, 0.10), 0 2px 8px rgba(15, 23, 42, 0.06);
    z-index: 150;
    pointer-events: auto;
    overflow: hidden;
}
.preview-thumb-panel.visible {
    display: flex;
    animation: thumb-panel-in var(--duration-normal) var(--ease-out);
}
@keyframes thumb-panel-in {
    from { opacity: 0; transform: translateX(-50%) translateY(-4px) scale(0.96); }
    to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}

.preview-thumb-panel-header {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 7px 10px 6px;
    border-bottom: 1px solid rgba(203, 213, 225, 0.22);
    flex-shrink: 0;
    background: linear-gradient(180deg, rgba(255,255,255,0.28), rgba(255,255,255,0.08));
}
.preview-thumb-panel-count {
    font-size: 10px;
    font-weight: 700;
    color: var(--text-secondary, #64748b);
    letter-spacing: 0.04em;
}

.preview-thumb-panel-list {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 6px;
    padding: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    max-width: 100%;
    scrollbar-width: none;
}
.preview-thumb-panel-list::-webkit-scrollbar { height: 0; display: none; }

/* 每张图完整显示，不裁切；作为横向小卡片整体排列 */
.preview-thumb-panel-item {
    position: relative;
    width: 64px;
    min-width: 64px;
    flex: 0 0 64px;
    border-radius: 10px;
    overflow: hidden;
    background: var(--node-neu-surface, #f1f5f9);
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.06);
    cursor: pointer;
    transition: transform var(--duration-fast), box-shadow var(--duration-fast), opacity var(--duration-fast);
    opacity: 0.92;
}
.preview-thumb-panel-item:hover {
    transform: translateY(-1px);
    opacity: 1;
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.12);
}
.preview-thumb-panel-item.active {
    opacity: 1;
    box-shadow: 0 0 0 2px var(--accent), 0 4px 12px rgba(15, 23, 42, 0.14);
}
.preview-thumb-panel-item img {
    width: 100%;
    height: auto;
    max-height: 120px;
    display: block;
    object-fit: contain;
    background: rgba(255,255,255,0.35);
}
.preview-thumb-panel-idx {
    position: absolute;
    right: 4px;
    bottom: 4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    font-weight: 700;
    color: #fff;
    background: rgba(15, 23, 42, 0.55);
    border-radius: 999px;
    pointer-events: none;
}

/* === 8. 对比节点 === */
.node-shell-compare .node-frame { padding: 12px; }
.node-shell-compare .node-frame-body { gap: 0; }

.compare-wrapper {
    position: relative;
    width: 100%; height: 100%;
    display: flex; flex-direction: column;
    min-height: 0; overflow: hidden;
    border-radius: 14px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    cursor: move;
}
.compare-stage {
    position: relative;
    flex: 1; min-height: 0;
    overflow: hidden;
    background: var(--node-neu-surface);
}
.compare-stage-mismatch {
    background-color: var(--node-neu-surface);
    background-image:
        linear-gradient(45deg, rgba(148,163,184,0.08) 25%, transparent 25%),
        linear-gradient(-45deg, rgba(148,163,184,0.08) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, rgba(148,163,184,0.08) 75%),
        linear-gradient(-45deg, transparent 75%, rgba(148,163,184,0.08) 75%);
    background-size: 18px 18px;
    background-position: 0 0, 0 9px, 9px -9px, -9px 0;
}
.compare-layer {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.compare-wrapper img {
    width: auto; height: auto;
    max-width: 100%; max-height: 100%;
    object-fit: contain;
    pointer-events: none; user-select: none;
}
.compare-wrapper .compare-top { z-index: 2; clip-path: inset(0 50% 0 0); background: transparent; }
.compare-corner-tag {
    position: absolute; top: 10px; z-index: 4;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; height: 24px;
    padding: 0 8px; border-radius: 999px;
    font-size: 11px; font-weight: 800;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text);
}
.compare-corner-left { left: 10px; }
.compare-corner-right { right: 10px; color: var(--type-compare); }
.compare-divider {
    position: absolute;
    top: 8px; bottom: 8px; left: 50%;
    width: 2px;
    background: linear-gradient(180deg, transparent, var(--accent), transparent);
    z-index: 3; pointer-events: none;
}
.compare-divider::before {
    content: '◀ ▶';
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text);
    padding: 6px 10px;
    border-radius: 999px;
    font-size: 10px; font-weight: 800;
    white-space: nowrap;
}
.compare-labels {
    position: absolute; bottom: 10px; left: 50%;
    transform: translateX(-50%); z-index: 4;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    padding: 5px 12px; border-radius: 999px;
    font-size: 10px; pointer-events: none;
    letter-spacing: 0.02em;
}
.compare-empty-state {
    flex: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 10px; padding: 20px;
    text-align: center; color: var(--text-muted);
}
.compare-empty-icon {
    width: 48px; height: 48px;
    border-radius: 14px;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px; font-weight: 700;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--type-compare);
}
.compare-empty-title { font-size: 14px; font-weight: 700; color: var(--text); }
.compare-empty-desc { max-width: 260px; font-size: 12px; line-height: 1.6; color: var(--text-muted); }

/* === 9. AI 绘图节点 === */
.node-frame.node-shell-chat,
.node-frame.node-shell-ai,
.node-frame.node-shell-control { padding: 12px; }

.node-frame.node-shell-ai {
    overflow: visible;
}
.node-frame.node-shell-ai .node-frame-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: visible;
}

.ai-node-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%; max-width: 100%;
    overflow: visible;
    box-sizing: border-box;
}
.ai-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    width: 100%; max-width: 100%;
    flex-shrink: 0;
    box-sizing: border-box;
    padding: 10px;
    border-radius: 12px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
}

.ai-ref-section { flex: 0 0 auto; overflow: hidden; }
.ai-prompt-section {
    flex: 1 1 168px;
    min-height: 168px;
    overflow: hidden;
    padding: 12px;
}
.node-frame.node-shell-ai .ai-prompt-section .node-ai-prompt {
    flex: 1 1 auto;
    min-height: 128px;
    max-height: none;
    padding: 14px 16px;
}
.ai-config-section { flex: 0 0 auto; }
.node-frame.node-shell-ai .node-ai-btn {
    margin-top: 2px;
    margin-bottom: 8px;
}

.ai-section-label {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.04em;
}
.ai-section-label::before {
    content: '';
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--node-type-color);
    flex-shrink: 0;
}
.ai-connected-info {
    flex-shrink: 0;
    color: var(--type-ai);
    background: color-mix(in srgb, var(--type-ai) 8%, var(--node-neu-surface));
    box-shadow: var(--neu-inset);
    padding: 6px 9px;
    border-radius: 9px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.35;
    text-align: center;
}
.ai-param-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
}
.ai-param-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.ai-param-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    margin-top: 0;
    font-size: 12px;
    color: var(--text-soft);
    flex-shrink: 0;
    position: relative;
    min-width: 0;
}
.ai-param-row > span {
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    flex-shrink: 0;
}
.ai-param-row-model { margin-bottom: 8px; }
.ai-param-compact { flex-direction: column; align-items: stretch; gap: 5px; }


/* 自定义参数下拉菜单 (比例/尺寸/数量) */
.param-dropdown {
    position: relative;
    width: 100%;
    min-width: 0;
}
.param-trigger {
    height: 32px;
    padding: 0 28px 0 10px;
    border: none;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 600;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    cursor: pointer;
    display: flex;
    align-items: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    user-select: none;
    box-sizing: border-box;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast);
    position: relative;
}
.param-trigger::after {
    content: '';
    position: absolute;
    right: 9px;
    top: 50%;
    transform: translateY(-50%);
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid var(--text-muted);
}
.param-trigger:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
}
.param-trigger:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}

/* 下拉面板 — fixed 定位脱离节点层级，不被裁切 */
.param-panel {
    display: none;
    position: fixed;
    min-width: 80px;
    width: max-content;
    background: var(--surface);
    border: 1px solid rgba(203, 213, 225, 0.4);
    border-radius: 12px;
    box-shadow:
        8px 8px 20px rgba(163, 177, 198, 0.3),
        -8px -8px 20px rgba(255, 255, 255, 0.65);
    z-index: 2100;
    padding: 4px;
    box-sizing: border-box;
    animation: dropdown-enter var(--duration-normal) var(--ease-out);
}
.param-panel.show { display: block; }

/* 选项 */
.param-option {
    padding: 7px 10px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-soft);
    cursor: pointer;
    transition: background var(--duration-fast), box-shadow var(--duration-fast), transform var(--duration-fast);
    white-space: nowrap;
}
.param-option:hover {
    background: var(--model-item-hover-bg);
    box-shadow: var(--model-item-hover-shadow);
    transform: translateX(2px);
}
.param-option:active {
    box-shadow: var(--neu-inset-deep);
    transform: translateX(2px) scale(0.97);
}
.param-option.active {
    color: var(--accent);
    font-weight: 700;
    background: var(--image-edit-active-bg);
    box-shadow: var(--neu-inset);
}

/* 旧的 select 样式保留兼容（如果其他地方还用到） */
.ai-param-select {
    height: 32px;
    padding: 0 28px 0 10px;
    border: none;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 600;
    outline: none;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    cursor: pointer;
    width: 100%; max-width: none; min-width: 0;
    text-overflow: ellipsis;
    box-sizing: border-box;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px;
}
.ai-param-select:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
}
.ai-param-select:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}
.ai-param-select:focus {
    box-shadow: var(--neu-shadow), 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}

/* 生成按钮 */
.node-ai-btn {
    width: 100%;
    height: 40px;
    margin-top: 0;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text);
    border: none;
    padding: 0 12px;
    border-radius: 12px;
    cursor: pointer;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.02em;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast), background var(--duration-normal);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    flex: 0 0 40px;
    flex-shrink: 0;
}
.node-ai-btn:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
    background: var(--image-edit-active-bg);
    color: var(--accent);
}
.node-ai-btn:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}
.node-ai-stop-btn {
    background: color-mix(in srgb, var(--danger) 12%, var(--node-neu-surface));
    color: var(--danger);
}
.node-ai-stop-btn:hover {
    background: color-mix(in srgb, var(--danger) 18%, var(--node-neu-surface));
    color: var(--danger);
}
.node-ai-btn:disabled {
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    cursor: not-allowed;
    opacity: 0.6;
    transform: none;
    color: var(--text-muted);
}

/* === 10. 参考图面板 (AI/Chat 共用) === */
.ref-images-panel {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin: 0;
    padding: 8px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    border-radius: 12px;
    min-height: 44px;
    max-height: 200px;
    align-content: start;
    box-sizing: border-box;
    width: 100%; max-width: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    flex: 0 0 auto;
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--text-muted) 35%, transparent) transparent;
}
.ref-images-panel::-webkit-scrollbar { width: 6px; }
.ref-images-panel::-webkit-scrollbar-track { background: transparent; }
.ref-images-panel::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--text-muted) 35%, transparent);
    border-radius: 3px;
}
.ref-images-panel::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--text-muted) 55%, transparent);
}
.ref-img-item {
    width: 42px; height: 42px;
    border-radius: 10px;
    position: relative;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
    transition: transform var(--duration-fast), box-shadow var(--duration-fast);
}
.ref-img-item:hover {
    transform: translateY(-2px) scale(1.04);
    box-shadow: var(--neu-shadow-hover);
}
.ref-img-item img { width: 100%; height: 100%; object-fit: cover; }
.ref-img-badge {
    position: absolute;
    top: 0; right: 0;
    background: rgba(15, 23, 42, 0.75);
    color: white;
    font-size: 9px;
    padding: 1px 4px;
    border-radius: 0 0 0 4px;
    font-family: monospace;
}
.ref-parallel-item {
    width: 42px; height: 42px;
    border: 1.5px dashed color-mix(in srgb, var(--type-ai) 50%, transparent);
    background: color-mix(in srgb, var(--type-ai) 6%, var(--node-neu-surface));
    box-shadow: var(--neu-inset);
    color: var(--text-muted);
    flex-direction: column;
    gap: 2px;
    text-align: center;
    box-sizing: border-box;
    padding-top: 7px;
}
.ref-parallel-item:hover {
    border-color: var(--type-ai);
    box-shadow: var(--neu-shadow);
}
.ref-parallel-label, .ref-parallel-count {
    font-size: 10px; font-weight: 700;
    line-height: 1; color: var(--text-muted);
}
.ref-parallel-item .ref-img-badge { background: var(--type-ai); }
.ref-folder-item {
    width: 42px; height: 42px;
    border: 1.5px dashed color-mix(in srgb, var(--type-parallel) 50%, transparent);
    background: color-mix(in srgb, var(--type-parallel) 6%, var(--node-neu-surface));
    box-shadow: var(--neu-inset);
    color: var(--text-muted);
    flex-direction: column;
    gap: 1px;
    text-align: center;
    box-sizing: border-box;
    padding-top: 5px;
}
.ref-folder-item:hover {
    border-color: var(--type-parallel);
    box-shadow: var(--neu-shadow);
}
.ref-folder-icon {
    width: 16px; height: 16px;
    fill: none;
    stroke: var(--text-muted);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.ref-folder-item:hover .ref-folder-icon { stroke: var(--type-parallel); }
.ref-folder-count {
    font-size: 9px; font-weight: 700;
    line-height: 1; color: var(--text-muted);
}
.ref-folder-badge {
    font-size: 9px;
    background: var(--type-parallel) !important;
}
.ref-folder-expanded {
    border-style: solid;
    border-color: var(--type-parallel);
    background: color-mix(in srgb, var(--type-parallel) 12%, var(--node-neu-surface));
}
.ref-folder-child {
    border: 1px solid color-mix(in srgb, var(--type-parallel) 30%, transparent);
    background: color-mix(in srgb, var(--type-parallel) 4%, var(--node-neu-surface));
}
.ref-folder-child:hover {
    border-color: var(--type-parallel);
    box-shadow: var(--neu-shadow);
}
body.ref-order-dragging {
    cursor: grabbing;
    user-select: none;
}
body.ref-order-dragging .ref-img-item:not(.ref-folder-item):not(.ref-folder-child) {
    cursor: grabbing;
}
.ref-drag-ghost,
.ref-drag-active {
    opacity: 1;
    transform: translateY(-2px) scale(1.05);
    box-shadow: 0 10px 22px color-mix(in srgb, var(--accent) 30%, transparent), var(--neu-shadow-hover) !important;
    outline: 2px solid color-mix(in srgb, var(--accent) 72%, transparent);
    outline-offset: 2px;
    z-index: 4;
}
.ref-drop-before,
.ref-drop-after {
    transform: translateY(-1px) scale(1.03);
    box-shadow: var(--neu-shadow-hover) !important;
}
.ref-drop-before::before,
.ref-drop-after::before {
    content: '';
    position: absolute;
    top: -4px;
    bottom: -4px;
    width: 3px;
    border-radius: 999px;
    background: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
    z-index: 5;
}
.ref-drop-before::before { left: -6px; }
.ref-drop-after::before { right: -6px; }
.ref-drag-preview {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 999999;
    pointer-events: none;
    opacity: .96;
    transform-origin: left top;
    transition: none !important;
    animation: none !important;
    will-change: transform;
    box-shadow: 0 16px 30px rgba(15, 23, 42, .24), 0 0 0 2px color-mix(in srgb, var(--accent) 70%, transparent) !important;
    filter: saturate(1.05);
}
.ref-drag-preview .ref-img-badge {
    background: var(--accent);
}

/* === 11. 模型选择器 (AI/Chat 共用) === */
.model-selector { position: relative; width: 100%; max-width: 100%; flex: 1; min-width: 0; }
.ms-trigger {
    padding: 0 12px;
    border: none;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 600;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    user-select: none;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast);
    min-height: 34px; height: 34px;
    width: 100%; box-sizing: border-box;
}
.ms-trigger:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
}
.ms-trigger:active { box-shadow: var(--neu-inset); transform: translateY(0); }
.ms-trigger::after { content: '▾'; font-size: 10px; margin-left: 8px; color: var(--text-muted); flex-shrink: 0; }

/* 下拉面板 — 新拟态浮层 */
.ms-dropdown {
    position: fixed !important;
    top: auto; left: auto; right: auto; bottom: auto;
    width: min(440px, 95vw);
    max-width: 95vw;
    background: var(--model-dropdown-bg);
    border: var(--model-dropdown-border);
    border-radius: var(--model-dropdown-radius);
    box-shadow: var(--model-dropdown-shadow);
    z-index: 2000;
    display: none;
    flex-direction: column;
    max-height: 380px;
    overflow: hidden;
    animation: dropdown-enter var(--duration-normal) var(--ease-out);
}
@keyframes dropdown-enter {
    from { opacity: 0; transform: translateY(-6px) scale(0.97); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
.ms-dropdown.show { display: flex; }
.ms-dropdown.ai-model-dropdown { width: min(350px, 95vw); }

/* 搜索框 */
.ms-search {
    padding: 14px 16px;
    border: none;
    border-bottom: var(--model-search-border);
    font-size: 13px;
    outline: none;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    color: var(--text);
    border-radius: 14px 14px 0 0;
    margin: 8px 8px 0;
    transition: box-shadow var(--duration-fast);
}
.ms-search:focus {
    background: var(--surface);
    box-shadow: var(--neu-inset-deep), 0 0 0 2px color-mix(in srgb, var(--accent) 15%, transparent);
}
.ms-search::placeholder { color: var(--text-muted); opacity: 0.7; }

/* 列表区域 */
.ms-list {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    min-width: 0;
    padding: 4px 4px 8px;
}
.ms-list::-webkit-scrollbar { width: 4px; }
.ms-list::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }
.ms-list::-webkit-scrollbar-track { background: transparent; }

/* 分组标题 */
.ms-group {
    font-size: 10px; font-weight: 800;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text-muted);
    padding: 12px 12px 6px;
    background: var(--surface);
    position: sticky; top: 0; z-index: 2;
    margin: 0 4px;
    border-radius: 8px 8px 0 0;
}

/* 列表项 — 新拟态交互 */
.ms-item {
    display: flex; align-items: center;
    padding: 10px 12px;
    margin: 2px 4px;
    cursor: pointer;
    border-radius: 10px;
    transition: background var(--duration-fast), box-shadow var(--duration-fast), transform var(--duration-fast);
    gap: 8px;
    min-width: 0; max-width: 100%; box-sizing: border-box;
}
.ms-item:hover {
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    transform: translateX(2px);
}
.ms-item:active {
    box-shadow: var(--neu-inset-deep);
    transform: translateX(2px) scale(0.98);
}
.ms-name {
    font-size: 12px; color: var(--text);
    flex: 1 1 auto;
    white-space: normal; overflow-wrap: anywhere;
    overflow: hidden; text-overflow: clip;
    min-width: 0; max-width: 100%;
    line-height: 1.42; word-break: break-word;
}
.ms-fav-btn {
    color: var(--line-strong);
    cursor: pointer;
    transition: all var(--duration-fast);
    display: flex; align-items: center; justify-content: center;
    width: 28px; height: 28px;
    border-radius: 50%;
    background: transparent;
}
.ms-fav-btn:hover {
    color: #fbbf24;
    transform: scale(1.12);
    background: color-mix(in srgb, #fbbf24 8%, transparent);
}
.ms-fav-btn.active { color: #f59e0b; }
.ms-fav-btn svg { width: 14px; height: 14px; fill: currentColor; stroke: none; }

/* === 12. 节点状态与交互 === */
.node-shell-compare .node-frame { background: transparent; }

/* 预览节点 grid 图片 — cover 填满容器 */
.preview-grid .preview-img { object-fit: cover; }

/* 预览节点主图容器 */
.preview-main-image { width: 100%; height: 100%; }

/* === 13. 文件夹节点 === */
.node-type-folder { min-width: 280px; min-height: 220px; }
.folder-node-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    color: var(--text);
}
/* 分区 */
.folder-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.folder-section-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
/* 路径区 */
.folder-path-row {
    display: flex;
    gap: 6px;
    align-items: stretch;
}
.folder-path-input {
    flex: 1;
    min-height: 40px;
    max-height: 88px;
    overflow-y: auto;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-xs, 6px);
    background: var(--node-neu-surface, rgba(255,255,255,0.74));
    box-shadow: var(--neu-inset, inset 1px 1px 2px rgba(0,0,0,0.04));
    color: var(--text, #1e293b);
    font-size: 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    line-height: 1.5;
    word-break: break-all;
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.folder-path-input:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted, #94a3b8);
    font-family: inherit;
    pointer-events: none;
}
.folder-path-input.focused,
.folder-path-input:focus {
    border-color: var(--accent-line, rgba(37,66,243,0.4));
    box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--accent, #2563eb) 10%, transparent);
}
/* 状态区 */
.folder-status-section {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    border-radius: var(--radius-xs, 6px);
    background: color-mix(in srgb, var(--accent, #2563eb) 5%, var(--node-neu-surface, #fff));
}
.folder-status-text {
    font-size: 12px;
    color: var(--text-soft, #334155);
}
.folder-status-text strong {
    color: var(--accent, #2563eb);
    font-weight: 800;
}
.folder-status-loading {
    color: var(--text-muted, #94a3b8);
    font-style: italic;
}
.folder-status-skip {
    font-size: 11px;
    color: var(--text-muted, #94a3b8);
}
/* 错误 */
.folder-error {
    padding: 6px 10px;
    border-radius: var(--radius-xs, 6px);
    background: color-mix(in srgb, var(--danger, #dc2626) 6%, var(--node-neu-surface, #fff));
    color: var(--danger, #dc2626);
    border: 1px solid color-mix(in srgb, var(--danger, #dc2626) 18%, transparent);
    font-size: 11px;
    line-height: 1.4;
}
/* 操作区 */
.folder-actions-section {
    gap: 8px;
}
.folder-option {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--text-soft, #475569);
    font-size: 12px;
    cursor: pointer;
    user-select: none;
}
.folder-option input {
    width: 14px; height: 14px;
    accent-color: var(--accent, #2563eb);
    cursor: pointer;
    margin: 0;
}
.folder-btn-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 8px;
}
.folder-btn-row:has(.folder-btn:only-child) {
    grid-template-columns: 1fr;
}
.folder-btn {
    border: 1px solid var(--border, rgba(203,213,225,0.92));
    border-radius: var(--radius-xs, 6px);
    background: var(--node-neu-surface, rgba(255,255,255,0.82));
    box-shadow: var(--neu-shadow, 2px 2px 4px rgba(0,0,0,0.06), -1px -1px 3px rgba(255,255,255,0.7));
    color: var(--text, #334155);
    padding: 0 14px;
    min-height: 32px;
    font-size: 12px;
    font-weight: 650;
    cursor: pointer;
    transition: background 0.15s, transform 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.folder-btn:hover {
    background: var(--accent-soft, rgba(37,66,243,0.06));
    border-color: var(--accent-line, rgba(37,66,243,0.3));
    color: var(--accent, #2563eb);
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(37,66,243,0.1);
}
.folder-btn:active {
    transform: translateY(0);
    box-shadow: var(--neu-inset, inset 1px 1px 2px rgba(0,0,0,0.06));
}
/* 底部提示 */
.folder-hint {
    padding-top: 2px;
    color: var(--text-muted, #94a3b8);
    font-size: 11px;
    line-height: 1.5;
    text-align: center;
}


:root {
    --image-edit-node-accent: var(--accent, #2563eb);
    --image-edit-node-danger: var(--danger, #ef4444);
    --image-edit-primary-bg: linear-gradient(180deg, color-mix(in srgb, var(--image-edit-node-accent) 88%, white), var(--image-edit-node-accent));
    --image-edit-primary-text: #ffffff;
    --image-edit-primary-shadow: 0 10px 22px color-mix(in srgb, var(--image-edit-node-accent) 20%, transparent), inset 0 1px 0 rgba(255,255,255,.22);
    --image-edit-primary-hover-shadow: 0 14px 28px color-mix(in srgb, var(--image-edit-node-accent) 26%, transparent), inset 0 1px 0 rgba(255,255,255,.28);
    --image-edit-active-bg: color-mix(in srgb, var(--image-edit-node-accent) 8%, var(--node-neu-surface));
    --image-edit-muted-text: #94a3b8;
    --image-edit-disabled-bg: color-mix(in srgb, var(--node-neu-surface) 78%, var(--surface-muted, #e2e8f0));
    --image-edit-panel-bg: color-mix(in srgb, var(--node-neu-bg) 72%, white);
    --image-edit-toolbar-bg: color-mix(in srgb, var(--node-neu-surface) 88%, white);
    --image-edit-card-bg: color-mix(in srgb, var(--node-neu-surface) 70%, transparent);
    --image-edit-result-bg: color-mix(in srgb, var(--node-neu-surface) 86%, var(--type-preview) 6%);
    --image-edit-result-empty-bg: color-mix(in srgb, var(--node-neu-bg) 72%, white);
    --image-edit-viewport-shadow: var(--neu-inset), 0 8px 24px rgba(15,23,42,.04);
    --image-edit-overlay-dimmer: rgba(0,0,0,0.42);
    --image-edit-selection-fill: color-mix(in srgb, var(--image-edit-node-accent) 10%, transparent);
    --image-edit-selection-stroke: var(--image-edit-node-accent);
    --image-edit-handle-fill: var(--node-neu-surface, #fff);
    --image-edit-brush-fill: color-mix(in srgb, var(--image-edit-node-accent) 22%, transparent);
    --image-edit-brush-stroke: color-mix(in srgb, var(--image-edit-node-accent) 85%, transparent);
    --image-edit-eraser-stroke: color-mix(in srgb, var(--image-edit-node-danger) 80%, transparent);
    --image-edit-thumb-bg: var(--node-neu-surface, #fff);
}

/* === 裁剪 / 拼回节点 === */
.node-type-crop,
.node-type-stitch,
.node-type-local-repaint { min-width: 300px; min-height: 240px; }
.node-shell-crop { --node-type-color: var(--type-crop, var(--type-preview)); }
.node-shell-stitch { --node-type-color: var(--type-stitch, var(--type-preview)); }
.node-shell-local-repaint { --node-type-color: var(--type-local-repaint, var(--type-preview)); }
.node-shell-crop .node-frame-body,
.node-shell-stitch .node-frame-body,
.node-shell-local-repaint .node-frame-body { min-height: 0; flex: 1; display: flex; }

/* --- body 容器 --- */
.crop-node-body,
.stitch-node-body,
.local-repaint-node-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
    min-height: 0;
    width: 100%;
}

/* === 裁剪节点 === */

/* 顶部只放模式和比例，避免把所有按钮挤在一行 */
.crop-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}
.crop-lower-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
.crop-action-row {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* 模式按钮：对标绘图节点 param-trigger 的 32px 拟态按钮 */
.crop-mode-group {
    display: inline-flex;
    gap: 8px;
    min-width: 0;
}
.crop-mode-btn {
    height: 32px;
    padding: 0 12px;
    border: none;
    border-radius: 10px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    box-sizing: border-box;
    transition: box-shadow var(--duration-normal), transform var(--duration-fast), color var(--duration-fast);
}
.crop-mode-btn:hover {
    box-shadow: var(--neu-shadow-hover);
    transform: translateY(-1px);
    color: var(--image-edit-node-accent);
}
.crop-mode-btn:active {
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}
.crop-mode-btn.active {
    color: var(--image-edit-node-accent);
    font-weight: 700;
    background: var(--image-edit-active-bg);
    box-shadow: var(--neu-inset);
    transform: translateY(0);
}

/* 裁剪比例下拉：直接复用绘图节点 .param-dropdown / .param-trigger */
.crop-ratio-dropdown {
    flex: 0 0 104px;
    width: 104px;
    min-width: 0;
}
.crop-ratio-dropdown.disabled .param-trigger {
    color: var(--image-edit-muted-text);
    cursor: not-allowed;
    box-shadow: var(--neu-inset);
    opacity: .65;
    transform: none;
}
.crop-ratio-dropdown.disabled .param-trigger::after { border-top-color: var(--image-edit-muted-text); }

/* 操作按钮 */
.crop-output-btn,
.crop-clear-btn {
    height: 32px;
    padding: 0 14px;
    border: 0;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: transform var(--duration-fast), box-shadow var(--duration-fast), background var(--duration-fast), color var(--duration-fast);
    flex: 0 0 auto;
}
.crop-output-btn {
    background: var(--image-edit-primary-bg);
    box-shadow: var(--image-edit-primary-shadow);
    color: var(--image-edit-primary-text);
}
.crop-output-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: var(--image-edit-primary-hover-shadow);
}
.crop-output-btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--neu-inset); }
.crop-clear-btn {
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-muted, #64748b);
}
.crop-clear-btn:hover { transform: translateY(-1px); box-shadow: var(--neu-shadow-hover); color: var(--image-edit-node-danger); }
.crop-clear-btn:active { transform: translateY(0); box-shadow: var(--neu-inset); }
.crop-output-btn:disabled {
    color: var(--image-edit-muted-text);
    cursor: not-allowed;
    background: var(--image-edit-disabled-bg);
    box-shadow: var(--neu-inset);
    transform: none;
}

/* 画笔行 */
.crop-brush-row {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 5px 8px;
    border-radius: 12px;
    background: var(--image-edit-panel-bg);
    box-shadow: var(--neu-inset);
}
.crop-brush-row.is-hidden { display: none; }
.crop-brush-toggle { display: inline-flex; gap: 4px; flex: 0 0 auto; }
.crop-tool-btn {
    width: 30px; height: 28px; padding: 0;
    border: 0; border-radius: 8px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft, #475569);
    font-size: 12px; font-weight: 800;
    cursor: pointer;
    transition: transform var(--duration-fast), box-shadow var(--duration-fast), background var(--duration-fast), color var(--duration-fast);
}
.crop-tool-btn:hover { transform: translateY(-1px); box-shadow: var(--neu-shadow-hover); color: var(--image-edit-node-accent); }
.crop-tool-btn:active { transform: translateY(0); box-shadow: var(--neu-inset); }
.crop-tool-btn.active {
    background: var(--image-edit-primary-bg);
    box-shadow: var(--image-edit-primary-shadow);
    color: var(--image-edit-primary-text);
}
.crop-brush-size {
    flex: 1 1 auto;
    min-width: 132px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 8px;
    border-radius: 8px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    color: var(--text-muted, #64748b);
    font-size: 11px;
    font-weight: 700;
    user-select: none;
    white-space: nowrap;
}
.crop-brush-size > span:first-child { flex: 0 0 auto; min-width: 24px; white-space: nowrap; }
.crop-brush-size-input { flex: 1 1 auto; min-width: 54px; accent-color: var(--image-edit-node-accent); height: 4px; }
.crop-brush-val { flex: 0 0 auto; min-width: 22px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text-soft); font-weight: 750; }
.crop-brush-square {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; gap: 5px;
    height: 28px;
    padding: 0 8px;
    border-radius: 8px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft, #475569);
    font-size: 11px; font-weight: 700;
    cursor: pointer;
    user-select: none;
    transition: box-shadow var(--duration-fast), transform var(--duration-fast);
}
.crop-brush-square:hover { box-shadow: var(--neu-shadow-hover); transform: translateY(-1px); }
.crop-brush-square input { accent-color: var(--image-edit-node-accent); margin: 0; }

/* 裁剪/局部重绘视口 — SVG Overlay 方案 */
.crop-viewport {
    flex: 0 0 auto;
    align-self: center;
    box-sizing: border-box;
    min-height: 0;
    position: relative;
    border: 1px solid color-mix(in srgb, var(--node-type-color) 16%, rgba(203,213,225,.6));
    border-radius: 16px;
    background: var(--node-neu-surface);
    box-shadow: var(--image-edit-viewport-shadow);
    overflow: hidden;
    touch-action: none;
    cursor: crosshair;
    user-select: none;
}
.crop-source-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: fill;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
}
.crop-svg-overlay {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    overflow: visible;
}
.crop-svg-overlay .crop-dimmer { fill: var(--image-edit-overlay-dimmer); }
.crop-svg-overlay .crop-brush-fill { fill: var(--image-edit-brush-fill); }
.crop-svg-overlay .crop-selection-rect {
    fill: var(--image-edit-selection-fill);
    stroke: var(--image-edit-selection-stroke);
    stroke-width: 2px;
    stroke-dasharray: 8 6;
    vector-effect: non-scaling-stroke;
}
.crop-svg-overlay .crop-handle {
    fill: var(--image-edit-handle-fill);
    stroke: var(--image-edit-selection-stroke);
    stroke-width: 2px;
    vector-effect: non-scaling-stroke;
}
.crop-svg-overlay .crop-brush-path {
    fill: none;
    stroke: var(--image-edit-brush-stroke);
    stroke-linecap: round;
    stroke-linejoin: round;
}
.crop-svg-overlay .crop-eraser-path {
    fill: none;
    stroke: var(--image-edit-eraser-stroke);
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 8 6;
}
/* 裁剪空状态 */
.crop-empty-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 140px;
    border-radius: 16px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    text-align: center;
    padding: 24px;
    border: 1px solid color-mix(in srgb, var(--node-type-color) 12%, rgba(203,213,225,.4));
}
.crop-empty-icon {
    width: 52px; height: 52px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 16px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    font-size: 24px;
}
.crop-empty-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--text, #1e293b);
    letter-spacing: .01em;
}
.crop-empty-desc {
    max-width: 240px;
    font-size: 12px;
    color: var(--text-muted, #64748b);
    line-height: 1.5;
}

/* 裁剪脚标 */
.crop-footer {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    min-height: 32px;
    padding: 0 10px;
    border-radius: 10px;
    color: var(--text-muted, #64748b);
    background: var(--image-edit-card-bg);
    box-shadow: var(--neu-inset);
    font-size: 11px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* === 拼回节点 === */

/* 拼回工具栏（底部） */
.stitch-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 5px 8px;
    border-radius: 12px;
    background: var(--image-edit-toolbar-bg);
    box-shadow: var(--neu-inset);
    box-sizing: border-box;
}
.stitch-toolbar > span:first-child {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-height: 26px;
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    border-radius: 999px;
    color: var(--text-muted, #64748b);
    font-size: 11px;
    font-weight: 700;
}
/* 拼回刷新按钮 */
.stitch-run-btn {
    min-width: 64px;
    min-height: 30px;
    padding: 4px 12px;
    border: 0;
    border-radius: 10px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft, #475569);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    flex: 0 0 auto;
    transition: transform var(--duration-fast), box-shadow var(--duration-fast), color var(--duration-fast);
}
.stitch-run-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: var(--neu-shadow-hover);
    color: var(--image-edit-node-accent);
}
.stitch-run-btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--neu-inset); }
.stitch-run-btn:disabled {
    color: var(--image-edit-muted-text);
    cursor: not-allowed;
    box-shadow: var(--neu-inset);
    transform: none;
}

/* 拼回预览框 */
.stitch-preview-frame {
    flex: 0 0 auto;
    align-self: center;
    box-sizing: border-box;
    min-height: 0;
    border: 1px solid color-mix(in srgb, var(--node-type-color) 16%, rgba(203,213,225,.6));
    border-radius: 16px;
    background: var(--node-neu-surface);
    box-shadow: var(--image-edit-viewport-shadow);
    overflow: hidden;
    position: relative;
}
.stitch-preview-frame img { width: 100%; height: 100%; object-fit: fill; display: block; }
.stitch-preview-container { flex: 0 0 auto; align-self: center; height: auto; margin-top: 0; position: relative; }
.stitch-feather-control {
    margin-top: 0;
    flex: 0 0 auto;
    width: 100%;
}

/* 拼回空状态 */
.stitch-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    min-height: 120px;
    border-radius: 16px;
    border: 1px dashed color-mix(in srgb, var(--node-type-color) 16%, rgba(203,213,225,.5));
    background: var(--image-edit-card-bg);
    color: var(--text-muted, #94a3b8);
    font-size: 12px;
    font-weight: 700;
    text-align: center;
}

/* 端口层级 */
.node-type-crop .port,
.node-type-stitch .port { z-index: 90; }


/* === 局部重绘节点 === */
.local-repaint-node-body .crop-action-row {
    flex-wrap: wrap;
}
.local-repaint-footer {
    flex: 1 1 120px;
}
.local-repaint-upload-btn {
    min-width: 58px;
}
.local-repaint-empty-state .local-repaint-upload-btn {
    margin-top: 8px;
}
.local-repaint-result-strip {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 54px;
    padding: 8px 10px;
    border-radius: 14px;
    background: var(--image-edit-result-bg);
    box-shadow: var(--neu-inset);
    color: var(--text-soft);
    box-sizing: border-box;
    overflow: hidden;
}
.local-repaint-result-strip img {
    width: 46px;
    height: 46px;
    border-radius: 10px;
    object-fit: cover;
    flex: 0 0 auto;
    box-shadow: var(--neu-shadow);
    background: var(--image-edit-thumb-bg);
}
.local-repaint-result-strip > div {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 3px;
}
.local-repaint-result-strip strong {
    font-size: 12px;
    font-weight: 800;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.local-repaint-result-strip span {
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.local-repaint-result-strip.preview-img-container {
    cursor: zoom-in;
}
.local-repaint-result-strip.is-empty {
    border: 1px dashed color-mix(in srgb, var(--text-muted) 24%, transparent);
    background: var(--image-edit-result-empty-bg);
}
.node-shell-local-repaint .crop-viewport {
    position: relative;
}

/* === 图片处理节点补充样式 === */
.proc-seg {
    border: none; background: transparent; border-radius: 8px;
    color: var(--processor-text-muted); font-size: 12px; font-weight: 700;
    cursor: pointer; user-select: none; padding: 0; white-space: nowrap;
    transition: box-shadow var(--duration-fast), color var(--duration-fast), background var(--duration-fast);
}
.proc-seg:hover:not(.active) { color: var(--processor-text); }
.proc-seg.active { background: var(--processor-control-bg); box-shadow: var(--processor-control-raised-shadow); color: var(--processor-accent); }

/* 参数卡片 — 凹陷面板 */
.proc-params-card {
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--processor-panel-bg);
    box-shadow: var(--processor-panel-shadow);
    display: flex;
    flex-direction: column;
    gap: 0;
}
.proc-param-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 36px;
    padding: 6px 0;
    min-width: 0;
}
.proc-param-row + .proc-param-row {
    border-top: 1px solid var(--processor-divider);
}
.proc-param-section-divider {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0 2px;
    color: var(--processor-text-muted);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    user-select: none;
}
.proc-param-section-divider::before,
.proc-param-section-divider::after {
    content: '';
    flex: 1 1 0;
    border-top: 1px solid var(--processor-divider);
}
.proc-param-section-divider + .proc-param-row {
    border-top: 0;
}
.proc-param-row.is-inactive > .proc-param-controls { opacity: 0.38; pointer-events: none; }
.proc-param-row.is-inactive > .proc-param-label { color: var(--processor-text-muted); }

/* 开关圆点 */
.proc-toggle { flex: 0 0 auto; width: 16px; height: 16px; cursor: pointer; position: relative; }
.proc-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.proc-toggle-dot {
    display: block; width: 14px; height: 14px; border-radius: 50%;
    background: var(--processor-control-bg); box-shadow: var(--processor-control-shadow);
    transition: box-shadow var(--duration-fast), background var(--duration-fast);
}
.proc-toggle input:checked + .proc-toggle-dot {
    background: var(--processor-accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--processor-accent) 25%, transparent), inset 1px 1px 2px rgba(0,0,0,0.18);
}
.proc-toggle:hover .proc-toggle-dot { box-shadow: var(--processor-control-hover-shadow); }

/* 标签 */
.proc-param-label {
    flex: 0 0 32px; font-size: 11px; font-weight: 700;
    color: var(--processor-text); user-select: none;
    white-space: nowrap;
}
.node-shell-image-processor .proc-param-label {
    flex-basis: 46px;
}

/* 控件区 */
.proc-param-controls {
    flex: 1 1 0; min-width: 0;
    display: flex; align-items: center; gap: 8px;
}

/* 尺寸行 */
.proc-param-controls-resize {
    display: grid;
    grid-template-columns: 64px minmax(70px, 1fr) 10px minmax(70px, 1fr);
    gap: 6px;
    width: 100%;
}
.proc-param-controls-resize .proc-aspect-dropdown {
    width: 64px;
    min-width: 64px;
}
.proc-param-controls-resize .param-trigger { height: 28px; padding: 0 18px 0 8px; font-size: 11px; }
.proc-mini-input {
    flex: 1 1 0;
    min-width: 64px;
    height: 28px; padding: 0 6px; text-align: center;
    font-size: 11px; font-weight: 600;
}
.processor-width-input,
.processor-height-input {
    width: 100%;
    min-width: 70px;
}
.proc-dim-x { display: flex; align-items: center; justify-content: center; font-size: 10px; color: var(--processor-text-muted); font-weight: 700; }

/* 质量滑块 */
.proc-slider {
    flex: 1 1 auto; min-width: 0; height: 5px;
    -webkit-appearance: none; appearance: none;
    background: var(--processor-accent-track);
    border-radius: 999px; outline: none; cursor: pointer; margin: 0; padding: 0;
}
.proc-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 14px; height: 14px; border: none; border-radius: 50%;
    background: var(--processor-accent);
    box-shadow: 0 1px 4px rgba(0,0,0,0.2), 0 0 0 2px var(--processor-control-bg);
    cursor: grab; transition: transform var(--duration-fast);
}
.proc-slider::-webkit-slider-thumb:hover { transform: scale(1.18); }
.proc-slider::-webkit-slider-thumb:active { cursor: grabbing; }
.proc-slider:disabled { opacity: 0.45; cursor: not-allowed; }
.processor-quality-input { max-width: 50px; flex: 0 0 50px; }

/* 限制行 */
.proc-unit-dropdown { flex: 0 0 52px; width: 52px; }
.proc-unit-dropdown .param-trigger { height: 28px; padding: 0 18px 0 7px; font-size: 11px; }
.proc-param-controls .processor-max-size-input { min-width: 96px; flex: 1 1 0; }

/* 预设行：补齐参数卡片的左右内边距后，再复用同一套行栅格 */
.proc-preset-row {
    box-sizing: border-box;
    width: 100%;
    margin-left: 0;
    padding: 6px 12px;
}
.proc-preset-spacer { pointer-events: none; cursor: default; opacity: 0; }
.proc-preset-controls { gap: 8px; }
.proc-preset-wrap { position: relative; flex: 1 1 0; min-width: 0; display: flex; }
.proc-preset-trigger {
    box-sizing: border-box;
    width: 100%; min-width: 0; height: 28px;
    padding: 0 8px 0 10px;
    border: none; border-radius: 10px;
    background: var(--processor-control-bg);
    box-shadow: var(--processor-control-shadow);
    color: var(--processor-text-soft);
    font-size: 12px; font-weight: 750;
    cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 10px;
    transition: box-shadow var(--duration-fast), color var(--duration-fast), transform var(--duration-fast);
}
.proc-preset-trigger-label {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.proc-preset-caret { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-muted); transition: transform var(--duration-fast), color var(--duration-fast); }
.proc-preset-trigger:hover { box-shadow: var(--processor-control-shadow), var(--processor-control-hover-shadow); color: var(--processor-text); }
.proc-preset-trigger:hover .proc-preset-caret { color: var(--processor-accent); }
.proc-preset-trigger.active { color: var(--processor-accent); }
.proc-preset-trigger.is-open { color: var(--processor-accent); box-shadow: var(--processor-control-shadow); transform: none; }
.proc-preset-trigger.is-open .proc-preset-caret { color: var(--processor-accent); transform: rotate(180deg); }

.proc-preset-save-btn {
    box-sizing: border-box;
    flex: 0 0 28px; width: 28px; height: 28px; min-height: 28px; padding: 0;
    border: none; border-radius: 8px;
    background: var(--processor-control-bg); box-shadow: var(--processor-control-raised-shadow);
    color: var(--processor-text-soft);
    cursor: pointer; display: flex; align-items: center; justify-content: center;
    transition: box-shadow var(--duration-fast), transform var(--duration-fast), color var(--duration-fast);
}
.proc-preset-save-btn svg { width: 13px; height: 13px; }
.proc-preset-save-btn:hover { box-shadow: var(--processor-control-hover-shadow); transform: translateY(-1px); color: var(--processor-accent); }

/* 参数预设下拉：跟绘图节点 param-panel 一样悬浮到 body 上 */
.proc-preset-popup {
    display: none;
    position: fixed;
    left: 0;
    top: 0;
    min-width: 240px;
    max-width: 360px;
    padding: 6px;
    background: var(--processor-popup-bg);
    border: var(--processor-popup-border);
    border-radius: 10px;
    box-shadow: var(--processor-popup-shadow);
    z-index: 2600;
    animation: dropdown-enter var(--duration-normal) var(--ease-out);
}
.proc-preset-popup.show { display: block; }
.proc-preset-popup-body { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow-y: auto; }
.proc-preset-item {
    min-width: 0;
    min-height: 30px;
    display: flex;
    align-items: center;
    border-radius: 7px;
    background: transparent;
    box-shadow: none;
    overflow: hidden;
    color: var(--processor-text-soft);
}
.proc-preset-item.active { color: var(--processor-accent); background: var(--processor-option-active-bg); }
.proc-preset-chip {
    flex: 1 1 auto; min-width: 0; height: 30px; padding: 0 8px 0 10px;
    border: none; background: transparent; color: inherit;
    font-size: 12px; font-weight: 650; cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left;
}
.proc-preset-delete {
    flex: 0 0 28px; height: 30px; border: none; background: transparent;
    color: var(--processor-text-muted); font-size: 14px; font-weight: 800; cursor: pointer;
}
.proc-preset-item:hover { background: var(--processor-option-hover-bg); color: var(--processor-text); }
.proc-preset-item.active .proc-preset-chip { color: var(--processor-accent); font-weight: 750; }
.proc-preset-delete:hover { color: var(--danger); background: var(--processor-danger-soft); }
.proc-preset-empty { font-size: 12px; color: var(--processor-text-muted); opacity: 0.75; padding: 8px 10px; text-align: center; }

/* 处理按钮 — 和绘图节点"发送生成"一致 */
.proc-run-btn { width: 100%; flex: 0 0 40px; height: 40px; margin-top: 2px; }
.proc-run-btn:disabled {
    background: var(--node-neu-surface); box-shadow: var(--neu-inset);
    cursor: not-allowed; opacity: 0.55; transform: none; color: var(--text-muted);
}

/* 前后对比 */
.proc-compare-strip {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    min-height: 82px;
}
.proc-compare-card {
    position: relative;
    min-width: 0;
    height: 82px;
    border-radius: 12px;
    overflow: hidden;
    background: var(--processor-card-bg);
    box-shadow: var(--processor-card-shadow);
    cursor: zoom-in;
}
.proc-compare-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.proc-compare-card span {
    position: absolute;
    left: 7px;
    top: 7px;
    z-index: 1;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--processor-badge-bg);
    color: var(--processor-badge-text);
    font-size: 10px;
    font-weight: 800;
}

/* 属性列表容器 */
.proc-props {
    display: flex;
    flex-direction: column;
}
.proc-prop-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 34px;
    padding: 5px 0;
    min-width: 0;
}
.proc-prop-row + .proc-prop-row {
    border-top: 1px solid color-mix(in srgb, var(--text-muted) 12%, transparent);
}
.proc-prop-row.is-inactive .proc-prop-control:not(.proc-limit-preset-control) { opacity: 0.42; pointer-events: none; }
.proc-prop-row.is-inactive .proc-limit-preset-control > :not(.proc-preset-wrap) { opacity: 0.42; pointer-events: none; }
.proc-prop-row.is-inactive .proc-prop-label { color: var(--text-muted); }

/* 开关圆点 */
.proc-prop-toggle {
    flex: 0 0 auto;
    width: 16px; height: 16px;
    cursor: pointer;
    position: relative;
}
.proc-prop-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.proc-toggle-dot {
    display: block;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--processor-control-bg);
    box-shadow: var(--processor-control-shadow);
    transition: box-shadow var(--duration-fast), background var(--duration-fast);
}
.proc-prop-toggle input:checked + .proc-toggle-dot {
    background: var(--processor-accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--processor-accent) 25%, transparent), inset 1px 1px 2px rgba(0,0,0,0.18);
}
.proc-prop-toggle:hover .proc-toggle-dot { box-shadow: var(--processor-control-hover-shadow); }
.proc-prop-toggle input:checked:hover + .proc-toggle-dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--processor-accent) 28%, transparent), inset 1px 1px 2px rgba(0,0,0,0.18); }

/* 标签 */
.proc-prop-label {
    flex: 0 0 34px;
    font-size: 12px;
    font-weight: 700;
    color: var(--processor-text);
    user-select: none;
}

/* 控件容器 */
.proc-prop-control {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: flex-end;
}

/* 分段控件（格式选择） */
.proc-segmented {
    flex: 0 0 30px;
    min-width: 0;
    height: 30px;
    min-height: 30px;
    max-height: 30px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0;
    padding: 3px;
    border-radius: 9px;
    background: var(--processor-panel-bg);
    box-shadow: var(--processor-panel-shadow);
}
.proc-seg {
    border: none;
    background: transparent;
    border-radius: 7px;
    color: var(--processor-text-muted);
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    user-select: none;
    transition: box-shadow var(--duration-fast), color var(--duration-fast), background var(--duration-fast);
    padding: 0 4px;
    white-space: nowrap;
}
.proc-seg:hover:not(.active) { color: var(--processor-text); }
.proc-seg.active {
    background: var(--processor-control-bg);
    box-shadow: var(--processor-control-raised-shadow);
    color: var(--processor-accent);
}

/* 尺寸行 */
.proc-prop-control-resize { gap: 6px; }
.proc-prop-control-resize .proc-aspect-dropdown {
    flex: 0 0 74px;
    min-width: 74px;
    max-width: 74px;
}
.proc-prop-control-resize .param-trigger { height: 28px; padding: 0 20px 0 8px; font-size: 11px; }
.proc-mini-input {
    flex: 0 0 56px;
    width: 56px;
    height: 28px;
    padding: 0 6px;
    text-align: center;
    font-size: 11px;
    font-weight: 600;
}
.proc-dim-x {
    flex: 0 0 auto;
    font-size: 11px;
    color: var(--processor-text-muted);
    font-weight: 700;
}

/* 滑块 */
.proc-slider {
    flex: 1 1 auto;
    min-width: 0;
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    background: var(--processor-accent-track);
    box-shadow: var(--processor-control-shadow);
    border-radius: 999px;
    outline: none;
    cursor: pointer;
    margin: 0;
    padding: 0;
}
.proc-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px; height: 16px;
    border: none;
    border-radius: 50%;
    background: var(--processor-accent);
    box-shadow: 0 2px 5px rgba(0,0,0,0.18), 0 0 0 2px var(--processor-control-bg);
    cursor: grab;
    transition: transform var(--duration-fast);
}
.proc-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
.proc-slider::-webkit-slider-thumb:active { cursor: grabbing; }
.proc-slider:disabled { opacity: 0.5; cursor: not-allowed; }

/* 限制 + 预设行 */
.proc-limit-preset-control {
    justify-content: flex-start;
    gap: 10px;
}
.proc-limit-preset-control .processor-max-size-input {
    flex: 0 0 72px;
    width: 72px;
}
/* 单位下拉 */
.proc-unit-dropdown {
    flex: 0 0 58px;
    width: 58px;
}
.proc-unit-dropdown .param-trigger { height: 28px; padding: 0 20px 0 8px; font-size: 11px; }

/* 底部操作栏 */
.proc-bottom-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
}

/* 预设触发按钮 + 浮层 */
.proc-preset-wrap { position: relative; flex: 0 0 auto; }
.proc-icon-btn {
    width: auto; height: 30px;
    min-width: 74px;
    padding: 0 10px;
    border: none;
    border-radius: 9px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    font-size: 11px;
    font-weight: 800;
    transition: box-shadow var(--duration-fast), color var(--duration-fast), transform var(--duration-fast);
}
.proc-icon-btn svg { width: 14px; height: 14px; }
.proc-icon-btn:hover { box-shadow: var(--neu-shadow-hover); transform: translateY(-1px); color: var(--node-type-color); }
.proc-icon-btn.active { color: var(--node-type-color); box-shadow: var(--neu-inset); }

.proc-preset-popup {
    display: none;
    position: absolute;
    bottom: calc(100% + 8px);
    right: 0;
    min-width: 220px;
    max-width: 320px;
    padding: 10px;
    background: var(--surface);
    border: 1px solid rgba(203, 213, 225, 0.4);
    border-radius: 12px;
    box-shadow: 8px 8px 20px rgba(163, 177, 198, 0.3), -8px -8px 20px rgba(255,255,255,0.65);
    z-index: 2100;
    animation: dropdown-enter var(--duration-normal) var(--ease-out);
}
.proc-preset-popup.show { display: block; }
.proc-preset-popup-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    font-size: 11px;
    font-weight: 800;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.proc-preset-save-btn {
    height: 24px;
    padding: 0 10px;
    border: none;
    border-radius: 7px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    color: var(--text-soft);
    font-size: 10.5px;
    font-weight: 700;
    cursor: pointer;
    text-transform: none;
    letter-spacing: 0;
}
.proc-preset-save-btn:hover { box-shadow: var(--neu-shadow-hover); color: var(--node-type-color); }
.proc-preset-popup-body {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    max-height: 180px;
    overflow-y: auto;
}
.proc-preset-item {
    flex: 0 1 100%;
    min-width: 0;
    height: 28px;
    display: flex;
    align-items: center;
    border-radius: 8px;
    background: var(--node-neu-surface);
    box-shadow: var(--neu-shadow);
    overflow: hidden;
}
.proc-preset-item.active { color: var(--node-type-color); box-shadow: var(--neu-inset); }
.proc-preset-chip {
    flex: 1 1 auto;
    min-width: 0;
    height: 28px;
    padding: 0 8px 0 10px;
    border: none;
    background: transparent;
    color: inherit;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: left;
}
.proc-preset-delete {
    flex: 0 0 26px;
    height: 28px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 15px;
    font-weight: 800;
    cursor: pointer;
}
.proc-preset-item:hover { box-shadow: var(--neu-shadow-hover); color: var(--text); }
.proc-preset-item.active .proc-preset-chip { color: var(--node-type-color); font-weight: 700; }
.proc-preset-delete:hover { color: var(--danger); }
.proc-preset-empty { font-size: 11px; color: var(--text-muted); opacity: 0.7; padding: 6px 4px; }

/* 处理按钮：尺寸与绘图节点“发送生成”一致 */
.proc-run-btn {
    width: 100%;
    flex: 0 0 40px;
    height: 40px;
    margin-top: 0;
}
.proc-run-btn:hover:not(:disabled) {
    color: var(--accent, #2440ED);
}
.proc-run-btn:disabled {
    background: var(--node-neu-surface);
    box-shadow: var(--neu-inset);
    cursor: not-allowed;
    opacity: 0.6;
    transform: none;
    color: var(--text-muted);
}

/* 图片处理参数预设：下拉与保存按钮合并为一个整体，外宽对齐参数面板 */
.node-shell-image-processor .proc-preset-combo {
    box-sizing: border-box;
    width: 100%;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 38px;
    align-items: stretch;
    margin: 0;
    border-radius: 12px;
    background: var(--processor-panel-bg);
    box-shadow: var(--processor-panel-shadow);
    overflow: hidden;
}
.node-shell-image-processor .proc-preset-dropdown {
    width: 100%;
    min-width: 0;
}
.node-shell-image-processor .proc-preset-trigger.param-trigger {
    width: 100%;
    height: 34px;
    padding: 0 30px 0 12px;
    border-radius: 12px 0 0 12px;
    background: transparent;
    box-shadow: none;
    color: var(--processor-text-soft);
    font-size: 12px;
    font-weight: 800;
    transform: none;
}
.node-shell-image-processor .proc-preset-trigger.param-trigger:hover {
    box-shadow: none;
    transform: none;
    color: var(--processor-accent);
}
.node-shell-image-processor .proc-preset-trigger.param-trigger.active {
    color: var(--processor-accent);
}
.node-shell-image-processor .proc-preset-trigger.param-trigger::after {
    right: 12px;
}
.node-shell-image-processor .proc-preset-save-btn {
    box-sizing: border-box;
    width: 38px;
    height: 34px;
    min-width: 38px;
    min-height: 34px;
    padding: 0;
    border: none;
    border-left: 1px solid var(--processor-save-divider);
    border-radius: 0 12px 12px 0;
    background: transparent;
    box-shadow: none;
    color: var(--processor-text-soft);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color var(--duration-fast), background var(--duration-fast);
}
.node-shell-image-processor .proc-preset-save-btn svg {
    width: 14px;
    height: 14px;
}
.node-shell-image-processor .proc-preset-save-btn:hover {
    color: var(--processor-accent);
    background: var(--processor-save-hover-bg);
    box-shadow: none;
    transform: none;
}
.node-shell-image-processor .proc-preset-panel.param-panel {
    min-width: 220px;
    max-width: 360px;
    padding: 4px;
    z-index: 2600;
}
.node-shell-image-processor .proc-preset-panel-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 220px;
    overflow-y: auto;
}
.node-shell-image-processor .proc-preset-option.param-option,
.proc-preset-panel .proc-preset-option.param-option {
    position: relative;
    min-width: 0;
    min-height: 32px;
    padding: 0 42px 0 10px;
    display: flex;
    align-items: center;
    white-space: normal;
}
.node-shell-image-processor .proc-preset-option.param-option:hover,
.proc-preset-panel .proc-preset-option.param-option:hover {
    background: var(--processor-option-hover-bg);
    color: var(--processor-text);
}
.node-shell-image-processor .proc-preset-option.param-option.active,
.proc-preset-panel .proc-preset-option.param-option.active {
    background: var(--processor-option-active-bg);
    color: var(--processor-accent);
}
.node-shell-image-processor .proc-preset-option-label,
.proc-preset-panel .proc-preset-option-label {
    min-width: 0;
    width: 100%;
    padding-right: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.node-shell-image-processor .proc-preset-option .proc-preset-delete,
.proc-preset-panel .proc-preset-option .proc-preset-delete {
    position: absolute;
    top: 50%;
    right: 7px;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    min-width: 22px;
    min-height: 22px;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--processor-text-muted) 30%, transparent);
    border-radius: 50%;
    background: color-mix(in srgb, var(--processor-text-muted) 7%, transparent);
    color: var(--processor-text-muted);
    font-size: 14px;
    line-height: 18px;
    font-weight: 900;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
}
.node-shell-image-processor .proc-preset-option .proc-preset-delete:hover,
.proc-preset-panel .proc-preset-option .proc-preset-delete:hover {
    color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 45%, transparent);
    background: var(--processor-danger-soft);
    transform: translateY(-50%);
}
.node-shell-image-processor .proc-preset-empty {
    padding: 8px 10px;
    color: var(--processor-text-muted);
    font-size: 12px;
    text-align: center;
    opacity: 0.75;
}
.node-shell-image-processor .proc-param-controls-resize {
    grid-template-columns: 64px minmax(70px, 1fr) 10px minmax(70px, 1fr);
    gap: 6px;
}
.node-shell-image-processor .proc-param-controls-resize .proc-aspect-dropdown {
    width: 64px;
    min-width: 64px;
    max-width: 64px;
}
.node-shell-image-processor .proc-mini-input {
    flex: 1 1 0;
    min-width: 64px;
    height: 28px;
    padding: 0 6px;
}
.node-shell-image-processor .processor-width-input,
.node-shell-image-processor .processor-height-input {
    width: 100%;
    min-width: 70px;
}
.node-shell-image-processor .processor-quality-input {
    flex: 0 0 46px;
    width: 46px;
    max-width: 46px;
    min-width: 46px;
}
.node-shell-image-processor .proc-unit-dropdown {
    flex: 0 0 50px;
    width: 50px;
}
