/* ==================== Reset & Variables ==================== */ * { margin: 0; padding: 0; box-sizing: border-box; } :root { --bg: #f6f7fb; --bg-gradient: radial-gradient(1200px 800px at 15% -10%, #eef2ff 0%, transparent 55%), radial-gradient(1000px 700px at 110% 110%, #fdf4ff 0%, transparent 60%), #f6f7fb; --panel-bg: #ffffff; --panel-bg-subtle: #f8fafc; --border: #e5e7eb; --border-light: #eef0f4; --border-hover: #d1d5db; --text: #0f172a; --text-secondary: #64748b; --text-placeholder: #94a3b8; --primary: #6366f1; --primary-hover: #4f46e5; --primary-light: #eef2ff; --primary-dark: #4338ca; --primary-ring: rgba(99, 102, 241, 0.18); --primary-gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); --success: #10b981; --success-light: #ecfdf5; --warning: #f59e0b; --warning-light: #fffbeb; --danger: #ef4444; --danger-light: #fef2f2; --info: #64748b; --info-light: #f1f5f9; --shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.04); --shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 2px 8px rgba(15, 23, 42, 0.04); --shadow-lg: 0 4px 20px rgba(15, 23, 42, 0.08); --shadow-primary: 0 4px 14px rgba(99, 102, 241, 0.25); --radius-sm: 6px; --radius: 10px; --radius-lg: 14px; --transition: all 160ms cubic-bezier(0.4, 0, 0.2, 1); } body { font-family: 'Inter', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; background: var(--bg-gradient); color: var(--text); height: 100vh; overflow: hidden; font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* ==================== App Layout ==================== */ .app { height: 100vh; display: flex; flex-direction: column; padding: 14px; gap: 12px; } /* ==================== History Bar ==================== */ .history-bar { flex-shrink: 0; background: var(--panel-bg); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow); display: flex; align-items: center; padding: 0 18px; height: 52px; gap: 14px; } .history-title { font-weight: 700; font-size: 11.5px; color: var(--text-secondary); flex-shrink: 0; user-select: none; letter-spacing: 0.7px; text-transform: uppercase; } .history-scroll { flex: 1; display: flex; gap: 6px; overflow-x: auto; overflow-y: hidden; align-items: center; padding: 4px 0; } .history-scroll::-webkit-scrollbar { height: 3px; } .history-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } .history-empty { color: var(--text-placeholder); font-size: 13px; white-space: nowrap; } .history-clear-btn { flex-shrink: 0; } /* History Item */ .history-item { flex-shrink: 0; display: flex; align-items: center; gap: 5px; padding: 4px 8px; border-radius: 6px; cursor: pointer; transition: var(--transition); border: 1px solid var(--border); background: var(--bg); font-size: 11px; white-space: nowrap; } .history-item:hover { border-color: var(--primary); background: var(--primary-light); } .history-thumb { width: 26px; height: 26px; border-radius: 3px; object-fit: cover; border: 1px solid var(--border); } .history-thumb.repeated { border: 2px solid #333; } .history-badge { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 3px; font-size: 10px; font-weight: 700; color: white; flex-shrink: 0; } .history-badge.badge-p { background: var(--primary); } .history-badge.badge-c { background: var(--warning); } .history-badge.badge-s { background: var(--success); } .history-type-label { font-size: 10px; font-weight: 600; color: var(--text-secondary); } .history-separator { width: 1px; height: 22px; background: var(--border); flex-shrink: 0; margin: 0 2px; } /* History group tinting — one muted palette with a subtle left-accent bar */ .history-item.hc-0 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #6366f1; } .history-item.hc-1 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #10b981; } .history-item.hc-2 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #f59e0b; } .history-item.hc-3 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #ef4444; } .history-item.hc-4 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #64748b; } .history-item.hc-5 { background: var(--panel-bg); border-color: var(--border); border-left: 3px solid #06b6d4; } .history-item.hc-0:hover, .history-item.hc-1:hover, .history-item.hc-2:hover, .history-item.hc-3:hover, .history-item.hc-4:hover, .history-item.hc-5:hover { background: var(--primary-light); border-color: var(--primary); } /* ==================== Workspace (CSS Grid) ==================== */ .workspace { flex: 1; display: grid; grid-template-columns: 1fr minmax(280px, 0.45fr); grid-template-rows: 1fr auto auto; gap: 10px; min-height: 0; } /* Grid placement */ .image-panel { grid-row: 1; grid-column: 1; } .sp-panel { grid-row: 1; grid-column: 2; } .params-bar { grid-row: 2; grid-column: 1; } .gen-sp-btn { grid-row: 2; grid-column: 2; } .prompt-bar { grid-row: 3; grid-column: 1; } .gen-image-btn { grid-row: 3; grid-column: 2; } /* ==================== Panel Base ==================== */ .panel { background: var(--panel-bg); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow); overflow: hidden; } .panel-toolbar { display: flex; align-items: center; justify-content: space-between; padding: 8px 14px; border-bottom: 1px solid var(--border-light); background: var(--panel-bg-subtle); flex-shrink: 0; } .panel-label { font-weight: 700; font-size: 11.5px; color: var(--text-secondary); letter-spacing: 0.7px; text-transform: uppercase; user-select: none; } .panel-actions { display: flex; gap: 2px; } /* Tool Buttons */ .tool-btn { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border: 1px solid transparent; background: transparent; color: var(--text-secondary); border-radius: var(--radius-sm); cursor: pointer; transition: var(--transition); } .tool-btn:hover { background: var(--primary-light); color: var(--primary); border-color: var(--border-light); } /* ==================== Image Panel ==================== */ .image-panel { display: flex; flex-direction: column; min-height: 0; } .image-area { flex: 1; display: flex; align-items: center; justify-content: center; position: relative; min-height: 0; overflow: hidden; } /* Dropzone */ .dropzone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; width: calc(100% - 28px); height: calc(100% - 28px); margin: 14px; cursor: pointer; border: 1.5px dashed var(--border-hover); border-radius: var(--radius); transition: var(--transition); background: var(--panel-bg-subtle); } .dropzone:hover, .dropzone.dragover { border-color: var(--primary); background: var(--primary-light); transform: scale(1.005); } .dropzone-icon { font-size: 44px; opacity: 0.55; transition: var(--transition); } .dropzone:hover .dropzone-icon { opacity: 0.85; transform: translateY(-2px); } .dropzone-text { color: var(--text-secondary); font-size: 13px; font-weight: 500; letter-spacing: 0.1px; } /* Image Display */ .image-display { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; padding: 8px; } .image-display img { max-width: 100%; max-height: 100%; object-fit: contain; cursor: pointer; border-radius: 4px; transition: opacity 0.2s; } .image-display img:hover { opacity: 0.95; } /* BBox Overlay */ .bbox-container { position: absolute; pointer-events: none; display: none; } .bbox-box { position: absolute; border: 2px solid; pointer-events: auto; cursor: default; border-radius: 2px; } .bbox-box.focused { border-width: 3px; z-index: 10; } .bbox-box.active { border-width: 3px; z-index: 10; cursor: move; } .bbox-box .bbox-handle { display: none; } .bbox-box.active .bbox-handle { display: block; } .bbox-box .bbox-label { position: absolute; top: -20px; left: -1px; padding: 1px 6px; font-size: 10px; color: white; border-radius: 3px 3px 0 0; white-space: nowrap; max-width: 140px; overflow: hidden; text-overflow: ellipsis; font-weight: 500; line-height: 16px; pointer-events: none; } /* BBox Resize Handles */ .bbox-handle { position: absolute; width: 8px; height: 8px; background: white; border: 2px solid; border-radius: 2px; pointer-events: auto; z-index: 11; } .bbox-handle.h-nw { top: -5px; left: -5px; cursor: nw-resize; } .bbox-handle.h-ne { top: -5px; right: -5px; cursor: ne-resize; } .bbox-handle.h-sw { bottom: -5px; left: -5px; cursor: sw-resize; } .bbox-handle.h-se { bottom: -5px; right: -5px; cursor: se-resize; } .bbox-handle.h-n { top: -5px; left: 50%; margin-left: -4px; cursor: n-resize; } .bbox-handle.h-s { bottom: -5px; left: 50%; margin-left: -4px; cursor: s-resize; } .bbox-handle.h-w { top: 50%; margin-top: -4px; left: -5px; cursor: w-resize; } .bbox-handle.h-e { top: 50%; margin-top: -4px; right: -5px; cursor: e-resize; } /* ==================== Structured Prompt Panel ==================== */ .sp-panel { display: flex; flex-direction: column; min-height: 0; } .sp-area { flex: 1; display: flex; align-items: center; justify-content: center; min-height: 0; position: relative; overflow: hidden; } .sp-empty { text-align: center; color: var(--text-placeholder); padding: 20px; } .sp-empty-icon { font-size: 36px; margin-bottom: 8px; opacity: 0.5; } .sp-empty-hint { font-size: 12px; margin-top: 6px; color: var(--text-placeholder); } .sp-area textarea { width: 100%; height: 100%; border: none; outline: none; resize: none; padding: 12px; font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', 'Liberation Mono', monospace; font-size: 12px; line-height: 1.65; color: var(--text); background: transparent; tab-size: 2; } .sp-area textarea::placeholder { color: var(--text-placeholder); } /* ==================== SP Structured View ==================== */ .sp-structured { width: 100%; height: 100%; overflow-y: auto; padding: 8px; } /* Section (collapsible) */ .sp-section { border: 1px solid var(--border-light); border-radius: 6px; margin-bottom: 6px; overflow: hidden; background: var(--panel-bg); } .sp-section:last-child { margin-bottom: 0; } .sp-section-header { display: flex; align-items: center; justify-content: space-between; padding: 7px 10px; cursor: pointer; user-select: none; font-size: 12px; font-weight: 600; color: var(--text); transition: var(--transition); } .sp-section-header:hover { background: var(--bg); } .sp-section-title { display: flex; align-items: center; gap: 6px; } .sp-section-badge { background: var(--primary); color: white; border-radius: 8px; padding: 0 6px; font-size: 10px; font-weight: 700; line-height: 16px; min-width: 16px; text-align: center; } .sp-section-actions { display: flex; align-items: center; gap: 4px; } .sp-section-add-btn { width: 20px; height: 20px; border: 1px dashed var(--border); background: transparent; color: var(--text-secondary); border-radius: 3px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px; transition: var(--transition); padding: 0; line-height: 1; } .sp-section-add-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); } .sp-section-clear-btn { width: 20px; height: 20px; border: none; background: transparent; color: var(--text-placeholder); border-radius: 3px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 11px; transition: var(--transition); padding: 0; opacity: 0; } .sp-section-header:hover .sp-section-clear-btn { opacity: 1; } .sp-section-clear-btn:hover { background: var(--danger-light); color: var(--danger); } .sp-section-arrow { font-size: 12px; color: var(--text-secondary); transition: transform 0.2s; } .sp-section.collapsed .sp-section-arrow { transform: rotate(-90deg); } .sp-section-body { padding: 4px 8px 8px; overflow: hidden; } .sp-section.collapsed .sp-section-body { display: none; } /* Field row */ .sp-field { display: flex; align-items: flex-start; padding: 4px 6px; border-radius: 4px; transition: background 0.15s; gap: 8px; position: relative; } .sp-field:hover { background: #f5f7fa; } .sp-field-key { font-size: 11px; font-weight: 600; color: var(--primary-dark); min-width: 80px; flex-shrink: 0; padding-top: 1px; font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace; cursor: default; border-radius: 3px; transition: background 0.15s; } .sp-field-key[contenteditable="true"] { outline: none; background: #fff; border: 1px solid var(--warning); padding: 0 3px; box-shadow: 0 0 0 2px rgba(230, 162, 60, 0.12); user-select: text; } .sp-field-value { flex: 1; font-size: 12px; line-height: 1.5; color: var(--text); word-break: break-word; cursor: default; min-height: 18px; border-radius: 3px; transition: background 0.15s; } .sp-field-value[contenteditable="true"] { outline: none; background: #fff; border: 1px solid var(--primary); border-radius: 3px; padding: 1px 4px; box-shadow: 0 0 0 2px var(--primary-ring); } .sp-field-actions { display: none; gap: 2px; flex-shrink: 0; align-items: center; } .sp-field:hover .sp-field-actions { display: flex; } .sp-field-btn { width: 20px; height: 20px; border: none; background: transparent; color: var(--text-secondary); border-radius: 3px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 12px; transition: var(--transition); padding: 0; } .sp-field-btn:hover { background: var(--danger-light); color: var(--danger); } .sp-field-btn.edit-btn:hover, .sp-field-btn.sp-elem-add-btn:hover { background: var(--primary-light); color: var(--primary); } /* Dict field (nested) */ .sp-dict-block { flex: 1; display: flex; flex-direction: column; gap: 1px; } .sp-dict-row { display: flex; gap: 6px; padding: 2px 0; align-items: flex-start; } .sp-dict-key { font-size: 11px; color: var(--text-secondary); min-width: 70px; flex-shrink: 0; font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace; cursor: default; border-radius: 3px; } .sp-dict-key[contenteditable="true"] { outline: none; background: #fff; border: 1px solid var(--warning); padding: 0 3px; box-shadow: 0 0 0 2px rgba(230, 162, 60, 0.12); } .sp-dict-value { flex: 1; font-size: 12px; color: var(--text); word-break: break-word; cursor: default; border-radius: 3px; } .sp-dict-value[contenteditable="true"] { outline: none; background: #fff; border: 1px solid var(--primary); border-radius: 3px; padding: 0 4px; box-shadow: 0 0 0 2px var(--primary-ring); } /* Element card */ .sp-element { border: 1px solid var(--border-light); border-radius: 6px; margin-bottom: 5px; overflow: hidden; transition: border-color 0.15s, box-shadow 0.15s; } .sp-element:last-child { margin-bottom: 0; } .sp-element:hover { border-color: var(--border); } .sp-element.highlight { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-ring); } .sp-element-header { display: flex; align-items: center; padding: 5px 8px; gap: 6px; cursor: pointer; user-select: none; transition: background 0.15s; } .sp-element-header:hover { background: #f5f7fa; } .sp-element-color { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } .sp-element-id { font-size: 11px; font-weight: 700; color: var(--text-secondary); font-family: monospace; flex-shrink: 0; } .sp-element-caption { flex: 1; font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 500; } .sp-element-actions { display: none; gap: 2px; } .sp-element-header:hover .sp-element-actions { display: flex; } .sp-element-body { padding: 2px 8px 6px; border-top: 1px solid var(--border-light); } .sp-element.collapsed .sp-element-body { display: none; } /* Position badge (bbox) */ .sp-pos-badge { display: inline-flex; align-items: center; gap: 4px; background: var(--info-light); padding: 1px 6px; border-radius: 3px; font-family: monospace; font-size: 11px; color: var(--text-secondary); cursor: pointer; transition: var(--transition); } .sp-pos-badge:hover { background: var(--primary-light); color: var(--primary); } .sp-pos-badge .pos-icon { font-size: 10px; } .sp-bbox-edit-btn { margin-left: 4px; padding: 0 4px; font-size: 11px; line-height: 18px; vertical-align: middle; border-radius: 3px; cursor: pointer; border: 1px solid transparent; background: transparent; opacity: 0.5; transition: var(--transition); } .sp-bbox-edit-btn:hover { opacity: 1; background: var(--primary-light); border-color: var(--primary); } /* Relationship list */ .sp-rel-list { list-style: none; padding: 0; margin: 0; } .sp-rel-item { display: flex; align-items: flex-start; gap: 6px; padding: 3px 6px; border-radius: 4px; transition: background 0.15s; font-size: 12px; color: var(--text); } .sp-rel-item:hover { background: #f5f7fa; } .sp-rel-bullet { color: var(--text-placeholder); flex-shrink: 0; } .sp-rel-text { flex: 1; word-break: break-word; cursor: default; border-radius: 3px; } /* Active state for raw toggle button */ .tool-btn.active { background: var(--primary-light); color: var(--primary); } /* ==================== Params Bar ==================== */ .params-bar { display: flex; align-items: center; padding: 0 12px; gap: 10px; min-height: 46px; flex-wrap: wrap; } .params-label { font-size: 11.5px; font-weight: 700; color: var(--text-secondary); white-space: nowrap; user-select: none; letter-spacing: 0.7px; text-transform: uppercase; } .params-separator { width: 1px; height: 20px; background: var(--border); flex-shrink: 0; } .params-spacer { flex: 1; } .params-group { display: flex; align-items: center; gap: 4px; } .params-group label { font-size: 11px; font-weight: 500; color: var(--text-secondary); white-space: nowrap; user-select: none; } .params-group input[type="number"] { width: 66px; height: 28px; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0 6px; font-size: 12px; color: var(--text); background: var(--panel-bg); text-align: center; outline: none; transition: var(--transition); font-variant-numeric: tabular-nums; } .params-group input[type="number"]:hover:not(:disabled) { border-color: var(--border-hover); } .params-group input[type="number"]:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); } .params-group input[type="number"]:disabled { background: var(--bg); color: var(--text-placeholder); cursor: not-allowed; } .params-group select { height: 26px; border: 1px solid var(--border); border-radius: 4px; padding: 0 4px; font-size: 12px; color: var(--text); background: var(--panel-bg); outline: none; cursor: pointer; transition: var(--transition); } .params-group select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); } .params-checkbox { gap: 3px !important; } .params-checkbox input[type="checkbox"] { width: 14px; height: 14px; cursor: pointer; accent-color: var(--primary); } /* ==================== Prompt Bar ==================== */ .prompt-bar { display: flex; align-items: center; padding: 0 16px; gap: 12px; min-height: 50px; } .prompt-label { font-size: 11.5px; font-weight: 700; color: var(--text-secondary); white-space: nowrap; user-select: none; flex-shrink: 0; letter-spacing: 0.7px; text-transform: uppercase; } .prompt-bar textarea { flex: 1; border: none; outline: none; resize: none; font-size: 14px; line-height: 1.5; color: var(--text); background: transparent; height: 32px; font-family: inherit; padding: 4px 0; } .prompt-bar textarea::placeholder { color: var(--text-placeholder); } /* ==================== Action Buttons ==================== */ .action-btn { border: 1px solid var(--border); border-radius: var(--radius); font-size: 14px; font-weight: 600; cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-xs); user-select: none; background: var(--panel-bg); color: var(--text); letter-spacing: 0.15px; } .action-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--primary); color: var(--primary); } .action-btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--shadow-xs); } .action-btn:disabled { opacity: 0.5; cursor: not-allowed; } /* Secondary action — Generate SP */ .gen-sp-btn { min-height: 46px; font-size: 14px; } /* Primary action — the CTA */ .gen-image-btn { min-height: 52px; font-size: 14.5px; font-weight: 600; background: var(--primary-gradient); color: #ffffff; border: 1px solid transparent; box-shadow: var(--shadow-primary); } .gen-image-btn:hover:not(:disabled) { color: #ffffff; border-color: transparent; filter: brightness(1.06); box-shadow: 0 6px 22px rgba(99, 102, 241, 0.32); transform: translateY(-1px); } .gen-image-btn:active:not(:disabled) { filter: brightness(0.98); box-shadow: var(--shadow-primary); } .gen-sp-btn.loading, .gen-image-btn.loading { pointer-events: none; opacity: 0.75; } /* ==================== Modals ==================== */ .modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.55); z-index: 1000; align-items: center; justify-content: center; backdrop-filter: blur(2px); } .modal-overlay.visible { display: flex; } .modal-close-btn { position: fixed; top: 16px; right: 16px; width: 36px; height: 36px; border: none; background: rgba(255, 255, 255, 0.92); color: #333; border-radius: 50%; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; z-index: 1001; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); transition: var(--transition); } .modal-close-btn:hover { background: white; transform: scale(1.1); } .modal-close-btn-sm { width: 28px; height: 28px; border: none; background: transparent; color: var(--text-secondary); border-radius: 4px; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; transition: var(--transition); } .modal-close-btn-sm:hover { background: var(--bg); color: var(--text); } /* ==================== Diff Dialog ==================== */ .diff-dialog { background: var(--panel-bg); border-radius: var(--radius-lg); width: 80%; max-width: 800px; max-height: 80vh; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); overflow: hidden; } .diff-header { padding: 16px 20px; font-weight: 600; font-size: 15px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; } .diff-content { flex: 1; overflow-y: auto; padding: 16px 20px; } .diff-section-title { font-weight: 600; font-size: 13px; color: var(--text); margin-bottom: 8px; } .diff-block { font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace; font-size: 12px; line-height: 1.6; margin-bottom: 20px; border: 1px solid var(--border-light); border-radius: 6px; overflow: hidden; } .diff-line { padding: 1px 10px; white-space: pre-wrap; word-break: break-word; } .diff-line.diff-added { background: #e6ffed; color: #22863a; } .diff-line.diff-removed { background: #ffeef0; color: #cb2431; } .diff-line.diff-same { color: var(--text-secondary); } .diff-no-change { color: var(--text-placeholder); font-size: 13px; padding: 8px 0; } .diff-actions { padding: 12px 20px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; flex-shrink: 0; } .cancel-btn { padding: 8px 20px; background: var(--panel-bg); color: var(--text); border: 1px solid var(--border); border-radius: 6px; font-size: 13px; cursor: pointer; } .cancel-btn:hover { background: var(--bg); } .confirm-btn { padding: 8px 20px; background: var(--primary); color: white; border: none; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: var(--transition); } .confirm-btn:hover { background: var(--primary-dark); } /* ==================== History Detail Modal ==================== */ .history-detail { background: var(--panel-bg); border-radius: var(--radius-lg); width: 60%; max-width: 640px; max-height: 80vh; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); overflow: hidden; } .history-detail-header { padding: 16px 20px; font-weight: 600; font-size: 15px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; } .history-detail-body { flex: 1; overflow-y: auto; padding: 20px; } .history-detail-footer { padding: 12px 20px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; flex-shrink: 0; gap: 8px; flex-wrap: wrap; } .restore-part-btn { padding: 6px 14px; background: var(--panel-bg); color: var(--text); border: 1px solid var(--border); border-radius: 6px; font-size: 12px; font-weight: 500; cursor: pointer; transition: var(--transition); } .restore-part-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); } .restore-btn { padding: 6px 20px; background: var(--primary); color: white; border: none; border-radius: 6px; font-size: 12px; font-weight: 500; cursor: pointer; transition: var(--transition); } .restore-btn:hover { background: var(--primary-dark); } .detail-section { margin-bottom: 16px; } .detail-section:last-child { margin-bottom: 0; } .detail-section-title { font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; } .detail-section-content { font-size: 13px; line-height: 1.6; color: var(--text); white-space: pre-wrap; word-break: break-word; background: var(--bg); padding: 10px 12px; border-radius: 6px; max-height: 200px; overflow-y: auto; border: 1px solid var(--border-light); } .detail-section-content.mono { font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace; font-size: 11px; } .detail-image { max-width: 100%; max-height: 200px; border-radius: 6px; border: 1px solid var(--border); } /* ==================== Toast ==================== */ .toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 2000; display: flex; flex-direction: column-reverse; gap: 8px; pointer-events: none; } .toast { padding: 10px 18px; border-radius: var(--radius); font-size: 13px; font-weight: 500; box-shadow: var(--shadow-lg); animation: toast-in 0.3s ease; max-width: 380px; word-break: break-word; pointer-events: auto; } .toast.toast-info { background: #edf2fc; color: #606266; border: 1px solid #d9ecff; } .toast.toast-success { background: #f0f9eb; color: #529b2e; border: 1px solid #e1f3d8; } .toast.toast-warning { background: #fdf6ec; color: #b88230; border: 1px solid #faecd8; } .toast.toast-error { background: #fef0f0; color: #c45656; border: 1px solid #fde2e2; } @keyframes toast-in { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: translateX(0); } } @keyframes toast-out { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(24px); } } /* ==================== Add Field Dropdown ==================== */ .sp-add-dropdown { position: fixed; z-index: 3000; background: var(--panel-bg); border: 1px solid var(--border); border-radius: 6px; box-shadow: var(--shadow-lg); padding: 4px; min-width: 140px; } .sp-add-option { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 4px; font-size: 12px; color: var(--text); cursor: pointer; transition: var(--transition); white-space: nowrap; } .sp-add-option:hover { background: var(--primary-light); color: var(--primary); } /* Inline add buttons (in dict blocks / element bodies) */ .sp-inline-add-btn { border: 1px dashed var(--border); background: transparent; color: var(--text-placeholder); border-radius: 4px; cursor: pointer; font-size: 11px; padding: 2px 8px; transition: var(--transition); } .sp-inline-add-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); } .sp-dict-add-row { padding: 2px 0; } .sp-elem-add-row { padding: 4px 0; text-align: center; } /* Dict sub-key delete */ .sp-dict-del { width: 16px; height: 16px; border: none; background: transparent; color: transparent; border-radius: 3px; cursor: pointer; font-size: 10px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: var(--transition); padding: 0; } .sp-dict-row:hover .sp-dict-del { color: var(--text-secondary); } .sp-dict-del:hover { background: var(--danger-light); color: var(--danger); } /* ==================== Modal Image Zoom ==================== */ .modal-image-container { display: flex; align-items: center; justify-content: center; max-width: 92vw; max-height: 92vh; overflow: hidden; } .modal-image { max-width: 92vw; max-height: 92vh; object-fit: contain; border-radius: 8px; box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3); transition: none; transform-origin: center center; user-select: none; -webkit-user-drag: none; } /* ==================== Loading Spinner ==================== */ .spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(0, 0, 0, 0.12); border-radius: 50%; border-top-color: var(--primary); animation: spin 0.8s linear infinite; margin-right: 6px; vertical-align: middle; } @keyframes spin { to { transform: rotate(360deg); } } /* ==================== Scrollbar ==================== */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { background: var(--text-secondary); } /* ==================== Selection ==================== */ ::selection { background: rgba(99, 102, 241, 0.22); } /* ==================== Responsive ==================== */ @media (max-width: 900px) { .workspace { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr auto auto auto auto; } .image-panel { grid-row: 1; grid-column: 1; min-height: 250px; } .sp-panel { grid-row: 2; grid-column: 1; min-height: 200px; } .params-bar { grid-row: 3; grid-column: 1; } .gen-sp-btn { grid-row: 4; grid-column: 1; } .prompt-bar { grid-row: 5; grid-column: 1; } .gen-image-btn { grid-row: 6; grid-column: 1; } .right-col { max-width: none; } .params-bar { flex-wrap: wrap; gap: 8px; } .history-detail, .diff-dialog { width: 95%; } } /* ==================== Floating Input Popup ==================== */ .sp-input-popup { position: fixed; z-index: 3000; background: var(--panel-bg); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow-lg); padding: 12px; min-width: 240px; max-width: 320px; animation: popup-in 0.15s ease; } @keyframes popup-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } .sp-input-popup .popup-title { font-size: 12px; font-weight: 600; color: var(--text); margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border-light); } .sp-input-popup .popup-field { margin-bottom: 8px; } .sp-input-popup .popup-field label { display: block; font-size: 11px; font-weight: 500; color: var(--text-secondary); margin-bottom: 3px; } .sp-input-popup .popup-field input { width: 100%; height: 28px; border: 1px solid var(--border); border-radius: 4px; padding: 0 8px; font-size: 12px; color: var(--text); background: var(--panel-bg); outline: none; transition: var(--transition); } .sp-input-popup .popup-field input:focus { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-ring); } .sp-input-popup .popup-field input.input-error { border-color: var(--danger); box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.12); } .sp-input-popup .popup-actions { display: flex; justify-content: flex-end; gap: 6px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border-light); } .sp-input-popup .popup-btn { height: 26px; padding: 0 14px; border-radius: 4px; font-size: 12px; font-weight: 500; cursor: pointer; border: 1px solid var(--border); background: var(--panel-bg); color: var(--text); transition: var(--transition); } .sp-input-popup .popup-btn:hover { border-color: var(--text-secondary); color: var(--text); } .sp-input-popup .popup-btn-primary { background: var(--primary); color: white; border-color: var(--primary); } .sp-input-popup .popup-btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: white; }