@polderlabs/bizar 4.3.0 → 4.4.1

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.
Files changed (57) hide show
  1. package/bizar-dash/src/server/opencode-sdk.mjs +72 -0
  2. package/bizar-dash/src/server/routes/background.mjs +92 -0
  3. package/bizar-dash/src/server/routes/chat.mjs +300 -123
  4. package/bizar-dash/src/server/routes/opencode-session-detail.mjs +26 -0
  5. package/bizar-dash/src/server/routes/tasks.mjs +59 -1
  6. package/bizar-dash/src/server/task-delegator.mjs +154 -8
  7. package/bizar-dash/src/server/tasks-store.mjs +50 -2
  8. package/bizar-dash/src/web/components/background/AttachButton.tsx +96 -0
  9. package/bizar-dash/src/web/components/background/TmuxAttachCard.tsx +122 -0
  10. package/bizar-dash/src/web/components/chat/AgentNode.tsx +127 -0
  11. package/bizar-dash/src/web/components/chat/AgentTree.tsx +80 -0
  12. package/bizar-dash/src/web/components/chat/ChatComposer.tsx +76 -0
  13. package/bizar-dash/src/web/components/chat/ChatInfoPanel.tsx +144 -0
  14. package/bizar-dash/src/web/components/chat/ChatRail.tsx +387 -0
  15. package/bizar-dash/src/web/components/chat/ChatThread.tsx +28 -7
  16. package/bizar-dash/src/web/components/chat/JumpToLatest.tsx +58 -0
  17. package/bizar-dash/src/web/components/chat/MessageBlock.tsx +260 -0
  18. package/bizar-dash/src/web/components/chat/SessionRowMenu.tsx +206 -0
  19. package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +33 -5
  20. package/bizar-dash/src/web/components/chat/_legacy.ts +30 -0
  21. package/bizar-dash/src/web/components/chat/index.ts +11 -0
  22. package/bizar-dash/src/web/components/chat/useChat.ts +345 -167
  23. package/bizar-dash/src/web/components/tasks/BacklogPanel.css +109 -0
  24. package/bizar-dash/src/web/components/tasks/BacklogPanel.tsx +209 -0
  25. package/bizar-dash/src/web/styles/chat.css +1536 -133
  26. package/bizar-dash/src/web/views/BackgroundAgents.tsx +3 -0
  27. package/bizar-dash/src/web/views/Chat.tsx +147 -57
  28. package/bizar-dash/src/web/views/Tasks.tsx +23 -1
  29. package/cli/bg.mjs +94 -71
  30. package/cli/bin.mjs +36 -8
  31. package/cli/service-controller.mjs +587 -0
  32. package/cli/service-controller.test.mjs +92 -0
  33. package/cli/service.mjs +162 -14
  34. package/config/agents/baldr.md +2 -0
  35. package/config/agents/browser-harness.md +2 -0
  36. package/config/agents/forseti.md +2 -0
  37. package/config/agents/frigg.md +2 -0
  38. package/config/agents/heimdall.md +2 -0
  39. package/config/agents/hermod.md +2 -0
  40. package/config/agents/mimir.md +2 -0
  41. package/config/agents/odin.md +2 -0
  42. package/config/agents/quick.md +2 -0
  43. package/config/agents/semble-search.md +2 -0
  44. package/config/agents/thor.md +2 -0
  45. package/config/agents/tyr.md +2 -0
  46. package/config/agents/vidarr.md +2 -0
  47. package/config/agents/vor.md +2 -0
  48. package/config/opencode.json.template +1 -0
  49. package/install.sh +448 -787
  50. package/package.json +2 -2
  51. package/packages/sdk/package.json +20 -0
  52. package/packages/sdk/src/client.ts +5 -0
  53. package/packages/sdk/src/errors.ts +11 -2
  54. package/packages/sdk/src/index.ts +19 -0
  55. package/packages/sdk/src/opencode-events.ts +134 -0
  56. package/packages/sdk/src/opencode-types.ts +66 -0
  57. package/packages/sdk/src/opencode.ts +335 -0
@@ -1,198 +1,1601 @@
1
1
  /* =====================================================================
2
- Chat UI — desktop + responsive (v3.21.x Gemini-inspired)
2
+ Chat UI — desktop redesign (v3.22)
3
+ =====================================================================
4
+ Ports the visual design from
5
+ open-design/.od/projects/ea47b7b3-9f17-41f4-871e-0c5b4c7114df/index.html
6
+ into the dashboard. Token vars are mapped to the project's existing
7
+ palette (`--bg` == `--surface-0`, `--bg-1` == `--surface-1`,
8
+ `--bg-2` == `--surface-2`, etc.) — every new rule uses the project's
9
+ token vars, never hard-coded colors.
10
+
11
+ The new layout is a 3-column grid:
12
+ ┌──────────┬──────────────────────────────┬──────────┐
13
+ │ rail │ thread │ info │
14
+ │ 280px │ 1fr │ 300px │
15
+ └──────────┴──────────────────────────────┴──────────┘
16
+
17
+ The legacy 2-column wrapper (`.chat-shell > .chat-body > chat-sessions
18
+ | chat-main | chat-info`) is kept at the bottom of the file so the
19
+ mobile view continues to render without changes.
3
20
  ===================================================================== */
4
21
 
5
- /* Shell + topbar */
22
+ /* -------- page-level layout (3-column) -------- */
23
+ .chat-page {
24
+ display: grid;
25
+ grid-template-columns: 280px 1fr 300px;
26
+ height: 100%;
27
+ background: var(--bg);
28
+ color: var(--text);
29
+ min-height: 0;
30
+ }
31
+
32
+ @media (max-width: 1280px) {
33
+ .chat-page { grid-template-columns: 240px 1fr 260px; }
34
+ }
35
+ @media (max-width: 1024px) {
36
+ .chat-page { grid-template-columns: 220px 1fr; }
37
+ .chat-page .chat-info { display: none; }
38
+ }
39
+ @media (max-width: 768px) {
40
+ .chat-page { grid-template-columns: 1fr; }
41
+ .chat-page .chat-rail { display: none; }
42
+ }
43
+
44
+ /* ============================================================
45
+ SESSION RAIL
46
+ ============================================================ */
47
+ .chat-rail {
48
+ display: flex; flex-direction: column;
49
+ border-right: 1px solid var(--border);
50
+ background: var(--bg);
51
+ overflow: hidden;
52
+ min-height: 0;
53
+ }
54
+ .chat-rail-head {
55
+ padding: var(--space-3);
56
+ border-bottom: 1px solid var(--border);
57
+ flex-shrink: 0;
58
+ }
59
+ .chat-new-btn {
60
+ display: flex; align-items: center; justify-content: center; gap: 6px;
61
+ width: 100%;
62
+ padding: 8px 12px;
63
+ background: var(--bg-1);
64
+ border: 1px solid var(--border);
65
+ border-radius: var(--radius-md);
66
+ color: var(--text);
67
+ font: 13px/1 var(--font-sans);
68
+ cursor: pointer;
69
+ transition: border-color var(--motion-fast) var(--motion-ease);
70
+ }
71
+ .chat-new-btn:hover { border-color: var(--border-strong); }
72
+ .chat-new-btn:focus-visible {
73
+ outline: 1px solid var(--accent);
74
+ outline-offset: 1px;
75
+ }
76
+ .chat-new-btn:disabled { opacity: 0.4; cursor: not-allowed; }
77
+
78
+ .chat-rail-list {
79
+ flex: 1; overflow-y: auto;
80
+ padding: var(--space-2) var(--space-2) var(--space-6);
81
+ min-height: 0;
82
+ }
83
+ .chat-rail-group { margin-bottom: var(--space-4); }
84
+ .chat-rail-group-label {
85
+ padding: var(--space-2) var(--space-3);
86
+ font: 10px/1 var(--font-mono);
87
+ letter-spacing: 0.08em;
88
+ text-transform: uppercase;
89
+ color: var(--text-muted);
90
+ }
91
+
92
+ /* -------- rail row -------- */
93
+ .chat-rail-item {
94
+ position: relative;
95
+ display: block; width: 100%;
96
+ padding: 8px 10px 8px 18px;
97
+ background: transparent;
98
+ border: 1px solid transparent;
99
+ border-radius: var(--radius-md);
100
+ color: var(--text);
101
+ text-align: left;
102
+ cursor: pointer;
103
+ margin-bottom: 2px;
104
+ font: inherit;
105
+ transition: background var(--motion-fast) var(--motion-ease);
106
+ }
107
+ .chat-rail-item:hover { background: var(--bg-1); }
108
+ .chat-rail-item.active {
109
+ background: var(--bg-1);
110
+ border-color: var(--border);
111
+ }
112
+ .chat-rail-item-title {
113
+ font: 13px/1.4 var(--font-sans);
114
+ display: flex; align-items: center; gap: 6px;
115
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
116
+ /* FIX #2 — leave room for the 3-dot trigger (top-right) so the title
117
+ can never collide with it. The chevron column (also on the right)
118
+ only appears on the active row, see .chat-rail-tree-chevron below. */
119
+ padding-right: 30px;
120
+ }
121
+ .chat-rail-pin { color: var(--text-muted); font-size: 11px; flex-shrink: 0; }
122
+
123
+ /* FIX #2 — notification badge lives on the meta row (bottom), pinned
124
+ right-aligned. Title never gets pushed. Meta row reserves fixed
125
+ width on the right for the badge + chevron. */
126
+ .chat-rail-item-meta {
127
+ display: flex; align-items: center; justify-content: space-between;
128
+ margin-top: 4px;
129
+ padding-right: 38px; /* clear chevron column when active */
130
+ font: 11px/1 var(--font-mono);
131
+ color: var(--text-muted);
132
+ min-height: 16px;
133
+ }
134
+ .chat-rail-item-meta-time {
135
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
136
+ }
137
+ .chat-rail-badge {
138
+ display: inline-grid; place-items: center;
139
+ min-width: 16px; height: 16px; padding: 0 5px;
140
+ background: var(--accent);
141
+ color: white;
142
+ border-radius: 999px;
143
+ font: 10px/1 var(--font-mono);
144
+ flex-shrink: 0;
145
+ animation: chat-rail-badge-pulse 2.4s var(--motion-ease) infinite;
146
+ }
147
+ @keyframes chat-rail-badge-pulse {
148
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0.4); }
149
+ 50% { box-shadow: 0 0 0 4px rgba(139, 92, 246, 0); }
150
+ }
151
+
152
+ /* -------- state-encoded row -------- */
153
+ .chat-rail-item.state-streaming { color: var(--accent); }
154
+ .chat-rail-item.state-awaiting { color: var(--warning); }
155
+ .chat-rail-item.state-streaming .chat-rail-item-title {
156
+ color: var(--accent);
157
+ font-weight: 500;
158
+ }
159
+ .chat-rail-item.state-awaiting .chat-rail-item-title {
160
+ color: var(--text);
161
+ font-weight: 400;
162
+ }
163
+
164
+ /* -------- status dot (left edge of row) -------- */
165
+ .session-state {
166
+ position: absolute;
167
+ left: 4px; top: 50%;
168
+ transform: translateY(-50%);
169
+ border-radius: 50%;
170
+ }
171
+ .session-state-idle {
172
+ width: 6px; height: 6px;
173
+ background: var(--border);
174
+ opacity: 0.6;
175
+ }
176
+ .session-state-awaiting {
177
+ width: 6px; height: 6px;
178
+ background: var(--warning);
179
+ animation: awaiting-pulse 2s var(--motion-ease) infinite;
180
+ }
181
+ @keyframes awaiting-pulse {
182
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(251, 191, 36, 0.4); }
183
+ 50% { box-shadow: 0 0 0 5px rgba(251, 191, 36, 0); }
184
+ }
185
+ .session-state-streaming {
186
+ width: 6px; height: 6px;
187
+ background: var(--accent);
188
+ animation: rail-stream-pulse 1.4s var(--motion-ease) infinite;
189
+ }
190
+ @keyframes rail-stream-pulse {
191
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0.5); transform: scale(1); }
192
+ 50% { box-shadow: 0 0 0 5px rgba(139, 92, 246, 0); transform: scale(1.15); }
193
+ }
194
+
195
+ /* ============================================================
196
+ FIX #2 — 3-dot trigger + collapse chevron positioning
197
+ ============================================================
198
+ The two affordances sit on the right side of the row but never
199
+ overlap because:
200
+ - 3-dot trigger: position: absolute; top: 6px; right: 6px;
201
+ (square 22×22 cell at the top-right corner)
202
+ - collapse chevron: position: absolute; top: 50%; right: 28px;
203
+ transform: translateY(-50%); (square 18×18 cell VERTICALLY
204
+ centered in the row, sitting 22px to the LEFT of the 3-dot
205
+ trigger's left edge — they never overlap)
206
+ ============================================================ */
207
+ .chat-rail-item-menu-trigger {
208
+ position: absolute;
209
+ top: 6px; right: 6px;
210
+ width: 22px; height: 22px;
211
+ display: inline-grid; place-items: center;
212
+ background: transparent;
213
+ border: 0;
214
+ border-radius: var(--radius-sm);
215
+ color: var(--text-muted);
216
+ cursor: pointer;
217
+ opacity: 0;
218
+ transition: opacity var(--motion-fast) var(--motion-ease),
219
+ background var(--motion-fast) var(--motion-ease),
220
+ color var(--motion-fast) var(--motion-ease);
221
+ z-index: 3;
222
+ }
223
+ .chat-rail-item:hover .chat-rail-item-menu-trigger,
224
+ .chat-rail-item:focus-within .chat-rail-item-menu-trigger,
225
+ .chat-rail-item-menu-trigger.open { opacity: 1; }
226
+ .chat-rail-item-menu-trigger:hover {
227
+ background: var(--bg-2);
228
+ color: var(--text);
229
+ }
230
+ .chat-rail-item-menu-trigger:focus-visible {
231
+ outline: 1px solid var(--accent);
232
+ outline-offset: 1px;
233
+ }
234
+ .chat-rail-item-menu-trigger svg { width: 14px; height: 14px; }
235
+
236
+ /* Collapse chevron — only on the ACTIVE row, and only when the row
237
+ has children. Right: 28px puts it to the LEFT of the 3-dot trigger
238
+ (which is 22px wide and starts at right: 6px → 28px is its left
239
+ edge). Vertical center via translateY(-50%). */
240
+ .chat-rail-item .chat-rail-tree-chevron {
241
+ position: absolute;
242
+ top: 50%;
243
+ right: 28px;
244
+ width: 18px; height: 18px;
245
+ display: inline-grid; place-items: center;
246
+ background: transparent;
247
+ border: 0;
248
+ border-radius: var(--radius-sm);
249
+ color: var(--text-muted);
250
+ cursor: pointer;
251
+ opacity: 0;
252
+ transform: translateY(-50%) rotate(0deg);
253
+ transform-origin: 50% 50%;
254
+ transition: opacity var(--motion-fast) var(--motion-ease),
255
+ transform var(--motion-fast) var(--motion-ease),
256
+ color var(--motion-fast) var(--motion-ease),
257
+ background var(--motion-fast) var(--motion-ease);
258
+ z-index: 2;
259
+ }
260
+ .chat-rail-item:hover .chat-rail-tree-chevron,
261
+ .chat-rail-item:focus-within .chat-rail-tree-chevron { opacity: 1; }
262
+ .chat-rail-item .chat-rail-tree-chevron.open {
263
+ transform: translateY(-50%) rotate(90deg);
264
+ opacity: 1; /* stay visible when tree is open so user can re-collapse */
265
+ }
266
+ .chat-rail-item .chat-rail-tree-chevron:hover {
267
+ background: var(--bg-2);
268
+ color: var(--text);
269
+ }
270
+ .chat-rail-item .chat-rail-tree-chevron:focus-visible {
271
+ outline: 1px solid var(--accent);
272
+ outline-offset: 1px;
273
+ }
274
+ .chat-rail-item .chat-rail-tree-chevron svg {
275
+ width: 10px; height: 10px;
276
+ stroke: currentColor; stroke-width: 1.6; fill: none;
277
+ stroke-linecap: round; stroke-linejoin: round;
278
+ }
279
+
280
+ /* ============================================================
281
+ SESSION ROW MENU (popover — three modes)
282
+ ============================================================ */
283
+ .session-row-menu {
284
+ position: absolute;
285
+ top: calc(100% + 2px);
286
+ right: 0;
287
+ min-width: 180px;
288
+ background: var(--bg-1);
289
+ border: 1px solid var(--border);
290
+ border-radius: var(--radius-md);
291
+ padding: 4px;
292
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
293
+ z-index: 50;
294
+ animation: session-menu-in var(--motion-base) var(--motion-ease);
295
+ }
296
+ @keyframes session-menu-in {
297
+ from { opacity: 0; transform: translateY(-4px); }
298
+ to { opacity: 1; transform: none; }
299
+ }
300
+ .session-row-menu-item {
301
+ display: flex; align-items: center; gap: 8px;
302
+ width: 100%;
303
+ padding: 6px 10px;
304
+ background: transparent;
305
+ border: 0;
306
+ border-radius: var(--radius-sm);
307
+ color: var(--text);
308
+ font: 12px/1 var(--font-sans);
309
+ text-align: left;
310
+ cursor: pointer;
311
+ transition: background var(--motion-fast) var(--motion-ease),
312
+ color var(--motion-fast) var(--motion-ease);
313
+ }
314
+ .session-row-menu-item:hover {
315
+ background: var(--bg-2);
316
+ color: var(--text);
317
+ }
318
+ .session-row-menu-item svg {
319
+ width: 13px; height: 13px;
320
+ flex-shrink: 0;
321
+ color: var(--text-muted);
322
+ }
323
+ .session-row-menu-item:hover svg { color: var(--text); }
324
+ .session-row-menu-item kbd {
325
+ margin-left: auto;
326
+ font: 10px/1 var(--font-mono);
327
+ padding: 2px 5px;
328
+ background: var(--bg-2);
329
+ border: 1px solid var(--border);
330
+ border-radius: 3px;
331
+ color: var(--text-muted);
332
+ }
333
+ .session-row-menu-item-danger:hover { color: var(--error); }
334
+ .session-row-menu-item-danger:hover svg { color: var(--error); }
335
+
336
+ .session-row-menu-inline {
337
+ padding: 8px 10px 10px;
338
+ min-width: 220px;
339
+ }
340
+ .session-row-menu-inline-label {
341
+ font: 10px/1 var(--font-mono);
342
+ text-transform: uppercase;
343
+ letter-spacing: 0.06em;
344
+ color: var(--text-muted);
345
+ margin-bottom: 8px;
346
+ }
347
+ .session-row-menu-inline-message {
348
+ font: 12px/1.4 var(--font-sans);
349
+ color: var(--text-muted);
350
+ margin-bottom: 10px;
351
+ }
352
+ .session-row-menu-input {
353
+ width: 100%;
354
+ padding: 6px 8px;
355
+ background: var(--bg);
356
+ border: 1px solid var(--border);
357
+ border-radius: var(--radius-sm);
358
+ color: var(--text);
359
+ font: 12px/1.4 var(--font-sans);
360
+ outline: 0;
361
+ margin-bottom: 8px;
362
+ }
363
+ .session-row-menu-input:focus { border-color: var(--accent); }
364
+ .session-row-menu-inline-actions {
365
+ display: flex; justify-content: flex-end; gap: 6px;
366
+ }
367
+ .session-row-menu-inline-actions button {
368
+ font-size: 11px;
369
+ padding: 4px 10px;
370
+ }
371
+
372
+ /* ============================================================
373
+ AGENT ORCHESTRATION TREE (sub-agent cards hanging off the row)
374
+ ============================================================ */
375
+ .agent-tree {
376
+ border-bottom: 1px solid var(--border);
377
+ background: rgba(255, 255, 255, 0.01);
378
+ }
379
+ .agent-tree-empty {
380
+ padding: 6px var(--space-3);
381
+ font: 12px/1 var(--font-sans);
382
+ }
383
+
384
+ .agent-node {
385
+ position: relative;
386
+ margin-bottom: 8px;
387
+ }
388
+ .agent-node:last-child { margin-bottom: 0; }
389
+ .agent-node-head {
390
+ display: flex; align-items: center; gap: 8px;
391
+ width: 100%;
392
+ padding: 8px 12px;
393
+ background: var(--bg-1);
394
+ border: 1px solid var(--border);
395
+ border-radius: var(--radius-md);
396
+ color: var(--text);
397
+ font: 13px/1 var(--font-sans);
398
+ text-align: left;
399
+ cursor: pointer;
400
+ transition: border-color var(--motion-fast) var(--motion-ease),
401
+ background var(--motion-fast) var(--motion-ease);
402
+ position: relative;
403
+ }
404
+ .agent-node-head:hover { border-color: var(--border-strong); }
405
+ .agent-node-head:focus-visible {
406
+ outline: 1px solid var(--accent);
407
+ outline-offset: 1px;
408
+ }
409
+ .agent-node.depth-0 > .agent-node-head {
410
+ padding: 10px 14px;
411
+ font-size: 14px;
412
+ }
413
+ .agent-node.depth-1 > .agent-node-head {
414
+ margin-left: 16px;
415
+ width: calc(100% - 16px);
416
+ }
417
+
418
+ .agent-node-children {
419
+ position: relative;
420
+ padding-top: 8px;
421
+ padding-left: 0;
422
+ margin-left: 14px;
423
+ }
424
+ .agent-node-children::before {
425
+ content: '';
426
+ position: absolute;
427
+ left: 0; top: 0; bottom: 12px;
428
+ width: 1px;
429
+ background: var(--border);
430
+ }
431
+ .agent-node.depth-0 > .agent-node-children::before { left: 6px; }
432
+ .agent-node-head::before {
433
+ content: '';
434
+ position: absolute;
435
+ left: -14px; top: 50%;
436
+ width: 14px; height: 1px;
437
+ background: var(--border);
438
+ }
439
+ .agent-node.depth-0 > .agent-node-head::before {
440
+ left: -8px;
441
+ width: 8px;
442
+ }
443
+
444
+ .agent-node-summary {
445
+ margin: 8px 0 0;
446
+ padding: 8px 12px 10px 30px;
447
+ font: 12px/1.5 var(--font-sans);
448
+ color: var(--text-muted);
449
+ border-left: 1px solid var(--border);
450
+ margin-left: 14px;
451
+ }
452
+ .agent-node.depth-0 > .agent-node-summary {
453
+ margin-left: 6px;
454
+ border-left-color: var(--accent);
455
+ border-left-width: 2px;
456
+ padding-left: 14px;
457
+ background: linear-gradient(180deg, rgba(139, 92, 246, 0.04), transparent);
458
+ }
459
+
460
+ .agent-node-chevron {
461
+ display: inline-grid; place-items: center;
462
+ width: 14px; height: 14px;
463
+ background: transparent;
464
+ border: 0;
465
+ color: var(--text-muted);
466
+ font: 10px/1 var(--font-mono);
467
+ cursor: pointer;
468
+ transition: transform var(--motion-fast) var(--motion-ease),
469
+ color var(--motion-fast) var(--motion-ease);
470
+ }
471
+ .agent-node.depth-0 > .agent-node-head .agent-node-chevron {
472
+ width: 18px; height: 18px;
473
+ font-size: 11px;
474
+ }
475
+ .agent-node-chevron.open { transform: rotate(90deg); }
476
+
477
+ .agent-node-dot {
478
+ width: 6px; height: 6px;
479
+ border-radius: 50%;
480
+ background: var(--text-muted);
481
+ flex-shrink: 0;
482
+ }
483
+ .agent-node-dot.status-streaming {
484
+ background: var(--accent);
485
+ box-shadow: 0 0 4px var(--accent);
486
+ }
487
+ .agent-node-dot.status-done { background: var(--success); }
488
+ .agent-node-dot.status-blocked { background: var(--warning); }
489
+ .agent-node-dot.status-awaiting { background: var(--warning); }
490
+ .agent-node-dot.status-idle { background: var(--text-muted); opacity: 0.5; }
491
+
492
+ .agent-node-name {
493
+ font-weight: 500;
494
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
495
+ }
496
+ .agent-node.depth-0 > .agent-node-head .agent-node-name { font-weight: 600; }
497
+ .agent-node-role {
498
+ font-size: 11px;
499
+ color: var(--text-muted);
500
+ letter-spacing: 0.02em;
501
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
502
+ }
503
+ .agent-node-pill {
504
+ margin-left: auto;
505
+ font: 10px/1 var(--font-mono);
506
+ padding: 3px 8px;
507
+ border-radius: var(--radius-pill);
508
+ letter-spacing: 0.04em;
509
+ text-transform: uppercase;
510
+ background: var(--bg-2);
511
+ color: var(--text-muted);
512
+ border: 1px solid var(--border);
513
+ white-space: nowrap;
514
+ }
515
+ .agent-node-pill.status-streaming {
516
+ color: var(--accent);
517
+ border-color: var(--accent);
518
+ background: rgba(139, 92, 246, 0.08);
519
+ }
520
+ .agent-node-pill.status-done { color: var(--success); border-color: var(--success); background: rgba(167, 196, 115, 0.06); }
521
+ .agent-node-pill.status-blocked { color: var(--warning); border-color: var(--warning); background: rgba(251, 191, 36, 0.06); }
522
+ .agent-node-pill.status-awaiting{ color: var(--warning); border-color: var(--warning); background: rgba(251, 191, 36, 0.06); }
523
+ .agent-node-pill.status-idle { color: var(--text-muted); }
524
+
525
+ .agent-node.closed > .agent-node-children,
526
+ .agent-node.closed > .agent-node-summary { display: none; }
527
+ .agent-node.closed > .agent-node-head { border-style: dashed; }
528
+
529
+ /* Rail variant — tighter cards. Used by SubAgentList hanging off the
530
+ active rail row. */
531
+ .agent-tree.variant-rail {
532
+ background: rgba(139, 92, 246, 0.04);
533
+ border: 1px solid rgba(139, 92, 246, 0.18);
534
+ border-radius: var(--radius-md);
535
+ padding: 0;
536
+ margin: 0 4px 4px;
537
+ animation: tree-rail-in var(--motion-base) var(--motion-ease);
538
+ }
539
+ @keyframes tree-rail-in {
540
+ from { opacity: 0; transform: translateY(-4px); }
541
+ to { opacity: 1; transform: none; }
542
+ }
543
+ .agent-tree.variant-rail .agent-node { margin-bottom: 4px; }
544
+ .agent-tree.variant-rail .agent-node-head {
545
+ padding: 5px 8px;
546
+ font-size: 11px;
547
+ border-radius: var(--radius-sm);
548
+ }
549
+ .agent-tree.variant-rail .agent-node.depth-0 > .agent-node-head {
550
+ padding: 6px 10px;
551
+ font-size: 12px;
552
+ }
553
+ .agent-tree.variant-rail .agent-node.depth-1 > .agent-node-head {
554
+ margin-left: 10px;
555
+ width: calc(100% - 10px);
556
+ }
557
+ .agent-tree.variant-rail .agent-node-children { margin-left: 8px; padding-top: 4px; }
558
+ .agent-tree.variant-rail .agent-node-children::before { left: 0; bottom: 6px; }
559
+ .agent-tree.variant-rail .agent-node-head::before { left: -8px; width: 8px; }
560
+ .agent-tree.variant-rail .agent-node-name { font-size: 11px; }
561
+ .agent-tree.variant-rail .agent-node-role { font-size: 10px; }
562
+ .agent-tree.variant-rail .agent-node-pill { font-size: 9px; padding: 2px 6px; }
563
+ .agent-tree.variant-rail .agent-node-summary { display: none; }
564
+ .agent-tree.variant-rail .agent-node-chevron {
565
+ width: 12px; height: 12px;
566
+ font-size: 9px;
567
+ }
568
+ .agent-tree-empty.variant-rail { padding: 8px 10px; font-size: 11px; }
569
+
570
+ /* ============================================================
571
+ THREAD
572
+ ============================================================ */
573
+ .chat-thread-section {
574
+ display: grid;
575
+ grid-template-rows: auto 1fr auto;
576
+ min-width: 0;
577
+ background: var(--bg);
578
+ min-height: 0;
579
+ position: relative;
580
+ }
581
+ /* legacy class kept for the legacy ChatThread component which wraps
582
+ its content in <div className="chat-thread">. */
583
+ .chat-thread.legacy {
584
+ display: flex;
585
+ flex-direction: column;
586
+ gap: 1rem;
587
+ }
588
+ .chat-thread-head {
589
+ display: flex; align-items: center; justify-content: space-between;
590
+ padding: var(--space-4) var(--space-6);
591
+ border-bottom: 1px solid var(--border);
592
+ }
593
+ .chat-thread-title {
594
+ font: 15px/1.2 var(--font-display);
595
+ letter-spacing: -0.01em;
596
+ font-weight: 500;
597
+ }
598
+ .chat-thread-sub {
599
+ display: flex; align-items: center; gap: 6px;
600
+ margin-top: 4px;
601
+ font: 12px/1 var(--font-sans);
602
+ color: var(--text-muted);
603
+ }
604
+ .chat-thread-dot {
605
+ width: 6px; height: 6px; border-radius: 50%;
606
+ background: var(--success);
607
+ box-shadow: 0 0 6px var(--success);
608
+ animation: dot-throb 2s var(--motion-ease) infinite;
609
+ }
610
+ @keyframes dot-throb {
611
+ 0%, 100% { box-shadow: 0 0 4px var(--success); }
612
+ 50% { box-shadow: 0 0 10px var(--success); }
613
+ }
614
+ .chat-thread-sub.state-streaming .chat-thread-dot {
615
+ background: var(--accent);
616
+ animation: thread-dot-pulse 1.4s var(--motion-ease) infinite;
617
+ }
618
+ @keyframes thread-dot-pulse {
619
+ 0%, 100% { box-shadow: 0 0 4px var(--accent); transform: scale(1); }
620
+ 50% { box-shadow: 0 0 12px var(--accent); transform: scale(1.2); }
621
+ }
622
+ .chat-thread-sub.state-awaiting .chat-thread-dot { background: var(--warning); }
623
+ .chat-thread-sub.state-idle .chat-thread-dot { background: var(--text-muted); animation: none; }
624
+ .chat-thread-actions { display: flex; gap: 4px; }
625
+
626
+ .chat-thread-scroll {
627
+ overflow-y: auto;
628
+ padding: var(--space-6) var(--space-8);
629
+ display: flex; flex-direction: column; gap: var(--space-5);
630
+ min-height: 0;
631
+ }
632
+
633
+ /* ============================================================
634
+ MESSAGE BLOCKS
635
+ ============================================================ */
636
+ .msg { display: flex; gap: var(--space-3); position: relative; }
637
+ .msg-user { justify-content: flex-end; }
638
+ .msg-assistant { justify-content: flex-start; }
639
+ .msg-system {
640
+ align-self: center;
641
+ display: inline-flex; align-items: center; gap: 8px;
642
+ padding: 4px 10px;
643
+ background: var(--bg-1);
644
+ border: 1px solid var(--border);
645
+ border-radius: var(--radius-pill);
646
+ font: 11px/1 var(--font-sans);
647
+ color: var(--text-muted);
648
+ }
649
+ .msg-system-dot {
650
+ width: 6px; height: 6px; border-radius: 50%;
651
+ background: var(--success);
652
+ }
653
+
654
+ .msg-avatar {
655
+ flex: 0 0 auto;
656
+ width: 28px; height: 28px;
657
+ display: grid; place-items: center;
658
+ border-radius: 50%;
659
+ font: 12px/1 var(--font-mono);
660
+ font-weight: 500;
661
+ color: white;
662
+ position: relative;
663
+ overflow: visible;
664
+ }
665
+ .msg-avatar-user {
666
+ background: var(--bg-2);
667
+ color: var(--text);
668
+ border: 1px solid var(--border);
669
+ }
670
+ .msg-avatar-assistant { background: var(--accent); }
671
+ .msg-avatar-letter { position: relative; z-index: 1; }
672
+ .msg-avatar-pulse {
673
+ position: absolute; inset: -2px;
674
+ border-radius: 50%;
675
+ border: 1.5px solid var(--accent);
676
+ opacity: 0;
677
+ pointer-events: none;
678
+ }
679
+ .msg-avatar-pulse.phase-think {
680
+ animation: pulse-think 1.4s var(--motion-ease) infinite;
681
+ }
682
+ .msg-avatar-pulse.phase-stream {
683
+ animation: pulse-stream 1.8s var(--motion-ease) infinite;
684
+ border-color: var(--accent);
685
+ }
686
+ .msg-avatar-pulse.phase-commit {
687
+ animation: pulse-commit 360ms var(--motion-ease) 1;
688
+ border-color: var(--success);
689
+ border-width: 2px;
690
+ }
691
+ @keyframes pulse-think {
692
+ 0% { opacity: 0; transform: scale(0.85); }
693
+ 50% { opacity: 0.6; transform: scale(1.15); }
694
+ 100% { opacity: 0; transform: scale(1.3); }
695
+ }
696
+ @keyframes pulse-stream {
697
+ 0% { opacity: 0.8; transform: scale(1); }
698
+ 100% { opacity: 0; transform: scale(1.5); }
699
+ }
700
+ @keyframes pulse-commit {
701
+ 0% { opacity: 1; transform: scale(1); }
702
+ 100% { opacity: 0; transform: scale(2); }
703
+ }
704
+
705
+ .msg-body { min-width: 0; max-width: 720px; }
706
+
707
+ .msg-bubble-wrap {
708
+ position: relative;
709
+ }
710
+ .msg-bubble-wrap::before,
711
+ .msg-bubble-wrap::after {
712
+ content: '';
713
+ position: absolute;
714
+ left: 0; right: 0;
715
+ height: 14px;
716
+ z-index: 1;
717
+ }
718
+ .msg-bubble-wrap::before { top: -14px; }
719
+ .msg-bubble-wrap::after { bottom: -14px; }
720
+ .msg-bubble-user-wrap { position: relative; }
721
+ .msg-bubble-user-wrap::before,
722
+ .msg-bubble-user-wrap::after {
723
+ content: '';
724
+ position: absolute;
725
+ left: 0; right: 0;
726
+ height: 14px;
727
+ z-index: 1;
728
+ }
729
+ .msg-bubble-user-wrap::before { top: -14px; }
730
+ .msg-bubble-user-wrap::after { bottom: -14px; }
731
+
732
+ .msg-actions {
733
+ position: absolute;
734
+ bottom: -18px;
735
+ display: inline-flex; align-items: center;
736
+ gap: 1px;
737
+ padding: 3px 4px;
738
+ background: var(--bg);
739
+ border: 1px solid var(--border);
740
+ border-radius: var(--radius-md);
741
+ opacity: 0;
742
+ transform: translateY(-2px);
743
+ transition: opacity 180ms var(--motion-ease),
744
+ transform 180ms var(--motion-ease);
745
+ pointer-events: none;
746
+ z-index: 3;
747
+ }
748
+ .msg-actions-assistant { left: 0; }
749
+ .msg-actions-user { right: 0; }
750
+ .msg-bubble-wrap:hover .msg-actions,
751
+ .msg-bubble-wrap:focus-within .msg-actions,
752
+ .msg-bubble-user-wrap:hover .msg-actions,
753
+ .msg-bubble-user-wrap:focus-within .msg-actions,
754
+ .msg-actions:hover,
755
+ .msg-actions:focus-within {
756
+ opacity: 1;
757
+ transform: translateY(0);
758
+ pointer-events: auto;
759
+ }
760
+ .msg-action-btn {
761
+ display: inline-flex; align-items: center; gap: 4px;
762
+ padding: 4px 6px;
763
+ background: transparent;
764
+ border: 0;
765
+ border-radius: var(--radius-sm);
766
+ color: var(--text-muted);
767
+ font: 11px/1 var(--font-sans);
768
+ cursor: pointer;
769
+ white-space: nowrap;
770
+ transition: background var(--motion-fast) var(--motion-ease),
771
+ color var(--motion-fast) var(--motion-ease);
772
+ }
773
+ .msg-action-btn:hover { background: var(--bg-1); color: var(--text); }
774
+ .msg-action-btn.active { color: var(--accent); }
775
+ .msg-action-feedback { padding: 4px 6px; }
776
+ .msg-action-feedback.active { background: var(--bg-2); }
777
+ .msg-action-label { letter-spacing: 0.01em; }
778
+ .msg-action-sep {
779
+ width: 1px; height: 14px;
780
+ background: var(--border);
781
+ margin: 0 2px;
782
+ }
783
+ .msg-action-btn:focus-visible {
784
+ outline: 1px solid var(--accent);
785
+ outline-offset: 1px;
786
+ }
787
+
788
+ .msg-meta {
789
+ display: flex; align-items: baseline; gap: 8px;
790
+ margin-bottom: 4px;
791
+ }
792
+ .msg-author { font: 12px/1 var(--font-sans); font-weight: 500; }
793
+ .msg-ts { font: 11px/1 var(--font-mono); color: var(--text-muted); }
794
+
795
+ .msg-bubble {
796
+ padding: 10px 14px;
797
+ border-radius: var(--radius-md);
798
+ font: 14px/1.55 var(--font-sans);
799
+ border: 1px solid var(--border);
800
+ background: var(--bg-1);
801
+ }
802
+ .msg-bubble-user {
803
+ background: var(--bg-1);
804
+ border-color: var(--border);
805
+ }
806
+ .msg-bubble-assistant {
807
+ background: var(--bg-1);
808
+ }
809
+ .msg-bubble p { margin: 0 0 var(--space-3); }
810
+ .msg-bubble p:first-child { margin-top: 0; }
811
+ .msg-bubble p:last-child { margin-bottom: 0; }
812
+ .msg-bubble ul {
813
+ margin: 0 0 var(--space-3);
814
+ padding-left: 20px;
815
+ }
816
+ .msg-bubble ul li { margin-bottom: 4px; }
817
+ .msg-bubble ul li:last-child { margin-bottom: 0; }
818
+ .msg-code {
819
+ margin: var(--space-3) 0;
820
+ padding: 12px 14px;
821
+ background: var(--bg);
822
+ border: 1px solid var(--border);
823
+ border-radius: var(--radius-md);
824
+ font: 12px/1.55 var(--font-mono);
825
+ overflow-x: auto;
826
+ color: var(--text);
827
+ }
828
+ .msg-code code { background: transparent; padding: 0; }
829
+ .msg-cursor {
830
+ display: inline-block;
831
+ width: 7px; height: 14px;
832
+ margin-left: 2px;
833
+ background: var(--accent);
834
+ vertical-align: -2px;
835
+ animation: cursor-blink 1s steps(2) infinite;
836
+ }
837
+ @keyframes cursor-blink { 50% { opacity: 0; } }
838
+ .msg-phase-stream .msg-cursor {
839
+ animation: cursor-pulse 0.9s steps(2) infinite,
840
+ cursor-color 1.6s var(--motion-ease) infinite;
841
+ width: 8px; height: 14px;
842
+ background: var(--accent);
843
+ }
844
+ @keyframes cursor-pulse { 50% { opacity: 0; } }
845
+ @keyframes cursor-color {
846
+ 0%, 100% { background: var(--accent); box-shadow: 0 0 4px var(--accent); }
847
+ 50% { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
848
+ }
849
+
850
+ /* Streaming indicator in meta row */
851
+ .msg-stream-indicator {
852
+ display: inline-flex; align-items: center; gap: 6px;
853
+ font: 11px/1 var(--font-mono);
854
+ color: var(--text-muted);
855
+ letter-spacing: 0.02em;
856
+ }
857
+ .msg-stream-label { opacity: 0.85; }
858
+ .msg-stream-dots { display: inline-flex; gap: 2px; }
859
+ .msg-stream-dots span {
860
+ width: 3px; height: 3px; border-radius: 50%;
861
+ background: var(--accent);
862
+ animation: dot-bounce 1.2s var(--motion-ease) infinite;
863
+ }
864
+ .msg-stream-dots span:nth-child(2) { animation-delay: 0.15s; }
865
+ .msg-stream-dots span:nth-child(3) { animation-delay: 0.3s; }
866
+ @keyframes dot-bounce {
867
+ 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
868
+ 30% { opacity: 1; transform: translateY(-3px); }
869
+ }
870
+ .msg-phase-stream .msg-stream-dots span { animation-duration: 0.9s; }
871
+ .msg-phase-commit .msg-stream-dots span {
872
+ animation-duration: 0.7s;
873
+ background: var(--success);
874
+ }
875
+ .msg-phase-commit .msg-bubble-assistant {
876
+ animation: commit-ring 480ms var(--motion-ease) 1;
877
+ border-color: var(--success);
878
+ }
879
+ @keyframes commit-ring {
880
+ 0% { box-shadow: 0 0 0 0 var(--success); border-color: var(--success); }
881
+ 100% { box-shadow: 0 0 0 8px transparent; border-color: var(--border); }
882
+ }
883
+
884
+ .msg-enter { animation: msg-in var(--motion-slow) var(--motion-ease) both; }
885
+ @keyframes msg-in {
886
+ from { opacity: 0; transform: translateY(8px); }
887
+ to { opacity: 1; transform: none; }
888
+ }
889
+
890
+ /* ============================================================
891
+ COMPOSER (pill layout)
892
+ ============================================================ */
893
+ .chat-composer-wrap {
894
+ position: relative;
895
+ padding: var(--space-3) var(--space-8) var(--space-5);
896
+ border-top: 1px solid var(--border);
897
+ background: var(--bg);
898
+ }
899
+ .chat-composer-pill {
900
+ display: flex; align-items: center; gap: var(--space-2);
901
+ width: 100%;
902
+ padding: 8px 8px 8px 16px;
903
+ background: var(--bg-1);
904
+ border: 1px solid var(--border);
905
+ border-radius: var(--radius-pill);
906
+ transition: border-color var(--motion-fast) var(--motion-ease);
907
+ }
908
+ .chat-composer-pill:focus-within { border-color: var(--accent); }
909
+ .chat-composer-pill .agent-chip,
910
+ .chat-composer-pill .model-badge {
911
+ font: 11px/1 var(--font-mono);
912
+ padding: 6px 10px;
913
+ border-radius: var(--radius-pill);
914
+ background: var(--bg-2);
915
+ color: var(--text-muted);
916
+ border: 1px solid var(--border);
917
+ white-space: nowrap;
918
+ }
919
+ .chat-composer-pill input,
920
+ .chat-composer-pill textarea {
921
+ flex: 1;
922
+ background: transparent;
923
+ border: 0; outline: 0;
924
+ color: var(--text);
925
+ font: 14px/1.4 var(--font-sans);
926
+ min-width: 0;
927
+ resize: none;
928
+ }
929
+ .chat-composer-pill input::placeholder,
930
+ .chat-composer-pill textarea::placeholder { color: var(--text-muted); }
931
+ .chat-composer-pill .icon-btn {
932
+ width: 32px; height: 32px;
933
+ display: grid; place-items: center;
934
+ background: transparent;
935
+ border: 0;
936
+ border-radius: 50%;
937
+ color: var(--text-muted);
938
+ cursor: pointer;
939
+ flex-shrink: 0;
940
+ }
941
+ .chat-composer-pill .icon-btn:hover { background: var(--bg-2); color: var(--text); }
942
+ .chat-composer-pill .icon-btn:focus-visible {
943
+ outline: 1px solid var(--accent);
944
+ outline-offset: 1px;
945
+ }
946
+ .chat-composer-pill .send-btn {
947
+ width: 32px; height: 32px;
948
+ display: grid; place-items: center;
949
+ background: var(--accent);
950
+ border: 0;
951
+ border-radius: 50%;
952
+ color: white;
953
+ cursor: pointer;
954
+ flex-shrink: 0;
955
+ }
956
+ .chat-composer-pill .send-btn:hover:not(:disabled) { filter: brightness(1.1); }
957
+ .chat-composer-pill .send-btn:disabled { opacity: 0.4; cursor: not-allowed; }
958
+ .chat-composer-pill .send-btn.takeoff { animation: send-takeoff 280ms var(--motion-ease) 1; }
959
+ @keyframes send-takeoff {
960
+ 0% { transform: scale(1); }
961
+ 35% { transform: scale(0.85); }
962
+ 70% { transform: scale(1.08); box-shadow: 0 0 0 6px rgba(139, 92, 246, 0.18); }
963
+ 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(139, 92, 246, 0); }
964
+ }
965
+ .chat-composer-hint {
966
+ display: flex; align-items: center; gap: 12px;
967
+ margin-top: 8px;
968
+ padding: 0 var(--space-3);
969
+ font: 11px/1 var(--font-mono);
970
+ letter-spacing: 0.02em;
971
+ color: var(--text-muted);
972
+ }
973
+ .chat-composer-hint kbd {
974
+ display: inline-block;
975
+ padding: 2px 6px;
976
+ background: var(--bg-1);
977
+ border: 1px solid var(--border);
978
+ border-radius: 4px;
979
+ color: var(--text);
980
+ font: 10px/1 var(--font-mono);
981
+ }
982
+
983
+ /* ============================================================
984
+ JUMP-TO-LATEST FLOATING PILL
985
+ ============================================================ */
986
+ .jump-to-latest {
987
+ position: absolute;
988
+ bottom: calc(100% + 6px);
989
+ left: 50%;
990
+ transform: translateX(-50%) translateY(6px);
991
+ display: inline-flex; align-items: center; gap: 8px;
992
+ padding: 8px 14px;
993
+ background: var(--bg-1);
994
+ border: 1px solid var(--border);
995
+ border-radius: var(--radius-pill);
996
+ color: var(--text);
997
+ font: 12px/1 var(--font-sans);
998
+ font-weight: 500;
999
+ cursor: pointer;
1000
+ z-index: 10;
1001
+ opacity: 0;
1002
+ animation: jump-in var(--motion-base) var(--motion-ease) forwards;
1003
+ transition: transform var(--motion-fast) var(--motion-ease),
1004
+ background var(--motion-fast) var(--motion-ease),
1005
+ border-color var(--motion-fast) var(--motion-ease);
1006
+ white-space: nowrap;
1007
+ }
1008
+ .jump-to-latest:hover {
1009
+ background: var(--bg-2);
1010
+ border-color: var(--border-strong);
1011
+ }
1012
+ .jump-to-latest:focus-visible {
1013
+ outline: 1px solid var(--accent);
1014
+ outline-offset: 2px;
1015
+ }
1016
+ @keyframes jump-in {
1017
+ from { opacity: 0; transform: translateX(-50%) translateY(14px); }
1018
+ to { opacity: 1; transform: translateX(-50%) translateY(6px); }
1019
+ }
1020
+ .jump-to-latest.is-streaming {
1021
+ border-color: var(--accent);
1022
+ box-shadow: 0 0 0 1px var(--accent), 0 4px 18px rgba(139, 92, 246, 0.25);
1023
+ }
1024
+ .jump-dots { display: inline-flex; align-items: center; gap: 3px; }
1025
+ .jump-dots > span {
1026
+ width: 4px; height: 4px; border-radius: 50%;
1027
+ background: var(--accent);
1028
+ animation: jump-dot 1.2s var(--motion-ease) infinite;
1029
+ }
1030
+ .jump-dots > span:nth-child(2) { animation-delay: 0.15s; }
1031
+ .jump-dots > span:nth-child(3) { animation-delay: 0.3s; }
1032
+ @keyframes jump-dot {
1033
+ 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
1034
+ 30% { opacity: 1; transform: translateY(-2px); }
1035
+ }
1036
+ .jump-badge {
1037
+ display: inline-grid; place-items: center;
1038
+ min-width: 18px; height: 18px; padding: 0 6px;
1039
+ margin-left: 2px;
1040
+ background: var(--accent);
1041
+ color: white;
1042
+ border-radius: var(--radius-pill);
1043
+ font: 10px/1 var(--font-mono);
1044
+ letter-spacing: 0.04em;
1045
+ }
1046
+ .jump-badge-live {
1047
+ background: var(--success);
1048
+ animation: live-pulse 1.4s var(--motion-ease) infinite;
1049
+ }
1050
+ @keyframes live-pulse {
1051
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0.5); }
1052
+ 50% { box-shadow: 0 0 0 4px rgba(52, 211, 153, 0); }
1053
+ }
1054
+
1055
+ /* ============================================================
1056
+ INFO PANEL
1057
+ ============================================================ */
1058
+ .chat-info {
1059
+ border-left: 1px solid var(--border);
1060
+ background: var(--bg);
1061
+ padding: var(--space-3) var(--space-4);
1062
+ overflow-y: auto;
1063
+ font: 13px/1.5 var(--font-sans);
1064
+ min-height: 0;
1065
+ }
1066
+ .chat-info-section {
1067
+ padding: var(--space-3) 0;
1068
+ border-bottom: 1px solid var(--border);
1069
+ }
1070
+ .chat-info-section:last-child { border-bottom: 0; }
1071
+ .chat-info-section h4 {
1072
+ font: 10px/1 var(--font-mono);
1073
+ text-transform: uppercase;
1074
+ letter-spacing: 0.08em;
1075
+ color: var(--text-muted);
1076
+ margin: 0 0 8px;
1077
+ font-weight: 600;
1078
+ }
1079
+ .chat-info-bar {
1080
+ margin-top: 6px;
1081
+ height: 3px;
1082
+ background: var(--bg-2);
1083
+ border-radius: 2px;
1084
+ overflow: hidden;
1085
+ }
1086
+ .chat-info-bar-fill {
1087
+ height: 100%;
1088
+ background: var(--accent);
1089
+ border-radius: 2px;
1090
+ }
1091
+ .chat-info-agents { display: flex; flex-wrap: wrap; gap: 4px; }
1092
+ .chat-info-agent {
1093
+ font: 11px/1 var(--font-mono);
1094
+ padding: 3px 8px;
1095
+ background: var(--bg-1);
1096
+ border: 1px solid var(--border);
1097
+ border-radius: var(--radius-pill);
1098
+ color: var(--text);
1099
+ }
1100
+ .chat-info-link {
1101
+ display: block;
1102
+ padding: 4px 0;
1103
+ font: 12px/1.4 var(--font-sans);
1104
+ color: var(--text);
1105
+ }
1106
+ .chat-info-link:hover { color: var(--accent); cursor: pointer; }
1107
+ .chat-info-mono { font: 11px/1.4 var(--font-mono); color: var(--text-muted); margin-top: 4px; }
1108
+
1109
+ /* ============================================================
1110
+ TOAST (in-thread feedback)
1111
+ ============================================================ */
1112
+ .chat-toast {
1113
+ position: fixed;
1114
+ bottom: 96px;
1115
+ left: 50%;
1116
+ transform: translateX(-50%);
1117
+ padding: 8px 14px;
1118
+ background: rgba(10, 14, 26, 0.94);
1119
+ color: #fff;
1120
+ font: 12px/1 var(--font-sans);
1121
+ border-radius: var(--radius-pill);
1122
+ z-index: 100;
1123
+ animation: chat-toast-in var(--motion-base) var(--motion-ease);
1124
+ white-space: nowrap;
1125
+ }
1126
+ @keyframes chat-toast-in {
1127
+ from { opacity: 0; transform: translate(-50%, 6px); }
1128
+ to { opacity: 1; transform: translate(-50%, 0); }
1129
+ }
1130
+
1131
+ /* ============================================================
1132
+ SHARED UTILITIES (scoped helpers used inside chat components)
1133
+ ============================================================ */
1134
+ .chat-mono { font-family: var(--font-mono); }
1135
+ .chat-muted { color: var(--text-muted); }
1136
+ .chat-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1137
+
1138
+ /* ============================================================
1139
+ REDUCED MOTION — strip animations inside chat components
1140
+ ============================================================ */
1141
+ @media (prefers-reduced-motion: reduce) {
1142
+ .msg-enter,
1143
+ .msg-avatar-pulse,
1144
+ .msg-stream-dots span,
1145
+ .msg-stream-commit,
1146
+ .msg-phase-commit .msg-bubble-assistant,
1147
+ .msg-phase-stream .msg-cursor,
1148
+ .send-btn.takeoff,
1149
+ .chat-rail-badge,
1150
+ .chat-thread-dot,
1151
+ .msg-cursor,
1152
+ .chat-toast,
1153
+ .session-state-awaiting,
1154
+ .session-state-streaming,
1155
+ .chat-thread-sub.state-streaming .chat-thread-dot,
1156
+ .jump-to-latest,
1157
+ .jump-dots > span,
1158
+ .jump-badge-live,
1159
+ .session-row-menu {
1160
+ animation: none !important;
1161
+ }
1162
+ .msg-enter { opacity: 1; transform: none; }
1163
+ .jump-to-latest { opacity: 1; transform: translateX(-50%); }
1164
+ .session-row-menu { animation: none !important; opacity: 1; transform: none; }
1165
+ .chat-rail-item-menu-trigger,
1166
+ .chat-rail-item .chat-rail-tree-chevron { transition: none !important; }
1167
+ .msg-actions { transition: none !important; }
1168
+ }
1169
+
1170
+ /* ============================================================
1171
+ LEGACY WRAPPER — keeps the MobileChat view (which uses the OLD
1172
+ `.chat-shell / .chat-body / .chat-sessions / .chat-main / .chat-info`
1173
+ grid) rendering. The legacy grid mirrors the new 3-column page
1174
+ using the same token palette so MobileChat picks up the same
1175
+ visual language even though it still uses ChatTopBar + SessionList
1176
+ (via _legacy) + ChatThread + FloatingComposer (via _legacy) +
1177
+ InfoPanel (via _legacy).
1178
+ ============================================================ */
6
1179
  .chat-shell { display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--bg); color: var(--text); }
7
- .chat-topbar { display: flex; align-items: center; gap: 0.5rem; height: 48px; box-sizing: border-box; padding: 0 1rem; border-bottom: 1px solid var(--border); flex-shrink: 0; background: var(--bg); }
8
- .chat-topbar-project { display: flex; align-items: center; gap: 0.375rem; height: 32px; padding: 0 0.75rem; background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); color: var(--text); font-size: 0.8125rem; font-weight: 500; cursor: pointer; max-width: 240px; }
1180
+ .chat-topbar {
1181
+ display: flex; align-items: center; gap: 0.5rem; height: 48px; box-sizing: border-box;
1182
+ padding: 0 1rem; border-bottom: 1px solid var(--border); flex-shrink: 0;
1183
+ background: var(--bg);
1184
+ }
1185
+ .chat-topbar-project {
1186
+ display: flex; align-items: center; gap: 0.375rem; height: 32px;
1187
+ padding: 0 0.75rem; background: var(--bg-1);
1188
+ border: 1px solid var(--border); border-radius: var(--radius-md);
1189
+ color: var(--text); font-size: 0.8125rem; font-weight: 500;
1190
+ cursor: pointer; max-width: 240px;
1191
+ }
9
1192
  .chat-topbar-project:hover { background: var(--bg-2); }
10
1193
  .chat-topbar-project-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
11
1194
  .chat-topbar-spacer { flex: 1; }
12
- .chat-topbar-btn { height: 32px; padding: 0 0.75rem; background: transparent; border: 1px solid transparent; border-radius: var(--radius-md); color: var(--text-muted); font-size: 0.8125rem; font-weight: 500; cursor: pointer; }
1195
+ .chat-topbar-btn {
1196
+ height: 32px; padding: 0 0.75rem; background: transparent;
1197
+ border: 1px solid transparent; border-radius: var(--radius-md);
1198
+ color: var(--text-muted); font-size: 0.8125rem; font-weight: 500;
1199
+ cursor: pointer;
1200
+ }
13
1201
  .chat-topbar-btn:hover { background: var(--bg-1); color: var(--text); }
14
1202
  .chat-topbar-btn.active { background: var(--bg-2); border-color: var(--border); color: var(--text); }
1203
+
15
1204
  .chat-body { display: flex; flex: 1; min-height: 0; }
16
1205
 
17
- /* Sessions */
18
- .chat-sessions { width: 200px; flex-shrink: 0; display: flex; flex-direction: column; background: var(--bg); border-right: 1px solid var(--border); overflow: hidden; transition: width var(--motion-slow) var(--motion-ease); }
1206
+ .chat-sessions {
1207
+ width: 200px; flex-shrink: 0; display: flex; flex-direction: column;
1208
+ background: var(--bg); border-right: 1px solid var(--border);
1209
+ overflow: hidden; transition: width var(--motion-slow) var(--motion-ease);
1210
+ }
19
1211
  @media (min-width: 1400px) { .chat-sessions { width: 220px; } }
20
1212
  .chat-sessions-hidden { width: 0; border-right: none; opacity: 0; pointer-events: none; }
21
- .chat-sessions-header { display: flex; align-items: center; justify-content: space-between; padding: 0.875rem 1rem 0.5rem; flex-shrink: 0; }
22
- .chat-sessions-header-title { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); }
23
- .chat-sessions-count { font-size: 0.6875rem; font-weight: 600; padding: 0.0625rem 0.4375rem; background: var(--bg-2); border-radius: 999px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
24
- .chat-sessions-toggle { display: flex; gap: 2px; margin: 0 0.75rem 0.5rem; padding: 2px; background: var(--bg-1); border-radius: var(--radius-sm); }
25
- .chat-sessions-toggle-btn { flex: 1; padding: 0.25rem 0.375rem; background: transparent; border: none; border-radius: 3px; font-size: 0.6875rem; font-weight: 500; color: var(--text-muted); cursor: pointer; transition: all var(--motion-base) var(--motion-ease); white-space: nowrap; }
1213
+ .chat-sessions-header {
1214
+ display: flex; align-items: center; justify-content: space-between;
1215
+ padding: 0.875rem 1rem 0.5rem; flex-shrink: 0;
1216
+ }
1217
+ .chat-sessions-header-title {
1218
+ font-size: 0.6875rem; font-weight: 600;
1219
+ text-transform: uppercase; letter-spacing: 0.08em;
1220
+ color: var(--text-muted);
1221
+ }
1222
+ .chat-sessions-count {
1223
+ font-size: 0.6875rem; font-weight: 600; padding: 0.0625rem 0.4375rem;
1224
+ background: var(--bg-2); border-radius: 999px;
1225
+ color: var(--text-muted); font-variant-numeric: tabular-nums;
1226
+ }
1227
+ .chat-sessions-toggle {
1228
+ display: flex; gap: 2px; margin: 0 0.75rem 0.5rem; padding: 2px;
1229
+ background: var(--bg-1); border-radius: var(--radius-sm);
1230
+ }
1231
+ .chat-sessions-toggle-btn {
1232
+ flex: 1; padding: 0.25rem 0.375rem; background: transparent; border: none;
1233
+ border-radius: 3px; font-size: 0.6875rem; font-weight: 500;
1234
+ color: var(--text-muted); cursor: pointer;
1235
+ transition: all var(--motion-base) var(--motion-ease); white-space: nowrap;
1236
+ }
26
1237
  .chat-sessions-toggle-btn:hover { color: var(--text); }
27
1238
  .chat-sessions-toggle-btn.active { background: var(--bg-2); color: var(--text); }
28
- .chat-sessions-new { display: flex; align-items: center; justify-content: center; gap: 0.375rem; margin: 0.5rem 0.75rem 0.75rem; padding: 0.5rem; background: transparent; border: 1px dashed var(--border); border-radius: var(--radius-md); color: var(--text); font-size: 0.8125rem; font-weight: 500; cursor: pointer; transition: all var(--motion-base) var(--motion-ease); }
29
- .chat-sessions-new:hover:not(:disabled) { background: var(--bg-1); border-color: var(--border-strong); border-style: solid; }
1239
+ .chat-sessions-new {
1240
+ display: flex; align-items: center; justify-content: center; gap: 0.375rem;
1241
+ margin: 0.5rem 0.75rem 0.75rem; padding: 0.5rem;
1242
+ background: transparent; border: 1px dashed var(--border);
1243
+ border-radius: var(--radius-md); color: var(--text);
1244
+ font-size: 0.8125rem; font-weight: 500; cursor: pointer;
1245
+ transition: all var(--motion-base) var(--motion-ease);
1246
+ }
1247
+ .chat-sessions-new:hover:not(:disabled) {
1248
+ background: var(--bg-1); border-color: var(--border-strong); border-style: solid;
1249
+ }
30
1250
  .chat-sessions-new:disabled { opacity: 0.4; cursor: not-allowed; }
31
- .chat-sessions-list { list-style: none; margin: 0; padding: 0 0.375rem 0.75rem; overflow-y: auto; flex: 1; min-height: 0; }
32
- .chat-sessions-item { display: flex; flex-direction: column; gap: 0.125rem; padding: 0.5rem 0.625rem; margin: 0.0625rem 0; border-radius: var(--radius-sm); cursor: pointer; }
1251
+ .chat-sessions-list {
1252
+ list-style: none; margin: 0; padding: 0 0.375rem 0.75rem;
1253
+ overflow-y: auto; flex: 1; min-height: 0;
1254
+ }
1255
+ .chat-sessions-item {
1256
+ display: flex; flex-direction: column; gap: 0.125rem;
1257
+ padding: 0.5rem 0.625rem; margin: 0.0625rem 0;
1258
+ border-radius: var(--radius-sm); cursor: pointer;
1259
+ }
33
1260
  .chat-sessions-item:hover { background: var(--bg-1); }
34
1261
  .chat-sessions-item.active { background: var(--bg-2); }
35
- .chat-sessions-item-id { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
1262
+ .chat-sessions-item-id {
1263
+ font-family: var(--font-mono); font-size: 0.75rem; color: var(--text);
1264
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
1265
+ }
36
1266
  .chat-sessions-item-meta { font-size: 0.6875rem; color: var(--text-muted); }
37
1267
  .chat-sessions-item-opencode { opacity: 0.8; }
38
1268
  .chat-sessions-item-opencode .chat-sessions-item-id { font-family: var(--font-sans); }
39
1269
  .chat-sessions-item-icon { flex-shrink: 0; color: var(--text-muted); margin-top: 2px; }
40
- .chat-sessions-empty { flex: 1; display: flex; align-items: center; justify-content: center; padding: 1rem; }
1270
+ .chat-sessions-empty {
1271
+ flex: 1; display: flex; align-items: center; justify-content: center; padding: 1rem;
1272
+ }
41
1273
 
42
- /* Main + thread */
43
- .chat-main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--bg); position: relative; }
44
- .chat-thread { flex: 1; overflow-y: auto; padding: 1.5rem 2rem; display: flex; flex-direction: column; gap: 1rem; }
45
- .chat-thread:has(.chat-welcome) { padding: 0; align-items: center; justify-content: flex-start; }
1274
+ .chat-main {
1275
+ flex: 1; min-width: 0; display: flex; flex-direction: column;
1276
+ background: var(--bg); position: relative; min-height: 0;
1277
+ }
1278
+
1279
+ .chat-info-hidden { width: 0; padding: 0; border-left: none; opacity: 0; pointer-events: none; overflow: hidden; }
46
1280
 
47
- /* Welcome screen */
48
- .chat-welcome { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; text-align: center; padding: 6vh 2rem 2rem; width: 100%; max-width: 920px; }
49
- .chat-welcome-h1 { margin: 0; font-size: clamp(2.25rem, 5vw, 3.5rem); font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; }
50
- .chat-greeting-hello { background: var(--gradient-hello); -webkit-background-clip: text; background-clip: text; color: transparent; display: inline-block; }
51
- .chat-greeting-name { background: var(--gradient-name); -webkit-background-clip: text; background-clip: text; color: transparent; display: inline-block; }
52
- .chat-welcome-subtitle { font-size: clamp(1.125rem, 2vw, 1.5rem); font-weight: 500; color: var(--text-muted); margin: 0.5rem 0 0; letter-spacing: -0.005em; }
1281
+ .chat-info-card {
1282
+ background: var(--bg-1); border: 1px solid var(--border);
1283
+ border-radius: var(--radius-md); padding: 0.75rem 0.875rem;
1284
+ }
1285
+ .chat-info-card-title {
1286
+ display: flex; align-items: center; gap: 0.4375rem;
1287
+ font-size: 0.6875rem; font-weight: 600;
1288
+ text-transform: uppercase; letter-spacing: 0.06em;
1289
+ color: var(--text-muted); margin-bottom: 0.5rem;
1290
+ width: 100%; background: transparent; border: none;
1291
+ padding: 0; text-align: left;
1292
+ }
1293
+ .chat-info-card-title-button { cursor: pointer; }
1294
+ .chat-info-card-title-button:hover { color: var(--text); }
1295
+ .chat-info-card-count {
1296
+ margin-left: auto; font-size: 0.6875rem; background: var(--bg-2);
1297
+ padding: 0.0625rem 0.375rem; border-radius: 999px;
1298
+ color: var(--text-muted); font-weight: 500;
1299
+ }
1300
+ .chat-info-card-chevron { color: var(--text-muted); transition: transform var(--motion-base) var(--motion-ease); }
1301
+ .chat-info-card-chevron.open { transform: rotate(180deg); }
1302
+ .chat-info-card-toggle {
1303
+ margin-top: 0.4375rem; padding: 0.25rem 0; background: transparent;
1304
+ border: none; color: var(--text-muted);
1305
+ font-size: 0.6875rem; font-weight: 500; cursor: pointer; text-align: left;
1306
+ }
1307
+ .chat-info-card-toggle:hover { color: var(--text); }
53
1308
 
54
- /* Suggestion cards explicit breakpoints: <600:1col, 600-1099:2col, ≥1100:4col */
55
- .chat-suggestions { display: grid; grid-template-columns: 1fr; gap: 0.75rem; width: 100%; max-width: 920px; margin-top: 2.5rem; }
56
- @media (min-width: 600px) { .chat-suggestions { grid-template-columns: repeat(2, 1fr); } }
1309
+ .env-table { display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 0.625rem; margin: 0; font-size: 0.75rem; }
1310
+ .env-table dt { color: var(--text-muted); }
1311
+ .env-table dd { margin: 0; color: var(--text); font-family: var(--font-mono); font-size: 0.6875rem; }
1312
+ .env-table dd.ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1313
+
1314
+ .mod-mini-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.1875rem; max-height: 200px; overflow-y: auto; }
1315
+ .mod-mini { display: flex; align-items: center; gap: 0.4375rem; padding: 0.25rem 0; font-size: 0.75rem; }
1316
+ .mod-mini-name { font-family: var(--font-mono); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
1317
+ .mod-mini-meta { font-size: 0.6875rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1318
+ .mod-mini-pill { font-size: 0.625rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.0625rem 0.375rem; border-radius: 999px; }
1319
+ .mod-mini-pill.on { background: color-mix(in oklab, var(--success), transparent 70%); color: var(--success); }
1320
+ .mod-mini-pill.off { background: var(--bg-2); color: var(--text-muted); }
1321
+
1322
+ /* The legacy ChatThread component still uses .chat-thread — it has
1323
+ its own internal padding + welcome-screen styling. */
1324
+ .chat-thread.legacy { flex: 1; overflow-y: auto; padding: 1.5rem 2rem; display: flex; flex-direction: column; gap: 1rem; min-height: 0; }
1325
+ .chat-thread:has(.chat-welcome) { padding: 0; align-items: center; justify-content: flex-start; }
1326
+
1327
+ /* Welcome / suggestions / message bubble — old layout. Kept so
1328
+ legacy components (WelcomeScreen, MessageBubble, SuggestionCards)
1329
+ continue to render via MobileChat. */
1330
+ .chat-welcome {
1331
+ display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
1332
+ text-align: center; padding: 6vh 2rem 2rem;
1333
+ width: 100%; max-width: 920px;
1334
+ }
1335
+ .chat-welcome-h1 {
1336
+ margin: 0; font-size: clamp(2.25rem, 5vw, 3.5rem);
1337
+ font-weight: 700; line-height: 1.1; letter-spacing: -0.02em;
1338
+ }
1339
+ .chat-greeting-hello {
1340
+ background: var(--gradient-hello);
1341
+ -webkit-background-clip: text; background-clip: text;
1342
+ color: transparent; display: inline-block;
1343
+ }
1344
+ .chat-greeting-name {
1345
+ background: var(--gradient-name);
1346
+ -webkit-background-clip: text; background-clip: text;
1347
+ color: transparent; display: inline-block;
1348
+ }
1349
+ .chat-welcome-subtitle {
1350
+ font-size: clamp(1.125rem, 2vw, 1.5rem); font-weight: 500;
1351
+ color: var(--text-muted); margin: 0.5rem 0 0; letter-spacing: -0.005em;
1352
+ }
1353
+ .chat-suggestions {
1354
+ display: grid; grid-template-columns: 1fr;
1355
+ gap: 0.75rem; width: 100%; max-width: 920px; margin-top: 2.5rem;
1356
+ }
1357
+ @media (min-width: 600px) { .chat-suggestions { grid-template-columns: repeat(2, 1fr); } }
57
1358
  @media (min-width: 1100px) { .chat-suggestions { grid-template-columns: repeat(4, 1fr); } }
58
- .chat-suggestion { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem 1.125rem; background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); cursor: pointer; text-align: left; font: inherit; color: var(--text); transition: all var(--motion-base) var(--motion-ease); min-height: 120px; }
1359
+ .chat-suggestion {
1360
+ display: flex; flex-direction: column; gap: 0.5rem;
1361
+ padding: 1rem 1.125rem; background: var(--bg-1);
1362
+ border: 1px solid var(--border); border-radius: var(--radius-md);
1363
+ cursor: pointer; text-align: left; font: inherit; color: var(--text);
1364
+ transition: all var(--motion-base) var(--motion-ease); min-height: 120px;
1365
+ }
59
1366
  .chat-suggestion:hover { transform: translateY(-2px); border-color: var(--border-strong); background: var(--bg-2); }
60
1367
  .chat-suggestion-title { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; font-weight: 600; line-height: 1.3; }
61
1368
  .chat-suggestion-title span { flex: 1; }
62
- .chat-suggestion-preview { font-size: 0.75rem; color: var(--text-muted); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
63
-
64
- /* Messages */
65
- .chat-message { background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 0.875rem 1.125rem; transition: border-color var(--motion-base) var(--motion-ease); max-width: 880px; width: 100%; align-self: flex-start; }
1369
+ .chat-suggestion-preview {
1370
+ font-size: 0.75rem; color: var(--text-muted); line-height: 1.45;
1371
+ display: -webkit-box; -webkit-line-clamp: 4;
1372
+ -webkit-box-orient: vertical; overflow: hidden;
1373
+ }
1374
+ .chat-message {
1375
+ background: var(--bg-1); border: 1px solid var(--border);
1376
+ border-radius: var(--radius-lg); padding: 0.875rem 1.125rem;
1377
+ transition: border-color var(--motion-base) var(--motion-ease);
1378
+ max-width: 880px; width: 100%; align-self: flex-start;
1379
+ }
66
1380
  .chat-message-user { background: var(--bg-2); }
67
1381
  .chat-message-pinned { border-left: 2px solid var(--accent); }
68
- .chat-message-meta { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
69
- .chat-message-role { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
1382
+ .chat-message-meta {
1383
+ display: flex; align-items: center; gap: 0.5rem;
1384
+ margin-bottom: 0.5rem; flex-wrap: wrap;
1385
+ }
1386
+ .chat-message-role {
1387
+ font-size: 0.6875rem; font-weight: 600;
1388
+ text-transform: uppercase; letter-spacing: 0.05em;
1389
+ color: var(--text-muted);
1390
+ }
70
1391
  .chat-message-agent { font-family: var(--font-mono); font-size: 0.75rem; color: var(--accent); }
71
1392
  .chat-message-time { font-size: 0.6875rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
72
1393
  .chat-message-pin { font-size: 0.6875rem; color: var(--accent); font-weight: 600; }
73
- .chat-message-actions { margin-left: auto; display: flex; gap: 0.125rem; opacity: 0; transition: opacity var(--motion-base) var(--motion-ease); }
74
- .chat-message:hover .chat-message-actions, .chat-message:focus-within .chat-message-actions { opacity: 1; }
75
- .chat-msg-action-btn { display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; background: transparent; border: none; border-radius: var(--radius-sm); color: var(--text-muted); cursor: pointer; }
1394
+ .chat-message-actions {
1395
+ margin-left: auto; display: flex; gap: 0.125rem;
1396
+ opacity: 0; transition: opacity var(--motion-base) var(--motion-ease);
1397
+ }
1398
+ .chat-message:hover .chat-message-actions,
1399
+ .chat-message:focus-within .chat-message-actions { opacity: 1; }
1400
+ .chat-msg-action-btn {
1401
+ display: flex; align-items: center; justify-content: center;
1402
+ width: 24px; height: 24px; padding: 0; background: transparent;
1403
+ border: none; border-radius: var(--radius-sm);
1404
+ color: var(--text-muted); cursor: pointer;
1405
+ }
76
1406
  .chat-msg-action-btn:hover { background: var(--bg-2); color: var(--text); }
77
1407
  .chat-msg-action-btn-danger:hover { color: var(--error); }
78
- .chat-message-content { font-size: 0.9375rem; line-height: 1.6; color: var(--text); word-wrap: break-word; }
1408
+ .chat-message-content {
1409
+ font-size: 0.9375rem; line-height: 1.6; color: var(--text);
1410
+ word-wrap: break-word;
1411
+ }
79
1412
  .markdown-body p { margin: 0.5em 0; }
80
1413
  .markdown-body p:first-child { margin-top: 0; }
81
1414
  .markdown-body p:last-child { margin-bottom: 0; }
82
1415
  .markdown-body h1, .markdown-body h2, .markdown-body h3 { margin: 0.75em 0 0.5em; font-weight: 600; }
83
- .markdown-body code { font-family: var(--font-mono); font-size: 0.875em; background: var(--bg-2); padding: 0.0625em 0.25em; border-radius: 3px; }
84
- .markdown-body pre { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.75rem; overflow-x: auto; }
1416
+ .markdown-body code {
1417
+ font-family: var(--font-mono); font-size: 0.875em;
1418
+ background: var(--bg-2); padding: 0.0625em 0.25em; border-radius: 3px;
1419
+ }
1420
+ .markdown-body pre {
1421
+ background: var(--bg); border: 1px solid var(--border);
1422
+ border-radius: var(--radius-sm); padding: 0.75rem; overflow-x: auto;
1423
+ }
85
1424
  .markdown-body pre code { background: transparent; padding: 0; }
86
1425
  .markdown-body ul, .markdown-body ol { margin: 0.5em 0; padding-left: 1.5em; }
87
- .markdown-body blockquote { border-left: 2px solid var(--border-strong); margin: 0.5em 0; padding: 0 0 0 0.75em; color: var(--text-muted); }
1426
+ .markdown-body blockquote {
1427
+ border-left: 2px solid var(--border-strong); margin: 0.5em 0;
1428
+ padding: 0 0 0 0.75em; color: var(--text-muted);
1429
+ }
88
1430
  .markdown-body a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
89
1431
 
90
- /* Composer */
91
- .chat-composer-wrap { position: sticky; bottom: 0; left: 0; right: 0; padding: 0.5rem 1rem 1rem; background: linear-gradient(to top, var(--bg) 0%, var(--bg) 50%, transparent 100%); pointer-events: none; z-index: 10; max-width: 100%; }
92
- .chat-composer-wrap > * { pointer-events: auto; }
93
- .chat-composer-pill { max-width: min(880px, 100%); margin: 0 auto; background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: 0 4px 32px rgba(0, 0, 0, 0.4); transition: border-color var(--motion-base) var(--motion-ease); }
94
- .chat-composer-pill:focus-within { border-color: var(--accent); }
95
- .chat-composer { display: flex; flex-direction: column; gap: 0.375rem; padding: 0.5rem 0.625rem; }
96
- .chat-composer-suggestions { display: flex; flex-direction: column; gap: 0.125rem; margin: -0.25rem 0 0.25rem; padding: 0.25rem; background: var(--bg-2); border-radius: var(--radius-md); max-height: 240px; overflow-y: auto; }
97
- .chat-composer-suggestion { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.625rem; background: transparent; border: none; border-radius: var(--radius-sm); color: var(--text); font: inherit; font-size: 0.8125rem; text-align: left; cursor: pointer; }
1432
+ .chat-composer-wrap.legacy {
1433
+ position: sticky; bottom: 0; left: 0; right: 0;
1434
+ padding: 0.5rem 1rem 1rem;
1435
+ background: linear-gradient(to top, var(--bg) 0%, var(--bg) 50%, transparent 100%);
1436
+ pointer-events: none; z-index: 10; max-width: 100%;
1437
+ }
1438
+ .chat-composer-wrap.legacy > * { pointer-events: auto; }
1439
+ .chat-composer-pill.legacy {
1440
+ max-width: min(880px, 100%); margin: 0 auto;
1441
+ background: var(--bg-1); border: 1px solid var(--border);
1442
+ border-radius: var(--radius-lg); box-shadow: 0 4px 32px rgba(0, 0, 0, 0.4);
1443
+ transition: border-color var(--motion-base) var(--motion-ease);
1444
+ }
1445
+ .chat-composer-pill.legacy:focus-within { border-color: var(--accent); }
1446
+ .chat-composer {
1447
+ display: flex; flex-direction: column; gap: 0.375rem; padding: 0.5rem 0.625rem;
1448
+ }
1449
+ .chat-composer-suggestions {
1450
+ display: flex; flex-direction: column; gap: 0.125rem;
1451
+ margin: -0.25rem 0 0.25rem; padding: 0.25rem;
1452
+ background: var(--bg-2); border-radius: var(--radius-md);
1453
+ max-height: 240px; overflow-y: auto;
1454
+ }
1455
+ .chat-composer-suggestion {
1456
+ display: flex; align-items: center; gap: 0.5rem;
1457
+ padding: 0.5rem 0.625rem; background: transparent; border: none;
1458
+ border-radius: var(--radius-sm); color: var(--text);
1459
+ font: inherit; font-size: 0.8125rem; text-align: left; cursor: pointer;
1460
+ }
98
1461
  .chat-composer-suggestion:hover { background: var(--bg); }
99
- .chat-composer-suggestion .mono { font-family: var(--font-mono); font-size: 0.75rem; color: var(--accent); min-width: 80px; }
1462
+ .chat-composer-suggestion .mono {
1463
+ font-family: var(--font-mono); font-size: 0.75rem;
1464
+ color: var(--accent); min-width: 80px;
1465
+ }
100
1466
  .chat-composer-attachments { display: flex; flex-wrap: wrap; gap: 0.25rem; padding: 0 0.25rem; }
101
- .chat-composer-attachment-tag { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.1875rem 0.4375rem; background: var(--bg-2); border-radius: 999px; font-size: 0.75rem; color: var(--text); }
102
- .chat-composer-attachment-remove { display: flex; align-items: center; justify-content: center; width: 14px; height: 14px; padding: 0; background: transparent; border: none; color: var(--text-muted); cursor: pointer; }
1467
+ .chat-composer-attachment-tag {
1468
+ display: inline-flex; align-items: center; gap: 0.25rem;
1469
+ padding: 0.1875rem 0.4375rem; background: var(--bg-2);
1470
+ border-radius: 999px; font-size: 0.75rem; color: var(--text);
1471
+ }
1472
+ .chat-composer-attachment-remove {
1473
+ display: flex; align-items: center; justify-content: center;
1474
+ width: 14px; height: 14px; padding: 0; background: transparent;
1475
+ border: none; color: var(--text-muted); cursor: pointer;
1476
+ }
103
1477
  .chat-composer-input { display: flex; align-items: flex-end; gap: 0.375rem; }
104
- .chat-composer-textarea { flex: 1; min-width: 0; width: 100%; resize: none; background: transparent; border: none; outline: none; color: var(--text); font: inherit; font-size: 0.9375rem; line-height: 1.5; padding: 0.5rem 0.5rem; max-height: 200px; overflow-y: auto; }
1478
+ .chat-composer-textarea {
1479
+ flex: 1; min-width: 0; width: 100%; resize: none;
1480
+ background: transparent; border: none; outline: none;
1481
+ color: var(--text); font: inherit; font-size: 0.9375rem;
1482
+ line-height: 1.5; padding: 0.5rem 0.5rem;
1483
+ max-height: 200px; overflow-y: auto;
1484
+ }
105
1485
  .chat-composer-textarea::placeholder { color: var(--text-muted); }
106
- .chat-attach-btn { flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; background: transparent; border: none; border-radius: var(--radius-sm); color: var(--text-muted); cursor: pointer; }
1486
+ .chat-attach-btn {
1487
+ flex-shrink: 0; display: flex; align-items: center; justify-content: center;
1488
+ width: 32px; height: 32px; padding: 0; background: transparent;
1489
+ border: none; border-radius: var(--radius-sm);
1490
+ color: var(--text-muted); cursor: pointer;
1491
+ }
107
1492
  .chat-attach-btn:hover { background: var(--bg-2); color: var(--text); }
108
- .chat-send-btn { flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; background: var(--accent); color: white; border: none; border-radius: var(--radius-sm); cursor: pointer; }
109
- .chat-send-btn:hover:not(:disabled) { background: color-mix(in oklab, var(--accent), white 15%); transform: scale(1.05); }
110
- .chat-send-btn:disabled { background: var(--bg-2); color: var(--text-muted); cursor: not-allowed; }
1493
+ .chat-send-btn {
1494
+ flex-shrink: 0; display: flex; align-items: center; justify-content: center;
1495
+ width: 32px; height: 32px; padding: 0; background: var(--accent);
1496
+ color: white; border: none; border-radius: var(--radius-sm); cursor: pointer;
1497
+ }
1498
+ .chat-send-btn:hover:not(:disabled) {
1499
+ background: color-mix(in oklab, var(--accent), white 15%);
1500
+ transform: scale(1.05);
1501
+ }
1502
+ .chat-send-btn:disabled {
1503
+ background: var(--bg-2); color: var(--text-muted); cursor: not-allowed;
1504
+ }
111
1505
 
112
- /* Agent chip */
113
1506
  .chat-agent-chip { position: relative; flex-shrink: 0; }
114
- .chat-agent-chip-btn { display: flex; align-items: center; gap: 0.375rem; height: 32px; padding: 0 0.625rem; background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--radius-md); color: var(--text); font-size: 0.8125rem; font-weight: 500; cursor: pointer; min-width: 100px; max-width: 160px; }
115
- .chat-agent-chip-btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; text-align: left; }
1507
+ .chat-agent-chip-btn {
1508
+ display: flex; align-items: center; gap: 0.375rem;
1509
+ height: 32px; padding: 0 0.625rem;
1510
+ background: var(--bg-2); border: 1px solid var(--border);
1511
+ border-radius: var(--radius-md); color: var(--text);
1512
+ font-size: 0.8125rem; font-weight: 500; cursor: pointer;
1513
+ min-width: 100px; max-width: 160px;
1514
+ }
1515
+ .chat-agent-chip-btn > span {
1516
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
1517
+ flex: 1; text-align: left;
1518
+ }
116
1519
  .chat-agent-chip-btn:hover { background: var(--bg); border-color: var(--border-strong); }
117
- .chat-agent-chip-btn .rotated { transform: rotate(180deg); transition: transform var(--motion-base) var(--motion-ease); }
118
- .chat-agent-chip-menu { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 60; min-width: 200px; max-height: 280px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; padding: 0.375rem; background: var(--bg-1); border: 1px solid var(--border-strong); border-radius: var(--radius-md); box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.4); }
119
- .chat-agent-chip-menu button { display: flex; align-items: center; padding: 0.5rem 0.75rem; background: transparent; border: none; border-radius: var(--radius-sm); color: var(--text); font: inherit; font-size: 0.8125rem; text-align: left; cursor: pointer; }
1520
+ .chat-agent-chip-btn .rotated {
1521
+ transform: rotate(180deg);
1522
+ transition: transform var(--motion-base) var(--motion-ease);
1523
+ }
1524
+ .chat-agent-chip-menu {
1525
+ position: absolute; bottom: calc(100% + 6px); left: 0;
1526
+ z-index: 60; min-width: 200px; max-height: 280px; overflow-y: auto;
1527
+ display: flex; flex-direction: column; gap: 2px; padding: 0.375rem;
1528
+ background: var(--bg-1); border: 1px solid var(--border-strong);
1529
+ border-radius: var(--radius-md); box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.4);
1530
+ }
1531
+ .chat-agent-chip-menu button {
1532
+ display: flex; align-items: center; padding: 0.5rem 0.75rem;
1533
+ background: transparent; border: none; border-radius: var(--radius-sm);
1534
+ color: var(--text); font: inherit; font-size: 0.8125rem;
1535
+ text-align: left; cursor: pointer;
1536
+ }
120
1537
  .chat-agent-chip-menu button:hover { background: var(--bg-2); }
121
- .chat-agent-chip-menu button[aria-selected="true"] { background: var(--accent); color: white; }
1538
+ .chat-agent-chip-menu button[aria-selected="true"] {
1539
+ background: var(--accent); color: white;
1540
+ }
1541
+
1542
+ .chat-info.legacy {
1543
+ width: 240px; flex-shrink: 0; display: flex; flex-direction: column;
1544
+ gap: 0.625rem; padding: 1rem;
1545
+ background: var(--bg); border-left: 1px solid var(--border); overflow-y: auto;
1546
+ }
1547
+ @media (min-width: 1400px) { .chat-info.legacy { width: 260px; } }
122
1548
 
123
- /* Info panel */
124
- .chat-info { width: 240px; flex-shrink: 0; display: flex; flex-direction: column; gap: 0.625rem; padding: 1rem; background: var(--bg); border-left: 1px solid var(--border); overflow-y: auto; }
125
- @media (min-width: 1400px) { .chat-info { width: 260px; } }
126
- .chat-info-hidden { width: 0; padding: 0; border-left: none; opacity: 0; pointer-events: none; overflow: hidden; }
127
- .chat-info-card { background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 0.75rem 0.875rem; }
128
- .chat-info-card-title { display: flex; align-items: center; gap: 0.4375rem; font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-bottom: 0.5rem; width: 100%; background: transparent; border: none; padding: 0; text-align: left; }
129
- .chat-info-card-title-button { cursor: pointer; }
130
- .chat-info-card-title-button:hover { color: var(--text); }
131
- .chat-info-card-count { margin-left: auto; font-size: 0.6875rem; background: var(--bg-2); padding: 0.0625rem 0.375rem; border-radius: 999px; color: var(--text-muted); font-weight: 500; }
132
- .chat-info-card-chevron { color: var(--text-muted); transition: transform var(--motion-base) var(--motion-ease); }
133
- .chat-info-card-chevron.open { transform: rotate(180deg); }
134
- .chat-info-card-toggle { margin-top: 0.4375rem; padding: 0.25rem 0; background: transparent; border: none; color: var(--text-muted); font-size: 0.6875rem; font-weight: 500; cursor: pointer; text-align: left; }
135
- .chat-info-card-toggle:hover { color: var(--text); }
136
- .env-table { display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 0.625rem; margin: 0; font-size: 0.75rem; }
137
- .env-table dt { color: var(--text-muted); }
138
- .env-table dd { margin: 0; color: var(--text); font-family: var(--font-mono); font-size: 0.6875rem; }
139
- .env-table dd.ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
140
- .mod-mini-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.1875rem; max-height: 200px; overflow-y: auto; }
141
- .mod-mini { display: flex; align-items: center; gap: 0.4375rem; padding: 0.25rem 0; font-size: 0.75rem; }
142
- .mod-mini-name { font-family: var(--font-mono); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
143
- .mod-mini-meta { font-size: 0.6875rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
144
- .mod-mini-pill { font-size: 0.625rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.0625rem 0.375rem; border-radius: 999px; }
145
- .mod-mini-pill.on { background: color-mix(in oklab, var(--success), transparent 70%); color: var(--success); }
146
- .mod-mini-pill.off { background: var(--bg-2); color: var(--text-muted); }
147
1549
  .mono { font-family: var(--font-mono); }
148
1550
  .muted { color: var(--text-muted); }
149
1551
  .ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
150
1552
 
151
- /* Loading skeleton + streaming */
152
- .chat-loading-skeleton { display: flex; flex-direction: column; gap: 0.75rem; padding: 1rem 0; }
153
- .chat-loading-skeleton-bubble { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.875rem 1.125rem; background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-lg); max-width: 600px; }
154
- .chat-loading-skeleton-meta { height: 12px; width: 80px; background: var(--bg-2); border-radius: 4px; animation: skeleton-pulse 1.4s ease-in-out infinite; }
155
- .chat-loading-skeleton-line { height: 12px; background: var(--bg-2); border-radius: 4px; animation: skeleton-pulse 1.4s ease-in-out infinite; }
1553
+ .chat-loading-skeleton {
1554
+ display: flex; flex-direction: column; gap: 0.75rem; padding: 1rem 0;
1555
+ }
1556
+ .chat-loading-skeleton-bubble {
1557
+ display: flex; flex-direction: column; gap: 0.5rem;
1558
+ padding: 0.875rem 1.125rem; background: var(--bg-1);
1559
+ border: 1px solid var(--border); border-radius: var(--radius-lg);
1560
+ max-width: 600px;
1561
+ }
1562
+ .chat-loading-skeleton-meta {
1563
+ height: 12px; width: 80px;
1564
+ background: var(--bg-2); border-radius: 4px;
1565
+ animation: skeleton-pulse 1.4s ease-in-out infinite;
1566
+ }
1567
+ .chat-loading-skeleton-line {
1568
+ height: 12px; background: var(--bg-2); border-radius: 4px;
1569
+ animation: skeleton-pulse 1.4s ease-in-out infinite;
1570
+ }
156
1571
  .chat-loading-skeleton-line.short { width: 60%; }
157
1572
  @keyframes skeleton-pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
158
- .chat-streaming-indicator { display: inline-flex; align-items: center; gap: 4px; padding: 0.5rem 1rem; }
159
- .chat-streaming-indicator span { display: inline-block; width: 6px; height: 6px; background: var(--text-muted); border-radius: 50%; animation: streaming-bounce 1.4s ease-in-out infinite; }
1573
+
1574
+ .chat-streaming-indicator {
1575
+ display: inline-flex; align-items: center; gap: 4px;
1576
+ padding: 0.5rem 1rem;
1577
+ }
1578
+ .chat-streaming-indicator span {
1579
+ display: inline-block; width: 6px; height: 6px;
1580
+ background: var(--text-muted); border-radius: 50%;
1581
+ animation: streaming-bounce 1.4s ease-in-out infinite;
1582
+ }
160
1583
  .chat-streaming-indicator span:nth-child(2) { animation-delay: 0.16s; }
161
1584
  .chat-streaming-indicator span:nth-child(3) { animation-delay: 0.32s; }
162
- @keyframes streaming-bounce { 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-4px); } }
163
- .chat-empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 2rem; gap: 0.625rem; }
1585
+ @keyframes streaming-bounce {
1586
+ 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
1587
+ 30% { opacity: 1; transform: translateY(-4px); }
1588
+ }
1589
+
1590
+ .chat-empty-state {
1591
+ display: flex; flex-direction: column; align-items: center;
1592
+ justify-content: center; text-align: center;
1593
+ padding: 2rem; gap: 0.625rem;
1594
+ }
164
1595
  .chat-empty-state-icon { color: var(--text-muted); opacity: 0.6; }
165
1596
  .chat-empty-state-title { font-size: 1rem; font-weight: 600; color: var(--text); margin: 0; }
166
- .chat-empty-state-message { font-size: 0.8125rem; color: var(--text-muted); margin: 0; max-width: 320px; }
167
- .chat-empty-state-action { margin-top: 0.5rem; }
168
-
169
- /* Responsive — tablet 768-1024px: sessions overlay sheet (info stays inline) */
170
- @media (min-width: 768px) and (max-width: 1024px) {
171
- .chat-sessions { position: fixed !important; left: 0; top: 48px; bottom: 0; width: 280px; z-index: 100; border-right: 1px solid var(--border); background: var(--bg); transform: translateX(-100%); transition: transform var(--motion-slow) var(--motion-ease); }
172
- .chat-sessions:not(.chat-sessions-hidden) { transform: translateX(0); }
173
- .chat-info { width: 220px; }
174
- }
175
-
176
- /* Responsive — mobile under 768px: both overlay sheets */
177
- @media (max-width: 767.98px) {
178
- .chat-sessions, .chat-info { position: fixed !important; top: 48px; bottom: 0; width: 85vw; max-width: 320px; z-index: 100; background: var(--bg); }
179
- .chat-sessions { left: 0; border-right: 1px solid var(--border); transform: translateX(-100%); transition: transform var(--motion-slow) var(--motion-ease); }
180
- .chat-sessions:not(.chat-sessions-hidden) { transform: translateX(0); }
181
- .chat-info { right: 0; border-left: 1px solid var(--border); transform: translateX(100%); transition: transform var(--motion-slow) var(--motion-ease); }
182
- .chat-info:not(.chat-info-hidden) { transform: translateX(0); }
183
- .chat-thread { padding: 1rem; }
184
- .chat-welcome { padding: 3rem 1rem 1rem; }
185
- .chat-composer-wrap { padding: 0.5rem 0.5rem 0.75rem; }
186
- .chat-composer-pill { border-radius: var(--radius-md); }
187
- .chat-agent-chip-btn { min-width: 80px; padding: 0 0.5rem; }
188
- }
189
-
190
- /* Reduced motion */
191
- @media (prefers-reduced-motion: reduce) {
192
- *, *::before, *::after {
193
- animation-duration: 0.01ms !important;
194
- animation-iteration-count: 1 !important;
195
- transition-duration: 0.01ms !important;
196
- scroll-behavior: auto !important;
197
- }
1597
+ .chat-empty-state-message {
1598
+ font-size: 0.8125rem; color: var(--text-muted); margin: 0;
1599
+ max-width: 320px;
198
1600
  }
1601
+ .chat-empty-state-action { margin-top: 0.5rem; }