Spaces:
Running
Running
yzhang2863
v0.1.19: Logs modal, coord scale, square spots, 3D bounds, spot detection, scipy compat
bb1ef7c | /* ============================================================ | |
| 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 ; } | |
| /* --- 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; | |
| } | |