reasonix 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dashboard/app.css CHANGED
@@ -1,2693 +1,2264 @@
1
- /*
2
- * Reasonix dashboard styles. Hand-rolled, no Tailwind colors line
3
- * up with src/cli/ui/theme.ts so the web surface reads as the same
4
- * product as the TUI:
5
- *
6
- * gradient (brand wordmark, accent rules) — teal → fuchsia
7
- * primary cyan → focus / link / accent text
8
- * accent violet → hover / pill backgrounds
9
- * slate scale → backgrounds, borders, dim text
10
- *
11
- * Variables live in `:root` so future themes (light mode, alt brand)
12
- * can swap them without touching component selectors.
1
+ /* Reasonix dashboard styles — anchored to design/agent-dashboard.html.
2
+ * Re-import: extract the <style> block from the design mockup verbatim.
3
+ * Doc-chrome selectors (.page / .toc / .section / .subsec / .mock) are
4
+ * unused in the live dashboard but kept so the CSS stays in lockstep
5
+ * with the mockup; they cost nothing at runtime.
13
6
  */
14
-
7
+ /* ============================================================================
8
+ Reasonix Dashboard — design anchor for the web companion to the TUI.
9
+
10
+ Positioning: NOT a TUI mirror. Does what the TUI cannot:
11
+ - long-form session reading
12
+ - real charts (usage / cost / latency)
13
+ - multi-file editing
14
+ - browsing inventories (tools, MCP servers, skills, memory)
15
+
16
+ Aesthetic: TUI heritage (palette, glyph icons, sharp edges) + web fluency
17
+ (sans-serif body, real form controls, hover states, modal dialogs).
18
+ NOT slavish terminal mimicry — that's a portfolio gimmick, not a tool.
19
+ ============================================================================ */
15
20
  :root {
16
- /* Brand gradient — lifted verbatim from theme.ts GRADIENT[]. */
17
- --grad-1: #5eead4; /* teal */
18
- --grad-2: #67e8f9; /* cyan */
19
- --grad-3: #7dd3fc; /* sky */
20
- --grad-4: #93c5fd; /* blue */
21
- --grad-5: #a5b4fc; /* indigo */
22
- --grad-6: #c4b5fd; /* violet */
23
- --grad-7: #d8b4fe; /* purple */
24
- --grad-8: #f0abfc; /* fuchsia */
25
-
26
- /* Semantic palette mirrors COLOR{} from theme.ts. */
27
- --primary: #67e8f9;
28
- --accent: #c4b5fd;
29
- --brand: #5eead4;
30
-
31
- --user: #67e8f9;
32
- --assistant: #86efac;
33
- --tool: #fcd34d;
34
- --tool-err: #fda4af;
35
- --info: #94a3b8;
36
- --warn: #fbbf24;
37
- --err: #f87171;
38
- --ok: #4ade80;
39
-
40
- /* Surfacesterminal-dark background with subtle slate steps. */
41
- --bg-0: #0a0e14;
42
- --bg-1: #11161e;
43
- --bg-2: #161c26;
44
- --bg-3: #1f2733;
45
- --bg-hover: rgba(103, 232, 249, 0.08);
46
-
47
- --fg-0: #e2e8f0; /* slate-200 — body text */
48
- --fg-1: #cbd5e1; /* slate-300 — primary text */
49
- --fg-2: #94a3b8; /* slate-400 — secondary */
50
- --fg-3: #64748b; /* slate-500 — dim */
51
-
52
- --border: #1e2733;
53
- --border-focus: var(--primary);
54
-
55
- --gradient-rule: linear-gradient(
56
- 90deg,
57
- var(--grad-1),
58
- var(--grad-2),
59
- var(--grad-3),
60
- var(--grad-4),
61
- var(--grad-5),
62
- var(--grad-6),
63
- var(--grad-7),
64
- var(--grad-8)
65
- );
66
-
67
- --mono: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;
68
- --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
69
-
70
- --radius-sm: 4px;
71
- --radius-md: 6px;
72
- --radius-lg: 10px;
73
- }
74
-
75
- * {
76
- box-sizing: border-box;
77
- }
78
-
79
- html,
21
+ /* Surfacessame family as TUI, slightly lifted for screen comfort */
22
+ --bg: #0a0c10;
23
+ --bg-elev: #11141a;
24
+ --bg-elev-2: #161a22;
25
+ --bg-input: #0d1015;
26
+ --bg-code: #06080c;
27
+ --bg-hover: #1a1f29;
28
+
29
+ /* Text */
30
+ --fg-0: #e6edf3; /* primary */
31
+ --fg-1: #c9d1d9; /* body */
32
+ --fg-2: #8b949e; /* secondary */
33
+ --fg-3: #6e7681; /* dim */
34
+ --fg-4: #484f58; /* very dim, separators in text */
35
+
36
+ /* Accents — TUI lineage, unchanged */
37
+ --c-brand: #79c0ff; /* sky — in-progress, links */
38
+ --c-accent: #d2a8ff; /* purple — reasoning, plan */
39
+ --c-violet: #b395f5; /* violet — sub-agent */
40
+ --c-ok: #7ee787; /* green — success */
41
+ --c-warn: #f0b07d; /* amber — warning, approval */
42
+ --c-err: #ff8b81; /* coral — error */
43
+ --c-info: #79c0ff;
44
+
45
+ /* Chart spectrum for series; 6-stop gradient that reads in dark mode */
46
+ --s1: #79c0ff; /* sky */
47
+ --s2: #56d4dd; /* teal */
48
+ --s3: #7ee787; /* mint */
49
+ --s4: #f0b07d; /* amber */
50
+ --s5: #ff8b81; /* coral */
51
+ --s6: #d2a8ff; /* purple */
52
+
53
+ /* Borders */
54
+ --bd: #1a1d24;
55
+ --bd-strong: #232831;
56
+
57
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
58
+ --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, Consolas, monospace;
59
+
60
+ /* Spacing / radius — tiny radius (2px) keeps web feel without going SaaS */
61
+ --r: 2px;
62
+ --r-md: 4px;
63
+ }
64
+
65
+ * { box-sizing: border-box; }
66
+ html, body { background: var(--bg); color: var(--fg-1); margin: 0; padding: 0; }
67
+
68
+ * { scrollbar-width: thin; scrollbar-color: var(--bd-strong) transparent; }
69
+ *::-webkit-scrollbar { width: 10px; height: 10px; }
70
+ *::-webkit-scrollbar-track { background: transparent; }
71
+ *::-webkit-scrollbar-thumb { background: var(--bd); border: 2px solid var(--bg); border-radius: 6px; }
72
+ *::-webkit-scrollbar-thumb:hover { background: var(--fg-4); }
73
+ *::-webkit-scrollbar-corner { background: transparent; }
80
74
  body {
81
- margin: 0;
82
- padding: 0;
83
- background: var(--bg-0);
84
- color: var(--fg-0);
85
- font-family: var(--sans);
75
+ font-family: var(--font-sans);
86
76
  font-size: 14px;
87
- line-height: 1.5;
88
- height: 100%;
77
+ line-height: 1.55;
78
+ -webkit-font-smoothing: antialiased;
89
79
  }
80
+ code, .mono { font-family: var(--font-mono); }
90
81
 
91
- /* ---------- Animations ----------
92
- *
93
- * Conservative, opacity-led — no horizontal slides because messages
94
- * land in a scrolling container and any non-y motion fights the
95
- * auto-scroll. `prefers-reduced-motion` users get instant transitions.
96
- */
97
- @keyframes fade-in {
98
- from {
99
- opacity: 0;
100
- transform: translateY(4px);
101
- }
102
- to {
103
- opacity: 1;
104
- transform: translateY(0);
105
- }
106
- }
107
- @keyframes modal-slide-in {
108
- from {
109
- opacity: 0;
110
- transform: translateY(8px);
111
- }
112
- to {
113
- opacity: 1;
114
- transform: translateY(0);
115
- }
116
- }
117
- @keyframes toast-slide-in {
118
- from {
119
- opacity: 0;
120
- transform: translateX(20px);
121
- }
122
- to {
123
- opacity: 1;
124
- transform: translateX(0);
125
- }
126
- }
127
- .chat-msg {
128
- animation: fade-in 0.18s ease-out;
129
- }
130
- .modal-card {
131
- animation: modal-slide-in 0.20s ease-out;
132
- }
133
- @media (prefers-reduced-motion: reduce) {
134
- .chat-msg,
135
- .modal-card {
136
- animation: none;
137
- }
138
- }
82
+ a { color: var(--c-brand); text-decoration: none; }
83
+ a:hover { text-decoration: underline; }
139
84
 
140
- /* ---------- Custom scrollbars ----------
141
- *
142
- * Default OS scrollbars look out of place against the dark TUI palette.
143
- * WebKit (Chrome / Edge / Safari) gets the `::-webkit-scrollbar` route;
144
- * Firefox uses `scrollbar-color` / `scrollbar-width`. Both render a thin
145
- * slate thumb on the bg-0 background, with the accent violet on hover.
146
- */
147
- *::-webkit-scrollbar {
148
- width: 10px;
149
- height: 10px;
150
- }
151
- *::-webkit-scrollbar-track {
152
- background: var(--bg-0);
153
- }
154
- *::-webkit-scrollbar-thumb {
155
- background: var(--bg-3);
156
- border-radius: 5px;
157
- /* Border carves the thumb a hair thinner so it doesn't crowd the
158
- * track; uses bg-0 so it visually merges with the background. */
159
- border: 2px solid var(--bg-0);
85
+ /* ── Doc chrome ─────────────────────────────────────────────────────────── */
86
+ .page {
87
+ display: grid;
88
+ grid-template-columns: 240px minmax(0, 1fr);
89
+ max-width: 1320px;
90
+ margin: 0 auto;
91
+ min-height: 100vh;
92
+ }
93
+ .toc {
94
+ position: sticky; top: 0; align-self: start;
95
+ height: 100vh; overflow-y: auto;
96
+ border-right: 1px solid var(--bd);
97
+ padding: 28px 18px;
98
+ background: var(--bg);
99
+ }
100
+ .toc h1 { font-size: 14px; font-weight: 700; margin: 0 0 4px; color: var(--fg-0); letter-spacing: .03em; font-family: var(--font-mono); }
101
+ .toc h1 .dot { color: var(--c-brand); margin-right: 8px; }
102
+ .toc .sub { font-size: 11px; color: var(--fg-3); margin: 0 0 18px; letter-spacing: .04em; }
103
+ .toc-section { font-size: 10px; text-transform: uppercase; letter-spacing: .14em; color: var(--fg-4); margin: 22px 0 6px; font-weight: 700; }
104
+ .toc-section:first-of-type { margin-top: 0; }
105
+ .toc ul { list-style: none; padding: 0; margin: 0; }
106
+ .toc li a {
107
+ display: block; padding: 3px 8px; margin: 1px 0;
108
+ color: var(--fg-2); font-size: 12.5px; border-radius: var(--r);
109
+ }
110
+ .toc li a:hover { color: var(--fg-0); background: var(--bg-elev); text-decoration: none; }
111
+
112
+ main { padding: 32px 40px 60px 32px; min-width: 0; }
113
+ .section { padding: 28px 0 36px; border-bottom: 1px solid #14171e; }
114
+ .section:last-child { border-bottom: none; }
115
+ .section > h2 {
116
+ font-size: 22px; font-weight: 700; color: var(--fg-0);
117
+ margin: 0 0 4px; letter-spacing: -.005em; font-family: var(--font-mono);
118
+ }
119
+ .section > h2 .num { color: var(--fg-4); margin-right: 10px; font-weight: 500; }
120
+ .section > .lede {
121
+ color: var(--fg-2); margin: 0 0 22px; font-size: 13px; max-width: 700px; line-height: 1.6;
122
+ }
123
+ .subsec { margin-bottom: 22px; }
124
+ .subsec > h3 {
125
+ font-size: 13px; font-weight: 700; color: var(--fg-1);
126
+ margin: 24px 0 4px; letter-spacing: .04em; text-transform: uppercase;
127
+ font-family: var(--font-mono);
128
+ }
129
+ .subsec > h3 .desc { color: var(--fg-3); font-weight: 400; margin-left: 10px; font-size: 12px; text-transform: none; letter-spacing: 0; }
130
+ .subsec > p { color: var(--fg-3); font-size: 12.5px; margin: 0 0 12px; max-width: 720px; line-height: 1.6; }
131
+
132
+ /* "Mock" — a faux-window frame to display dashboard pieces inside the design doc */
133
+ .mock {
134
+ background: var(--bg-elev);
135
+ border: 1px solid var(--bd);
136
+ border-radius: var(--r);
137
+ margin: 14px 0;
138
+ overflow: hidden;
160
139
  }
161
- *::-webkit-scrollbar-thumb:hover {
162
- background: var(--accent);
140
+ .mock-cap {
141
+ font-family: var(--font-mono);
142
+ font-size: 11px;
143
+ color: var(--fg-3);
144
+ margin: 18px 0 6px;
145
+ letter-spacing: .06em;
163
146
  }
164
- *::-webkit-scrollbar-corner {
165
- background: var(--bg-0);
147
+
148
+ /* ── §1 Tokens display ─────────────────────────────────────────────────── */
149
+ .swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 8px; margin: 8px 0 14px; }
150
+ .swatch {
151
+ background: var(--bg-elev); border: 1px solid var(--bd); padding: 10px 12px; border-radius: var(--r);
152
+ display: flex; align-items: center; gap: 10px;
153
+ font-family: var(--font-mono); font-size: 11.5px;
166
154
  }
167
- * {
168
- scrollbar-color: var(--bg-3) var(--bg-0);
169
- scrollbar-width: thin;
155
+ .swatch .chip { width: 22px; height: 22px; border-radius: var(--r); flex-shrink: 0; border: 1px solid rgba(255,255,255,.04); }
156
+ .swatch .meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
157
+ .swatch .name { color: var(--fg-1); font-size: 11.5px; }
158
+ .swatch .hex { color: var(--fg-3); font-size: 10.5px; }
159
+
160
+ .scale-row { display: flex; align-items: baseline; gap: 16px; padding: 6px 0; border-bottom: 1px dashed #181b22; }
161
+ .scale-row:last-child { border-bottom: none; }
162
+ .scale-row .lbl { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); width: 70px; flex-shrink: 0; }
163
+ .scale-row .ex { color: var(--fg-1); }
164
+
165
+ .glyph-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 6px; }
166
+ .glyph-cell {
167
+ background: var(--bg-elev); border: 1px solid var(--bd); padding: 8px 10px; border-radius: var(--r);
168
+ display: flex; align-items: center; gap: 10px; font-family: var(--font-mono); font-size: 12px;
170
169
  }
170
+ .glyph-cell .g { color: var(--c-brand); font-size: 16px; width: 18px; text-align: center; }
171
+ .glyph-cell .n { color: var(--fg-2); font-size: 11px; }
171
172
 
172
- #root {
173
- display: flex;
173
+ /* ── App shell — sidebar / topbar / statusrow ──────────────────────────── */
174
+ .app {
175
+ display: grid;
176
+ grid-template-columns: 220px minmax(0, 1fr);
177
+ grid-template-rows: 44px 1fr 26px;
178
+ grid-template-areas:
179
+ "side top"
180
+ "side body"
181
+ "side status";
174
182
  height: 100vh;
183
+ background: var(--bg);
184
+ font-size: 13px;
185
+ }
186
+ .app.collapsed { grid-template-columns: 56px minmax(0, 1fr); }
187
+
188
+ /* Sidebar */
189
+ .app-side {
190
+ grid-area: side;
191
+ background: var(--bg-elev);
192
+ border-right: 1px solid var(--bd);
193
+ display: flex; flex-direction: column;
194
+ }
195
+ .app-side .brand {
196
+ padding: 14px 16px 12px; display: flex; align-items: center; gap: 8px;
197
+ font-family: var(--font-mono); font-size: 13px; font-weight: 700; color: var(--fg-0);
198
+ letter-spacing: .08em;
199
+ }
200
+ .app-side .brand .glyph { color: var(--c-brand); font-size: 16px; }
201
+ .app-side .brand .ver { color: var(--fg-4); font-size: 10.5px; margin-left: auto; font-weight: 400; letter-spacing: .04em; }
202
+ .app.collapsed .app-side .brand .label,
203
+ .app.collapsed .app-side .brand .ver { display: none; }
204
+
205
+ .side-tabs { padding: 6px 8px; flex: 1; overflow-y: auto; }
206
+ .side-tab {
207
+ display: flex; align-items: center; gap: 10px;
208
+ padding: 6px 10px; margin: 1px 0;
209
+ color: var(--fg-2); font-family: var(--font-mono); font-size: 12px;
210
+ border-radius: var(--r); cursor: pointer;
211
+ border-left: 2px solid transparent;
212
+ letter-spacing: .02em;
213
+ }
214
+ .side-tab .g { font-family: var(--font-mono); font-size: 13px; width: 16px; text-align: center; color: var(--fg-3); flex-shrink: 0; }
215
+ .side-tab:hover { background: var(--bg-hover); color: var(--fg-0); }
216
+ .side-tab:hover .g { color: var(--fg-1); }
217
+ .side-tab.active { background: var(--bg-hover); color: var(--fg-0); border-left-color: var(--c-brand); }
218
+ .side-tab.active .g { color: var(--c-brand); }
219
+ .side-tab .badge { margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--fg-3); background: var(--bg-elev-2); padding: 1px 5px; border-radius: 8px; }
220
+ .app.collapsed .side-tab .label,
221
+ .app.collapsed .side-tab .badge { display: none; }
222
+ .app.collapsed .side-tab { justify-content: center; padding: 8px; }
223
+
224
+ .side-section { font-family: var(--font-mono); font-size: 10px; color: var(--fg-4); padding: 14px 14px 4px; letter-spacing: .12em; text-transform: uppercase; font-weight: 600; }
225
+ .app.collapsed .side-section { display: none; }
226
+
227
+ .side-foot {
228
+ padding: 8px; border-top: 1px solid var(--bd); display: flex; align-items: center; gap: 8px;
229
+ font-family: var(--font-mono); font-size: 11px; color: var(--fg-3);
230
+ }
231
+ .side-foot .toggle { margin-left: auto; cursor: pointer; color: var(--fg-3); padding: 2px 6px; border-radius: var(--r); }
232
+ .side-foot .toggle:hover { color: var(--fg-1); background: var(--bg-hover); }
233
+ .app.collapsed .side-foot .label { display: none; }
234
+
235
+ /* Top bar */
236
+ .app-top {
237
+ grid-area: top;
238
+ display: flex; align-items: center; gap: 12px;
239
+ padding: 0 16px;
240
+ background: var(--bg-elev);
241
+ border-bottom: 1px solid var(--bd);
242
+ font-family: var(--font-mono); font-size: 12px;
243
+ }
244
+ .app-top .ws { color: var(--fg-1); display: flex; align-items: center; gap: 6px; }
245
+ .app-top .ws .path { color: var(--fg-2); }
246
+ .app-top .ws .branch { color: var(--c-ok); padding: 1px 5px; background: rgba(126,231,135,.08); border-radius: var(--r); font-size: 10.5px; }
247
+ .app-top .sep { color: var(--fg-4); margin: 0 4px; }
248
+ .app-top .session { color: var(--c-accent); }
249
+ .app-top .grow { flex: 1; }
250
+ .app-top .meter { display: flex; align-items: center; gap: 6px; color: var(--fg-2); }
251
+ .app-top .meter .v { color: var(--fg-0); font-weight: 600; }
252
+ .app-top .meter .lbl { color: var(--fg-4); font-size: 10.5px; }
253
+
254
+ /* Body / panel content slot */
255
+ .app-body {
256
+ grid-area: body;
257
+ overflow-y: auto;
258
+ padding: 24px 28px;
175
259
  }
176
260
 
177
- .boot {
178
- margin: auto;
179
- color: var(--fg-3);
180
- font-family: var(--mono);
261
+ /* Status row */
262
+ .app-status {
263
+ grid-area: status;
264
+ display: flex; align-items: center; gap: 14px;
265
+ padding: 0 14px;
266
+ background: var(--bg-elev);
267
+ border-top: 1px solid var(--bd);
268
+ font-family: var(--font-mono); font-size: 11px; color: var(--fg-3);
181
269
  }
270
+ .app-status .item { display: flex; align-items: center; gap: 4px; }
271
+ .app-status .item .v { color: var(--fg-1); }
272
+ .app-status .item .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--c-ok); }
273
+ .app-status .item .dot.warn { background: var(--c-warn); }
274
+ .app-status .item .dot.err { background: var(--c-err); }
275
+ .app-status .grow { flex: 1; }
182
276
 
183
- /* ---------- Layout: sidebar + main ---------- */
277
+ /* ── §3 Components ─────────────────────────────────────────────────────── */
184
278
 
185
- .sidebar {
186
- width: 220px;
187
- flex-shrink: 0;
188
- background: var(--bg-1);
189
- border-right: 1px solid var(--border);
190
- display: flex;
191
- flex-direction: column;
192
- transition: width 0.18s ease-out;
193
- }
194
- .sidebar.collapsed {
195
- width: 52px;
196
- }
197
- .sidebar.collapsed .sidebar-label {
198
- display: none;
279
+ /* Card */
280
+ .card {
281
+ background: var(--bg-elev);
282
+ border: 1px solid var(--bd);
283
+ border-radius: var(--r);
284
+ padding: 14px 16px;
199
285
  }
200
- .sidebar.collapsed .sidebar-header {
201
- padding: 14px 8px 10px;
202
- text-align: center;
286
+ .card.accent-brand { border-left: 2px solid var(--c-brand); }
287
+ .card.accent-accent { border-left: 2px solid var(--c-accent); }
288
+ .card.accent-warn { border-left: 2px solid var(--c-warn); }
289
+ .card.accent-err { border-left: 2px solid var(--c-err); }
290
+ .card-h { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
291
+ .card-h .glyph { font-family: var(--font-mono); color: var(--c-brand); font-size: 14px; }
292
+ .card-h .title { color: var(--fg-0); font-weight: 600; font-size: 13px; }
293
+ .card-h .meta { margin-left: auto; color: var(--fg-3); font-family: var(--font-mono); font-size: 11px; }
294
+ .card-b { color: var(--fg-1); font-size: 13px; line-height: 1.55; }
295
+
296
+ /* Pill */
297
+ .pill {
298
+ display: inline-flex; align-items: center; gap: 4px;
299
+ font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
300
+ padding: 1px 7px;
301
+ border-radius: 9px;
302
+ background: var(--bg-elev-2);
303
+ color: var(--fg-2);
304
+ letter-spacing: .04em;
305
+ }
306
+ .pill .g { font-size: 9px; }
307
+ .pill.ok { color: var(--c-ok); background: rgba(126,231,135,.08); }
308
+ .pill.warn { color: var(--c-warn); background: rgba(240,176,125,.10); }
309
+ .pill.err { color: var(--c-err); background: rgba(255,139,129,.10); }
310
+ .pill.info { color: var(--c-brand); background: rgba(121,192,255,.10); }
311
+ .pill.acc { color: var(--c-accent); background: rgba(210,168,255,.10); }
312
+
313
+ /* Table */
314
+ .tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
315
+ .tbl th, .tbl td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--bd); }
316
+ .tbl th { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em; background: var(--bg-elev); }
317
+ .tbl td { color: var(--fg-1); }
318
+ .tbl tbody tr:hover { background: var(--bg-hover); }
319
+ .tbl td.num { font-family: var(--font-mono); text-align: right; color: var(--fg-0); font-variant-numeric: tabular-nums; }
320
+ .tbl td.dim { color: var(--fg-3); }
321
+ .tbl td.path { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-2); }
322
+
323
+ /* Toast */
324
+ .toast-wrap { display: flex; flex-direction: column; gap: 8px; max-width: 360px; }
325
+ .toast {
326
+ background: var(--bg-elev-2); border: 1px solid var(--bd);
327
+ border-left: 2px solid var(--c-brand);
328
+ padding: 10px 12px; border-radius: var(--r);
329
+ display: flex; align-items: flex-start; gap: 8px;
330
+ font-size: 12.5px; color: var(--fg-1);
331
+ }
332
+ .toast .g { font-family: var(--font-mono); color: var(--c-brand); font-size: 13px; flex-shrink: 0; margin-top: 1px; }
333
+ .toast.ok { border-left-color: var(--c-ok); } .toast.ok .g { color: var(--c-ok); }
334
+ .toast.warn { border-left-color: var(--c-warn); } .toast.warn .g { color: var(--c-warn); }
335
+ .toast.err { border-left-color: var(--c-err); } .toast.err .g { color: var(--c-err); }
336
+ .toast .x { margin-left: auto; color: var(--fg-3); cursor: pointer; }
337
+ .toast .x:hover { color: var(--fg-0); }
338
+
339
+ /* Code block */
340
+ .code {
341
+ background: var(--bg-code);
342
+ border: 1px solid var(--bd);
343
+ border-radius: var(--r);
344
+ padding: 10px 14px;
345
+ font-family: var(--font-mono);
346
+ font-size: 12.5px;
347
+ color: var(--fg-1);
348
+ white-space: pre;
349
+ overflow-x: auto;
350
+ line-height: 1.6;
203
351
  }
204
- .sidebar.collapsed .sidebar-brand {
205
- font-size: 0;
352
+ .code .ln { color: var(--fg-4); user-select: none; padding-right: 14px; }
353
+ .code .kw { color: var(--c-accent); }
354
+ .code .str { color: var(--c-ok); }
355
+ .code .com { color: var(--fg-3); font-style: italic; }
356
+ .code .num { color: var(--c-warn); }
357
+
358
+ /* Diff */
359
+ .diff {
360
+ background: var(--bg-code); border: 1px solid var(--bd); border-radius: var(--r);
361
+ font-family: var(--font-mono); font-size: 12px; line-height: 1.55;
362
+ overflow: hidden;
206
363
  }
207
- .sidebar.collapsed .sidebar-brand .glyph {
208
- font-size: 18px;
209
- margin: 0;
364
+ .diff-h { padding: 6px 12px; background: var(--bg-elev); color: var(--fg-2); font-size: 11px; border-bottom: 1px solid var(--bd); display: flex; gap: 12px; align-items: center; }
365
+ .diff-h .file { color: var(--fg-1); }
366
+ .diff-h .stat { margin-left: auto; }
367
+ .diff-h .stat .add { color: var(--c-ok); }
368
+ .diff-h .stat .rem { color: var(--c-err); }
369
+ .diff-row { display: grid; grid-template-columns: 32px 32px 1fr; }
370
+ .diff-row .gut { color: var(--fg-4); padding: 0 8px; text-align: right; user-select: none; }
371
+ .diff-row .txt { padding: 0 10px; white-space: pre; }
372
+ .diff-row.add { background: rgba(126,231,135,.06); }
373
+ .diff-row.add .gut { color: var(--c-ok); }
374
+ .diff-row.add .txt { color: var(--c-ok); }
375
+ .diff-row.rem { background: rgba(255,139,129,.05); }
376
+ .diff-row.rem .gut { color: var(--c-err); }
377
+ .diff-row.rem .txt { color: var(--c-err); }
378
+ .diff-row.ctx .txt { color: var(--fg-2); }
379
+ .diff-row.hunk { background: var(--bg-elev); color: var(--fg-3); }
380
+ .diff-row.hunk .txt, .diff-row.hunk .gut { color: var(--fg-3); }
381
+
382
+ /* Inline syntax tokens inherit color from .kw/.str/.com defined in .code; intra-line word diff. */
383
+ .diff-row .word-add { background: rgba(126,231,135,.22); color: var(--c-ok); border-radius: 2px; padding: 0 2px; }
384
+ .diff-row .word-rem { background: rgba(255,139,129,.20); color: var(--c-err); border-radius: 2px; padding: 0 2px; text-decoration: line-through; text-decoration-color: rgba(255,139,129,.55); }
385
+
386
+ /* Expand-context chevron row sits between hunks; clicking loads the gap. */
387
+ .diff-row.expand { grid-template-columns: 1fr; cursor: pointer; user-select: none; background: transparent; }
388
+ .diff-row.expand .txt { padding: 4px 12px; color: var(--fg-3); text-align: center; font-size: 11px; border-top: 1px dashed var(--bd); border-bottom: 1px dashed var(--bd); }
389
+ .diff-row.expand:hover .txt { color: var(--fg-1); border-color: var(--c-brand); }
390
+
391
+ /* Side-by-side variant — content split into two cells, no shared gutter strip. */
392
+ .diff.split .diff-row { grid-template-columns: 32px 1fr 32px 1fr; }
393
+ .diff.split .diff-row .pane { padding: 0 10px; white-space: pre; }
394
+ .diff.split .diff-row.add .pane.l, .diff.split .diff-row.rem .pane.r { background: var(--bg-elev); color: var(--fg-4); }
395
+
396
+ /* Edit-review panel — multi-file aggregator card list. */
397
+ .review-summary {
398
+ display: flex; align-items: center; gap: 14px; padding: 10px 14px;
399
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r);
400
+ font-family: var(--font-mono); font-size: 12px; margin-bottom: 12px;
401
+ }
402
+ .review-summary .count { color: var(--fg-0); font-weight: 600; }
403
+ .review-summary .stat .add { color: var(--c-ok); }
404
+ .review-summary .stat .rem { color: var(--c-err); }
405
+ .review-summary .actions { margin-left: auto; display: flex; gap: 6px; }
406
+ .review-mode { display: inline-flex; gap: 0; border: 1px solid var(--bd); border-radius: var(--r); overflow: hidden; }
407
+ .review-mode button {
408
+ background: transparent; border: 0; color: var(--fg-3); padding: 4px 10px;
409
+ font-family: var(--font-mono); font-size: 11px; cursor: pointer;
410
+ }
411
+ .review-mode button.on { background: var(--bg-input); color: var(--fg-0); }
412
+
413
+ .review-file { border: 1px solid var(--bd); border-radius: var(--r); margin-bottom: 10px; overflow: hidden; }
414
+ .review-file-h {
415
+ display: flex; align-items: center; gap: 10px; padding: 8px 12px;
416
+ background: var(--bg-elev); cursor: pointer; user-select: none;
417
+ font-family: var(--font-mono); font-size: 12px;
418
+ }
419
+ .review-file-h .chev { color: var(--fg-3); width: 12px; }
420
+ .review-file-h .file { color: var(--fg-1); }
421
+ .review-file-h .stat { color: var(--fg-3); }
422
+ .review-file-h .stat .add { color: var(--c-ok); }
423
+ .review-file-h .stat .rem { color: var(--c-err); }
424
+ .review-file-h .acts { margin-left: auto; display: flex; gap: 6px; }
425
+ .review-file.collapsed .review-file-body { display: none; }
426
+ .review-file.collapsed .review-file-h .chev::before { content: "▸"; }
427
+ .review-file:not(.collapsed) .review-file-h .chev::before { content: "▾"; }
428
+
429
+ /* Chart frame */
430
+ .chart {
431
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 14px 16px;
432
+ }
433
+ .chart-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
434
+ .chart-h .title { color: var(--fg-3); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
435
+ .chart-h .delta { margin-left: auto; font-family: var(--font-mono); font-size: 11px; }
436
+ .chart-h .delta.up { color: var(--c-ok); }
437
+ .chart-h .delta.down { color: var(--c-err); }
438
+ .chart-v { font-family: var(--font-mono); font-size: 22px; font-weight: 700; color: var(--fg-0); margin-bottom: 4px; letter-spacing: -.01em; }
439
+ .chart-v .unit { color: var(--fg-3); font-size: 13px; font-weight: 400; margin-left: 4px; }
440
+ .chart-spark svg { width: 100%; height: 38px; display: block; }
441
+
442
+ /* Form */
443
+ .form-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px; }
444
+ .form-row .lbl { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em; }
445
+ .form-row .help { color: var(--fg-3); font-size: 11.5px; margin-top: 2px; }
446
+ .input, .select, .textarea {
447
+ background: var(--bg-input); border: 1px solid var(--bd); border-radius: var(--r);
448
+ padding: 6px 10px; color: var(--fg-0); font-family: var(--font-mono); font-size: 12.5px;
449
+ outline: none; width: 100%;
450
+ }
451
+ .input:focus, .select:focus, .textarea:focus { border-color: var(--c-brand); }
452
+ .checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--fg-1); }
453
+ .checkbox-row .box { width: 13px; height: 13px; border: 1px solid var(--bd-strong); border-radius: var(--r); display: inline-flex; align-items: center; justify-content: center; background: var(--bg-input); }
454
+ .checkbox-row .box.on { background: var(--c-brand); border-color: var(--c-brand); color: var(--bg); font-family: var(--font-mono); font-size: 10px; font-weight: 700; }
455
+
456
+ .btn {
457
+ display: inline-flex; align-items: center; gap: 6px;
458
+ background: var(--bg-elev-2); border: 1px solid var(--bd-strong); color: var(--fg-1);
459
+ padding: 5px 12px; border-radius: var(--r);
460
+ font-family: var(--font-mono); font-size: 12px; font-weight: 600; cursor: pointer;
461
+ letter-spacing: .02em;
462
+ }
463
+ .btn:hover { background: var(--bg-hover); color: var(--fg-0); border-color: var(--fg-4); }
464
+ .btn.primary { background: var(--c-brand); color: var(--bg); border-color: var(--c-brand); }
465
+ .btn.primary:hover { background: #94cdff; border-color: #94cdff; color: var(--bg); }
466
+ .btn.ghost { background: transparent; }
467
+ .btn .g { font-size: 11px; }
468
+
469
+ /* ── Progress ─────────────────────────────────────────────────────────── */
470
+ /* Linear bar */
471
+ .progress {
472
+ width: 100%; height: 6px; background: var(--bg-input);
473
+ border-radius: 3px; overflow: hidden; position: relative;
474
+ }
475
+ .progress-fill {
476
+ height: 100%; background: var(--c-brand);
477
+ transition: width .3s ease; border-radius: 3px;
478
+ }
479
+ .progress.thin { height: 3px; }
480
+ .progress.thick { height: 10px; }
481
+ .progress.ok .progress-fill { background: var(--c-ok); }
482
+ .progress.warn .progress-fill { background: var(--c-warn); }
483
+ .progress.err .progress-fill { background: var(--c-err); }
484
+ .progress.acc .progress-fill { background: var(--c-accent); }
485
+
486
+ /* Indeterminate — shimmer slice loops left-to-right */
487
+ .progress.indet .progress-fill {
488
+ width: 30%; animation: progress-indet 1.4s linear infinite;
489
+ }
490
+ @keyframes progress-indet {
491
+ 0% { transform: translateX(-100%); }
492
+ 100% { transform: translateX(400%); }
493
+ }
494
+
495
+ /* Segmented — multiple fills side by side, e.g. cache-hit / cache-miss split */
496
+ .progress.segmented { display: flex; gap: 1px; background: transparent; padding: 0; height: 6px; }
497
+ .progress.segmented .progress-seg { height: 100%; }
498
+ .progress.segmented .progress-seg.s1 { background: var(--s1); }
499
+ .progress.segmented .progress-seg.s2 { background: var(--s2); }
500
+ .progress.segmented .progress-seg.s3 { background: var(--s3); }
501
+ .progress.segmented .progress-seg.s4 { background: var(--s4); }
502
+ .progress.segmented .progress-seg.s5 { background: var(--s5); }
503
+ .progress.segmented .progress-seg.dim { background: var(--bg-input); }
504
+
505
+ /* Progress with caption row */
506
+ .progress-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; }
507
+ .progress-row .lbl { font-family: var(--font-mono); font-size: 11px; color: var(--fg-3); flex-shrink: 0; min-width: 110px; }
508
+ .progress-row .v { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-0); flex-shrink: 0; min-width: 60px; text-align: right; }
509
+ .progress-row .progress { flex: 1; }
510
+
511
+ /* Step progress — numbered dots connected by lines */
512
+ .steps { display: flex; align-items: center; gap: 0; padding: 4px 0; }
513
+ .step-dot {
514
+ width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
515
+ background: var(--bg-input); border: 1px solid var(--bd-strong);
516
+ display: flex; align-items: center; justify-content: center;
517
+ font-family: var(--font-mono); font-size: 11px; color: var(--fg-3); font-weight: 600;
518
+ }
519
+ .step-dot.done { background: var(--c-ok); border-color: var(--c-ok); color: var(--bg); }
520
+ .step-dot.active { background: var(--c-brand); border-color: var(--c-brand); color: var(--bg); }
521
+ .step-dot.fail { background: var(--c-err); border-color: var(--c-err); color: var(--bg); }
522
+ .step-line { flex: 1; height: 1px; background: var(--bd-strong); margin: 0 -1px; }
523
+ .step-line.done { background: var(--c-ok); }
524
+ .step-line.active { background: linear-gradient(90deg, var(--c-ok), var(--c-brand)); }
525
+
526
+ /* Ring — circular progress, anchors its own value text */
527
+ .ring { position: relative; display: inline-block; line-height: 0; }
528
+ .ring svg { transform: rotate(-90deg); display: block; }
529
+ .ring-bg { fill: none; stroke: var(--bg-input); }
530
+ .ring-fill { fill: none; stroke: var(--c-brand); stroke-linecap: round; transition: stroke-dashoffset .4s ease; }
531
+ .ring.ok .ring-fill { stroke: var(--c-ok); }
532
+ .ring.warn .ring-fill { stroke: var(--c-warn); }
533
+ .ring.err .ring-fill { stroke: var(--c-err); }
534
+ .ring-label { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; flex-direction: column; line-height: 1.1; }
535
+ .ring-label .v { font-family: var(--font-mono); font-size: 14px; font-weight: 700; color: var(--fg-0); }
536
+ .ring-label .u { font-family: var(--font-mono); font-size: 9px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em; }
537
+
538
+ /* ── Modal / Overlay ──────────────────────────────────────────────────── */
539
+ .overlay {
540
+ position: relative;
541
+ background: rgba(6,8,12,.78);
542
+ padding: 28px;
543
+ border-radius: var(--r);
544
+ min-height: 280px;
545
+ display: flex; align-items: center; justify-content: center;
546
+ }
547
+ .overlay::before {
548
+ /* Box-drawing corner ticks at the four corners — TUI signature */
549
+ content: "";
550
+ position: absolute; inset: 8px;
551
+ border: 1px solid #14171e;
552
+ pointer-events: none;
553
+ border-radius: var(--r);
554
+ }
555
+ .dialog {
556
+ background: var(--bg-elev);
557
+ border: 1px solid var(--bd-strong);
558
+ border-radius: var(--r);
559
+ width: 100%; max-width: 540px;
560
+ box-shadow: 0 18px 48px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.02);
561
+ }
562
+ .dialog-h {
563
+ padding: 11px 16px; border-bottom: 1px solid var(--bd);
564
+ display: flex; align-items: center; gap: 10px; font-family: var(--font-mono);
565
+ }
566
+ .dialog-h .glyph { font-size: 14px; color: var(--c-brand); }
567
+ .dialog-h .title { color: var(--fg-0); font-weight: 600; font-size: 12.5px; letter-spacing: .04em; text-transform: uppercase; }
568
+ .dialog-h .meta { margin-left: auto; font-size: 11px; color: var(--fg-3); }
569
+ .dialog-b { padding: 14px 16px; }
570
+ .dialog-f { padding: 10px 16px; border-top: 1px solid var(--bd); display: flex; align-items: center; gap: 8px; }
571
+ .dialog-f .grow { flex: 1; }
572
+ .dialog-f .hint { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); }
573
+
574
+ .dialog.warn .dialog-h .glyph,
575
+ .dialog.warn .dialog-h .title { color: var(--c-warn); }
576
+ .dialog.warn { border-top: 2px solid var(--c-warn); }
577
+
578
+ .dialog.acc .dialog-h .glyph,
579
+ .dialog.acc .dialog-h .title { color: var(--c-accent); }
580
+ .dialog.acc { border-top: 2px solid var(--c-accent); }
581
+
582
+ /* Command palette — centered, larger, search-driven */
583
+ .cmd-palette {
584
+ background: var(--bg-elev);
585
+ border: 1px solid var(--bd-strong);
586
+ border-radius: var(--r);
587
+ width: 100%; max-width: 560px;
588
+ box-shadow: 0 24px 64px rgba(0,0,0,.6);
589
+ overflow: hidden;
210
590
  }
211
- .sidebar.collapsed .tab {
212
- padding: 9px 0;
213
- justify-content: center;
214
- border-left: 2px solid transparent;
591
+ .cmd-palette .cmd-input-row {
592
+ display: flex; align-items: center; gap: 10px; padding: 11px 16px;
593
+ border-bottom: 1px solid var(--bd);
594
+ }
595
+ .cmd-palette .cmd-input-row .g { font-family: var(--font-mono); color: var(--c-brand); font-size: 14px; }
596
+ .cmd-palette .cmd-input-row input {
597
+ flex: 1; background: transparent; border: none; outline: none;
598
+ color: var(--fg-0); font-family: var(--font-mono); font-size: 14px;
599
+ }
600
+ .cmd-palette .cmd-input-row .kbd {
601
+ font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3);
602
+ border: 1px solid var(--bd); padding: 1px 5px; border-radius: var(--r); background: var(--bg-input);
603
+ }
604
+ .cmd-palette .cmd-list { padding: 4px 0; max-height: 320px; overflow-y: auto; }
605
+ .cmd-row {
606
+ display: flex; align-items: center; gap: 10px; padding: 6px 16px;
607
+ cursor: pointer; font-size: 13px; color: var(--fg-1);
608
+ }
609
+ .cmd-row:hover, .cmd-row.sel { background: var(--bg-hover); }
610
+ .cmd-row.sel { border-left: 2px solid var(--c-brand); padding-left: 14px; }
611
+ .cmd-row .g { font-family: var(--font-mono); color: var(--c-brand); font-size: 12px; width: 14px; flex-shrink: 0; }
612
+ .cmd-row .name { font-family: var(--font-mono); color: var(--fg-0); }
613
+ .cmd-row .desc { color: var(--fg-3); font-size: 12px; margin-left: auto; }
614
+ .cmd-row .kbd { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); border: 1px solid var(--bd); padding: 1px 5px; border-radius: var(--r); background: var(--bg-input); }
615
+ .cmd-section-h { font-family: var(--font-mono); font-size: 10px; color: var(--fg-4); padding: 8px 16px 4px; text-transform: uppercase; letter-spacing: .12em; }
616
+
617
+ /* Popover — anchored dropdown for slash / @ menus */
618
+ .popover {
619
+ background: var(--bg-elev-2);
620
+ border: 1px solid var(--bd-strong);
621
+ border-radius: var(--r);
622
+ box-shadow: 0 12px 32px rgba(0,0,0,.5);
623
+ padding: 4px 0; min-width: 240px; max-width: 360px;
624
+ }
625
+ .popover-h { padding: 6px 12px 4px; font-family: var(--font-mono); font-size: 10px; color: var(--fg-4); text-transform: uppercase; letter-spacing: .12em; }
626
+ .popover-row {
627
+ padding: 5px 12px; display: flex; align-items: center; gap: 8px;
628
+ font-size: 12.5px; color: var(--fg-1); cursor: pointer;
629
+ }
630
+ .popover-row:hover, .popover-row.sel { background: var(--bg-hover); }
631
+ .popover-row.sel { border-left: 2px solid var(--c-brand); padding-left: 10px; }
632
+ .popover-row .g { font-family: var(--font-mono); color: var(--c-brand); font-size: 12px; width: 14px; flex-shrink: 0; }
633
+ .popover-row .name { font-family: var(--font-mono); color: var(--fg-0); }
634
+ .popover-row .meta { margin-left: auto; color: var(--fg-3); font-family: var(--font-mono); font-size: 11px; }
635
+
636
+ /* ── Composer (chat input, multi-line, with chips) ────────────────────── */
637
+ .composer {
638
+ background: var(--bg-input); border: 1px solid var(--bd);
639
+ border-radius: var(--r); padding: 8px 10px;
640
+ display: flex; flex-direction: column; gap: 6px;
641
+ }
642
+ .composer:focus-within { border-color: var(--c-brand); }
643
+ .composer-tags { display: flex; flex-wrap: wrap; gap: 4px; }
644
+ .composer-chip {
645
+ display: inline-flex; align-items: center; gap: 4px;
646
+ background: var(--bg-elev-2); padding: 2px 6px 2px 8px;
647
+ border-radius: var(--r); font-family: var(--font-mono); font-size: 11px;
648
+ border: 1px solid var(--bd);
649
+ }
650
+ .composer-chip.attach { color: var(--c-brand); border-color: rgba(121,192,255,.25); }
651
+ .composer-chip.paste { color: var(--c-accent); border-color: rgba(210,168,255,.25); }
652
+ .composer-chip .x { color: var(--fg-3); cursor: pointer; padding: 0 2px; }
653
+ .composer-chip .x:hover { color: var(--fg-0); }
654
+ .composer-text {
655
+ background: transparent; border: none; outline: none;
656
+ color: var(--fg-0); font-family: var(--font-mono); font-size: 13px;
657
+ width: 100%; resize: none; min-height: 22px; line-height: 1.6;
658
+ padding: 4px 0;
659
+ }
660
+ .composer-text .caret { display: inline-block; width: 8px; height: 16px; background: var(--c-brand); vertical-align: text-bottom; animation: caret 1s steps(2) infinite; margin-left: 1px; }
661
+ @keyframes caret { 50% { opacity: 0; } }
662
+ .composer-foot {
663
+ display: flex; align-items: center; gap: 14px; padding-top: 4px;
664
+ font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4);
665
+ border-top: 1px solid #14171e;
666
+ }
667
+ .composer-foot .grow { flex: 1; }
668
+ .composer-foot .hint .kbd {
669
+ border: 1px solid var(--bd); padding: 0 4px; border-radius: var(--r);
670
+ color: var(--fg-3); margin: 0 2px; background: var(--bg-elev);
671
+ }
672
+ .composer-foot .send { color: var(--c-brand); cursor: pointer; }
673
+
674
+ /* TUI status indicator (small pill in topbar) */
675
+ .tui-status {
676
+ display: inline-flex; align-items: center; gap: 6px;
677
+ font-family: var(--font-mono); font-size: 10.5px;
678
+ padding: 2px 8px; border-radius: 9px;
679
+ background: var(--bg-elev-2); color: var(--fg-3); border: 1px solid var(--bd);
680
+ }
681
+ .tui-status .dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
682
+ .tui-status.online { color: var(--c-ok); } .tui-status.online .dot { background: var(--c-ok); box-shadow: 0 0 6px rgba(126,231,135,.5); }
683
+ .tui-status.laggy { color: var(--c-warn); } .tui-status.laggy .dot { background: var(--c-warn); }
684
+ .tui-status.offline { color: var(--c-err); } .tui-status.offline .dot { background: var(--c-err); }
685
+
686
+ /* ── Breadcrumbs — replace topbar `·` with `›` for crumb-style flow ───── */
687
+ .crumbs { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 12px; }
688
+ .crumbs .crumb { color: var(--fg-1); }
689
+ .crumbs .crumb.dim { color: var(--fg-3); }
690
+ .crumbs .sep { color: var(--fg-4); }
691
+
692
+ /* ── Sessions panel ──────────────────────────────────────────────────── */
693
+ .sessions-grid { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 14px; min-height: 540px; }
694
+ .sessions-list { background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); display: flex; flex-direction: column; overflow: hidden; }
695
+ .sessions-list .ssl-h { padding: 10px 12px; border-bottom: 1px solid var(--bd); display: flex; align-items: center; gap: 8px; }
696
+ .sessions-list .ssl-h input {
697
+ flex: 1; background: var(--bg-input); border: 1px solid var(--bd); border-radius: var(--r);
698
+ padding: 4px 8px; font-family: var(--font-mono); font-size: 12px; color: var(--fg-0); outline: none;
699
+ }
700
+ .sessions-list .ssl-h input:focus { border-color: var(--c-brand); }
701
+ .sessions-list .ssl-rows { flex: 1; overflow-y: auto; }
702
+ .ssl-row {
703
+ padding: 8px 12px; border-bottom: 1px solid #14171e; cursor: pointer;
704
+ display: flex; flex-direction: column; gap: 3px;
705
+ }
706
+ .ssl-row:hover { background: var(--bg-hover); }
707
+ .ssl-row.sel { background: var(--bg-hover); border-left: 2px solid var(--c-brand); padding-left: 10px; }
708
+ .ssl-row .name { font-family: var(--font-mono); font-size: 12.5px; color: var(--fg-0); }
709
+ .ssl-row .preview { font-size: 11.5px; color: var(--fg-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
710
+ .ssl-row .meta { display: flex; gap: 10px; font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); margin-top: 2px; }
711
+ .ssl-row .meta .v { color: var(--fg-2); }
712
+
713
+ .sessions-detail { background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 14px 16px; overflow: auto; }
714
+ .sessions-detail-h { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--bd); }
715
+ .sessions-detail-h .name { font-family: var(--font-mono); font-size: 14px; color: var(--fg-0); font-weight: 600; }
716
+ .sessions-detail-h .ws { font-family: var(--font-mono); font-size: 11px; color: var(--fg-3); }
717
+ .sessions-detail-h .actions { margin-left: auto; display: flex; gap: 6px; }
718
+ .sessions-detail-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 14px; }
719
+ .sessions-detail-kpis .kp { padding: 8px 10px; background: var(--bg-input); border-radius: var(--r); }
720
+ .sessions-detail-kpis .kp .lbl { font-family: var(--font-mono); font-size: 10px; color: var(--fg-4); text-transform: uppercase; letter-spacing: .1em; }
721
+ .sessions-detail-kpis .kp .v { font-family: var(--font-mono); font-size: 16px; color: var(--fg-0); font-weight: 600; margin-top: 2px; }
722
+
723
+ /* ── File tree (Editor panel) ────────────────────────────────────────── */
724
+ .tree { font-family: var(--font-mono); font-size: 12px; padding: 6px 0; user-select: none; }
725
+ .tree-node {
726
+ padding: 3px 8px 3px 0; cursor: pointer; display: flex; align-items: center; gap: 4px;
727
+ color: var(--fg-2); border-left: 2px solid transparent;
728
+ }
729
+ .tree-node:hover { background: var(--bg-hover); color: var(--fg-1); }
730
+ .tree-node.sel { background: var(--bg-hover); color: var(--c-brand); border-left-color: var(--c-brand); }
731
+ .tree-node .indent { display: inline-block; width: 10px; flex-shrink: 0; }
732
+ .tree-node .arrow { width: 10px; color: var(--fg-3); }
733
+ .tree-node.open .arrow { color: var(--c-brand); }
734
+ .tree-node .icon { width: 12px; color: var(--fg-3); flex-shrink: 0; }
735
+ .tree-node .icon.dir { color: var(--c-brand); }
736
+ .tree-node .icon.tsx { color: var(--c-brand); }
737
+ .tree-node .icon.css { color: var(--c-accent); }
738
+ .tree-node .icon.md { color: var(--c-warn); }
739
+ .tree-node .icon.json { color: var(--c-violet); }
740
+ .tree-node .name { flex: 1; }
741
+ .tree-node .badge { font-size: 9px; color: var(--c-warn); margin-left: 4px; }
742
+ .tree-node .modified { color: var(--c-warn); font-size: 14px; line-height: 0.5; margin-left: 4px; }
743
+
744
+ /* ── Editor tabs ─────────────────────────────────────────────────────── */
745
+ .editor-tabs {
746
+ display: flex; border-bottom: 1px solid var(--bd); background: var(--bg-elev);
747
+ overflow-x: auto; scrollbar-width: none;
215
748
  }
216
- .sidebar.collapsed .tab.active {
217
- border-left-color: var(--primary);
749
+ .editor-tabs::-webkit-scrollbar { display: none; }
750
+ .editor-tab {
751
+ padding: 7px 14px; font-family: var(--font-mono); font-size: 12px;
752
+ color: var(--fg-3); border-right: 1px solid var(--bd);
753
+ display: flex; align-items: center; gap: 6px; cursor: pointer;
754
+ border-bottom: 2px solid transparent; margin-bottom: -1px; flex-shrink: 0;
755
+ }
756
+ .editor-tab:hover { color: var(--fg-1); background: var(--bg-hover); }
757
+ .editor-tab.active { color: var(--fg-0); background: var(--bg); border-bottom-color: var(--c-brand); }
758
+ .editor-tab .x { color: var(--fg-4); font-size: 10px; padding: 0 2px; border-radius: var(--r); }
759
+ .editor-tab .x:hover { color: var(--fg-0); background: var(--bd); }
760
+ .editor-tab .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--c-warn); flex-shrink: 0; }
761
+
762
+ /* ── Code editor area ────────────────────────────────────────────────── */
763
+ .editor-area {
764
+ background: var(--bg-code); padding: 8px 0;
765
+ font-family: var(--font-mono); font-size: 12.5px; line-height: 1.6;
766
+ color: var(--fg-1); overflow: auto;
767
+ flex: 1; min-height: 0;
768
+ }
769
+ .editor-line {
770
+ display: grid; grid-template-columns: 44px 1fr;
771
+ padding: 0; white-space: pre;
772
+ }
773
+ .editor-line:hover { background: rgba(121,192,255,.04); }
774
+ .editor-line.cur { background: rgba(121,192,255,.06); }
775
+ .editor-line .lineno { color: var(--fg-4); text-align: right; padding-right: 14px; user-select: none; font-variant-numeric: tabular-nums; }
776
+ .editor-line .ln-content { color: var(--fg-1); }
777
+ .editor-line .ln-content .kw { color: var(--c-accent); }
778
+ .editor-line .ln-content .str { color: var(--c-ok); }
779
+ .editor-line .ln-content .com { color: var(--fg-3); font-style: italic; }
780
+ .editor-line .ln-content .num { color: var(--c-warn); }
781
+ .editor-line .ln-content .typ { color: var(--c-violet); }
782
+ .editor-line .ln-content .fn { color: var(--c-brand); }
783
+ .editor-line .ln-content .gut { color: var(--fg-4); }
784
+
785
+ .editor-status {
786
+ display: flex; align-items: center; gap: 12px; padding: 4px 14px;
787
+ background: var(--bg-elev); border-top: 1px solid var(--bd);
788
+ font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3);
789
+ }
790
+ .editor-status .v { color: var(--fg-1); }
791
+ .editor-status .grow { flex: 1; }
792
+ .editor-status .glyph { color: var(--c-brand); }
793
+
794
+ /* ── Filter chips ────────────────────────────────────────────────────── */
795
+ .chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0 8px; }
796
+ .chip-f {
797
+ font-family: var(--font-mono); font-size: 11px; padding: 3px 9px;
798
+ border: 1px solid var(--bd); border-radius: 12px; cursor: pointer;
799
+ color: var(--fg-2); background: var(--bg-elev);
800
+ display: inline-flex; align-items: center; gap: 5px;
801
+ }
802
+ .chip-f:hover { background: var(--bg-hover); color: var(--fg-1); }
803
+ .chip-f.active { color: var(--c-brand); border-color: var(--c-brand); background: rgba(121,192,255,.08); }
804
+ .chip-f .ct { color: var(--fg-4); font-size: 10px; }
805
+ .chip-f.active .ct { color: var(--c-brand); }
806
+ .chip-f .x { color: var(--fg-4); padding: 0 2px; }
807
+ .chip-f .x:hover { color: var(--c-err); }
808
+
809
+ .chip-edit-row { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; padding: 4px 0; }
810
+ .chip-add-input {
811
+ background: transparent; border: 1px dashed var(--bd); border-radius: 12px;
812
+ padding: 3px 9px; font-family: var(--font-mono); font-size: 11px;
813
+ color: var(--fg-3); outline: none; min-width: 80px;
814
+ }
815
+ .chip-add-input:focus { border-color: var(--c-brand); color: var(--fg-0); border-style: solid; }
816
+
817
+ /* ── Stacked bar (chart) ─────────────────────────────────────────────── */
818
+ .stacked-bar { width: 100%; height: 12px; background: var(--bg-input); border-radius: var(--r); overflow: hidden; display: flex; }
819
+ .stacked-bar > div { height: 100%; }
820
+
821
+ /* ── Form sub-tabs ───────────────────────────────────────────────────── */
822
+ .form-tabs {
823
+ display: flex; border-bottom: 1px solid var(--bd); margin-bottom: 14px; gap: 0;
824
+ }
825
+ .form-tab {
826
+ padding: 8px 14px; font-family: var(--font-mono); font-size: 12px;
827
+ color: var(--fg-3); cursor: pointer; border-bottom: 2px solid transparent;
828
+ margin-bottom: -1px; letter-spacing: .04em; text-transform: uppercase; font-size: 11px;
829
+ }
830
+ .form-tab:hover { color: var(--fg-1); }
831
+ .form-tab.active { color: var(--fg-0); border-bottom-color: var(--c-brand); }
832
+
833
+ /* ── Schema (JSON-like display) ──────────────────────────────────────── */
834
+ .schema {
835
+ font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-1); line-height: 1.7;
836
+ padding: 10px 14px; background: var(--bg-code); border-radius: var(--r);
837
+ border: 1px solid var(--bd); white-space: pre; overflow-x: auto;
838
+ }
839
+ .schema .key { color: var(--c-brand); }
840
+ .schema .typ { color: var(--c-violet); }
841
+ .schema .req { color: var(--c-warn); font-style: italic; font-size: 10px; }
842
+ .schema .com { color: var(--fg-3); font-style: italic; }
843
+ .schema .str { color: var(--c-ok); }
844
+
845
+ /* ── Log tail ────────────────────────────────────────────────────────── */
846
+ .log-tail {
847
+ font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-2);
848
+ padding: 10px 14px; background: var(--bg-code); border: 1px solid var(--bd);
849
+ border-radius: var(--r); line-height: 1.7; max-height: 240px; overflow-y: auto;
850
+ white-space: pre;
218
851
  }
219
- .sidebar.collapsed .tab .glyph {
220
- width: auto;
221
- font-size: 14px;
852
+ .log-tail .ts { color: var(--fg-4); }
853
+ .log-tail .lvl { display: inline-block; width: 50px; }
854
+ .log-tail .info { color: var(--c-info); }
855
+ .log-tail .warn { color: var(--c-warn); }
856
+ .log-tail .err { color: var(--c-err); }
857
+ .log-tail .ok { color: var(--c-ok); }
858
+ .log-tail .src { color: var(--c-accent); }
859
+
860
+ /* ── Search result card ──────────────────────────────────────────────── */
861
+ .sr-card { padding: 10px 14px; border-bottom: 1px solid #14171e; cursor: pointer; }
862
+ .sr-card:hover { background: var(--bg-hover); }
863
+ .sr-card .sr-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
864
+ .sr-card .sr-path { font-family: var(--font-mono); font-size: 12px; color: var(--c-brand); }
865
+ .sr-card .sr-loc { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); }
866
+ .sr-card .sr-score { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-4); margin-left: auto; }
867
+ .sr-card .sr-snip { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-2); padding: 4px 0 0; white-space: pre; overflow-x: auto; }
868
+ .sr-card .sr-snip mark { background: rgba(240,176,125,.18); color: var(--c-warn); padding: 0 2px; border-radius: 1px; }
869
+
870
+ /* ── Health grid ─────────────────────────────────────────────────────── */
871
+ .health-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px; }
872
+ .health-item {
873
+ padding: 10px 12px; background: var(--bg-elev); border: 1px solid var(--bd);
874
+ border-left: 2px solid var(--c-ok); border-radius: var(--r);
875
+ }
876
+ .health-item.warn { border-left-color: var(--c-warn); }
877
+ .health-item.err { border-left-color: var(--c-err); }
878
+ .health-item .lbl { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em; display: flex; align-items: center; gap: 6px; }
879
+ .health-item .lbl .pill { font-size: 9px; padding: 0 5px; }
880
+ .health-item .v { font-family: var(--font-mono); font-size: 13px; color: var(--fg-0); margin-top: 4px; }
881
+ .health-item .meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); margin-top: 2px; }
882
+
883
+ /* ── Plan timeline (horizontal step bar with detail) ─────────────────── */
884
+ .plan-timeline {
885
+ display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
886
+ gap: 0; padding: 6px 0;
887
+ }
888
+ .plan-step {
889
+ position: relative; padding: 8px 10px;
890
+ border-top: 2px solid var(--bd-strong);
891
+ display: flex; flex-direction: column; gap: 2px;
892
+ }
893
+ .plan-step.done { border-top-color: var(--c-ok); }
894
+ .plan-step.active { border-top-color: var(--c-brand); }
895
+ .plan-step.fail { border-top-color: var(--c-err); }
896
+ .plan-step::before {
897
+ content: ""; position: absolute; top: -5px; left: 0;
898
+ width: 8px; height: 8px; border-radius: 50%; background: var(--bd-strong);
899
+ }
900
+ .plan-step.done::before { background: var(--c-ok); }
901
+ .plan-step.active::before { background: var(--c-brand); box-shadow: 0 0 0 3px rgba(121,192,255,.18); }
902
+ .plan-step.fail::before { background: var(--c-err); }
903
+ .plan-step .lbl { font-family: var(--font-mono); font-size: 10px; color: var(--fg-4); text-transform: uppercase; letter-spacing: .08em; }
904
+ .plan-step .name { font-family: var(--font-mono); font-size: 12px; color: var(--fg-1); }
905
+ .plan-step.active .name { color: var(--fg-0); }
906
+ .plan-step.done .name { color: var(--fg-2); }
907
+ .plan-step .meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); }
908
+
909
+ /* ── Donut chart (SVG inline) ────────────────────────────────────────── */
910
+ .donut-legend { display: grid; grid-template-columns: 1fr; gap: 4px; padding-left: 8px; font-family: var(--font-mono); font-size: 11px; }
911
+ .donut-legend .row { display: flex; align-items: center; gap: 6px; color: var(--fg-2); }
912
+ .donut-legend .row .dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
913
+ .donut-legend .row .v { color: var(--fg-0); margin-left: auto; }
914
+
915
+ /* ── Two-column inventory layout ─────────────────────────────────────── */
916
+ .inv-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; }
917
+
918
+ /* ── Sub-tabs sidebar variant for Configuration ──────────────────────── */
919
+ .cfg-grid { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 14px; }
920
+ .cfg-nav { background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 6px; }
921
+ .cfg-nav .cfg-item {
922
+ padding: 6px 10px; font-family: var(--font-mono); font-size: 12px;
923
+ color: var(--fg-2); cursor: pointer; border-radius: var(--r);
924
+ display: flex; align-items: center; gap: 8px;
925
+ border-left: 2px solid transparent; padding-left: 8px;
926
+ }
927
+ .cfg-nav .cfg-item:hover { background: var(--bg-hover); color: var(--fg-1); }
928
+ .cfg-nav .cfg-item.active { background: var(--bg-hover); color: var(--c-brand); border-left-color: var(--c-brand); }
929
+ .cfg-content { background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 16px 18px; }
930
+
931
+ /* ── Hook event matrix ───────────────────────────────────────────────── */
932
+ .matrix { font-family: var(--font-mono); font-size: 11px; }
933
+ .matrix .row { display: grid; grid-template-columns: 160px repeat(6, 1fr); border-bottom: 1px solid var(--bd); }
934
+ .matrix .row.h { color: var(--fg-3); padding-bottom: 4px; text-transform: uppercase; letter-spacing: .08em; font-size: 10px; }
935
+ .matrix .row.h > div { padding: 6px 8px; text-align: center; }
936
+ .matrix .row.h > div:first-child { text-align: left; }
937
+ .matrix .cell {
938
+ padding: 6px 8px; text-align: center; color: var(--fg-3);
939
+ border-left: 1px solid var(--bd);
940
+ display: flex; align-items: center; justify-content: center; min-height: 28px;
941
+ }
942
+ .matrix .cell:first-child { border-left: none; text-align: left; justify-content: flex-start; color: var(--fg-1); }
943
+ .matrix .cell.on { color: var(--c-brand); background: rgba(121,192,255,.05); }
944
+ .matrix .cell.off { color: var(--fg-4); }
945
+
946
+ /* ── §4 Chat panel ─────────────────────────────────────────────────────── */
947
+ .chat-banner {
948
+ background: rgba(121,192,255,.06);
949
+ border: 1px solid rgba(121,192,255,.18);
950
+ border-radius: var(--r);
951
+ padding: 10px 14px;
952
+ display: flex; align-items: center; gap: 12px;
953
+ margin-bottom: 16px;
954
+ font-size: 12.5px;
222
955
  }
223
- .sidebar.collapsed .sidebar-collapse-toggle {
224
- padding: 8px 0;
225
- justify-content: center;
956
+ .chat-banner .g { color: var(--c-brand); font-family: var(--font-mono); font-size: 14px; }
957
+ .chat-banner .txt { color: var(--fg-1); }
958
+ .chat-banner .txt b { color: var(--fg-0); }
959
+ .chat-banner .takeover { margin-left: auto; }
960
+
961
+ .chat-grid { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 20px; }
962
+
963
+ .chat-stream { display: flex; flex-direction: column; gap: 12px; }
964
+
965
+ /* Chat cards — web-flavored cards, more breathing room than the TUI */
966
+ .cc {
967
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r);
968
+ padding: 12px 14px;
226
969
  }
227
- .sidebar.collapsed .sidebar-footer {
228
- display: none;
970
+ .cc-h { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-family: var(--font-mono); font-size: 11.5px; }
971
+ .cc-h .glyph { font-size: 13px; width: 14px; text-align: center; }
972
+ .cc-h .role { font-weight: 600; letter-spacing: .04em; text-transform: uppercase; font-size: 10.5px; }
973
+ .cc-h .meta { margin-left: auto; color: var(--fg-3); font-size: 10.5px; }
974
+ .cc-b { color: var(--fg-1); font-size: 13.5px; line-height: 1.65; }
975
+ .cc-b p { margin: 0 0 6px; }
976
+ .cc-b p:last-child { margin-bottom: 0; }
977
+ .cc-b code.inline { background: var(--bg-code); padding: 1px 5px; border-radius: var(--r); font-size: 12px; color: var(--c-accent); }
978
+
979
+ .cc.user .cc-h .glyph, .cc.user .cc-h .role { color: var(--c-brand); }
980
+ .cc.assistant .cc-h .glyph, .cc.assistant .cc-h .role { color: var(--c-ok); }
981
+ .cc.tool .cc-h .glyph, .cc.tool .cc-h .role { color: var(--c-warn); }
982
+ .cc.reasoning .cc-h .glyph, .cc.reasoning .cc-h .role { color: var(--c-accent); }
983
+ .cc.reasoning .cc-b { color: var(--fg-2); font-size: 12.5px; font-style: italic; }
984
+
985
+ .cc.tool .tool-args { margin-top: 6px; font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-2); padding: 4px 8px; background: var(--bg-code); border-radius: var(--r); }
986
+ .cc.tool .tool-out { margin-top: 8px; }
987
+
988
+ /* Chat side rail */
989
+ .chat-rail { display: flex; flex-direction: column; gap: 12px; }
990
+ .rail-card {
991
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r);
992
+ padding: 10px 12px;
229
993
  }
994
+ .rail-card .rh {
995
+ font-family: var(--font-mono); font-size: 10px; color: var(--fg-4);
996
+ text-transform: uppercase; letter-spacing: .12em; margin-bottom: 8px;
997
+ }
998
+ .rail-step {
999
+ display: flex; align-items: flex-start; gap: 8px;
1000
+ padding: 4px 0; font-size: 12.5px;
1001
+ }
1002
+ .rail-step .g { font-family: var(--font-mono); color: var(--fg-3); width: 14px; flex-shrink: 0; }
1003
+ .rail-step.done .g { color: var(--c-ok); }
1004
+ .rail-step.active .g { color: var(--c-brand); }
1005
+ .rail-step.active { color: var(--fg-0); }
1006
+ .rail-step.done { color: var(--fg-2); text-decoration: line-through; text-decoration-color: var(--fg-4); }
1007
+
1008
+ .rail-kv { display: flex; justify-content: space-between; padding: 2px 0; font-family: var(--font-mono); font-size: 11.5px; }
1009
+ .rail-kv .k { color: var(--fg-3); }
1010
+ .rail-kv .v { color: var(--fg-0); }
1011
+
1012
+ /* ── §5 Overview cockpit ────────────────────────────────────────────────── */
1013
+ .cockpit { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
1014
+ .cock-w-1 { grid-column: span 1; }
1015
+ .cock-w-2 { grid-column: span 2; }
1016
+ .cock-w-3 { grid-column: span 3; }
1017
+ .cock-w-4 { grid-column: span 4; }
1018
+
1019
+ .kpi {
1020
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 14px 16px;
1021
+ }
1022
+ .kpi .label { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .1em; margin-bottom: 6px; }
1023
+ .kpi .value { font-family: var(--font-mono); font-size: 24px; color: var(--fg-0); font-weight: 700; letter-spacing: -.01em; }
1024
+ .kpi .value .unit { font-size: 13px; color: var(--fg-3); font-weight: 400; margin-left: 4px; }
1025
+ .kpi .delta { font-family: var(--font-mono); font-size: 11px; margin-top: 4px; }
1026
+ .kpi .delta.up { color: var(--c-ok); }
1027
+ .kpi .delta.down { color: var(--c-err); }
1028
+ .kpi .delta.flat { color: var(--fg-3); }
1029
+
1030
+ .cock-list {
1031
+ background: var(--bg-elev); border: 1px solid var(--bd); border-radius: var(--r); padding: 12px 14px;
1032
+ }
1033
+ .cock-list .ch { display: flex; align-items: center; gap: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--bd); margin-bottom: 8px; }
1034
+ .cock-list .ch .ttl { font-family: var(--font-mono); font-size: 11px; color: var(--fg-3); text-transform: uppercase; letter-spacing: .1em; }
1035
+ .cock-list .ch a { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--c-brand); }
1036
+
1037
+ .feed-row {
1038
+ display: grid; grid-template-columns: 14px 1fr auto; gap: 8px;
1039
+ padding: 5px 0; font-size: 12.5px; align-items: center;
1040
+ }
1041
+ .feed-row .g { font-family: var(--font-mono); color: var(--fg-3); }
1042
+ .feed-row.ok .g { color: var(--c-ok); }
1043
+ .feed-row.warn .g { color: var(--c-warn); }
1044
+ .feed-row.err .g { color: var(--c-err); }
1045
+ .feed-row .name { color: var(--fg-1); font-family: var(--font-mono); font-size: 12px; }
1046
+ .feed-row .when { color: var(--fg-4); font-family: var(--font-mono); font-size: 10.5px; }
1047
+ .feed-row .name .args { color: var(--fg-3); }
1048
+
1049
+ /* Notes / "why" callouts */
1050
+ .why {
1051
+ font-size: 12px; color: var(--fg-3); padding: 8px 12px;
1052
+ border-left: 2px solid var(--c-accent); background: rgba(210,168,255,.04);
1053
+ border-radius: 0 var(--r) var(--r) 0;
1054
+ margin: 14px 0;
1055
+ }
1056
+ .why b { color: var(--fg-1); font-weight: 600; }
1057
+
1058
+ /* ── Live-mode overrides — design mockup constrained .app to a 640px tile;
1059
+ * the actual dashboard fills the viewport. ──────────────────────────── */
1060
+ html, body, #root { height: 100%; }
1061
+ #root { display: contents; }
1062
+ .app { height: 100vh; }
1063
+
1064
+ /* ── Shared utilities — small classes used across multiple panels. ── */
1065
+ .boot { color: var(--fg-3); padding: 24px; text-align: center; font-family: var(--font-mono); font-size: 12px; }
1066
+ .empty { color: var(--fg-3); padding: 18px; border: 1px dashed var(--bd); border-radius: var(--r); font-size: 12.5px; }
1067
+ .notice { background: var(--bg-elev); border: 1px solid var(--bd); border-left: 2px solid var(--c-brand); border-radius: var(--r); padding: 8px 12px; margin: 8px 0; font-size: 12.5px; color: var(--fg-1); }
1068
+ .notice.err { border-left-color: var(--c-err); color: var(--c-err); }
1069
+ .notice.warn { border-left-color: var(--c-warn); color: var(--c-warn); }
1070
+ .muted { color: var(--fg-3); }
1071
+ .pill-err { color: var(--c-err); background: rgba(255,139,129,.10); }
1072
+ .pill-active { color: var(--c-brand); background: rgba(121,192,255,.10); }
1073
+ button.primary { background: var(--c-brand); color: var(--bg); border: 1px solid var(--c-brand); padding: 5px 12px; border-radius: var(--r); font-family: var(--font-sans); font-size: 12px; cursor: pointer; }
1074
+ button.primary:hover { background: rgba(121,192,255,.85); }
1075
+ button.danger { background: transparent; color: var(--c-err); border: 1px solid var(--c-err); padding: 5px 12px; border-radius: var(--r); font-family: var(--font-sans); font-size: 12px; cursor: pointer; }
1076
+ button:not(.primary):not(.danger):not(.btn):not(.mode-btn):not(.chat-banner-close):not(.chat-inflight-abort) { background: var(--bg-elev-2); color: var(--fg-1); border: 1px solid var(--bd); padding: 5px 12px; border-radius: var(--r); font-family: var(--font-sans); font-size: 12px; cursor: pointer; }
1077
+ button:hover:not(.primary):not(.danger):not(.btn):not(.mode-btn):not(.chat-banner-close):not(.chat-inflight-abort) { background: var(--bg-hover); border-color: var(--bd-strong); }
1078
+ input[type=text], input[type=number], input[type=password], textarea, select { background: var(--bg-input); color: var(--fg-0); border: 1px solid var(--bd); border-radius: var(--r); padding: 5px 10px; font-family: var(--font-mono); font-size: 12.5px; outline: none; }
1079
+ input:focus, textarea:focus, select:focus { border-color: var(--c-brand); }
1080
+ .kv-key { display: inline-block; min-width: 70px; color: var(--fg-3); font-family: var(--font-mono); font-size: 11px; margin-right: 8px; }
1081
+
1082
+ /* ── Chat-panel legacy CSS — restored from pre-foundation app.css.
1083
+ * These selectors back the Chat panel's interior (chat-shell /
1084
+ * chat-feed / chat-msg / mode-picker / composer / modals / toasts /
1085
+ * tool-card / markdown blocks). The design mockup §4 covers the
1086
+ * chat surface conceptually but doesn't enumerate every selector;
1087
+ * rather than rewrite all of these by hand against design tokens,
1088
+ * we restore the working set and let panel migration tweak as
1089
+ * needed. Tokens inside these rules use the new design palette
1090
+ * (--c-brand, --fg-0, --bg-elev, etc.) so the visual still aligns.
1091
+ */
1092
+ /* ---------- Markdown rendering (matches TUI markdown.tsx palette) ----------
1093
+ *
1094
+ * Mapping comes from src/cli/ui/markdown.tsx:
1095
+ * H1 → bg #67e8f9 (cyan) text black, bold — pill
1096
+ * H2 → bg #c4b5fd (violet) text black, bold — pill
1097
+ * H3 → bg #f0abfc (fuchsia) text black, bold — pill
1098
+ * inline code → amber text on bg-2
1099
+ * code block → bg-1, monospace, soft border
1100
+ * blockquote → teal-300 left bar (brand)
1101
+ * strong / em → bold / italic
1102
+ * tables → bordered, monospace
1103
+ * strike → red strikethrough
1104
+ * link → cyan underline
1105
+ * diff +/- → green / red lines (handled by code-block class)
1106
+ */
230
1107
 
231
- .sidebar-collapse-toggle {
232
- display: flex;
233
- align-items: center;
234
- gap: 8px;
235
- background: transparent;
236
- border: none;
237
- border-top: 1px solid var(--border);
238
- padding: 8px 20px;
239
- font-family: var(--mono);
240
- font-size: 11px;
241
- color: var(--fg-3);
242
- cursor: pointer;
243
- width: 100%;
244
- text-align: left;
1108
+ .md {
1109
+ color: var(--fg-0);
1110
+ font-size: 14px;
1111
+ line-height: 1.7;
245
1112
  }
246
- .sidebar-collapse-toggle:hover {
247
- background: var(--bg-hover);
248
- color: var(--primary);
1113
+ .md > *:first-child {
1114
+ margin-top: 0;
249
1115
  }
250
-
251
- .sidebar-header {
252
- padding: 18px 20px 14px;
253
- border-bottom: 1px solid var(--border);
1116
+ .md > *:last-child {
1117
+ margin-bottom: 0;
254
1118
  }
255
1119
 
256
- .sidebar-brand {
257
- font-family: var(--mono);
258
- font-size: 13px;
259
- letter-spacing: 0.08em;
260
- color: var(--fg-2);
1120
+ .md p {
1121
+ margin: 0.5em 0;
261
1122
  }
262
1123
 
263
- .sidebar-brand .glyph {
264
- background: var(--gradient-rule);
265
- background-clip: text;
266
- -webkit-background-clip: text;
267
- color: transparent;
268
- font-size: 16px;
1124
+ .md h1,
1125
+ .md h2,
1126
+ .md h3 {
1127
+ display: inline-block;
1128
+ padding: 2px 10px;
1129
+ margin: 0.8em 0 0.5em;
1130
+ border-radius: var(--r);
1131
+ color: #0a0e14;
269
1132
  font-weight: 700;
270
- margin-right: 6px;
1133
+ line-height: 1.4;
271
1134
  }
272
-
273
- .sidebar-version {
274
- margin-top: 4px;
275
- font-size: 11px;
276
- color: var(--fg-3);
277
- font-family: var(--mono);
1135
+ .md h1 {
1136
+ background: var(--c-brand);
1137
+ font-size: 18px;
278
1138
  }
279
-
280
- .sidebar-mode {
281
- display: inline-block;
282
- margin-top: 6px;
283
- padding: 1px 6px;
284
- font-size: 10px;
285
- letter-spacing: 0.06em;
286
- text-transform: uppercase;
287
- border-radius: var(--radius-sm);
288
- background: var(--bg-3);
289
- color: var(--accent);
1139
+ .md h2 {
1140
+ background: var(--c-accent);
1141
+ font-size: 16px;
290
1142
  }
291
-
292
- .sidebar-tabs {
293
- flex: 1;
294
- overflow-y: auto;
295
- padding: 8px 0;
1143
+ .md h3 {
1144
+ background: var(--grad-8);
1145
+ font-size: 14px;
296
1146
  }
297
1147
 
298
- .tab {
299
- display: flex;
300
- align-items: center;
301
- gap: 10px;
302
- padding: 8px 20px;
303
- cursor: pointer;
304
- color: var(--fg-2);
305
- font-size: 13px;
306
- border-left: 2px solid transparent;
307
- user-select: none;
1148
+ .md h4,
1149
+ .md h5,
1150
+ .md h6 {
1151
+ font-weight: 600;
1152
+ color: var(--c-accent);
1153
+ font-size: 14px;
1154
+ margin: 0.6em 0 0.3em;
308
1155
  }
309
1156
 
310
- .tab:hover {
311
- background: var(--bg-hover);
1157
+ .md strong {
312
1158
  color: var(--fg-0);
1159
+ font-weight: 700;
313
1160
  }
314
-
315
- .tab.active {
316
- background: var(--bg-2);
317
- color: var(--primary);
318
- border-left-color: var(--primary);
1161
+ .md em {
1162
+ color: var(--fg-0);
1163
+ font-style: italic;
319
1164
  }
320
-
321
- .tab-stub {
322
- opacity: 0.45;
323
- cursor: not-allowed;
1165
+ .md del {
1166
+ color: var(--c-err);
1167
+ text-decoration: line-through;
324
1168
  }
325
1169
 
326
- .tab-stub:hover {
327
- background: transparent;
328
- color: var(--fg-2);
1170
+ .md a {
1171
+ color: var(--c-brand);
1172
+ text-decoration: none;
329
1173
  }
330
-
331
- .tab .glyph {
332
- width: 16px;
333
- font-family: var(--mono);
334
- text-align: center;
1174
+ .md a:hover {
1175
+ text-decoration: underline;
335
1176
  }
336
1177
 
337
- .tab .badge {
338
- margin-left: auto;
339
- font-size: 10px;
340
- background: var(--bg-3);
341
- color: var(--fg-3);
1178
+ .md code {
1179
+ font-family: var(--font-mono);
1180
+ background: var(--bg-elev-2);
1181
+ color: var(--c-warn); /* amber matches TUI inline-code */
342
1182
  padding: 1px 6px;
343
- border-radius: var(--radius-sm);
1183
+ border-radius: var(--r);
1184
+ font-size: 12px;
344
1185
  }
345
1186
 
346
- .sidebar-footer {
347
- padding: 12px 20px;
348
- font-size: 11px;
349
- color: var(--fg-3);
350
- border-top: 1px solid var(--border);
351
- font-family: var(--mono);
1187
+ .md pre {
1188
+ background: var(--bg-elev);
1189
+ border: 1px solid var(--bd);
1190
+ border-radius: var(--r-md);
1191
+ padding: 12px 14px;
1192
+ overflow-x: auto;
1193
+ margin: 0.6em 0;
1194
+ font-family: var(--font-mono);
1195
+ font-size: 12.5px;
1196
+ line-height: 1.55;
1197
+ color: var(--c-warn);
1198
+ white-space: pre;
352
1199
  }
353
-
354
- .gradient-rule {
355
- height: 2px;
356
- background: var(--gradient-rule);
357
- margin: 0;
1200
+ .md pre code {
1201
+ background: transparent;
1202
+ padding: 0;
1203
+ border-radius: 0;
1204
+ color: inherit;
1205
+ font-size: inherit;
358
1206
  }
359
1207
 
360
- /* Hamburger that flips the mobile sidebar drawer. Pinned top-left of
361
- * the main panel; hidden on desktop (sidebar is always visible there). */
362
- .menu-toggle {
363
- display: none;
364
- position: absolute;
365
- top: 14px;
366
- left: 14px;
367
- z-index: 10;
368
- background: var(--bg-2);
369
- border: 1px solid var(--border);
1208
+ /* Diff blocks rendered by the custom renderer in app.js for
1209
+ * SEARCH/REPLACE markers and ``` diff fences. Mirror TUI's
1210
+ * markdown.tsx red/green palette so the experience reads as the same
1211
+ * tool whether you're in the terminal or the browser. */
1212
+ .md .diff-block,
1213
+ .diff-block {
1214
+ background: var(--bg-elev);
1215
+ border: 1px solid var(--bd);
1216
+ border-radius: var(--r-md);
1217
+ padding: 8px 12px;
1218
+ margin: 0.6em 0;
1219
+ font-family: var(--font-mono);
1220
+ font-size: 12.5px;
1221
+ line-height: 1.55;
1222
+ overflow-x: auto;
1223
+ white-space: pre;
370
1224
  color: var(--fg-1);
371
- padding: 4px 10px;
372
- font-family: var(--mono);
373
- font-size: 16px;
374
- border-radius: var(--radius-sm);
375
- cursor: pointer;
376
1225
  }
377
- .menu-toggle:hover {
378
- border-color: var(--primary);
379
- color: var(--primary);
1226
+ .diff-line {
1227
+ display: block;
1228
+ padding: 0 4px;
380
1229
  }
381
-
382
- .sidebar-backdrop {
383
- display: none;
384
- position: fixed;
385
- inset: 0;
386
- background: rgba(10, 14, 20, 0.6);
387
- z-index: 5;
1230
+ .diff-line.ins {
1231
+ background: rgba(74, 222, 128, 0.1);
1232
+ color: #86efac;
388
1233
  }
389
-
390
- @media (max-width: 800px) {
391
- .menu-toggle {
392
- display: block;
393
- }
394
- .sidebar {
395
- position: fixed;
396
- top: 0;
397
- bottom: 0;
398
- left: 0;
399
- z-index: 8;
400
- transform: translateX(-100%);
401
- transition: transform 0.18s ease-out;
402
- box-shadow: 4px 0 24px rgba(0, 0, 0, 0.4);
403
- }
404
- .sidebar.open {
405
- transform: translateX(0);
406
- }
407
- .sidebar.open ~ .sidebar-backdrop {
408
- display: block;
409
- }
410
- .main {
411
- padding: 60px 16px 16px;
412
- width: 100%;
413
- }
414
- .panel-header {
415
- flex-direction: column;
416
- align-items: flex-start;
417
- gap: 8px;
418
- }
419
- .header-pickers {
420
- margin-left: 0 !important;
421
- width: 100%;
422
- }
423
- .metric-grid {
424
- grid-template-columns: 1fr 1fr;
425
- }
1234
+ .diff-line.del {
1235
+ background: rgba(248, 113, 113, 0.1);
1236
+ color: #fda4af;
426
1237
  }
427
-
428
- /* ---------- Main panel ---------- */
429
-
430
- .main {
431
- flex: 1;
432
- overflow-y: auto;
433
- padding: 28px 36px;
434
- min-width: 0;
1238
+ .diff-line.hunk {
1239
+ color: var(--c-accent);
1240
+ font-weight: 500;
435
1241
  }
436
- .main-editor {
1242
+ .diff-line.meta {
1243
+ color: var(--fg-3);
1244
+ }
1245
+
1246
+ /* highlight.js github-dark loads from CDN; we tweak surface colors
1247
+ * to merge with our card backgrounds. The theme provides token colors
1248
+ * (keyword, string, number, comment etc.) we keep as-is — they read
1249
+ * well against bg-1. */
1250
+ .md .hljs,
1251
+ .hljs {
1252
+ background: var(--bg-elev) !important;
1253
+ color: var(--fg-0);
437
1254
  padding: 0;
438
- overflow: hidden;
439
- display: flex;
440
- flex-direction: column;
441
1255
  }
442
- .main-editor .editor-shell {
443
- flex: 1;
444
- height: auto;
445
- min-height: 0;
1256
+ .md pre code.hljs {
1257
+ background: transparent !important;
446
1258
  }
447
1259
 
448
- .panel-header {
449
- display: flex;
450
- align-items: baseline;
451
- gap: 12px;
452
- margin-bottom: 20px;
1260
+ .md ul,
1261
+ .md ol {
1262
+ margin: 0.4em 0;
1263
+ padding-left: 24px;
453
1264
  }
454
-
455
- .panel-title {
456
- font-size: 20px;
1265
+ .md li {
1266
+ margin: 0.15em 0;
1267
+ }
1268
+ .md ul > li::marker {
1269
+ color: var(--c-brand);
1270
+ }
1271
+ .md ol > li::marker {
1272
+ color: var(--c-accent);
457
1273
  font-weight: 600;
458
- margin: 0;
459
1274
  }
460
1275
 
461
- .panel-subtitle {
462
- color: var(--fg-2);
463
- font-size: 13px;
1276
+ .md blockquote {
1277
+ border-left: 3px solid var(--c-brand);
1278
+ padding: 4px 12px;
1279
+ margin: 0.6em 0;
1280
+ color: var(--fg-1);
1281
+ background: var(--bg-elev);
1282
+ border-radius: 0 var(--r) var(--r) 0;
464
1283
  }
465
1284
 
466
- .section-title {
1285
+ .md table {
1286
+ width: auto;
1287
+ margin: 0.6em 0;
1288
+ border-collapse: collapse;
1289
+ font-family: var(--font-mono);
1290
+ font-size: 12.5px;
1291
+ }
1292
+ .md thead {
1293
+ background: var(--bg-elev-2);
1294
+ }
1295
+ .md th,
1296
+ .md td {
1297
+ border: 1px solid var(--bd);
1298
+ padding: 6px 10px;
1299
+ text-align: left;
1300
+ }
1301
+ .md th {
1302
+ color: var(--c-brand);
1303
+ font-weight: 600;
467
1304
  font-size: 11px;
468
- letter-spacing: 0.1em;
1305
+ letter-spacing: 0.04em;
469
1306
  text-transform: uppercase;
470
- color: var(--fg-3);
471
- margin: 24px 0 12px;
1307
+ }
1308
+ .md td {
1309
+ color: var(--fg-1);
472
1310
  }
473
1311
 
474
- /* ---------- Cards / metric tiles ---------- */
475
-
476
- .card {
477
- background: var(--bg-1);
478
- border: 1px solid var(--border);
479
- border-radius: var(--radius-md);
480
- padding: 16px 18px;
1312
+ .md hr {
1313
+ border: none;
1314
+ height: 2px;
1315
+ background: var(--gradient-rule);
1316
+ margin: 1.2em 0;
1317
+ opacity: 0.6;
481
1318
  }
482
1319
 
483
- .card-title {
484
- font-size: 11px;
485
- letter-spacing: 0.08em;
486
- text-transform: uppercase;
487
- color: var(--fg-3);
488
- margin-bottom: 6px;
1320
+ .md img {
1321
+ max-width: 100%;
1322
+ border-radius: var(--r);
489
1323
  }
490
1324
 
491
- .card-value {
492
- font-family: var(--mono);
493
- font-size: 22px;
494
- color: var(--fg-0);
1325
+ /* ---------- Chat panel ---------- */
1326
+
1327
+ /* Subtracts .app-top (44) + .app-status (26) + .app-body padding (24×2). */
1328
+ .chat-shell {
1329
+ display: flex;
1330
+ flex-direction: column;
1331
+ height: calc(100vh - 44px - 26px - 48px);
495
1332
  }
496
1333
 
497
- .card-value.muted {
498
- color: var(--fg-3);
1334
+ .chat-body {
1335
+ flex: 1;
1336
+ min-height: 0;
1337
+ display: grid;
1338
+ grid-template-columns: minmax(0, 1fr) 280px;
1339
+ gap: 20px;
499
1340
  }
500
1341
 
501
- .card-hint {
502
- margin-top: 4px;
503
- font-size: 12px;
504
- color: var(--fg-2);
1342
+ .chat-main {
1343
+ display: flex;
1344
+ flex-direction: column;
1345
+ min-height: 0;
505
1346
  }
506
1347
 
507
- .metric-grid {
508
- display: grid;
509
- grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
1348
+ .chat-feed {
1349
+ flex: 1;
1350
+ min-height: 0;
1351
+ overflow-y: auto;
1352
+ padding: 4px 4px 16px;
1353
+ display: flex;
1354
+ flex-direction: column;
510
1355
  gap: 14px;
511
1356
  }
512
1357
 
513
- /* Pill labels — mirror TUI accent bgs. */
514
- .pill {
515
- display: inline-block;
516
- padding: 1px 8px;
517
- font-size: 11px;
518
- font-family: var(--mono);
519
- border-radius: 999px;
1358
+ .chat-msg {
1359
+ display: flex;
1360
+ gap: 12px;
1361
+ align-items: flex-start;
1362
+ line-height: 1.6;
520
1363
  }
521
1364
 
522
- .pill-primary {
523
- background: rgba(103, 232, 249, 0.18);
524
- color: var(--primary);
1365
+ .chat-msg .glyph {
1366
+ width: 22px;
1367
+ flex-shrink: 0;
1368
+ font-family: var(--font-mono);
1369
+ text-align: center;
1370
+ font-size: 14px;
1371
+ padding-top: 2px;
525
1372
  }
526
- .pill-accent {
527
- background: rgba(196, 181, 253, 0.18);
528
- color: var(--accent);
1373
+
1374
+ .chat-msg .body {
1375
+ flex: 1;
1376
+ min-width: 0;
529
1377
  }
530
- .pill-ok {
531
- background: rgba(74, 222, 128, 0.18);
532
- color: var(--ok);
1378
+
1379
+ .chat-msg.user .glyph {
1380
+ color: var(--c-brand);
533
1381
  }
534
- .pill-warn {
535
- background: rgba(251, 191, 36, 0.18);
536
- color: var(--warn);
1382
+ .chat-msg.assistant .glyph {
1383
+ color: var(--c-ok);
537
1384
  }
538
- .pill-err {
539
- background: rgba(248, 113, 113, 0.18);
540
- color: var(--err);
1385
+ .chat-msg.tool .glyph {
1386
+ color: var(--c-warn);
541
1387
  }
542
- .pill-dim {
543
- background: var(--bg-3);
544
- color: var(--fg-2);
1388
+ .chat-msg.info .glyph {
1389
+ color: var(--fg-3);
545
1390
  }
546
- .pill-active {
547
- background: rgba(103, 232, 249, 0.22);
548
- color: var(--primary);
1391
+ .chat-msg.warning .glyph {
1392
+ color: var(--c-warn);
1393
+ }
1394
+ .chat-msg.error .glyph {
1395
+ color: var(--c-err);
549
1396
  }
550
1397
 
551
- /* ---------- Key/value rows (compact metadata layout) ---------- */
552
- .kv {
553
- display: flex;
554
- flex-direction: column;
555
- gap: 6px;
556
- font-size: 13px;
557
- color: var(--fg-1);
558
- font-family: var(--mono);
1398
+ .chat-msg.user .body {
1399
+ color: var(--fg-0);
559
1400
  }
560
- .kv > div {
561
- display: flex;
562
- flex-wrap: wrap;
563
- align-items: baseline;
564
- gap: 8px;
1401
+ .chat-msg.assistant .body {
1402
+ color: var(--fg-0);
565
1403
  }
566
- .kv-key {
567
- display: inline-block;
568
- min-width: 84px;
569
- font-size: 11px;
570
- letter-spacing: 0.06em;
571
- text-transform: uppercase;
572
- color: var(--fg-3);
1404
+ /* Tool-card replaces the simple .body box for role="tool" rows. The
1405
+ * card carries a left accent bar (amber for success), a header with
1406
+ * tool name + path/lang pills, then the kind-specific body (diff for
1407
+ * edit_file, code block for read/write_file, terminal for run_command,
1408
+ * etc). Keeps the visual weight consistent across kinds. */
1409
+ .tool-card {
1410
+ flex: 1;
1411
+ background: var(--bg-elev);
1412
+ border: 1px solid var(--bd);
1413
+ border-left: 3px solid var(--c-warn);
1414
+ border-radius: var(--r-md);
1415
+ padding: 10px 12px;
1416
+ min-width: 0;
573
1417
  }
574
-
575
- /* ---------- Tables ---------- */
576
-
577
- table {
578
- width: 100%;
579
- border-collapse: collapse;
580
- margin: 8px 0;
581
- font-family: var(--mono);
582
- font-size: 13px;
1418
+ .tool-card-head {
1419
+ display: flex;
1420
+ align-items: center;
1421
+ gap: 8px;
1422
+ margin-bottom: 8px;
1423
+ font-family: var(--font-mono);
1424
+ font-size: 12px;
1425
+ flex-wrap: wrap;
583
1426
  }
584
-
585
- thead {
586
- background: var(--bg-2);
1427
+ .tool-card-icon {
1428
+ color: var(--c-warn);
1429
+ font-size: 14px;
1430
+ font-weight: 600;
587
1431
  }
588
-
589
- th {
590
- text-align: left;
1432
+ .tool-card-name {
1433
+ color: var(--c-accent);
591
1434
  font-weight: 500;
592
- color: var(--fg-3);
1435
+ }
1436
+ .tool-card-path {
1437
+ color: var(--c-brand);
1438
+ background: var(--bg-elev-2);
1439
+ padding: 1px 8px;
1440
+ border-radius: var(--r);
593
1441
  font-size: 11px;
594
- letter-spacing: 0.06em;
595
- text-transform: uppercase;
596
- padding: 10px 12px;
597
- border-bottom: 1px solid var(--border);
598
1442
  }
599
-
600
- td {
601
- padding: 8px 12px;
602
- border-bottom: 1px solid var(--border);
603
- color: var(--fg-1);
1443
+ .tool-card pre,
1444
+ .tool-card .md {
1445
+ margin: 0;
604
1446
  }
605
-
606
- tr:hover td {
607
- background: var(--bg-hover);
1447
+ .tool-card .md > pre,
1448
+ .tool-card-cmd,
1449
+ .tool-card-output {
1450
+ background: var(--bg-elev-2);
1451
+ border: 1px solid var(--bd);
1452
+ border-radius: var(--r);
1453
+ padding: 8px 10px;
1454
+ font-family: var(--font-mono);
1455
+ font-size: 12px;
1456
+ line-height: 1.55;
1457
+ max-height: 320px;
1458
+ overflow: auto;
608
1459
  }
609
-
610
- td.numeric,
611
- th.numeric {
612
- text-align: right;
1460
+ .tool-card .md > pre code {
1461
+ background: transparent;
1462
+ padding: 0;
1463
+ color: inherit;
613
1464
  }
614
-
615
- td.muted {
1465
+ .tool-card .diff-block {
1466
+ margin: 0;
1467
+ max-height: 320px;
1468
+ }
1469
+ .tool-card-cmd {
1470
+ background: var(--bg);
1471
+ white-space: pre;
1472
+ margin: 0 0 6px 0;
1473
+ }
1474
+ .tool-card-prompt {
616
1475
  color: var(--fg-3);
1476
+ margin-right: 6px;
617
1477
  }
618
-
619
- /* ---------- Inputs / buttons ---------- */
620
-
621
- button,
622
- .button {
623
- background: var(--bg-2);
1478
+ .tool-card-output {
1479
+ white-space: pre-wrap;
1480
+ word-break: break-word;
624
1481
  color: var(--fg-1);
625
- border: 1px solid var(--border);
626
- border-radius: var(--radius-sm);
627
- padding: 6px 12px;
628
- font-family: var(--sans);
629
- font-size: 12px;
630
- cursor: pointer;
631
- transition: border-color 0.12s, background 0.12s;
1482
+ margin: 0;
632
1483
  }
633
-
634
- button:hover,
635
- .button:hover {
636
- border-color: var(--primary);
637
- color: var(--primary);
1484
+ .tool-card-result {
1485
+ margin-top: 6px;
1486
+ font-size: 11px;
1487
+ color: var(--fg-3);
1488
+ font-family: var(--font-mono);
638
1489
  }
639
-
640
- button.primary {
641
- background: var(--primary);
642
- color: var(--bg-0);
643
- border-color: var(--primary);
644
- font-weight: 500;
1490
+ .tool-card-args {
1491
+ margin-bottom: 6px;
1492
+ font-size: 11px;
645
1493
  }
646
-
647
- button.primary:hover {
648
- background: var(--brand);
649
- border-color: var(--brand);
650
- color: var(--bg-0);
1494
+ .tool-card-args summary {
1495
+ cursor: pointer;
1496
+ color: var(--fg-2);
651
1497
  }
652
-
653
- button.danger {
654
- border-color: var(--err);
655
- color: var(--err);
1498
+ .tool-card-args summary:hover {
1499
+ color: var(--c-brand);
1500
+ }
1501
+ .tool-card-args pre {
1502
+ margin-top: 6px;
1503
+ white-space: pre;
656
1504
  }
657
1505
 
658
- button.danger:hover {
659
- background: rgba(248, 113, 113, 0.12);
1506
+ .chat-msg .reasoning {
1507
+ margin-top: 6px;
1508
+ padding: 6px 10px;
1509
+ background: var(--bg-elev);
1510
+ border-left: 2px solid var(--c-accent);
1511
+ color: var(--fg-2);
1512
+ font-size: 12px;
1513
+ font-style: italic;
1514
+ white-space: pre-wrap;
1515
+ word-break: break-word;
1516
+ border-radius: var(--r);
660
1517
  }
661
1518
 
662
- button:disabled {
663
- opacity: 0.4;
664
- cursor: not-allowed;
1519
+ .chat-msg .tool-name {
1520
+ color: var(--c-accent);
1521
+ font-weight: 500;
665
1522
  }
666
1523
 
667
- input[type="text"],
668
- input[type="search"],
669
- input[type="number"] {
670
- background: var(--bg-2);
671
- border: 1px solid var(--border);
672
- color: var(--fg-0);
673
- padding: 6px 10px;
674
- border-radius: var(--radius-sm);
675
- font-family: var(--mono);
676
- font-size: 13px;
677
- width: 100%;
678
- }
679
-
680
- input[type="text"]:focus,
681
- input[type="search"]:focus,
682
- input[type="number"]:focus,
683
- input[type="password"]:focus {
684
- border-color: var(--primary);
685
- outline: none;
686
- }
687
-
688
- input[type="password"] {
689
- background: var(--bg-2);
690
- border: 1px solid var(--border);
691
- color: var(--fg-0);
692
- padding: 6px 10px;
693
- border-radius: var(--radius-sm);
694
- font-family: var(--mono);
695
- font-size: 13px;
696
- width: 100%;
697
- }
698
-
699
- select {
700
- background: var(--bg-2);
701
- border: 1px solid var(--border);
702
- color: var(--fg-0);
703
- padding: 5px 10px;
704
- border-radius: var(--radius-sm);
705
- font-family: var(--sans);
706
- font-size: 13px;
707
- cursor: pointer;
708
- }
709
- select:focus {
710
- border-color: var(--primary);
711
- outline: none;
712
- }
713
-
714
- textarea {
715
- background: var(--bg-2);
716
- color: var(--fg-0);
717
- border: 1px solid var(--border);
718
- border-radius: var(--radius-sm);
719
- padding: 8px 10px;
720
- font-family: var(--mono);
721
- font-size: 12px;
722
- line-height: 1.5;
723
- resize: vertical;
724
- width: 100%;
725
- box-sizing: border-box;
726
- }
727
- textarea:focus {
728
- border-color: var(--primary);
729
- outline: none;
730
- }
731
-
732
- .row {
733
- display: flex;
734
- gap: 10px;
735
- align-items: center;
736
- margin-bottom: 12px;
737
- }
738
-
739
- .row > input {
740
- flex: 1;
741
- }
742
-
743
- /* ---------- Markdown rendering (matches TUI markdown.tsx palette) ----------
744
- *
745
- * Mapping comes from src/cli/ui/markdown.tsx:
746
- * H1 → bg #67e8f9 (cyan) text black, bold — pill
747
- * H2 → bg #c4b5fd (violet) text black, bold — pill
748
- * H3 → bg #f0abfc (fuchsia) text black, bold — pill
749
- * inline code → amber text on bg-2
750
- * code block → bg-1, monospace, soft border
751
- * blockquote → teal-300 left bar (brand)
752
- * strong / em → bold / italic
753
- * tables → bordered, monospace
754
- * strike → red strikethrough
755
- * link → cyan underline
756
- * diff +/- → green / red lines (handled by code-block class)
757
- */
758
-
759
- .md {
760
- color: var(--fg-0);
761
- font-size: 14px;
762
- line-height: 1.7;
763
- }
764
- .md > *:first-child {
765
- margin-top: 0;
766
- }
767
- .md > *:last-child {
768
- margin-bottom: 0;
769
- }
770
-
771
- .md p {
772
- margin: 0.5em 0;
773
- }
774
-
775
- .md h1,
776
- .md h2,
777
- .md h3 {
778
- display: inline-block;
779
- padding: 2px 10px;
780
- margin: 0.8em 0 0.5em;
781
- border-radius: var(--radius-sm);
782
- color: #0a0e14;
783
- font-weight: 700;
784
- line-height: 1.4;
785
- }
786
- .md h1 {
787
- background: var(--primary);
788
- font-size: 18px;
789
- }
790
- .md h2 {
791
- background: var(--accent);
792
- font-size: 16px;
793
- }
794
- .md h3 {
795
- background: var(--grad-8);
796
- font-size: 14px;
797
- }
798
-
799
- .md h4,
800
- .md h5,
801
- .md h6 {
802
- font-weight: 600;
803
- color: var(--accent);
804
- font-size: 14px;
805
- margin: 0.6em 0 0.3em;
806
- }
807
-
808
- .md strong {
809
- color: var(--fg-0);
810
- font-weight: 700;
811
- }
812
- .md em {
813
- color: var(--fg-0);
814
- font-style: italic;
815
- }
816
- .md del {
817
- color: var(--err);
818
- text-decoration: line-through;
819
- }
820
-
821
- .md a {
822
- color: var(--primary);
823
- text-decoration: none;
824
- }
825
- .md a:hover {
826
- text-decoration: underline;
827
- }
828
-
829
- .md code {
830
- font-family: var(--mono);
831
- background: var(--bg-2);
832
- color: var(--tool); /* amber matches TUI inline-code */
833
- padding: 1px 6px;
834
- border-radius: var(--radius-sm);
835
- font-size: 12px;
836
- }
837
-
838
- .md pre {
839
- background: var(--bg-1);
840
- border: 1px solid var(--border);
841
- border-radius: var(--radius-md);
842
- padding: 12px 14px;
843
- overflow-x: auto;
844
- margin: 0.6em 0;
845
- font-family: var(--mono);
846
- font-size: 12.5px;
847
- line-height: 1.55;
848
- color: var(--tool);
849
- white-space: pre;
850
- }
851
- .md pre code {
852
- background: transparent;
853
- padding: 0;
854
- border-radius: 0;
855
- color: inherit;
856
- font-size: inherit;
857
- }
858
-
859
- /* Diff blocks — rendered by the custom renderer in app.js for
860
- * SEARCH/REPLACE markers and ``` diff fences. Mirror TUI's
861
- * markdown.tsx red/green palette so the experience reads as the same
862
- * tool whether you're in the terminal or the browser. */
863
- .md .diff-block,
864
- .diff-block {
865
- background: var(--bg-1);
866
- border: 1px solid var(--border);
867
- border-radius: var(--radius-md);
868
- padding: 8px 12px;
869
- margin: 0.6em 0;
870
- font-family: var(--mono);
871
- font-size: 12.5px;
872
- line-height: 1.55;
873
- overflow-x: auto;
874
- white-space: pre;
875
- color: var(--fg-1);
876
- }
877
- .diff-line {
878
- display: block;
879
- padding: 0 4px;
880
- }
881
- .diff-line.ins {
882
- background: rgba(74, 222, 128, 0.1);
883
- color: #86efac;
884
- }
885
- .diff-line.del {
886
- background: rgba(248, 113, 113, 0.1);
887
- color: #fda4af;
888
- }
889
- .diff-line.hunk {
890
- color: var(--accent);
891
- font-weight: 500;
892
- }
893
- .diff-line.meta {
894
- color: var(--fg-3);
895
- }
896
-
897
- /* highlight.js github-dark loads from CDN; we tweak surface colors
898
- * to merge with our card backgrounds. The theme provides token colors
899
- * (keyword, string, number, comment etc.) we keep as-is — they read
900
- * well against bg-1. */
901
- .md .hljs,
902
- .hljs {
903
- background: var(--bg-1) !important;
904
- color: var(--fg-0);
905
- padding: 0;
906
- }
907
- .md pre code.hljs {
908
- background: transparent !important;
909
- }
910
-
911
- .md ul,
912
- .md ol {
913
- margin: 0.4em 0;
914
- padding-left: 24px;
915
- }
916
- .md li {
917
- margin: 0.15em 0;
918
- }
919
- .md ul > li::marker {
920
- color: var(--brand);
921
- }
922
- .md ol > li::marker {
923
- color: var(--accent);
924
- font-weight: 600;
925
- }
926
-
927
- .md blockquote {
928
- border-left: 3px solid var(--brand);
929
- padding: 4px 12px;
930
- margin: 0.6em 0;
931
- color: var(--fg-1);
932
- background: var(--bg-1);
933
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
934
- }
935
-
936
- .md table {
937
- width: auto;
938
- margin: 0.6em 0;
939
- border-collapse: collapse;
940
- font-family: var(--mono);
941
- font-size: 12.5px;
942
- }
943
- .md thead {
944
- background: var(--bg-2);
945
- }
946
- .md th,
947
- .md td {
948
- border: 1px solid var(--border);
949
- padding: 6px 10px;
950
- text-align: left;
951
- }
952
- .md th {
953
- color: var(--primary);
954
- font-weight: 600;
955
- font-size: 11px;
956
- letter-spacing: 0.04em;
957
- text-transform: uppercase;
958
- }
959
- .md td {
960
- color: var(--fg-1);
961
- }
962
-
963
- .md hr {
964
- border: none;
965
- height: 2px;
966
- background: var(--gradient-rule);
967
- margin: 1.2em 0;
968
- opacity: 0.6;
969
- }
970
-
971
- .md img {
972
- max-width: 100%;
973
- border-radius: var(--radius-sm);
974
- }
975
-
976
- /* ---------- Chat panel ---------- */
977
-
978
- .chat-shell {
979
- display: flex;
980
- flex-direction: column;
981
- height: calc(100vh - 56px);
982
- }
983
-
984
- .chat-feed {
985
- flex: 1;
986
- overflow-y: auto;
987
- padding: 4px 4px 16px;
988
- display: flex;
989
- flex-direction: column;
990
- gap: 14px;
991
- }
992
-
993
- .chat-msg {
994
- display: flex;
995
- gap: 12px;
996
- align-items: flex-start;
997
- line-height: 1.6;
998
- }
999
-
1000
- .chat-msg .glyph {
1001
- width: 22px;
1002
- flex-shrink: 0;
1003
- font-family: var(--mono);
1004
- text-align: center;
1005
- font-size: 14px;
1006
- padding-top: 2px;
1007
- }
1008
-
1009
- .chat-msg .body {
1010
- flex: 1;
1011
- min-width: 0;
1012
- }
1013
-
1014
- .chat-msg.user .glyph {
1015
- color: var(--user);
1016
- }
1017
- .chat-msg.assistant .glyph {
1018
- color: var(--assistant);
1019
- }
1020
- .chat-msg.tool .glyph {
1021
- color: var(--tool);
1022
- }
1023
- .chat-msg.info .glyph {
1024
- color: var(--info);
1025
- }
1026
- .chat-msg.warning .glyph {
1027
- color: var(--warn);
1028
- }
1029
- .chat-msg.error .glyph {
1030
- color: var(--err);
1031
- }
1032
-
1033
- .chat-msg.user .body {
1034
- color: var(--fg-0);
1035
- }
1036
- .chat-msg.assistant .body {
1037
- color: var(--fg-0);
1038
- }
1039
- /* Tool-card replaces the simple .body box for role="tool" rows. The
1040
- * card carries a left accent bar (amber for success), a header with
1041
- * tool name + path/lang pills, then the kind-specific body (diff for
1042
- * edit_file, code block for read/write_file, terminal for run_command,
1043
- * etc). Keeps the visual weight consistent across kinds. */
1044
- .tool-card {
1045
- flex: 1;
1046
- background: var(--bg-1);
1047
- border: 1px solid var(--border);
1048
- border-left: 3px solid var(--tool);
1049
- border-radius: var(--radius-md);
1050
- padding: 10px 12px;
1051
- min-width: 0;
1052
- }
1053
- .tool-card-head {
1054
- display: flex;
1055
- align-items: center;
1056
- gap: 8px;
1057
- margin-bottom: 8px;
1058
- font-family: var(--mono);
1059
- font-size: 12px;
1060
- flex-wrap: wrap;
1061
- }
1062
- .tool-card-icon {
1063
- color: var(--tool);
1064
- font-size: 14px;
1065
- font-weight: 600;
1066
- }
1067
- .tool-card-name {
1068
- color: var(--accent);
1069
- font-weight: 500;
1070
- }
1071
- .tool-card-path {
1072
- color: var(--primary);
1073
- background: var(--bg-2);
1074
- padding: 1px 8px;
1075
- border-radius: var(--radius-sm);
1076
- font-size: 11px;
1077
- }
1078
- .tool-card-path-link {
1079
- cursor: pointer;
1080
- border: 1px solid transparent;
1081
- transition: border-color 0.12s, background 0.12s;
1082
- }
1083
- .tool-card-path-link:hover {
1084
- border-color: var(--primary);
1085
- background: rgba(103, 232, 249, 0.12);
1086
- }
1087
- .tool-card pre,
1088
- .tool-card .md {
1089
- margin: 0;
1090
- }
1091
- .tool-card .md > pre,
1092
- .tool-card-cmd,
1093
- .tool-card-output {
1094
- background: var(--bg-2);
1095
- border: 1px solid var(--border);
1096
- border-radius: var(--radius-sm);
1097
- padding: 8px 10px;
1098
- font-family: var(--mono);
1099
- font-size: 12px;
1100
- line-height: 1.55;
1101
- max-height: 320px;
1102
- overflow: auto;
1103
- }
1104
- .tool-card .md > pre code {
1105
- background: transparent;
1106
- padding: 0;
1107
- color: inherit;
1108
- }
1109
- .tool-card .diff-block {
1110
- margin: 0;
1111
- max-height: 320px;
1112
- }
1113
- .tool-card-cmd {
1114
- background: var(--bg-0);
1115
- white-space: pre;
1116
- margin: 0 0 6px 0;
1117
- }
1118
- .tool-card-prompt {
1119
- color: var(--fg-3);
1120
- margin-right: 6px;
1121
- }
1122
- .tool-card-output {
1123
- white-space: pre-wrap;
1124
- word-break: break-word;
1125
- color: var(--fg-1);
1126
- margin: 0;
1127
- }
1128
- .tool-card-result {
1129
- margin-top: 6px;
1130
- font-size: 11px;
1131
- color: var(--fg-3);
1132
- font-family: var(--mono);
1133
- }
1134
- .tool-card-args {
1135
- margin-bottom: 6px;
1136
- font-size: 11px;
1137
- }
1138
- .tool-card-args summary {
1139
- cursor: pointer;
1140
- color: var(--fg-2);
1141
- }
1142
- .tool-card-args summary:hover {
1143
- color: var(--primary);
1144
- }
1145
- .tool-card-args pre {
1146
- margin-top: 6px;
1147
- white-space: pre;
1148
- }
1149
-
1150
- .chat-msg .reasoning {
1151
- margin-top: 6px;
1152
- padding: 6px 10px;
1153
- background: var(--bg-1);
1154
- border-left: 2px solid var(--accent);
1155
- color: var(--fg-2);
1156
- font-size: 12px;
1157
- font-style: italic;
1158
- white-space: pre-wrap;
1159
- word-break: break-word;
1160
- border-radius: var(--radius-sm);
1161
- }
1162
-
1163
- .chat-msg .tool-name {
1164
- color: var(--accent);
1165
- font-weight: 500;
1166
- }
1167
-
1168
- .chat-streaming-cursor {
1169
- display: inline-block;
1170
- width: 7px;
1171
- height: 14px;
1172
- background: var(--primary);
1173
- margin-left: 2px;
1174
- vertical-align: middle;
1175
- animation: blink 1s steps(1) infinite;
1176
- }
1177
-
1178
- @keyframes blink {
1179
- 50% {
1180
- opacity: 0;
1181
- }
1182
- }
1183
-
1184
- .chat-input-area {
1185
- display: flex;
1186
- gap: 10px;
1187
- padding-top: 12px;
1188
- border-top: 1px solid var(--border);
1189
- flex-shrink: 0;
1190
- }
1191
-
1192
- .chat-input-area textarea {
1193
- flex: 1;
1194
- background: var(--bg-2);
1195
- border: 1px solid var(--border);
1196
- color: var(--fg-0);
1197
- padding: 8px 12px;
1198
- border-radius: var(--radius-md);
1199
- font-family: var(--mono);
1200
- font-size: 13px;
1201
- resize: vertical;
1202
- min-height: 44px;
1203
- max-height: 200px;
1204
- }
1205
-
1206
- .chat-input-area textarea:focus {
1207
- border-color: var(--primary);
1208
- outline: none;
1209
- }
1210
-
1211
- .chat-input-area textarea:disabled {
1212
- opacity: 0.5;
1213
- cursor: not-allowed;
1214
- }
1215
-
1216
- .chat-empty {
1217
- margin: auto;
1218
- text-align: center;
1219
- color: var(--fg-3);
1220
- font-family: var(--mono);
1221
- font-size: 13px;
1222
- padding: 40px 20px;
1223
- }
1224
-
1225
- .chat-status {
1226
- display: flex;
1227
- align-items: center;
1228
- gap: 8px;
1229
- margin-bottom: 12px;
1230
- font-size: 12px;
1231
- color: var(--fg-2);
1232
- }
1233
-
1234
- /* Onboarding banner that nudges new users to the Semantic panel.
1235
- * Only shown when the project has no built index AND the user hasn't
1236
- * explicitly dismissed it (state in localStorage). The "Build it →"
1237
- * action navigates the sidebar via the appBus so the rest of the
1238
- * panel state isn't disturbed. */
1239
- .chat-banner {
1240
- display: flex;
1241
- align-items: center;
1242
- gap: 12px;
1243
- margin-bottom: 14px;
1244
- padding: 10px 14px;
1245
- background: var(--bg-1);
1246
- border: 1px solid var(--border);
1247
- border-left: 3px solid var(--accent);
1248
- border-radius: var(--radius-md);
1249
- font-size: 13px;
1250
- }
1251
- .chat-banner-icon {
1252
- font-family: var(--mono);
1253
- color: var(--accent);
1254
- font-size: 18px;
1255
- }
1256
- .chat-banner-text {
1257
- flex: 1;
1258
- display: flex;
1259
- flex-direction: column;
1260
- gap: 2px;
1261
- font-size: 13px;
1262
- }
1263
- .chat-banner-text strong {
1264
- color: var(--fg-0);
1265
- font-weight: 600;
1266
- }
1267
- .chat-banner-text .muted {
1268
- font-size: 12px;
1269
- line-height: 1.45;
1270
- }
1271
- .chat-banner-close {
1272
- background: transparent;
1273
- border: none;
1274
- color: var(--fg-3);
1275
- font-size: 20px;
1276
- line-height: 1;
1277
- padding: 0 6px;
1278
- cursor: pointer;
1279
- border-radius: var(--radius-sm);
1280
- }
1281
- .chat-banner-close:hover {
1282
- background: var(--bg-3);
1283
- color: var(--fg-0);
1284
- }
1285
-
1286
- /* In-flight row sits just above ChatStatusBar — the user's eyes are
1287
- * already at the input; this puts the spinner + elapsed + token
1288
- * stream in the same visual neighborhood instead of pushing them up
1289
- * to the top of the panel. Border on the bottom only so it shares the
1290
- * statusbar's top divider. */
1291
- .chat-inflight {
1292
- display: flex;
1293
- flex-wrap: wrap;
1294
- align-items: center;
1295
- gap: 8px;
1296
- padding: 7px 8px;
1297
- margin-top: 6px;
1298
- background: var(--bg-1);
1299
- border: 1px solid var(--border);
1300
- border-radius: var(--radius-sm);
1301
- font-family: var(--mono);
1302
- font-size: 12px;
1303
- color: var(--fg-1);
1304
- flex-shrink: 0;
1305
- }
1306
- .chat-inflight-phase {
1307
- color: var(--accent);
1308
- font-weight: 600;
1309
- }
1310
- .chat-inflight-sep {
1311
- color: var(--fg-3);
1312
- }
1313
- .chat-inflight-tool {
1314
- color: var(--fg-1);
1315
- white-space: nowrap;
1316
- overflow: hidden;
1317
- text-overflow: ellipsis;
1318
- max-width: 480px;
1319
- }
1320
- .chat-inflight-abort {
1321
- margin-left: auto;
1322
- background: transparent;
1323
- border: 1px solid var(--border);
1324
- color: var(--fg-2);
1325
- padding: 3px 10px;
1326
- border-radius: var(--radius-sm);
1327
- font-family: inherit;
1328
- font-size: 11px;
1329
- cursor: pointer;
1330
- }
1331
- .chat-inflight-abort:hover {
1332
- border-color: var(--err);
1333
- color: var(--err);
1334
- }
1335
-
1336
- /* ---------- Chat status bar ----------
1337
- *
1338
- * Compact metric strip below the input area. Mirrors the TUI's
1339
- * StatsPanel (model · ctx · cache · turn $ · session $ · balance) so
1340
- * the user has the same one-glance read-out without leaving Chat.
1341
- */
1342
- .chat-statusbar {
1343
- display: flex;
1344
- flex-wrap: wrap;
1345
- gap: 16px;
1346
- padding: 8px 4px 0;
1347
- margin-top: 8px;
1348
- border-top: 1px solid var(--border);
1349
- font-family: var(--mono);
1350
- font-size: 11px;
1351
- color: var(--fg-2);
1352
- flex-shrink: 0;
1353
- }
1354
- .status-item {
1355
- display: inline-flex;
1356
- align-items: center;
1357
- gap: 6px;
1358
- }
1359
- .status-label {
1360
- color: var(--fg-3);
1361
- font-size: 10px;
1362
- letter-spacing: 0.06em;
1363
- text-transform: uppercase;
1364
- }
1365
- .status-bar-mini {
1366
- display: inline-block;
1367
- width: 60px;
1368
- height: 4px;
1369
- background: var(--bg-3);
1370
- border-radius: 2px;
1371
- overflow: hidden;
1372
- }
1373
- .status-bar-mini-fill {
1374
- display: block;
1375
- height: 100%;
1376
- background: var(--gradient-rule);
1377
- }
1378
- .status-ok {
1379
- color: var(--ok);
1380
- }
1381
- .status-warn {
1382
- color: var(--warn);
1383
- }
1384
- .status-err {
1385
- color: var(--err);
1386
- }
1387
-
1388
- /* ---------- Header pickers (effort / preset / edit-mode) ----------
1389
- *
1390
- * Three segmented controls that flow on the chat header right side.
1391
- * On narrow screens they wrap onto multiple rows. The `accent` variant
1392
- * paints active segments violet (preset / effort) instead of cyan
1393
- * (edit-mode), so the three picker groups remain visually distinct.
1394
- */
1395
- .header-pickers {
1396
- display: flex;
1397
- gap: 8px;
1398
- flex-wrap: wrap;
1399
- justify-content: flex-end;
1400
- }
1401
-
1402
- .mode-picker {
1403
- display: inline-flex;
1404
- border: 1px solid var(--border);
1405
- border-radius: var(--radius-md);
1406
- overflow: hidden;
1407
- background: var(--bg-1);
1408
- }
1409
- .mode-btn {
1410
- background: transparent;
1411
- border: none;
1412
- border-radius: 0;
1413
- padding: 4px 12px;
1414
- font-family: var(--mono);
1415
- font-size: 11px;
1416
- letter-spacing: 0.05em;
1417
- text-transform: uppercase;
1418
- color: var(--fg-2);
1419
- cursor: pointer;
1420
- transition: color 0.12s, background 0.12s;
1421
- }
1422
- .mode-btn + .mode-btn {
1423
- border-left: 1px solid var(--border);
1424
- }
1425
- .mode-btn:hover {
1426
- background: var(--bg-2);
1427
- color: var(--fg-0);
1428
- }
1429
- .mode-btn.active {
1430
- background: var(--primary);
1431
- color: var(--bg-0);
1432
- font-weight: 600;
1433
- }
1434
- .mode-btn.active.accent {
1435
- background: var(--accent);
1436
- color: var(--bg-0);
1437
- }
1438
- .mode-btn.active.yolo {
1439
- background: var(--err);
1440
- color: var(--bg-0);
1441
- }
1442
-
1443
- /* ---------- Modal cards (shell / choice / plan / edit-review) ----------
1444
- *
1445
- * Mirrors the TUI's ModalCard shape — left-accent border in the modal
1446
- * kind's color (red shell, magenta choice, cyan plan, green edits)
1447
- * with an icon, title, optional subtitle, then content + actions. The
1448
- * card sits above the chat input area, full-width within the chat
1449
- * column. Styled minimal so it doesn't compete with conversation
1450
- * content for attention.
1451
- */
1452
-
1453
- .modal-card {
1454
- margin: 12px 0;
1455
- background: var(--bg-1);
1456
- border: 1px solid var(--border);
1457
- border-left: 3px solid var(--accent);
1458
- border-radius: var(--radius-md);
1459
- padding: 14px 16px;
1460
- display: flex;
1461
- flex-direction: column;
1462
- gap: 12px;
1463
- }
1464
-
1465
- .modal-card-head {
1466
- display: flex;
1467
- gap: 12px;
1468
- align-items: flex-start;
1469
- }
1470
-
1471
- .modal-card-icon {
1472
- font-size: 18px;
1473
- font-family: var(--mono);
1474
- line-height: 1.4;
1475
- }
1476
-
1477
- .modal-card-title {
1478
- font-size: 14px;
1479
- font-weight: 600;
1480
- color: var(--fg-0);
1481
- }
1482
-
1483
- .modal-card-subtitle {
1484
- font-size: 12px;
1485
- color: var(--fg-2);
1486
- margin-top: 2px;
1487
- }
1488
-
1489
- .modal-cmd {
1490
- background: var(--bg-2);
1491
- border-radius: var(--radius-sm);
1492
- padding: 8px 12px;
1493
- font-family: var(--mono);
1494
- font-size: 13px;
1495
- overflow-x: auto;
1496
- max-height: 240px;
1497
- overflow-y: auto;
1498
- white-space: pre-wrap;
1499
- word-break: break-all;
1500
- }
1501
- .modal-cmd-prompt {
1502
- color: var(--fg-3);
1503
- margin-right: 6px;
1504
- }
1505
- .modal-cmd code {
1506
- color: var(--primary);
1507
- background: transparent;
1508
- padding: 0;
1509
- word-break: break-all;
1510
- }
1511
-
1512
- .modal-actions {
1513
- display: flex;
1514
- gap: 8px;
1515
- flex-wrap: wrap;
1516
- }
1517
-
1518
- .modal-choice-row {
1519
- display: grid;
1520
- grid-template-columns: 28px 1fr;
1521
- grid-template-rows: auto auto;
1522
- gap: 2px 12px;
1523
- background: transparent;
1524
- border: 1px solid var(--border);
1525
- border-radius: var(--radius-sm);
1526
- padding: 8px 12px;
1527
- text-align: left;
1528
- cursor: pointer;
1529
- transition: border-color 0.12s, background 0.12s;
1530
- }
1531
- .modal-choice-row:hover {
1532
- border-color: var(--accent);
1533
- background: rgba(196, 181, 253, 0.06);
1534
- }
1535
- .modal-choice-row.modal-choice-cancel {
1536
- margin-top: 4px;
1537
- border-style: dashed;
1538
- }
1539
- .modal-choice-id {
1540
- grid-row: 1 / 3;
1541
- align-self: center;
1542
- font-family: var(--mono);
1543
- font-size: 14px;
1544
- color: var(--accent);
1545
- font-weight: 600;
1546
- text-align: center;
1547
- }
1548
- .modal-choice-title {
1549
- color: var(--fg-0);
1550
- font-size: 13px;
1551
- font-weight: 500;
1552
- }
1553
- .modal-choice-summary {
1554
- color: var(--fg-2);
1555
- font-size: 12px;
1556
- grid-column: 2;
1557
- }
1558
-
1559
- .modal-custom textarea {
1560
- width: 100%;
1561
- background: var(--bg-2);
1562
- border: 1px solid var(--border);
1563
- color: var(--fg-0);
1564
- padding: 8px 12px;
1565
- border-radius: var(--radius-sm);
1566
- font-family: var(--mono);
1567
- font-size: 13px;
1568
- resize: vertical;
1569
- min-height: 56px;
1570
- }
1571
-
1572
- .modal-plan-body {
1573
- background: var(--bg-2);
1574
- border-radius: var(--radius-sm);
1575
- padding: 12px 14px;
1576
- max-height: 320px;
1577
- overflow-y: auto;
1578
- }
1579
-
1580
- /* Plan-revision modal — list of remaining steps with risk dots. */
1581
- .modal-revise-reason {
1582
- background: var(--bg-2);
1583
- border-left: 3px solid #c4b5fd;
1584
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
1585
- padding: 8px 12px;
1586
- color: var(--fg-1);
1587
- font-size: 13px;
1588
- white-space: pre-wrap;
1589
- }
1590
- .modal-revise-steps {
1591
- list-style: none;
1592
- margin: 0;
1593
- padding: 0;
1594
- display: flex;
1595
- flex-direction: column;
1596
- gap: 6px;
1597
- max-height: 280px;
1598
- overflow-y: auto;
1599
- }
1600
- .modal-revise-steps li {
1601
- display: grid;
1602
- grid-template-columns: 12px 64px 1fr;
1603
- grid-template-rows: auto auto;
1604
- gap: 2px 10px;
1605
- background: var(--bg-2);
1606
- border: 1px solid var(--border);
1607
- border-radius: var(--radius-sm);
1608
- padding: 8px 12px;
1609
- align-items: center;
1610
- }
1611
- .modal-revise-dot {
1612
- grid-row: 1 / 3;
1613
- width: 8px;
1614
- height: 8px;
1615
- border-radius: 50%;
1616
- align-self: center;
1617
- }
1618
- .modal-revise-id {
1619
- grid-row: 1;
1620
- font-family: var(--mono);
1621
- font-size: 12px;
1622
- color: var(--fg-2);
1623
- }
1624
- .modal-revise-title {
1625
- grid-row: 1;
1626
- color: var(--fg-0);
1627
- font-size: 13px;
1628
- font-weight: 500;
1629
- }
1630
- .modal-revise-action {
1631
- grid-column: 2 / 4;
1632
- grid-row: 2;
1633
- color: var(--fg-2);
1634
- font-size: 12px;
1635
- white-space: pre-wrap;
1636
- }
1637
-
1638
- .modal-edit-preview {
1639
- background: var(--bg-2);
1640
- border: 1px solid var(--border);
1641
- border-radius: var(--radius-sm);
1642
- padding: 10px 12px;
1643
- margin: 0;
1644
- font-family: var(--mono);
1645
- font-size: 12px;
1646
- color: var(--fg-1);
1647
- white-space: pre;
1648
- overflow-x: auto;
1649
- max-height: 200px;
1650
- }
1651
-
1652
- /* Side-by-side diff for the edit-review modal — left is "before" (red
1653
- * tint), right is "after" (green tint), context rows render unchanged.
1654
- * Lines hljs-highlight per the file's language. */
1655
- .edit-diff-wrap {
1656
- border: 1px solid var(--border);
1657
- border-radius: var(--radius-sm);
1658
- background: var(--bg-2);
1659
- font-family: var(--mono);
1660
- font-size: 12px;
1661
- overflow: hidden;
1662
- max-height: 60vh;
1663
- display: flex;
1664
- flex-direction: column;
1665
- }
1666
- .edit-diff-head {
1667
- display: flex;
1668
- background: var(--bg-1);
1669
- border-bottom: 1px solid var(--border);
1670
- font-size: 11px;
1671
- text-transform: uppercase;
1672
- letter-spacing: 0.06em;
1673
- color: var(--fg-3);
1674
- flex-shrink: 0;
1675
- }
1676
- .edit-diff-side {
1677
- flex: 1;
1678
- padding: 6px 12px;
1679
- }
1680
- .edit-diff-side + .edit-diff-side {
1681
- border-left: 1px solid var(--border);
1682
- }
1683
- .edit-diff-side-old .edit-diff-marker {
1684
- color: #f87171;
1685
- font-weight: 700;
1686
- margin-right: 4px;
1687
- }
1688
- .edit-diff-side-new .edit-diff-marker {
1689
- color: #86efac;
1690
- font-weight: 700;
1691
- margin-right: 4px;
1692
- }
1693
- .edit-diff-body {
1694
- flex: 1;
1695
- overflow-y: auto;
1696
- overflow-x: auto;
1697
- }
1698
- .edit-diff-row {
1699
- display: flex;
1700
- width: 100%;
1701
- align-items: stretch;
1702
- min-height: 19px;
1703
- }
1704
- .edit-diff-cell {
1705
- flex: 1;
1706
- padding: 1px 12px;
1707
- white-space: pre;
1708
- overflow-x: auto;
1709
- border-right: 1px solid var(--border);
1710
- color: var(--fg-1);
1711
- line-height: 1.55;
1712
- }
1713
- .edit-diff-cell:last-child {
1714
- border-right: none;
1715
- }
1716
- .edit-diff-row-context .edit-diff-cell {
1717
- background: transparent;
1718
- color: var(--fg-2);
1719
- }
1720
- .edit-diff-row-del .edit-diff-cell-old,
1721
- .edit-diff-row-change .edit-diff-cell-old {
1722
- background: rgba(248, 113, 113, 0.12);
1723
- border-left: 2px solid #f87171;
1724
- padding-left: 10px;
1725
- }
1726
- .edit-diff-row-ins .edit-diff-cell-new,
1727
- .edit-diff-row-change .edit-diff-cell-new {
1728
- background: rgba(134, 239, 172, 0.12);
1729
- border-left: 2px solid #86efac;
1730
- padding-left: 10px;
1731
- }
1732
- .edit-diff-cell-old .edit-diff-empty,
1733
- .edit-diff-cell-new .edit-diff-empty {
1734
- display: inline-block;
1735
- width: 1px;
1736
- }
1737
- .edit-diff-row-del .edit-diff-cell-new,
1738
- .edit-diff-row-ins .edit-diff-cell-old {
1739
- background: var(--bg-3);
1740
- opacity: 0.5;
1741
- }
1742
- .edit-diff-line {
1743
- font-family: var(--mono);
1744
- }
1745
-
1746
- @media (max-width: 800px) {
1747
- .edit-diff-row {
1748
- flex-direction: column;
1749
- }
1750
- .edit-diff-cell {
1751
- border-right: none;
1752
- border-bottom: 1px solid var(--border);
1753
- }
1754
- .edit-diff-head {
1755
- flex-direction: column;
1756
- }
1757
- .edit-diff-side + .edit-diff-side {
1758
- border-left: none;
1759
- border-top: 1px solid var(--border);
1760
- }
1761
- }
1762
-
1763
- .muted {
1764
- color: var(--fg-3);
1765
- }
1766
-
1767
- /* ---------- Toast ----------
1768
- * Ephemeral notifications stacked bottom-right of the viewport. Fired
1769
- * by save / network success paths instead of inline banners that push
1770
- * the form around. Auto-dismiss after 3 seconds. */
1771
- .toast-stack {
1772
- position: fixed;
1773
- bottom: 20px;
1774
- right: 20px;
1775
- display: flex;
1776
- flex-direction: column;
1777
- gap: 8px;
1778
- z-index: 50;
1779
- pointer-events: none;
1780
- }
1781
- .toast {
1782
- pointer-events: auto;
1783
- background: var(--bg-1);
1784
- border: 1px solid var(--border);
1785
- border-left: 3px solid var(--ok);
1786
- border-radius: var(--radius-md);
1787
- padding: 10px 14px;
1788
- font-size: 13px;
1789
- color: var(--fg-0);
1790
- font-family: var(--sans);
1791
- min-width: 200px;
1792
- max-width: 360px;
1793
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
1794
- animation: toast-slide-in 0.18s ease-out;
1795
- }
1796
- .toast.warn {
1797
- border-left-color: var(--warn);
1798
- }
1799
- .toast.err {
1800
- border-left-color: var(--err);
1801
- }
1802
- .toast.info {
1803
- border-left-color: var(--accent);
1804
- }
1805
-
1806
- /* ---------- Error overlay ----------
1807
- *
1808
- * Full-screen modal triggered by uncaught exceptions / promise
1809
- * rejections / Preact render errors. The TUI is unaffected — this
1810
- * only blocks the browser tab. Includes "Copy details" + a GitHub
1811
- * issue link prefilled with redacted environment info.
1812
- */
1813
- .error-overlay {
1814
- position: fixed;
1815
- inset: 0;
1816
- background: rgba(10, 14, 20, 0.85);
1817
- backdrop-filter: blur(4px);
1818
- display: flex;
1819
- align-items: center;
1820
- justify-content: center;
1821
- padding: 32px;
1822
- z-index: 100;
1823
- animation: fade-in 0.18s ease-out;
1824
- }
1825
- .error-overlay-card {
1826
- max-width: 720px;
1827
- width: 100%;
1828
- max-height: 85vh;
1829
- overflow-y: auto;
1830
- background: var(--bg-1);
1831
- border: 1px solid var(--err);
1832
- border-left: 4px solid var(--err);
1833
- border-radius: var(--radius-md);
1834
- padding: 22px 26px;
1835
- box-shadow: 0 12px 60px rgba(248, 113, 113, 0.18);
1836
- }
1837
- .error-overlay-head {
1838
- display: flex;
1839
- gap: 14px;
1840
- align-items: flex-start;
1841
- margin-bottom: 16px;
1842
- }
1843
- .error-overlay-icon {
1844
- color: var(--err);
1845
- font-size: 22px;
1846
- font-weight: 700;
1847
- }
1848
- .error-overlay-title {
1849
- font-size: 16px;
1850
- font-weight: 600;
1851
- color: var(--fg-0);
1852
- }
1853
- .error-overlay-subtitle {
1854
- font-size: 13px;
1855
- color: var(--fg-2);
1856
- font-family: var(--mono);
1857
- margin-top: 4px;
1858
- word-break: break-word;
1859
- }
1860
- .error-overlay-trace {
1861
- background: var(--bg-2);
1862
- border: 1px solid var(--border);
1863
- border-radius: var(--radius-sm);
1864
- padding: 12px 14px;
1865
- font-family: var(--mono);
1866
- font-size: 12px;
1867
- line-height: 1.55;
1868
- color: var(--fg-1);
1869
- white-space: pre-wrap;
1870
- word-break: break-word;
1871
- max-height: 280px;
1872
- overflow-y: auto;
1873
- margin: 0 0 12px;
1874
- }
1875
- .error-overlay-info {
1876
- font-size: 12px;
1877
- font-family: var(--mono);
1878
- color: var(--fg-2);
1879
- margin-bottom: 12px;
1880
- }
1881
- .error-overlay-help {
1882
- font-size: 13px;
1883
- color: var(--fg-1);
1884
- margin-bottom: 18px;
1885
- line-height: 1.55;
1886
- }
1887
- .error-overlay-actions {
1888
- display: flex;
1889
- gap: 8px;
1890
- flex-wrap: wrap;
1891
- align-items: center;
1892
- }
1893
- .error-overlay-actions a.button {
1524
+ .chat-streaming-cursor {
1894
1525
  display: inline-block;
1895
- text-decoration: none;
1896
- background: var(--bg-2);
1897
- color: var(--fg-1);
1898
- border: 1px solid var(--border);
1899
- border-radius: var(--radius-sm);
1900
- padding: 6px 12px;
1901
- font-family: var(--sans);
1902
- font-size: 12px;
1903
- }
1904
- .error-overlay-actions a.button:hover {
1905
- border-color: var(--primary);
1906
- color: var(--primary);
1526
+ width: 7px;
1527
+ height: 14px;
1528
+ background: var(--c-brand);
1529
+ margin-left: 2px;
1530
+ vertical-align: middle;
1531
+ animation: blink 1s steps(1) infinite;
1907
1532
  }
1908
1533
 
1909
- /* ---------- Editor drawer ----------
1910
- *
1911
- * Sits to the right of the main panel. Hidden by default (width: 0,
1912
- * overflow hidden) so its DOM stays mounted and keeps its tab state.
1913
- * `.open` flips width to ~50% with a slide animation. On narrow
1914
- * viewports it covers the panel entirely (full-screen overlay).
1915
- */
1916
- .editor-drawer-host {
1917
- flex-shrink: 0;
1918
- width: 0;
1919
- overflow: hidden;
1920
- border-left: 1px solid var(--border);
1921
- background: var(--bg-0);
1922
- transition: width 0.2s ease-out;
1923
- }
1924
- .editor-drawer-host.open {
1925
- width: 65%;
1926
- min-width: 420px;
1534
+ @keyframes blink {
1535
+ 50% {
1536
+ opacity: 0;
1537
+ }
1927
1538
  }
1928
1539
 
1929
- .editor-drawer-head {
1540
+ .chat-input-area {
1930
1541
  display: flex;
1931
- align-items: center;
1932
- padding: 8px 12px;
1933
- border-bottom: 1px solid var(--border);
1934
- background: var(--bg-1);
1542
+ gap: 10px;
1543
+ padding-top: 12px;
1544
+ border-top: 1px solid var(--bd);
1935
1545
  flex-shrink: 0;
1936
1546
  }
1937
- .editor-drawer-title {
1938
- font-family: var(--mono);
1939
- font-size: 12px;
1940
- letter-spacing: 0.06em;
1941
- text-transform: uppercase;
1942
- color: var(--accent);
1943
- }
1944
- .editor-drawer-close {
1945
- margin-left: auto;
1946
- background: transparent;
1947
- border: 1px solid var(--border);
1948
- color: var(--fg-2);
1949
- font-size: 18px;
1950
- line-height: 1;
1951
- padding: 0 10px;
1952
- border-radius: var(--radius-sm);
1953
- cursor: pointer;
1547
+
1548
+ .chat-input-area textarea {
1549
+ flex: 1;
1550
+ background: var(--bg-elev-2);
1551
+ border: 1px solid var(--bd);
1552
+ color: var(--fg-0);
1553
+ padding: 8px 12px;
1554
+ border-radius: var(--r-md);
1555
+ font-family: var(--font-mono);
1556
+ font-size: 13px;
1557
+ resize: vertical;
1558
+ min-height: 44px;
1559
+ max-height: 200px;
1954
1560
  }
1955
- .editor-drawer-close:hover {
1956
- border-color: var(--err);
1957
- color: var(--err);
1561
+
1562
+ .chat-input-area textarea:focus {
1563
+ border-color: var(--c-brand);
1564
+ outline: none;
1958
1565
  }
1959
1566
 
1960
- @media (max-width: 800px) {
1961
- .editor-drawer-host {
1962
- position: fixed;
1963
- top: 0;
1964
- right: 0;
1965
- bottom: 0;
1966
- width: 0;
1967
- z-index: 7;
1968
- box-shadow: -4px 0 24px rgba(0, 0, 0, 0.4);
1969
- }
1970
- .editor-drawer-host.open {
1971
- width: 100%;
1972
- min-width: 0;
1973
- }
1567
+ .chat-input-area textarea:disabled {
1568
+ opacity: 0.5;
1569
+ cursor: not-allowed;
1974
1570
  }
1975
1571
 
1976
- /* ---------- Editor panel (CodeMirror multi-tab) ---------- */
1572
+ .chat-empty {
1573
+ margin: auto;
1574
+ text-align: center;
1575
+ color: var(--fg-3);
1576
+ font-family: var(--font-mono);
1577
+ font-size: 13px;
1578
+ padding: 40px 20px;
1579
+ }
1977
1580
 
1978
- .editor-shell {
1581
+ .chat-status {
1979
1582
  display: flex;
1980
- flex-direction: column;
1981
- height: calc(100vh - 56px);
1982
- padding: 0;
1983
- background: var(--bg-0);
1583
+ align-items: center;
1584
+ gap: 8px;
1585
+ margin-bottom: 12px;
1586
+ font-size: 12px;
1587
+ color: var(--fg-2);
1984
1588
  }
1985
1589
 
1986
- /* When the editor renders inside the right-side drawer, it follows
1987
- * the drawer's flex column instead of carrying its own viewport-tied
1988
- * height. Drawer-host gets `display: flex; flex-direction: column`
1989
- * via the descendant context. */
1990
- .editor-drawer-host {
1590
+ /* Onboarding banner that nudges new users to the Semantic panel.
1591
+ * Only shown when the project has no built index AND the user hasn't
1592
+ * explicitly dismissed it (state in localStorage). The "Build it →"
1593
+ * action navigates the sidebar via the appBus so the rest of the
1594
+ * panel state isn't disturbed. */
1595
+ .chat-banner {
1991
1596
  display: flex;
1992
- flex-direction: column;
1597
+ align-items: center;
1598
+ gap: 12px;
1599
+ margin-bottom: 14px;
1600
+ padding: 10px 14px;
1601
+ background: var(--bg-elev);
1602
+ border: 1px solid var(--bd);
1603
+ border-left: 3px solid var(--c-accent);
1604
+ border-radius: var(--r-md);
1605
+ font-size: 13px;
1993
1606
  }
1994
- .editor-drawer-host .editor-shell {
1995
- flex: 1;
1996
- height: auto;
1997
- min-height: 0;
1607
+ .chat-banner-icon {
1608
+ font-family: var(--font-mono);
1609
+ color: var(--c-accent);
1610
+ font-size: 18px;
1998
1611
  }
1999
- .editor-body {
2000
- display: flex;
1612
+ .chat-banner-text {
2001
1613
  flex: 1;
2002
- min-height: 0;
2003
- gap: 0;
2004
- }
2005
- .editor-side {
2006
- width: 260px;
2007
- flex-shrink: 0;
2008
1614
  display: flex;
2009
1615
  flex-direction: column;
2010
- background: var(--bg-1);
2011
- border-right: 1px solid var(--border);
2012
- padding: 8px 8px 8px 10px;
2013
- transition: width 0.15s ease-out;
2014
- }
2015
- .editor-side.collapsed {
2016
- width: 28px;
1616
+ gap: 2px;
1617
+ font-size: 13px;
2017
1618
  }
2018
- .editor-side-head {
2019
- display: flex;
2020
- align-items: center;
2021
- gap: 6px;
2022
- margin-bottom: 8px;
2023
- padding: 0 2px;
1619
+ .chat-banner-text strong {
1620
+ color: var(--fg-0);
1621
+ font-weight: 600;
2024
1622
  }
2025
- .editor-side-label {
2026
- font-family: var(--mono);
2027
- font-size: 10px;
2028
- letter-spacing: 0.08em;
2029
- color: var(--fg-3);
2030
- text-transform: uppercase;
1623
+ .chat-banner-text .muted {
1624
+ font-size: 12px;
1625
+ line-height: 1.45;
2031
1626
  }
2032
- .editor-side-toggle {
2033
- margin-left: auto;
1627
+ .chat-banner-close {
2034
1628
  background: transparent;
2035
- border: 1px solid var(--border);
1629
+ border: none;
2036
1630
  color: var(--fg-3);
2037
- font-size: 10px;
1631
+ font-size: 20px;
2038
1632
  line-height: 1;
2039
- padding: 3px 6px;
2040
- border-radius: var(--radius-sm);
1633
+ padding: 0 6px;
2041
1634
  cursor: pointer;
1635
+ border-radius: var(--r);
2042
1636
  }
2043
- .editor-side-toggle:hover {
2044
- border-color: var(--primary);
2045
- color: var(--primary);
1637
+ .chat-banner-close:hover {
1638
+ background: var(--bg-input);
1639
+ color: var(--fg-0);
2046
1640
  }
2047
- .editor-side.collapsed .editor-side-toggle {
2048
- margin: 8px auto 0;
2049
- width: 100%;
1641
+
1642
+ /* In-flight row sits just above ChatStatusBar — the user's eyes are
1643
+ * already at the input; this puts the spinner + elapsed + token
1644
+ * stream in the same visual neighborhood instead of pushing them up
1645
+ * to the top of the panel. Border on the bottom only so it shares the
1646
+ * statusbar's top divider. */
1647
+ .chat-inflight {
1648
+ display: flex;
1649
+ flex-wrap: wrap;
1650
+ align-items: center;
1651
+ gap: 8px;
1652
+ padding: 7px 8px;
1653
+ margin-top: 6px;
1654
+ background: var(--bg-elev);
1655
+ border: 1px solid var(--bd);
1656
+ border-radius: var(--r);
1657
+ font-family: var(--font-mono);
1658
+ font-size: 12px;
1659
+ color: var(--fg-1);
1660
+ flex-shrink: 0;
2050
1661
  }
2051
- .editor-files {
2052
- flex: 1;
2053
- overflow-y: auto;
2054
- border: 1px solid var(--border);
2055
- border-radius: var(--radius-sm);
2056
- background: var(--bg-0);
2057
- }
2058
- .editor-file {
2059
- padding: 5px 10px;
2060
- font-family: var(--mono);
2061
- font-size: 11.5px;
2062
- color: var(--fg-2);
2063
- cursor: pointer;
2064
- border-left: 2px solid transparent;
1662
+ .chat-inflight-phase {
1663
+ color: var(--c-accent);
1664
+ font-weight: 600;
1665
+ }
1666
+ .chat-inflight-sep {
1667
+ color: var(--fg-3);
1668
+ }
1669
+ .chat-inflight-tool {
1670
+ color: var(--fg-1);
2065
1671
  white-space: nowrap;
2066
1672
  overflow: hidden;
2067
1673
  text-overflow: ellipsis;
1674
+ max-width: 480px;
2068
1675
  }
2069
- .editor-file:hover {
2070
- background: var(--bg-hover);
2071
- color: var(--fg-0);
1676
+ .chat-inflight-abort {
1677
+ margin-left: auto;
1678
+ background: transparent;
1679
+ border: 1px solid var(--bd);
1680
+ color: var(--fg-2);
1681
+ padding: 3px 10px;
1682
+ border-radius: var(--r);
1683
+ font-family: inherit;
1684
+ font-size: 11px;
1685
+ cursor: pointer;
2072
1686
  }
2073
- .editor-file.open {
2074
- color: var(--primary);
2075
- border-left-color: var(--primary);
1687
+ .chat-inflight-abort:hover {
1688
+ border-color: var(--c-err);
1689
+ color: var(--c-err);
2076
1690
  }
2077
- .editor-tree-folder,
2078
- .editor-tree-file {
1691
+
1692
+ /* ---------- Chat status bar ----------
1693
+ *
1694
+ * Compact metric strip below the input area. Mirrors the TUI's
1695
+ * StatsPanel (model · ctx · cache · turn $ · session $ · balance) so
1696
+ * the user has the same one-glance read-out without leaving Chat.
1697
+ */
1698
+ .chat-statusbar {
2079
1699
  display: flex;
2080
- align-items: center;
2081
- gap: 4px;
2082
- font-family: var(--mono);
2083
- font-size: 11.5px;
1700
+ flex-wrap: wrap;
1701
+ gap: 16px;
1702
+ padding: 8px 4px 0;
1703
+ margin-top: 8px;
1704
+ border-top: 1px solid var(--bd);
1705
+ font-family: var(--font-mono);
1706
+ font-size: 11px;
2084
1707
  color: var(--fg-2);
2085
- cursor: pointer;
2086
- white-space: nowrap;
2087
- overflow: hidden;
2088
- text-overflow: ellipsis;
2089
- user-select: none;
2090
- border-left: 2px solid transparent;
2091
- padding-top: 3px;
2092
- padding-bottom: 3px;
2093
- padding-right: 8px;
1708
+ flex-shrink: 0;
2094
1709
  }
2095
- .editor-tree-folder:hover,
2096
- .editor-tree-file:hover {
2097
- background: var(--bg-hover);
2098
- color: var(--fg-0);
1710
+ .status-item {
1711
+ display: inline-flex;
1712
+ align-items: center;
1713
+ gap: 6px;
2099
1714
  }
2100
- .editor-tree-caret {
2101
- display: inline-block;
2102
- width: 12px;
2103
- font-size: 9px;
1715
+ .status-label {
2104
1716
  color: var(--fg-3);
2105
- flex-shrink: 0;
1717
+ font-size: 10px;
1718
+ letter-spacing: 0.06em;
1719
+ text-transform: uppercase;
2106
1720
  }
2107
- .editor-tree-name {
1721
+ .status-bar-mini {
1722
+ display: inline-block;
1723
+ width: 60px;
1724
+ height: 4px;
1725
+ background: var(--bg-input);
1726
+ border-radius: 2px;
2108
1727
  overflow: hidden;
2109
- text-overflow: ellipsis;
2110
1728
  }
2111
- .editor-tree-folder {
2112
- color: var(--fg-1);
1729
+ .status-bar-mini-fill {
1730
+ display: block;
1731
+ height: 100%;
1732
+ background: var(--gradient-rule);
2113
1733
  }
2114
- .editor-tree-file.open {
2115
- color: var(--primary);
2116
- border-left-color: var(--primary);
1734
+ .status-ok {
1735
+ color: var(--c-ok);
2117
1736
  }
2118
-
2119
- .editor-main {
2120
- flex: 1;
2121
- display: flex;
2122
- flex-direction: column;
2123
- min-width: 0;
2124
- background: #282c34;
1737
+ .status-warn {
1738
+ color: var(--c-warn);
2125
1739
  }
2126
- .editor-tabs {
1740
+ .status-err {
1741
+ color: var(--c-err);
1742
+ }
1743
+
1744
+ /* ---------- Header pickers (effort / preset / edit-mode) ----------
1745
+ *
1746
+ * Three segmented controls that flow on the chat header right side.
1747
+ * On narrow screens they wrap onto multiple rows. The `accent` variant
1748
+ * paints active segments violet (preset / effort) instead of cyan
1749
+ * (edit-mode), so the three picker groups remain visually distinct.
1750
+ */
1751
+ .header-pickers {
2127
1752
  display: flex;
2128
- align-items: stretch;
2129
- gap: 0;
2130
- background: var(--bg-1);
2131
- border-bottom: 1px solid var(--border);
2132
- overflow-x: auto;
2133
- flex-wrap: nowrap;
2134
- flex-shrink: 0;
2135
- height: 34px;
2136
- scrollbar-width: thin;
2137
- }
2138
- .editor-tabs::-webkit-scrollbar {
2139
- height: 3px;
2140
- }
2141
- .editor-tabs::-webkit-scrollbar-thumb {
2142
- background: var(--border);
1753
+ gap: 8px;
1754
+ flex-wrap: wrap;
1755
+ justify-content: flex-end;
2143
1756
  }
2144
- .editor-no-tabs {
2145
- padding: 9px 14px;
2146
- color: var(--fg-3);
2147
- font-size: 12px;
2148
- font-family: var(--mono);
1757
+
1758
+ .mode-picker {
1759
+ display: inline-flex;
1760
+ border: 1px solid var(--bd);
1761
+ border-radius: var(--r-md);
1762
+ overflow: hidden;
1763
+ background: var(--bg-elev);
2149
1764
  }
2150
- .editor-tab {
2151
- display: flex;
2152
- align-items: center;
2153
- gap: 6px;
2154
- padding: 0 10px 0 12px;
2155
- background: var(--bg-1);
1765
+ .mode-btn {
1766
+ background: transparent;
2156
1767
  border: none;
2157
- border-right: 1px solid var(--border);
2158
- border-top: 2px solid transparent;
2159
- border-bottom: 1px solid var(--border);
2160
- margin-bottom: -1px;
2161
- font-family: var(--mono);
2162
- font-size: 12px;
2163
- color: var(--fg-3);
1768
+ border-radius: 0;
1769
+ padding: 4px 12px;
1770
+ font-family: var(--font-mono);
1771
+ font-size: 11px;
1772
+ letter-spacing: 0.05em;
1773
+ text-transform: uppercase;
1774
+ color: var(--fg-2);
2164
1775
  cursor: pointer;
2165
- white-space: nowrap;
2166
- user-select: none;
2167
- height: 34px;
2168
- position: relative;
1776
+ transition: color 0.12s, background 0.12s;
2169
1777
  }
2170
- .editor-tab:hover {
2171
- color: var(--fg-1);
2172
- background: var(--bg-2);
1778
+ .mode-btn + .mode-btn {
1779
+ border-left: 1px solid var(--bd);
2173
1780
  }
2174
- .editor-tab.active {
2175
- background: #282c34;
1781
+ .mode-btn:hover {
1782
+ background: var(--bg-elev-2);
2176
1783
  color: var(--fg-0);
2177
- border-top-color: var(--primary);
2178
- border-bottom-color: #282c34;
2179
- }
2180
- .editor-tab-name {
2181
- max-width: 200px;
2182
- overflow: hidden;
2183
- text-overflow: ellipsis;
2184
1784
  }
2185
- .editor-tab-dirty {
2186
- color: var(--accent);
2187
- font-size: 14px;
2188
- line-height: 1;
2189
- width: 12px;
2190
- text-align: center;
1785
+ .mode-btn.active {
1786
+ background: var(--c-brand);
1787
+ color: var(--bg);
1788
+ font-weight: 600;
2191
1789
  }
2192
- .editor-tab-close {
2193
- margin-left: 2px;
2194
- color: var(--fg-3);
2195
- font-size: 14px;
2196
- line-height: 1;
2197
- padding: 1px 5px;
2198
- border-radius: var(--radius-sm);
2199
- width: 18px;
2200
- height: 18px;
2201
- display: inline-flex;
2202
- align-items: center;
2203
- justify-content: center;
1790
+ .mode-btn.active.accent {
1791
+ background: var(--c-accent);
1792
+ color: var(--bg);
2204
1793
  }
2205
- .editor-tab-close:hover {
2206
- background: var(--bg-3);
2207
- color: var(--err);
1794
+ .mode-btn.active.yolo {
1795
+ background: var(--c-err);
1796
+ color: var(--bg);
2208
1797
  }
2209
- .editor-bar {
1798
+
1799
+ /* ---------- Modal cards (shell / choice / plan / edit-review) ----------
1800
+ *
1801
+ * Mirrors the TUI's ModalCard shape — left-accent border in the modal
1802
+ * kind's color (red shell, magenta choice, cyan plan, green edits)
1803
+ * with an icon, title, optional subtitle, then content + actions. The
1804
+ * card sits above the chat input area, full-width within the chat
1805
+ * column. Styled minimal so it doesn't compete with conversation
1806
+ * content for attention.
1807
+ */
1808
+
1809
+ .modal-card {
1810
+ margin: 12px 0;
1811
+ background: var(--bg-elev);
1812
+ border: 1px solid var(--bd);
1813
+ border-left: 3px solid var(--c-accent);
1814
+ border-radius: var(--r-md);
1815
+ padding: 14px 16px;
2210
1816
  display: flex;
2211
- align-items: center;
1817
+ flex-direction: column;
2212
1818
  gap: 12px;
2213
- padding: 6px 12px;
2214
- background: var(--bg-1);
2215
- border-bottom: 1px solid var(--border);
2216
- flex-shrink: 0;
2217
- }
2218
- .editor-host {
2219
- flex: 1;
2220
- overflow: hidden;
2221
- background: #282c34;
2222
- border: none;
2223
- border-radius: 0;
2224
- min-height: 0;
2225
- }
2226
- .editor-host .cm-editor {
2227
- height: 100%;
2228
- font-family: var(--mono);
2229
- font-size: 13px;
2230
- outline: none;
2231
1819
  }
2232
- .editor-host .cm-editor.cm-focused {
2233
- outline: none;
1820
+
1821
+ .modal-card-head {
1822
+ display: flex;
1823
+ gap: 12px;
1824
+ align-items: flex-start;
2234
1825
  }
2235
- .editor-host .cm-scroller {
2236
- font-family: inherit;
2237
- line-height: 1.55;
1826
+
1827
+ .modal-card-icon {
1828
+ font-size: 18px;
1829
+ font-family: var(--font-mono);
1830
+ line-height: 1.4;
2238
1831
  }
2239
1832
 
2240
- /* VS Code-style gutter — darker bg, dim line numbers, accent on active */
2241
- .editor-host .cm-gutters {
2242
- background: #21252b;
2243
- border-right: 1px solid #181a1f;
2244
- color: #495162;
1833
+ .modal-card-title {
1834
+ font-size: 14px;
1835
+ font-weight: 600;
1836
+ color: var(--fg-0);
2245
1837
  }
2246
- .editor-host .cm-lineNumbers {
2247
- font-family: var(--mono);
1838
+
1839
+ .modal-card-subtitle {
2248
1840
  font-size: 12px;
2249
- min-width: 40px;
1841
+ color: var(--fg-2);
1842
+ margin-top: 2px;
2250
1843
  }
2251
- .editor-host .cm-lineNumbers .cm-gutterElement {
2252
- padding: 0 12px 0 16px;
2253
- color: #495162;
1844
+
1845
+ .modal-cmd {
1846
+ background: var(--bg-elev-2);
1847
+ border-radius: var(--r);
1848
+ padding: 8px 12px;
1849
+ font-family: var(--font-mono);
1850
+ font-size: 13px;
1851
+ overflow-x: auto;
1852
+ max-height: 240px;
1853
+ overflow-y: auto;
1854
+ white-space: pre-wrap;
1855
+ word-break: break-all;
2254
1856
  }
2255
- .editor-host .cm-activeLineGutter {
2256
- background: #2c313a;
2257
- color: #abb2bf;
1857
+ .modal-cmd-prompt {
1858
+ color: var(--fg-3);
1859
+ margin-right: 6px;
2258
1860
  }
2259
- .editor-host .cm-foldGutter {
2260
- color: #5c6370;
1861
+ .modal-cmd code {
1862
+ color: var(--c-brand);
1863
+ background: transparent;
1864
+ padding: 0;
1865
+ word-break: break-all;
2261
1866
  }
2262
- .editor-host .cm-foldGutter .cm-gutterElement {
2263
- padding: 0 4px;
2264
- cursor: pointer;
1867
+
1868
+ .modal-actions {
1869
+ display: flex;
1870
+ gap: 8px;
1871
+ flex-wrap: wrap;
2265
1872
  }
2266
- .editor-host .cm-activeLine {
2267
- background: rgba(99, 110, 123, 0.1);
1873
+
1874
+ .modal-choice-row {
1875
+ display: grid;
1876
+ grid-template-columns: 28px 1fr;
1877
+ grid-template-rows: auto auto;
1878
+ gap: 2px 12px;
1879
+ background: transparent;
1880
+ border: 1px solid var(--bd);
1881
+ border-radius: var(--r);
1882
+ padding: 8px 12px;
1883
+ text-align: left;
1884
+ cursor: pointer;
1885
+ transition: border-color 0.12s, background 0.12s;
2268
1886
  }
2269
- .editor-host .cm-selectionBackground,
2270
- .editor-host .cm-content ::selection {
2271
- background: #3e4451 !important;
1887
+ .modal-choice-row:hover {
1888
+ border-color: var(--c-accent);
1889
+ background: rgba(196, 181, 253, 0.06);
2272
1890
  }
2273
- .editor-host .cm-cursor {
2274
- border-left-color: #61afef;
2275
- border-left-width: 2px;
1891
+ .modal-choice-row.modal-choice-cancel {
1892
+ margin-top: 4px;
1893
+ border-style: dashed;
2276
1894
  }
2277
-
2278
- /* Autocomplete popup — match the dark theme */
2279
- .cm-tooltip.cm-tooltip-autocomplete {
2280
- background: #21252b;
2281
- border: 1px solid #181a1f;
2282
- border-radius: var(--radius-sm);
2283
- font-family: var(--mono);
2284
- font-size: 12px;
2285
- box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
1895
+ .modal-choice-id {
1896
+ grid-row: 1 / 3;
1897
+ align-self: center;
1898
+ font-family: var(--font-mono);
1899
+ font-size: 14px;
1900
+ color: var(--c-accent);
1901
+ font-weight: 600;
1902
+ text-align: center;
2286
1903
  }
2287
- .cm-tooltip.cm-tooltip-autocomplete > ul > li {
2288
- padding: 3px 10px;
2289
- color: #abb2bf;
1904
+ .modal-choice-title {
1905
+ color: var(--fg-0);
1906
+ font-size: 13px;
1907
+ font-weight: 500;
2290
1908
  }
2291
- .cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] {
2292
- background: var(--primary);
2293
- color: #1e2127;
1909
+ .modal-choice-summary {
1910
+ color: var(--fg-2);
1911
+ font-size: 12px;
1912
+ grid-column: 2;
2294
1913
  }
2295
- .cm-completionLabel {
2296
- font-family: var(--mono);
1914
+
1915
+ .modal-custom textarea {
1916
+ width: 100%;
1917
+ background: var(--bg-elev-2);
1918
+ border: 1px solid var(--bd);
1919
+ color: var(--fg-0);
1920
+ padding: 8px 12px;
1921
+ border-radius: var(--r);
1922
+ font-family: var(--font-mono);
1923
+ font-size: 13px;
1924
+ resize: vertical;
1925
+ min-height: 56px;
2297
1926
  }
2298
- .cm-completionDetail {
2299
- color: #5c6370;
2300
- font-style: normal;
2301
- margin-left: 8px;
1927
+
1928
+ .modal-plan-body {
1929
+ background: var(--bg-elev-2);
1930
+ border-radius: var(--r);
1931
+ padding: 12px 14px;
1932
+ max-height: 320px;
1933
+ overflow-y: auto;
2302
1934
  }
2303
1935
 
2304
- .editor-empty {
2305
- flex: 1;
2306
- display: flex;
2307
- align-items: center;
2308
- justify-content: center;
2309
- color: var(--fg-3);
2310
- font-family: var(--mono);
1936
+ /* Plan-revision modal — list of remaining steps with risk dots. */
1937
+ .modal-revise-reason {
1938
+ background: var(--bg-elev-2);
1939
+ border-left: 3px solid #c4b5fd;
1940
+ border-radius: 0 var(--r) var(--r) 0;
1941
+ padding: 8px 12px;
1942
+ color: var(--fg-1);
2311
1943
  font-size: 13px;
2312
- background: #282c34;
1944
+ white-space: pre-wrap;
2313
1945
  }
2314
-
2315
- /* Split view — left half source (CodeMirror), right half preview. */
2316
- .editor-stage {
2317
- flex: 1;
1946
+ .modal-revise-steps {
1947
+ list-style: none;
1948
+ margin: 0;
1949
+ padding: 0;
2318
1950
  display: flex;
2319
- min-height: 0;
2320
- overflow: hidden;
1951
+ flex-direction: column;
1952
+ gap: 6px;
1953
+ max-height: 280px;
1954
+ overflow-y: auto;
2321
1955
  }
2322
- .editor-stage > .editor-host,
2323
- .editor-stage > .editor-md-preview {
2324
- flex: 1;
2325
- min-width: 0;
2326
- min-height: 0;
1956
+ .modal-revise-steps li {
1957
+ display: grid;
1958
+ grid-template-columns: 12px 64px 1fr;
1959
+ grid-template-rows: auto auto;
1960
+ gap: 2px 10px;
1961
+ background: var(--bg-elev-2);
1962
+ border: 1px solid var(--bd);
1963
+ border-radius: var(--r);
1964
+ padding: 8px 12px;
1965
+ align-items: center;
1966
+ }
1967
+ .modal-revise-dot {
1968
+ grid-row: 1 / 3;
1969
+ width: 8px;
1970
+ height: 8px;
1971
+ border-radius: 50%;
1972
+ align-self: center;
1973
+ }
1974
+ .modal-revise-id {
1975
+ grid-row: 1;
1976
+ font-family: var(--font-mono);
1977
+ font-size: 12px;
1978
+ color: var(--fg-2);
2327
1979
  }
2328
- .editor-stage[data-mode="edit"] > .editor-md-preview {
2329
- display: none;
1980
+ .modal-revise-title {
1981
+ grid-row: 1;
1982
+ color: var(--fg-0);
1983
+ font-size: 13px;
1984
+ font-weight: 500;
2330
1985
  }
2331
- .editor-stage[data-mode="preview"] > .editor-host {
2332
- display: none;
1986
+ .modal-revise-action {
1987
+ grid-column: 2 / 4;
1988
+ grid-row: 2;
1989
+ color: var(--fg-2);
1990
+ font-size: 12px;
1991
+ white-space: pre-wrap;
2333
1992
  }
2334
- .editor-stage[data-mode="split"] > .editor-host + .editor-md-preview {
2335
- border-left: 1px solid #181a1f;
1993
+
1994
+ .modal-edit-preview {
1995
+ background: var(--bg-elev-2);
1996
+ border: 1px solid var(--bd);
1997
+ border-radius: var(--r);
1998
+ padding: 10px 12px;
1999
+ margin: 0;
2000
+ font-family: var(--font-mono);
2001
+ font-size: 12px;
2002
+ color: var(--fg-1);
2003
+ white-space: pre;
2004
+ overflow-x: auto;
2005
+ max-height: 200px;
2336
2006
  }
2337
2007
 
2338
- /* Segmented control for Edit / Split / Preview */
2339
- .view-mode-group {
2340
- display: inline-flex;
2341
- background: var(--bg-2);
2342
- border: 1px solid var(--border);
2343
- border-radius: var(--radius-sm);
2008
+ /* Side-by-side diff for the edit-review modal left is "before" (red
2009
+ * tint), right is "after" (green tint), context rows render unchanged.
2010
+ * Lines hljs-highlight per the file's language. */
2011
+ .edit-diff-wrap {
2012
+ border: 1px solid var(--bd);
2013
+ border-radius: var(--r);
2014
+ background: var(--bg-elev-2);
2015
+ font-family: var(--font-mono);
2016
+ font-size: 12px;
2344
2017
  overflow: hidden;
2345
- padding: 0;
2018
+ max-height: 60vh;
2019
+ display: flex;
2020
+ flex-direction: column;
2346
2021
  }
2347
- .view-mode-group .view-mode {
2348
- background: transparent;
2349
- border: none;
2350
- padding: 3px 10px;
2022
+ .edit-diff-head {
2023
+ display: flex;
2024
+ background: var(--bg-elev);
2025
+ border-bottom: 1px solid var(--bd);
2351
2026
  font-size: 11px;
2352
- font-family: var(--mono);
2027
+ text-transform: uppercase;
2028
+ letter-spacing: 0.06em;
2353
2029
  color: var(--fg-3);
2354
- cursor: pointer;
2355
- border-radius: 0;
2030
+ flex-shrink: 0;
2356
2031
  }
2357
- .view-mode-group .view-mode:hover {
2358
- color: var(--fg-1);
2359
- background: var(--bg-hover);
2032
+ .edit-diff-side {
2033
+ flex: 1;
2034
+ padding: 6px 12px;
2360
2035
  }
2361
- .view-mode-group .view-mode.active {
2362
- background: var(--primary);
2363
- color: #1e2127;
2036
+ .edit-diff-side + .edit-diff-side {
2037
+ border-left: 1px solid var(--bd);
2364
2038
  }
2365
-
2366
- /* Markdown preview — render the same .md styles used in chat,
2367
- * but with scroll and a comfortable max-width so prose doesn't
2368
- * stretch across the full editor width. */
2369
- .editor-md-preview {
2370
- overflow-y: auto;
2371
- padding: 24px 36px;
2372
- background: #282c34;
2373
- color: #abb2bf;
2374
- font-family: var(--font-sans, system-ui, sans-serif);
2375
- font-size: 14px;
2376
- line-height: 1.65;
2039
+ .edit-diff-side-old .edit-diff-marker {
2040
+ color: #f87171;
2041
+ font-weight: 700;
2042
+ margin-right: 4px;
2377
2043
  }
2378
- .editor-md-preview > *:first-child {
2379
- margin-top: 0;
2044
+ .edit-diff-side-new .edit-diff-marker {
2045
+ color: #86efac;
2046
+ font-weight: 700;
2047
+ margin-right: 4px;
2380
2048
  }
2381
- .editor-md-preview h1,
2382
- .editor-md-preview h2,
2383
- .editor-md-preview h3,
2384
- .editor-md-preview h4 {
2385
- color: #e5e9f0;
2386
- margin: 1.4em 0 0.6em;
2387
- line-height: 1.3;
2388
- }
2389
- .editor-md-preview h1 {
2390
- font-size: 1.8em;
2391
- border-bottom: 1px solid #3e4451;
2392
- padding-bottom: 0.3em;
2393
- }
2394
- .editor-md-preview h2 {
2395
- font-size: 1.4em;
2396
- border-bottom: 1px solid #3e4451;
2397
- padding-bottom: 0.3em;
2398
- }
2399
- .editor-md-preview h3 {
2400
- font-size: 1.15em;
2401
- }
2402
- .editor-md-preview a {
2403
- color: #61afef;
2404
- text-decoration: none;
2049
+ .edit-diff-body {
2050
+ flex: 1;
2051
+ overflow-y: auto;
2052
+ overflow-x: auto;
2405
2053
  }
2406
- .editor-md-preview a:hover {
2407
- text-decoration: underline;
2054
+ .edit-diff-row {
2055
+ display: flex;
2056
+ width: 100%;
2057
+ align-items: stretch;
2058
+ min-height: 19px;
2408
2059
  }
2409
- .editor-md-preview code {
2410
- background: #21252b;
2411
- color: #e06c75;
2412
- padding: 1px 6px;
2413
- border-radius: 3px;
2414
- font-family: var(--mono);
2415
- font-size: 0.92em;
2416
- }
2417
- .editor-md-preview pre {
2418
- background: #21252b;
2419
- border: 1px solid #181a1f;
2420
- border-radius: 4px;
2421
- padding: 12px 14px;
2060
+ .edit-diff-cell {
2061
+ flex: 1;
2062
+ padding: 1px 12px;
2063
+ white-space: pre;
2422
2064
  overflow-x: auto;
2065
+ border-right: 1px solid var(--bd);
2066
+ color: var(--fg-1);
2067
+ line-height: 1.55;
2423
2068
  }
2424
- .editor-md-preview pre code {
2425
- background: transparent;
2426
- color: #abb2bf;
2427
- padding: 0;
2428
- }
2429
- .editor-md-preview blockquote {
2430
- border-left: 3px solid #5c6370;
2431
- margin: 0.8em 0;
2432
- padding: 0.2em 0.9em;
2433
- color: #828997;
2069
+ .edit-diff-cell:last-child {
2070
+ border-right: none;
2434
2071
  }
2435
- .editor-md-preview table {
2436
- border-collapse: collapse;
2437
- margin: 0.8em 0;
2072
+ .edit-diff-row-context .edit-diff-cell {
2073
+ background: transparent;
2074
+ color: var(--fg-2);
2438
2075
  }
2439
- .editor-md-preview th,
2440
- .editor-md-preview td {
2441
- border: 1px solid #3e4451;
2442
- padding: 5px 10px;
2076
+ .edit-diff-row-del .edit-diff-cell-old,
2077
+ .edit-diff-row-change .edit-diff-cell-old {
2078
+ background: rgba(248, 113, 113, 0.12);
2079
+ border-left: 2px solid #f87171;
2080
+ padding-left: 10px;
2443
2081
  }
2444
- .editor-md-preview th {
2445
- background: #21252b;
2082
+ .edit-diff-row-ins .edit-diff-cell-new,
2083
+ .edit-diff-row-change .edit-diff-cell-new {
2084
+ background: rgba(134, 239, 172, 0.12);
2085
+ border-left: 2px solid #86efac;
2086
+ padding-left: 10px;
2446
2087
  }
2447
- .editor-md-preview hr {
2448
- border: none;
2449
- border-top: 1px solid #3e4451;
2450
- margin: 1.5em 0;
2088
+ .edit-diff-cell-old .edit-diff-empty,
2089
+ .edit-diff-cell-new .edit-diff-empty {
2090
+ display: inline-block;
2091
+ width: 1px;
2451
2092
  }
2452
- .editor-md-preview ul,
2453
- .editor-md-preview ol {
2454
- padding-left: 1.6em;
2093
+ .edit-diff-row-del .edit-diff-cell-new,
2094
+ .edit-diff-row-ins .edit-diff-cell-old {
2095
+ background: var(--bg-input);
2096
+ opacity: 0.5;
2455
2097
  }
2456
- .editor-md-preview img {
2457
- max-width: 100%;
2098
+ .edit-diff-line {
2099
+ font-family: var(--font-mono);
2458
2100
  }
2459
2101
 
2460
2102
  @media (max-width: 800px) {
2461
- .editor-shell {
2462
- height: calc(100vh - 100px);
2463
- }
2464
- .editor-body {
2103
+ .edit-diff-row {
2465
2104
  flex-direction: column;
2466
2105
  }
2467
- .editor-side {
2468
- width: 100%;
2469
- max-height: 200px;
2106
+ .edit-diff-cell {
2470
2107
  border-right: none;
2471
- border-bottom: 1px solid var(--border);
2108
+ border-bottom: 1px solid var(--bd);
2472
2109
  }
2473
- .editor-side.collapsed {
2474
- width: 100%;
2475
- max-height: 32px;
2110
+ .edit-diff-head {
2111
+ flex-direction: column;
2112
+ }
2113
+ .edit-diff-side + .edit-diff-side {
2114
+ border-left: none;
2115
+ border-top: 1px solid var(--bd);
2476
2116
  }
2477
2117
  }
2478
2118
 
2479
- /* ---------- Bars / charts ---------- */
2480
-
2481
- .bar {
2482
- background: var(--bg-3);
2483
- border-radius: var(--radius-sm);
2484
- overflow: hidden;
2485
- height: 8px;
2486
- position: relative;
2487
- }
2488
-
2489
- .bar > .fill {
2490
- height: 100%;
2491
- background: var(--gradient-rule);
2492
- }
2493
-
2494
- .spinner {
2495
- display: inline-block;
2496
- width: 12px;
2497
- height: 12px;
2498
- border: 2px solid var(--border);
2499
- border-top-color: var(--primary);
2500
- border-radius: 50%;
2501
- animation: spin 0.8s linear infinite;
2502
- vertical-align: middle;
2119
+ .muted {
2120
+ color: var(--fg-3);
2503
2121
  }
2504
2122
 
2505
- @keyframes spin {
2506
- to {
2507
- transform: rotate(360deg);
2508
- }
2123
+ /* ---------- Toast ----------
2124
+ * Ephemeral notifications stacked bottom-right of the viewport. Fired
2125
+ * by save / network success paths instead of inline banners that push
2126
+ * the form around. Auto-dismiss after 3 seconds. */
2127
+ .toast-stack {
2128
+ position: fixed;
2129
+ bottom: 20px;
2130
+ right: 20px;
2131
+ display: flex;
2132
+ flex-direction: column;
2133
+ gap: 8px;
2134
+ z-index: 50;
2135
+ pointer-events: none;
2509
2136
  }
2510
-
2511
- /* ---------- Notice / banners ---------- */
2512
-
2513
- .notice {
2137
+ .toast {
2138
+ pointer-events: auto;
2139
+ background: var(--bg-elev);
2140
+ border: 1px solid var(--bd);
2141
+ border-left: 3px solid var(--c-ok);
2142
+ border-radius: var(--r-md);
2514
2143
  padding: 10px 14px;
2515
- border-radius: var(--radius-md);
2516
- border-left: 3px solid var(--accent);
2517
- background: rgba(196, 181, 253, 0.06);
2518
- margin-bottom: 16px;
2519
2144
  font-size: 13px;
2520
- color: var(--fg-1);
2521
- }
2522
-
2523
- .notice.warn {
2524
- border-left-color: var(--warn);
2525
- background: rgba(251, 191, 36, 0.05);
2145
+ color: var(--fg-0);
2146
+ font-family: var(--font-sans);
2147
+ min-width: 200px;
2148
+ max-width: 360px;
2149
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
2150
+ animation: toast-slide-in 0.18s ease-out;
2526
2151
  }
2527
-
2528
- .notice.err {
2529
- border-left-color: var(--err);
2530
- background: rgba(248, 113, 113, 0.05);
2531
- color: var(--err);
2152
+ .toast.warn {
2153
+ border-left-color: var(--c-warn);
2532
2154
  }
2533
-
2534
- /* ---------- Code-ish inline ---------- */
2535
-
2536
- code,
2537
- .mono {
2538
- font-family: var(--mono);
2539
- background: var(--bg-2);
2540
- padding: 1px 6px;
2541
- border-radius: var(--radius-sm);
2542
- font-size: 12px;
2543
- color: var(--primary);
2155
+ .toast.err {
2156
+ border-left-color: var(--c-err);
2544
2157
  }
2545
-
2546
- /* ---------- Empty state ---------- */
2547
-
2548
- .empty {
2549
- padding: 28px;
2550
- text-align: center;
2551
- color: var(--fg-3);
2552
- font-family: var(--mono);
2553
- font-size: 13px;
2554
- border: 1px dashed var(--border);
2555
- border-radius: var(--radius-md);
2158
+ .toast.info {
2159
+ border-left-color: var(--c-accent);
2556
2160
  }
2557
2161
 
2558
- /* ---------- Excludes settings (Semantic tab) ---------- */
2559
-
2560
- .excludes-toggle {
2561
- margin: 24px 0 12px;
2162
+ /* ---------- Error overlay ----------
2163
+ *
2164
+ * Full-screen modal triggered by uncaught exceptions / promise
2165
+ * rejections / Preact render errors. The TUI is unaffected — this
2166
+ * only blocks the browser tab. Includes "Copy details" + a GitHub
2167
+ * issue link prefilled with redacted environment info.
2168
+ */
2169
+ .error-overlay {
2170
+ position: fixed;
2171
+ inset: 0;
2172
+ background: rgba(10, 14, 20, 0.85);
2173
+ backdrop-filter: blur(4px);
2562
2174
  display: flex;
2563
- align-items: baseline;
2564
- gap: 10px;
2565
- cursor: pointer;
2566
- user-select: none;
2567
- }
2568
- .excludes-toggle:hover {
2569
- color: var(--primary);
2570
- }
2571
- .excludes-toggle .caret {
2572
- font-size: 11px;
2573
- color: var(--fg-3);
2574
- width: 10px;
2575
- display: inline-block;
2576
- }
2577
- .excludes-toggle .label {
2578
- font-size: 11px;
2579
- letter-spacing: 0.1em;
2580
- text-transform: uppercase;
2581
- color: var(--fg-3);
2582
- }
2583
- .excludes-toggle:hover .label,
2584
- .excludes-toggle:hover .caret {
2585
- color: var(--primary);
2175
+ align-items: center;
2176
+ justify-content: center;
2177
+ padding: 32px;
2178
+ z-index: 100;
2179
+ animation: fade-in 0.18s ease-out;
2586
2180
  }
2587
- .excludes-toggle .hint {
2588
- font-size: 12px;
2589
- color: var(--fg-3);
2590
- font-weight: normal;
2181
+ .error-overlay-card {
2182
+ max-width: 720px;
2183
+ width: 100%;
2184
+ max-height: 85vh;
2185
+ overflow-y: auto;
2186
+ background: var(--bg-elev);
2187
+ border: 1px solid var(--c-err);
2188
+ border-left: 4px solid var(--c-err);
2189
+ border-radius: var(--r-md);
2190
+ padding: 22px 26px;
2191
+ box-shadow: 0 12px 60px rgba(248, 113, 113, 0.18);
2591
2192
  }
2592
-
2593
- .excludes-card {
2594
- font-size: 13px;
2193
+ .error-overlay-head {
2595
2194
  display: flex;
2596
- flex-direction: column;
2597
- gap: 12px;
2195
+ gap: 14px;
2196
+ align-items: flex-start;
2197
+ margin-bottom: 16px;
2598
2198
  }
2599
- .excludes-card .lead {
2600
- color: var(--fg-2);
2601
- font-size: 12px;
2602
- line-height: 1.5;
2199
+ .error-overlay-icon {
2200
+ color: var(--c-err);
2201
+ font-size: 22px;
2202
+ font-weight: 700;
2603
2203
  }
2604
- .excludes-grid {
2605
- display: grid;
2606
- grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
2607
- gap: 14px;
2204
+ .error-overlay-title {
2205
+ font-size: 16px;
2206
+ font-weight: 600;
2207
+ color: var(--fg-0);
2608
2208
  }
2609
- .excludes-field label {
2610
- display: block;
2611
- font-size: 12px;
2209
+ .error-overlay-subtitle {
2210
+ font-size: 13px;
2612
2211
  color: var(--fg-2);
2613
- margin-bottom: 4px;
2614
- font-weight: 500;
2615
- }
2616
- .excludes-field textarea {
2617
- min-height: 90px;
2212
+ font-family: var(--font-mono);
2213
+ margin-top: 4px;
2214
+ word-break: break-word;
2618
2215
  }
2619
- .excludes-options {
2620
- display: flex;
2621
- flex-wrap: wrap;
2622
- gap: 18px;
2623
- align-items: center;
2624
- padding-top: 4px;
2216
+ .error-overlay-trace {
2217
+ background: var(--bg-elev-2);
2218
+ border: 1px solid var(--bd);
2219
+ border-radius: var(--r);
2220
+ padding: 12px 14px;
2221
+ font-family: var(--font-mono);
2625
2222
  font-size: 12px;
2223
+ line-height: 1.55;
2626
2224
  color: var(--fg-1);
2225
+ white-space: pre-wrap;
2226
+ word-break: break-word;
2227
+ max-height: 280px;
2228
+ overflow-y: auto;
2229
+ margin: 0 0 12px;
2627
2230
  }
2628
- .excludes-options label {
2629
- display: inline-flex;
2630
- align-items: center;
2631
- gap: 6px;
2632
- }
2633
- .excludes-options input[type="number"] {
2634
- width: 110px;
2635
- }
2636
- .excludes-actions {
2637
- display: flex;
2638
- gap: 10px;
2639
- flex-wrap: wrap;
2640
- margin-top: 4px;
2641
- }
2642
-
2643
- .excludes-preview {
2644
- margin-top: 4px;
2645
- padding-top: 12px;
2646
- border-top: 1px solid var(--border);
2231
+ .error-overlay-info {
2647
2232
  font-size: 12px;
2648
- display: flex;
2649
- flex-direction: column;
2650
- gap: 8px;
2233
+ font-family: var(--font-mono);
2234
+ color: var(--fg-2);
2235
+ margin-bottom: 12px;
2651
2236
  }
2652
- .excludes-preview .summary {
2237
+ .error-overlay-help {
2653
2238
  font-size: 13px;
2654
2239
  color: var(--fg-1);
2240
+ margin-bottom: 18px;
2241
+ line-height: 1.55;
2655
2242
  }
2656
- .excludes-preview details {
2657
- background: var(--bg-2);
2658
- border: 1px solid var(--border);
2659
- border-radius: var(--radius-sm);
2660
- padding: 6px 10px;
2661
- }
2662
- .excludes-preview details[open] {
2663
- background: var(--bg-3);
2243
+ .error-overlay-actions {
2244
+ display: flex;
2245
+ gap: 8px;
2246
+ flex-wrap: wrap;
2247
+ align-items: center;
2664
2248
  }
2665
- .excludes-preview summary {
2666
- cursor: pointer;
2249
+ .error-overlay-actions a.button {
2250
+ display: inline-block;
2251
+ text-decoration: none;
2252
+ background: var(--bg-elev-2);
2667
2253
  color: var(--fg-1);
2668
- font-weight: 500;
2669
- }
2670
- .excludes-preview summary:hover {
2671
- color: var(--primary);
2672
- }
2673
- .excludes-preview ul {
2674
- margin: 6px 0 0 16px;
2675
- padding: 0;
2676
- font-size: 11.5px;
2677
- color: var(--fg-2);
2678
- }
2679
- .excludes-preview li {
2680
- margin: 2px 0;
2254
+ border: 1px solid var(--bd);
2255
+ border-radius: var(--r);
2256
+ padding: 6px 12px;
2257
+ font-family: var(--font-sans);
2258
+ font-size: 12px;
2681
2259
  }
2682
- .excludes-preview li code {
2683
- font-size: 11.5px;
2684
- background: transparent;
2685
- padding: 0;
2686
- color: var(--fg-1);
2260
+ .error-overlay-actions a.button:hover {
2261
+ border-color: var(--c-brand);
2262
+ color: var(--c-brand);
2687
2263
  }
2688
2264
 
2689
- .skip-buckets {
2690
- margin-top: 4px;
2691
- font-size: 12px;
2692
- color: var(--fg-2);
2693
- }