/* ============================================================ STAT - Spatial Transcriptomics Analysis Tool Modern minimal design: white panels, subtle borders, clean type ============================================================ */ /* --- Reset & Base --- */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #ffffff; --bg-subtle: #f8f9fa; --bg-muted: #f1f3f5; --border: #e1e4e8; --border-light: #eef0f2; --text: #1a1a2e; --text-secondary: #6b7280; --text-muted: #9ca3af; --accent: #2563eb; --accent-hover: #1d4ed8; --accent-light: #eff6ff; --danger: #dc2626; --danger-light: #fef2f2; --success: #16a34a; --success-light: #f0fdf4; --warning: #d97706; --warning-light: #fffbeb; --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; --font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace; --radius: 6px; --radius-lg: 10px; --shadow-sm: 0 1px 2px rgba(0,0,0,0.05); --shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06); --shadow-lg: 0 4px 12px rgba(0,0,0,0.1); --transition: 150ms ease; } html, body { height: 100%; font-family: var(--font); font-size: 13px; line-height: 1.5; color: var(--text); background: var(--bg-subtle); overflow: hidden; } .hidden { display: none !important; } /* --- Init Overlay --- */ #init-overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: var(--bg-subtle); z-index: 1000; } .init-card { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 40px; width: 420px; max-width: 90vw; box-shadow: var(--shadow-lg); } .init-logo { font-size: 32px; font-weight: 700; letter-spacing: -0.5px; color: var(--text); margin-bottom: 4px; } .init-subtitle { color: var(--text-secondary); font-size: 14px; margin-bottom: 28px; } /* --- Forms --- */ .form-group { margin-bottom: 14px; } .form-group label { display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.3px; } .form-group input, .form-group select { width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 13px; font-family: var(--font); background: var(--bg); color: var(--text); transition: border-color var(--transition); } .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); } .form-group .optional { font-weight: 400; color: var(--text-muted); text-transform: none; } .form-hint { display: block; font-size: 11px; color: var(--text-muted); margin-top: 3px; line-height: 1.4; } .form-hint code { background: var(--bg-muted); padding: 0 3px; border-radius: 2px; font-size: 10.5px; font-family: var(--font-mono); } .form-hint-inline { font-weight: 400; font-size: 10px; color: var(--text-muted); text-transform: none; letter-spacing: 0; } .form-group select { appearance: auto; cursor: pointer; } .form-row { display: flex; align-items: center; gap: 10px; margin-top: 8px; } /* --- LLM Config --- */ .llm-config { margin: 16px 0; border: 1px solid var(--border-light); border-radius: var(--radius); } .llm-config summary { padding: 10px 12px; font-size: 12px; font-weight: 600; color: var(--text-secondary); cursor: pointer; user-select: none; } .llm-config summary:hover { color: var(--text); } .llm-config-body { padding: 0 12px 12px; } /* --- Buttons --- */ .btn-primary { display: inline-flex; align-items: center; justify-content: center; width: 100%; padding: 10px 16px; background: var(--accent); color: white; border: none; border-radius: var(--radius); font-size: 13px; font-weight: 600; font-family: var(--font); cursor: pointer; transition: background var(--transition); } .btn-primary:hover { background: var(--accent-hover); } .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } .btn-secondary { padding: 6px 12px; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; transition: all var(--transition); } .btn-secondary:hover { background: var(--bg-subtle); } .btn-header { padding: 4px 10px; background: transparent; color: var(--text-secondary); border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; transition: all var(--transition); } .btn-header:hover { background: var(--bg-muted); color: var(--text); } .btn-logout { color: var(--danger); border-color: var(--danger); opacity: 0.7; } .btn-logout:hover { background: var(--danger); color: #fff; opacity: 1; } .btn-tool { padding: 4px 10px; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; transition: all var(--transition); min-width: 32px; text-align: center; } .btn-tool:hover { background: var(--bg-muted); } .btn-tool.active { background: var(--accent); color: white; border-color: var(--accent); } .btn-tiny { padding: 2px 6px; background: none; color: var(--text-muted); border: 1px solid var(--border-light); border-radius: 4px; font-size: 11px; font-family: var(--font); cursor: pointer; transition: all var(--transition); } .btn-tiny:hover { color: var(--text); border-color: var(--border); } .btn-danger { background: var(--danger); color: white; border-color: var(--danger); } .btn-danger:hover { background: #b91c1c; } /* --- Error/Loading Messages --- */ .error-msg { margin-top: 10px; padding: 8px 10px; background: var(--danger-light); color: var(--danger); border-radius: var(--radius); font-size: 12px; } .loading-msg { margin-top: 10px; color: var(--text-secondary); font-size: 12px; text-align: center; } .small-info { font-size: 11px; color: var(--text-muted); margin-top: 4px; } /* --- Header --- */ #app-header { display: flex; align-items: center; justify-content: space-between; height: 44px; padding: 0 16px; background: var(--bg); border-bottom: 1px solid var(--border); } .header-left { display: flex; align-items: center; gap: 12px; } .header-logo { font-size: 16px; font-weight: 700; letter-spacing: -0.3px; } .session-info { font-size: 12px; color: var(--text-secondary); } .header-nav { display: flex; align-items: center; gap: 8px; } /* --- Main Layout (Three Columns + resize handles) --- */ .main-layout { display: grid; grid-template-columns: 1fr 3px 260px 3px 600px; height: calc(100vh - 44px); } /* --- Resize Handles --- */ .resize-handle { width: 3px; cursor: col-resize; background: var(--border-light); position: relative; z-index: 20; transition: background 0.15s; } .resize-handle:hover, .resize-handle.active { background: var(--border); } /* --- Spatial Viewer (Left) --- */ .spatial-viewer { display: flex; flex-direction: column; background: var(--bg-muted); overflow: hidden; position: relative; /* anchor for skill panel */ } .canvas-container { flex: 1; position: relative; overflow: hidden; cursor: grab; } .canvas-container.panning { cursor: grabbing; } .canvas-container.roi-drawing { cursor: crosshair; } #spatial-canvas { display: block; width: 100%; height: 100%; } /* --- 3D Viewer --- */ .viewer-3d { position: absolute; inset: 0; background: linear-gradient(135deg, #f0f2f5 0%, #e2e6ec 100%); overflow: hidden; cursor: grab; } .viewer-3d.orbiting { cursor: grabbing; } .scene-3d { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; } .slice-plane { position: absolute; transform-style: preserve-3d; pointer-events: auto; cursor: pointer; border-radius: 4px; overflow: hidden; box-shadow: 0 2px 12px rgba(0,0,0,0.2); transition: box-shadow 0.15s; } .slice-plane:hover { box-shadow: 0 2px 12px rgba(0,0,0,0.2), 0 0 0 2px rgba(100,149,237,0.6); } .slice-plane.active-slice { box-shadow: 0 2px 12px rgba(0,0,0,0.2), 0 0 0 3px cornflowerblue; } .slice-plane canvas { display: block; width: 100%; height: 100%; } .slice-label { position: absolute; bottom: 0; right: 0; background: rgba(0,0,0,0.55); color: #fff; font-size: 11px; padding: 3px 10px; font-family: var(--font-mono); pointer-events: none; border-top-left-radius: 4px; } .viewer-3d-controls { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,0.85); backdrop-filter: blur(8px); padding: 5px 14px; border-radius: 16px; display: flex; align-items: center; gap: 8px; z-index: 2; box-shadow: 0 1px 6px rgba(0,0,0,0.12); } .viewer-3d-controls .toolbar-slider { width: 100px; } .btn-tiny.active { background: var(--accent); color: white; border-color: var(--accent); } .canvas-spinner { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(255,255,255,0.8); gap: 8px; font-size: 12px; color: var(--text-secondary); } .spinner { width: 24px; height: 24px; border: 2.5px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .viewer-toolbar { display: flex; align-items: center; justify-content: space-between; height: 34px; padding: 0 8px; background: var(--bg); border-top: 1px solid var(--border); } .toolbar-left, .toolbar-right { display: flex; align-items: center; gap: 4px; } .toolbar-info { font-size: 11px; color: var(--text-muted); font-family: var(--font-mono); padding: 0 4px; } .toolbar-center { display: flex; align-items: center; gap: 4px; } .toolbar-label { font-size: 10px; color: var(--text-muted); user-select: none; } .toolbar-number { width: 48px; padding: 1px 4px; border: 1px solid var(--border); border-radius: 3px; font-size: 11px; font-family: var(--font-mono); background: var(--bg); color: var(--text); text-align: center; } .toolbar-number:focus { outline: none; border-color: var(--accent); } .toolbar-slider { width: 60px; height: 3px; -webkit-appearance: none; appearance: none; background: var(--border); border-radius: 2px; outline: none; cursor: pointer; } .toolbar-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 10px; height: 10px; border-radius: 50%; background: var(--text-muted); cursor: pointer; } .toolbar-slider::-moz-range-thumb { width: 10px; height: 10px; border-radius: 50%; background: var(--text-muted); cursor: pointer; border: none; } .toolbar-sep { width: 1px; height: 14px; background: var(--border); margin: 0 2px; } .toolbar-checkbox { display: flex; align-items: center; gap: 3px; cursor: pointer; } .toolbar-checkbox input { margin: 0; accent-color: var(--accent); } /* --- Controls Panel (Center) --- */ .controls-panel { display: flex; flex-direction: column; background: var(--bg); overflow-y: auto; overflow-x: hidden; } .control-group { padding: 12px 14px; border-bottom: 1px solid var(--border-light); } .control-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.3px; margin-bottom: 8px; display: flex; align-items: center; justify-content: space-between; } .control-actions { display: flex; gap: 4px; } /* --- Slice Tabs --- */ .slice-tabs { display: flex; flex-wrap: wrap; gap: 4px; } .slice-tab { padding: 4px 10px; background: var(--bg-subtle); color: var(--text-secondary); border: 1px solid var(--border-light); border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; transition: all var(--transition); } .slice-tab:hover { background: var(--bg-muted); color: var(--text); } .slice-tab.active { background: var(--accent); color: white; border-color: var(--accent); } /* --- Segmented Control --- */ .segmented-control { display: flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; } .seg-btn { flex: 1; padding: 5px 12px; background: var(--bg); color: var(--text-secondary); border: none; border-right: 1px solid var(--border); font-size: 12px; font-family: var(--font); cursor: pointer; transition: all var(--transition); } .seg-btn:last-child { border-right: none; } .seg-btn:hover { background: var(--bg-subtle); } .seg-btn.active { background: var(--accent); color: white; } /* --- Radio Group --- */ .radio-group { display: flex; flex-direction: column; gap: 4px; } .radio-option { display: flex; align-items: center; gap: 6px; padding: 3px 0; font-size: 12px; cursor: pointer; } .radio-option input[type="radio"] { margin: 0; accent-color: var(--accent); } .radio-option input:disabled + span { color: var(--text-muted); } /* --- Search / Autocomplete --- */ .search-wrapper { position: relative; } .search-wrapper input { width: 100%; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); background: var(--bg); color: var(--text); } .search-wrapper input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); } .autocomplete-dropdown { position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: var(--bg); border: 1px solid var(--border); border-top: none; border-radius: 0 0 var(--radius) var(--radius); box-shadow: var(--shadow); z-index: 100; } .autocomplete-item { padding: 5px 8px; font-size: 12px; cursor: pointer; transition: background var(--transition); } .autocomplete-item:hover, .autocomplete-item.active { background: var(--accent-light); color: var(--accent); } /* --- Checkbox List (Celltypes) --- */ /* --- Proportion Select --- */ .proportion-select { width: 100%; padding: 5px 8px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); background: var(--bg); color: var(--text); cursor: pointer; } .proportion-select:focus { outline: none; border-color: var(--accent); } /* --- Colorbar & Vmax --- */ .colorbar-display { margin-bottom: 6px; } .colorbar-bar { height: 12px; border-radius: 3px; border: 1px solid var(--border); } .colorbar-labels { display: flex; justify-content: space-between; margin-top: 2px; font-size: 10px; font-family: var(--font-mono); color: var(--text-muted); } .vmax-control { display: flex; align-items: center; gap: 6px; margin-top: 4px; } .vmax-control label { flex-shrink: 0; font-size: 11px; } .vmax-slider { flex: 1; height: 4px; -webkit-appearance: none; appearance: none; background: var(--border); border-radius: 2px; outline: none; cursor: pointer; } .vmax-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); cursor: pointer; } .vmax-slider::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none; } .checkbox-list { max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; min-height: 40px; } .ct-resize-handle { height: 6px; cursor: row-resize; display: flex; align-items: center; justify-content: center; margin-top: 2px; } .ct-resize-handle::after { content: ''; width: 30px; height: 2px; background: var(--border); border-radius: 1px; transition: background 0.15s; } .ct-resize-handle:hover::after, .ct-resize-handle.active::after { background: var(--text-muted); } .ct-checkbox { display: flex; align-items: center; gap: 6px; padding: 2px 0; font-size: 12px; cursor: pointer; } .ct-checkbox input[type="checkbox"] { margin: 0; accent-color: var(--accent); } .ct-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 2px; border: 1px solid rgba(0,0,0,0.1); flex-shrink: 0; } /* --- ROI --- */ .roi-toolbar { display: flex; gap: 4px; margin-bottom: 8px; } .roi-list { display: flex; flex-direction: column; gap: 4px; } .roi-item { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; padding: 5px 8px; background: var(--bg-subtle); border-radius: 4px; font-size: 12px; border: 1px solid transparent; transition: all var(--transition); } .roi-item-main { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; } .roi-item-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .roi-item-slice { font-size: 10px; color: var(--text-muted); background: var(--bg-muted); padding: 0 4px; border-radius: 3px; white-space: nowrap; flex-shrink: 0; } .roi-item-detail { width: 100%; font-size: 11px; color: var(--text-muted); padding-top: 2px; } /* Inactive ROIs (different slice) */ .roi-item.roi-inactive { opacity: 0.45; } .roi-item.roi-inactive .roi-item-name { font-weight: 400; } .roi-item-actions { display: none; gap: 2px; margin-left: auto; flex-shrink: 0; } .roi-item:hover .roi-item-actions { display: flex; } .roi-item.highlighted { background: var(--accent-light); border-color: var(--accent); } .roi-action-btn { width: 20px; height: 20px; padding: 0; background: none; border: 1px solid var(--border-light); border-radius: 3px; font-size: 12px; line-height: 18px; text-align: center; cursor: pointer; color: var(--text-muted); font-family: var(--font); transition: all var(--transition); } .roi-action-btn:hover { background: var(--bg-muted); color: var(--text); } .roi-delete-btn:hover { background: var(--danger-light); color: var(--danger); border-color: var(--danger); } /* --- Chat Panel (Right) --- */ .chat-panel { display: flex; flex-direction: column; background: var(--bg); overflow: hidden; } .chat-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 14px; border-bottom: 1px solid var(--border); font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.3px; } .chat-messages { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px; } .chat-welcome { text-align: center; padding: 24px 16px; color: var(--text-secondary); } .chat-welcome p:first-child { font-size: 14px; margin-bottom: 8px; } /* --- Chat Messages --- */ .chat-msg { max-width: 95%; } .chat-msg.user { align-self: flex-end; } .chat-msg.user .chat-msg-body { background: var(--accent); color: white; border-radius: var(--radius) var(--radius) 2px var(--radius); padding: 8px 12px; font-size: 13px; } .chat-msg.assistant { align-self: flex-start; width: 100%; } .chat-msg.assistant .chat-msg-body { background: var(--bg-subtle); border: 1px solid var(--border-light); border-radius: 2px var(--radius) var(--radius) var(--radius); padding: 10px 12px; font-size: 13px; } /* --- Chat: Plan Card --- */ .plan-card { margin: 6px 0; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; } .plan-card summary { padding: 6px 10px; font-size: 12px; font-weight: 600; color: var(--text-secondary); background: var(--bg-subtle); cursor: pointer; } .plan-steps { padding: 6px 10px; list-style: none; } .plan-step { padding: 3px 0; font-size: 12px; display: flex; align-items: center; gap: 6px; } .plan-step-num { width: 18px; height: 18px; background: var(--bg-muted); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: var(--text-secondary); flex-shrink: 0; } .plan-step.active .plan-step-num { background: var(--accent); color: white; } .plan-step.done .plan-step-num { background: var(--success); color: white; } /* --- Chat: Code Block --- */ .chat-code-block { margin: 6px 0; background: #1e1e2e; color: #cdd6f4; border-radius: var(--radius); overflow: hidden; font-family: var(--font-mono); font-size: 12px; line-height: 1.5; } .chat-code-block pre { padding: 10px 12px; overflow-x: auto; white-space: pre; } /* --- Chat: Markdown Headings --- */ .chat-heading { margin: 8px 0 4px; font-weight: 600; } h1.chat-heading { font-size: 1.3em; } h2.chat-heading { font-size: 1.15em; } h3.chat-heading { font-size: 1.05em; } h4.chat-heading, h5.chat-heading, h6.chat-heading { font-size: 0.95em; } /* --- Chat: Blockquote --- */ .chat-blockquote { margin: 6px 0; padding: 4px 10px; border-left: 3px solid var(--border); color: var(--text-secondary); font-style: italic; } /* --- Chat: Horizontal Rule --- */ .chat-hr { border: none; border-top: 1px solid var(--border-light); margin: 8px 0; } /* --- Chat: Execution Output --- */ .exec-details { margin: 6px 0; border: 1px solid var(--border-light); border-radius: 4px; overflow: hidden; } .exec-details summary { padding: 4px 8px; font-size: 11px; color: var(--text-secondary); cursor: pointer; background: var(--bg-secondary); user-select: none; } .exec-details summary:hover { color: var(--text); } .exec-output { padding: 6px 8px; background: #1e1e2e; color: #a6adc8; font-family: var(--font-mono); font-size: 11px; line-height: 1.5; max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-word; } .exec-output .stderr { color: #f38ba8; } /* --- Chat: Plots --- */ .chat-plot { margin: 6px 0; text-align: center; } .chat-plot img { max-width: 100%; border-radius: var(--radius); border: 1px solid var(--border); } /* --- Chat: Tables --- */ .chat-table { border-collapse: collapse; margin: 6px 0; font-size: 12px; width: 100%; } .chat-table th, .chat-table td { border: 1px solid var(--border); padding: 4px 8px; text-align: left; } .chat-table th { background: var(--bg-secondary); font-weight: 600; } .chat-table tr:nth-child(even) td { background: var(--bg-secondary); } /* --- Chat: Alert Cards --- */ .alert-card { margin: 6px 0; padding: 8px 10px; border-radius: var(--radius); font-size: 12px; } .alert-card.warning { background: var(--warning-light); color: var(--warning); border: 1px solid #fde68a; } .alert-card.advice { background: var(--accent-light); color: var(--accent); border: 1px solid #bfdbfe; } .alert-card.error { background: var(--danger-light); color: var(--danger); border: 1px solid #fecaca; } .alert-card.success { background: var(--success-light); color: var(--success); border: 1px solid #bbf7d0; } /* --- Chat: Clarification / Skill Selection --- */ .clarification-ui { margin: 6px 0; padding: 8px 10px; background: var(--accent-light); border: 1px solid #bfdbfe; border-radius: var(--radius); } .clarification-ui .question { font-size: 13px; font-weight: 500; margin-bottom: 6px; } .clarification-options { display: flex; flex-direction: column; gap: 4px; } .clarification-option-btn { padding: 6px 10px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; text-align: left; transition: all var(--transition); } .clarification-option-btn:hover { background: var(--accent); color: white; border-color: var(--accent); } .clarification-option-btn.active { background: var(--accent); color: white; border-color: var(--accent); } .clarification-option-btn:disabled { opacity: 0.5; cursor: default; } .clarification-option-btn:disabled:hover { background: var(--bg); color: var(--text); border-color: var(--border); } .clarification-option-btn:disabled.active:hover { background: var(--accent); color: white; border-color: var(--accent); } /* --- Chat: Pipeline Log --- */ .pipeline-log { margin: 4px 0; border: 1px solid var(--border-light); border-radius: 4px; font-size: 11px; } .pipeline-log summary { padding: 4px 8px; color: var(--text-muted); cursor: pointer; } .pipeline-log-content { padding: 4px 8px; max-height: 120px; overflow-y: auto; color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; white-space: pre-wrap; } /* --- Chat Input --- */ .chat-input-area { padding: 10px 12px; border-top: 1px solid var(--border); display: flex; gap: 8px; align-items: flex-end; } #chat-input { flex: 1; resize: none; border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 10px; font-size: 13px; font-family: var(--font); line-height: 1.4; max-height: 120px; color: var(--text); background: var(--bg); } #chat-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); } .chat-buttons { display: flex; flex-direction: column; gap: 4px; } .chat-buttons .btn-primary { width: auto; padding: 8px 16px; } .chat-buttons .btn-danger { padding: 8px 12px; border: none; border-radius: var(--radius); font-size: 12px; font-family: var(--font); cursor: pointer; } /* --- Markdown in chat --- */ .chat-msg-body strong { font-weight: 600; } .chat-msg-body em { font-style: italic; } .chat-msg-body code { background: rgba(0,0,0,0.06); padding: 1px 4px; border-radius: 3px; font-family: var(--font-mono); font-size: 12px; } .chat-msg-body ul, .chat-msg-body ol { margin: 4px 0; padding-left: 18px; } .chat-msg-body li { margin: 2px 0; } .chat-msg-body a { color: var(--accent); text-decoration: none; } .chat-msg-body a:hover { text-decoration: underline; } .chat-msg-body p { margin: 4px 0; } /* --- Scrollbar Styling --- */ ::-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-muted); } /* --- Legend Overlay (rendered on canvas via CSS overlay) --- */ .legend-overlay { position: absolute; top: 8px; right: 8px; background: rgba(255,255,255,0.92); border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 10px; max-height: 250px; overflow-y: auto; font-size: 11px; z-index: 10; box-shadow: var(--shadow-sm); pointer-events: none; } .legend-item { display: flex; align-items: center; gap: 5px; padding: 1px 0; } .legend-swatch { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; } /* --- Expression Gradient Legend --- */ .gradient-legend { display: flex; align-items: center; gap: 6px; margin-top: 4px; } .gradient-bar { width: 80px; height: 10px; border-radius: 2px; border: 1px solid rgba(0,0,0,0.1); } .gradient-label { font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); } .btn-icon { background: none; border: none; cursor: pointer; font-size: 18px; color: var(--text-muted); padding: 2px 6px; border-radius: 4px; line-height: 1; } .btn-icon:hover { background: var(--bg-muted); color: var(--text); } /* ===== Skill Panel ===== */ /* The panel container: holds inner content + tab handle. Slides left/right; tab sticks out on the right edge always. */ .skill-panel { position: absolute; left: 0; top: 0; bottom: 0; /* Width = panel content (300px) + tab handle (22px) */ width: 322px; z-index: 11; display: flex; /* Start with only tab visible: shift left by content width */ transform: translateX(-300px); transition: transform 0.25s ease; pointer-events: none; /* let clicks pass through when collapsed */ } .skill-panel.open { transform: translateX(0); } /* Re-enable pointer events on the actual interactive children */ .skill-panel-inner, .skill-panel-tab { pointer-events: auto; } .skill-panel-inner { width: 300px; flex-shrink: 0; background: var(--bg); border-right: 1px solid var(--border); box-shadow: 4px 0 16px rgba(0,0,0,0.08); display: flex; flex-direction: column; overflow: hidden; } /* Tab handle: right edge of panel, always visible */ .skill-panel-tab { width: 22px; flex-shrink: 0; align-self: center; /* vertically center within the panel height */ height: 72px; background: var(--bg); border: 1px solid var(--border); border-left: none; border-radius: 0 6px 6px 0; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background var(--transition), width var(--transition); box-shadow: 2px 0 6px rgba(0,0,0,0.06); /* Position vertically centered */ margin-top: auto; margin-bottom: auto; } .skill-panel-tab:hover { background: var(--bg-muted); width: 26px; } .skill-panel-tab .tab-icon { font-size: 14px; color: var(--text-muted); line-height: 1; } .skill-panel.open .skill-panel-tab { background: var(--accent); border-color: var(--accent); } .skill-panel.open .skill-panel-tab .tab-icon { color: #fff; } .skill-panel-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border-bottom: 1px solid var(--border); flex-shrink: 0; } .skill-panel-header h3 { margin: 0; font-size: 14px; font-weight: 600; } .skill-panel-body { flex: 1; overflow-y: auto; padding: 8px 0; } .skill-row { display: flex; align-items: center; gap: 8px; padding: 7px 14px; cursor: default; transition: background 0.1s; position: relative; } .skill-row:hover { background: var(--bg-muted); } .skill-toggle { display: flex; align-items: center; cursor: pointer; flex-shrink: 0; } .skill-toggle input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; margin: 0; } .skill-name { flex: 1; font-size: 12.5px; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .skill-info-btn { flex-shrink: 0; background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 14px; padding: 2px 4px; border-radius: 4px; line-height: 1; opacity: 0; transition: opacity 0.15s; } .skill-row:hover .skill-info-btn { opacity: 1; } .skill-info-btn:hover { background: var(--bg-muted); color: var(--text); } /* Skill tooltip (on hover) — appears right of the panel, no scroll needed */ .skill-tooltip { position: fixed; z-index: 100; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.12); padding: 12px 14px; width: 300px; pointer-events: none; font-size: 12px; line-height: 1.5; } .skill-tooltip .tt-title { font-weight: 600; font-size: 13px; margin-bottom: 6px; } .skill-tooltip .tt-desc { color: var(--text-muted); margin-bottom: 8px; } .skill-tooltip .tt-section { margin-bottom: 6px; } .skill-tooltip .tt-label { font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 2px; } .skill-tooltip .tt-tag { display: inline-block; background: var(--bg-muted); border-radius: 3px; padding: 1px 5px; font-size: 11px; margin: 1px 2px; font-family: var(--font-mono); } /* Skill detail modal */ .modal-overlay { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; } .modal-overlay.hidden { display: none; } .modal-content { background: var(--bg); border-radius: 10px; box-shadow: 0 16px 48px rgba(0,0,0,0.18); width: 700px; max-width: 90vw; max-height: 80vh; display: flex; flex-direction: column; overflow: hidden; } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); flex-shrink: 0; } .modal-header h3 { margin: 0; font-size: 16px; font-weight: 600; } .markdown-body { padding: 20px; overflow-y: auto; flex: 1; font-size: 13.5px; line-height: 1.7; } .markdown-body h1, .markdown-body h2, .markdown-body h3 { margin-top: 1.2em; margin-bottom: 0.4em; font-weight: 600; } .markdown-body h1 { font-size: 20px; } .markdown-body h2 { font-size: 16px; border-bottom: 1px solid var(--border); padding-bottom: 4px; } .markdown-body h3 { font-size: 14px; } .markdown-body p { margin: 0.5em 0; } .markdown-body ul, .markdown-body ol { margin: 0.5em 0; padding-left: 1.5em; } .markdown-body li { margin: 0.2em 0; } .markdown-body code { background: var(--bg-muted); padding: 1px 5px; border-radius: 3px; font-size: 12px; font-family: var(--font-mono); } .markdown-body pre { background: var(--bg-muted); border-radius: 6px; padding: 12px 14px; overflow-x: auto; margin: 0.8em 0; } .markdown-body pre code { background: none; padding: 0; font-size: 12px; } /* ===== Logs Modal ===== */ .logs-modal-content { width: 900px; max-width: 95vw; max-height: 85vh; } .logs-modal-body { display: flex; flex: 1; overflow: hidden; min-height: 0; } .logs-sidebar { width: 240px; flex-shrink: 0; border-right: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; } .logs-path { padding: 10px 12px; font-size: 11px; font-family: var(--font-mono); color: var(--text-muted); border-bottom: 1px solid var(--border); word-break: break-all; line-height: 1.4; flex-shrink: 0; } .logs-nav { display: flex; border-bottom: 1px solid var(--border); flex-shrink: 0; } .logs-nav-btn { flex: 1; padding: 8px 0; font-size: 12px; font-weight: 600; border: none; background: none; cursor: pointer; color: var(--text-muted); border-bottom: 2px solid transparent; transition: color 0.15s, border-color 0.15s; } .logs-nav-btn:hover { color: var(--text); } .logs-nav-btn.active { color: var(--accent); border-bottom-color: var(--accent); } .logs-turn-list { flex: 1; overflow-y: auto; padding: 4px 0; } .logs-turn-item { padding: 8px 12px; cursor: pointer; border-bottom: 1px solid var(--border-light); transition: background 0.1s; } .logs-turn-item:hover { background: var(--bg-muted); } .logs-turn-item.active { background: rgba(37, 99, 235, 0.08); border-left: 3px solid var(--accent); } .logs-turn-item .turn-num { font-weight: 600; font-size: 12px; } .logs-turn-item .turn-preview { font-size: 11px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; } .logs-turn-item .turn-size { font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); } .logs-detail { flex: 1; overflow-y: auto; padding: 16px 20px; min-width: 0; } .logs-placeholder { color: var(--text-muted); font-size: 13px; text-align: center; margin-top: 60px; } /* Notebook viewer */ .nb-cell { margin-bottom: 12px; border: 1px solid var(--border-light); border-radius: 6px; overflow: hidden; } .nb-cell-header { display: flex; align-items: center; gap: 6px; padding: 4px 10px; background: var(--bg-muted); font-size: 10px; font-family: var(--font-mono); color: var(--text-muted); } .nb-cell-type { font-weight: 600; text-transform: uppercase; } .nb-cell-source { padding: 10px 12px; font-size: 12px; font-family: var(--font-mono); line-height: 1.5; white-space: pre-wrap; word-break: break-word; background: var(--bg); } .nb-cell-outputs { border-top: 1px solid var(--border-light); padding: 8px 12px; font-size: 12px; font-family: var(--font-mono); line-height: 1.5; white-space: pre-wrap; word-break: break-word; background: #fafbfc; max-height: 300px; overflow-y: auto; } .nb-cell-outputs .nb-stderr { color: #c0392b; } .nb-cell-outputs img { max-width: 100%; margin: 4px 0; border-radius: 4px; } .nb-markdown-cell { padding: 10px 12px; font-size: 13px; line-height: 1.6; }