experimental-a2 0.7.0 → 0.8.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 (150) hide show
  1. package/AGENTS.md +11 -0
  2. package/CHANGELOG.md +27 -0
  3. package/README.md +29 -0
  4. package/dist/ai-server.d.ts +1 -1
  5. package/dist/ai-server.d.ts.map +1 -1
  6. package/dist/ai-server.js +13 -11
  7. package/dist/ai-server.js.map +1 -1
  8. package/dist/ai.d.ts +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/scheduler-qstash.d.ts +2 -2
  11. package/dist/scheduler-qstash.js +1 -1
  12. package/dist/scheduler-vercel.d.ts +2 -2
  13. package/dist/scheduler-vercel.js +1 -1
  14. package/dist/{server-286j79Mt.js → server-B2XNevQA.js} +123 -53
  15. package/dist/server-B2XNevQA.js.map +1 -0
  16. package/dist/{server-DgXmORIq.d.ts → server-DjPhHnbI.d.ts} +7 -4
  17. package/dist/server-DjPhHnbI.d.ts.map +1 -0
  18. package/dist/server.d.ts +3 -3
  19. package/dist/server.js +1 -1
  20. package/dist/store-N8PXxDAS.js.map +1 -1
  21. package/dist/{store-flRz1OWh.d.ts → store-RJO35BMj.d.ts} +25 -8
  22. package/dist/store-RJO35BMj.d.ts.map +1 -0
  23. package/dist/store-memory.d.ts +1 -1
  24. package/dist/store-memory.d.ts.map +1 -1
  25. package/dist/store-memory.js +79 -19
  26. package/dist/store-memory.js.map +1 -1
  27. package/dist/store-postgres.d.ts +1 -1
  28. package/dist/store-postgres.d.ts.map +1 -1
  29. package/dist/store-postgres.js +230 -101
  30. package/dist/store-postgres.js.map +1 -1
  31. package/dist/{store-redis-core-DEYO8Ryv.js → store-redis-core-DT01r4GZ.js} +167 -29
  32. package/dist/store-redis-core-DT01r4GZ.js.map +1 -0
  33. package/dist/store-redis-http.d.ts +1 -1
  34. package/dist/store-redis-http.js +2 -2
  35. package/dist/store-redis-http.js.map +1 -1
  36. package/dist/store-redis.d.ts +1 -1
  37. package/dist/store-redis.js +2 -2
  38. package/dist/store-redis.js.map +1 -1
  39. package/dist/store-sqlite.d.ts +1 -1
  40. package/dist/store-sqlite.d.ts.map +1 -1
  41. package/dist/store-sqlite.js +103 -19
  42. package/dist/store-sqlite.js.map +1 -1
  43. package/docs/concepts/02-handlers.mdx +4 -0
  44. package/docs/concepts/04-state.mdx +57 -9
  45. package/docs/guides/06-ai-agents.mdx +2 -1
  46. package/docs/guides/07-examples.mdx +56 -0
  47. package/docs/index.mdx +13 -0
  48. package/docs/reference/01-api.mdx +39 -16
  49. package/examples/README.md +15 -0
  50. package/examples/playground/AGENTS.md +11 -0
  51. package/examples/playground/DEPLOY.md +106 -0
  52. package/examples/playground/README.md +19 -0
  53. package/examples/playground/activity-feed.test.ts +10 -0
  54. package/examples/playground/app/agent/[agentId]/agent-client.tsx +376 -0
  55. package/examples/playground/app/agent/[agentId]/page.tsx +29 -0
  56. package/examples/playground/app/agent/events/route.ts +4 -0
  57. package/examples/playground/app/agent/model.ts +3 -0
  58. package/examples/playground/app/agent/new-agent-session.tsx +98 -0
  59. package/examples/playground/app/agent/page.tsx +25 -0
  60. package/examples/playground/app/agent/scheduler/route.ts +5 -0
  61. package/examples/playground/app/agent/server.ts +153 -0
  62. package/examples/playground/app/agent/session.ts +13 -0
  63. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +682 -0
  64. package/examples/playground/app/canvas/[canvasId]/canvas-replay.test.ts +68 -0
  65. package/examples/playground/app/canvas/[canvasId]/canvas-replay.ts +19 -0
  66. package/examples/playground/app/canvas/[canvasId]/page.tsx +22 -0
  67. package/examples/playground/app/canvas/[canvasId]/session.ts +19 -0
  68. package/examples/playground/app/canvas/events/route.ts +13 -0
  69. package/examples/playground/app/canvas/model.ts +94 -0
  70. package/examples/playground/app/canvas/open-canvas.tsx +40 -0
  71. package/examples/playground/app/canvas/page.tsx +20 -0
  72. package/examples/playground/app/canvas/server.ts +9 -0
  73. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.test.tsx +118 -0
  74. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +316 -0
  75. package/examples/playground/app/chat/[chatId]/chat-client.tsx +922 -0
  76. package/examples/playground/app/chat/[chatId]/chat-view.test.ts +152 -0
  77. package/examples/playground/app/chat/[chatId]/chat-view.ts +101 -0
  78. package/examples/playground/app/chat/[chatId]/composer.test.ts +44 -0
  79. package/examples/playground/app/chat/[chatId]/composer.ts +30 -0
  80. package/examples/playground/app/chat/[chatId]/page.tsx +30 -0
  81. package/examples/playground/app/chat/[chatId]/session.ts +7 -0
  82. package/examples/playground/app/chat/events/route.ts +7 -0
  83. package/examples/playground/app/chat/model.test.ts +155 -0
  84. package/examples/playground/app/chat/model.ts +310 -0
  85. package/examples/playground/app/chat/new-conversation.tsx +16 -0
  86. package/examples/playground/app/chat/page.tsx +25 -0
  87. package/examples/playground/app/chat/scheduler/route.ts +5 -0
  88. package/examples/playground/app/chat/server.ts +184 -0
  89. package/examples/playground/app/components/activity-feed.tsx +54 -0
  90. package/examples/playground/app/components/connection-pill.tsx +29 -0
  91. package/examples/playground/app/counter/counter-client.tsx +72 -0
  92. package/examples/playground/app/counter/events/route.ts +4 -0
  93. package/examples/playground/app/counter/model.test.ts +36 -0
  94. package/examples/playground/app/counter/model.ts +31 -0
  95. package/examples/playground/app/counter/page.tsx +24 -0
  96. package/examples/playground/app/counter/server.ts +9 -0
  97. package/examples/playground/app/counter/session.ts +13 -0
  98. package/examples/playground/app/documents/[documentId]/code-editor.tsx +80 -0
  99. package/examples/playground/app/documents/[documentId]/document-client.tsx +525 -0
  100. package/examples/playground/app/documents/[documentId]/page.tsx +23 -0
  101. package/examples/playground/app/documents/[documentId]/session.ts +7 -0
  102. package/examples/playground/app/documents/events/route.ts +4 -0
  103. package/examples/playground/app/documents/model.ts +55 -0
  104. package/examples/playground/app/documents/open-document.tsx +40 -0
  105. package/examples/playground/app/documents/page.tsx +22 -0
  106. package/examples/playground/app/documents/server.ts +9 -0
  107. package/examples/playground/app/globals.css +2078 -0
  108. package/examples/playground/app/layout.tsx +44 -0
  109. package/examples/playground/app/orders/[orderId]/order-client.tsx +140 -0
  110. package/examples/playground/app/orders/[orderId]/page.tsx +29 -0
  111. package/examples/playground/app/orders/[orderId]/session.ts +11 -0
  112. package/examples/playground/app/orders/create/route.ts +30 -0
  113. package/examples/playground/app/orders/events/route.ts +4 -0
  114. package/examples/playground/app/orders/model.ts +79 -0
  115. package/examples/playground/app/orders/new-order-form.tsx +98 -0
  116. package/examples/playground/app/orders/page.tsx +22 -0
  117. package/examples/playground/app/orders/scheduler/route.ts +5 -0
  118. package/examples/playground/app/orders/server.ts +50 -0
  119. package/examples/playground/app/page.tsx +102 -0
  120. package/examples/playground/app/recovery/[recoveryId]/page.tsx +31 -0
  121. package/examples/playground/app/recovery/[recoveryId]/recovery-client.tsx +144 -0
  122. package/examples/playground/app/recovery/[recoveryId]/session.ts +7 -0
  123. package/examples/playground/app/recovery/events/route.ts +3 -0
  124. package/examples/playground/app/recovery/model.ts +55 -0
  125. package/examples/playground/app/recovery/new-recovery-session.tsx +20 -0
  126. package/examples/playground/app/recovery/page.tsx +22 -0
  127. package/examples/playground/app/recovery/scheduler/route.ts +7 -0
  128. package/examples/playground/app/recovery/server.ts +53 -0
  129. package/examples/playground/app/recovery/start/route.ts +41 -0
  130. package/examples/playground/css.d.ts +4 -0
  131. package/examples/playground/lib/store.ts +15 -0
  132. package/examples/playground/next-env.d.ts +5 -0
  133. package/examples/playground/next.config.ts +10 -0
  134. package/examples/playground/package.json +46 -0
  135. package/examples/playground/tsconfig.json +37 -0
  136. package/examples/playground/vercel.json +40 -0
  137. package/package.json +5 -2
  138. package/src/ai-server.ts +27 -10
  139. package/src/server.ts +242 -87
  140. package/src/store-memory.ts +138 -20
  141. package/src/store-postgres.ts +355 -138
  142. package/src/store-redis-core.ts +201 -27
  143. package/src/store-redis-http.ts +1 -1
  144. package/src/store-redis.ts +1 -1
  145. package/src/store-sqlite.ts +191 -34
  146. package/src/store.ts +27 -9
  147. package/dist/server-286j79Mt.js.map +0 -1
  148. package/dist/server-DgXmORIq.d.ts.map +0 -1
  149. package/dist/store-flRz1OWh.d.ts.map +0 -1
  150. package/dist/store-redis-core-DEYO8Ryv.js.map +0 -1
@@ -0,0 +1,2078 @@
1
+ :root {
2
+ --bg: #fbfaf8;
3
+ --surface: #ffffff;
4
+ --ink: #1a1917;
5
+ --muted: #6f6b64;
6
+ --line: #e6e2da;
7
+ --accent: #0d5c46;
8
+ --accent-ink: #ffffff;
9
+ --danger: #a3352b;
10
+ --code-bg: #f1efe9;
11
+ font-family:
12
+ ui-sans-serif,
13
+ system-ui,
14
+ -apple-system,
15
+ 'Segoe UI',
16
+ sans-serif;
17
+ }
18
+
19
+ * {
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ html {
24
+ min-height: 100%;
25
+ }
26
+
27
+ body {
28
+ margin: 0;
29
+ width: 100%;
30
+ min-width: 0;
31
+ background: var(--bg);
32
+ color: var(--ink);
33
+ line-height: 1.55;
34
+ }
35
+
36
+ code,
37
+ pre,
38
+ kbd {
39
+ font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
40
+ font-size: 0.9em;
41
+ }
42
+
43
+ code {
44
+ background: var(--code-bg);
45
+ border-radius: 4px;
46
+ padding: 0.1em 0.35em;
47
+ }
48
+
49
+ main {
50
+ width: 100%;
51
+ min-width: 0;
52
+ min-height: 0;
53
+ max-width: 58rem;
54
+ margin: 0 auto;
55
+ padding: 2.5rem 1.25rem 4rem;
56
+ }
57
+
58
+ body:has(.chat-page) {
59
+ display: grid;
60
+ grid-template-rows: auto minmax(0, 1fr) auto;
61
+ height: 100dvh;
62
+ min-height: 0;
63
+ overflow: hidden;
64
+ }
65
+
66
+ main:has(> .chat-page) {
67
+ max-width: none;
68
+ margin: 0;
69
+ padding: 0;
70
+ }
71
+
72
+ body:has(.chat-page) .site-footer {
73
+ display: none;
74
+ }
75
+
76
+ .sr-only {
77
+ position: absolute;
78
+ width: 1px;
79
+ height: 1px;
80
+ padding: 0;
81
+ margin: -1px;
82
+ overflow: hidden;
83
+ clip: rect(0, 0, 0, 0);
84
+ white-space: nowrap;
85
+ border: 0;
86
+ }
87
+
88
+ h1 {
89
+ font-size: 1.65rem;
90
+ letter-spacing: -0.015em;
91
+ margin: 0 0 0.5rem;
92
+ }
93
+
94
+ h2 {
95
+ font-size: 1.1rem;
96
+ margin: 2rem 0 0.5rem;
97
+ }
98
+
99
+ p {
100
+ margin: 0.5rem 0;
101
+ }
102
+
103
+ .lede {
104
+ color: var(--muted);
105
+ font-size: 1.05rem;
106
+ max-width: 38rem;
107
+ }
108
+
109
+ a {
110
+ color: var(--accent);
111
+ }
112
+
113
+ /* ── header / footer ─────────────────────────────────────────────── */
114
+
115
+ .site-header {
116
+ min-width: 0;
117
+ overflow: hidden;
118
+ border-bottom: 1px solid var(--line);
119
+ background: var(--surface);
120
+ }
121
+
122
+ .site-header nav {
123
+ width: 100%;
124
+ min-width: 0;
125
+ max-width: 58rem;
126
+ margin: 0 auto;
127
+ padding: 0.75rem 1.25rem;
128
+ display: flex;
129
+ gap: 1.25rem;
130
+ align-items: baseline;
131
+ overflow-x: auto;
132
+ white-space: nowrap;
133
+ scrollbar-width: none;
134
+ }
135
+
136
+ .site-header a {
137
+ color: var(--ink);
138
+ text-decoration: none;
139
+ }
140
+
141
+ .site-header a:hover {
142
+ text-decoration: underline;
143
+ }
144
+
145
+ .brand {
146
+ font-weight: 700;
147
+ margin-right: auto;
148
+ }
149
+
150
+ .brand span {
151
+ font-weight: 400;
152
+ color: var(--muted);
153
+ }
154
+
155
+ .site-footer {
156
+ border-top: 1px solid var(--line);
157
+ color: var(--muted);
158
+ font-size: 0.85rem;
159
+ }
160
+
161
+ .site-footer p {
162
+ max-width: 58rem;
163
+ margin: 0 auto;
164
+ padding: 1rem 1.25rem;
165
+ }
166
+
167
+ /* ── cards ───────────────────────────────────────────────────────── */
168
+
169
+ .card-grid {
170
+ display: grid;
171
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
172
+ gap: 1rem;
173
+ margin: 1.5rem 0;
174
+ }
175
+
176
+ .card {
177
+ display: block;
178
+ background: var(--surface);
179
+ border: 1px solid var(--line);
180
+ border-radius: 10px;
181
+ padding: 1.1rem 1.25rem;
182
+ color: inherit;
183
+ text-decoration: none;
184
+ transition: border-color 120ms ease;
185
+ }
186
+
187
+ .card:hover {
188
+ border-color: var(--accent);
189
+ }
190
+
191
+ .card h2 {
192
+ margin: 0 0 0.35rem;
193
+ }
194
+
195
+ .card p {
196
+ color: var(--muted);
197
+ font-size: 0.92rem;
198
+ }
199
+
200
+ /* ── forms & buttons ─────────────────────────────────────────────── */
201
+
202
+ form {
203
+ display: grid;
204
+ gap: 0.9rem;
205
+ background: var(--surface);
206
+ border: 1px solid var(--line);
207
+ border-radius: 10px;
208
+ padding: 1.25rem;
209
+ margin: 1.25rem 0;
210
+ }
211
+
212
+ label {
213
+ display: grid;
214
+ gap: 0.3rem;
215
+ font-size: 0.9rem;
216
+ font-weight: 600;
217
+ }
218
+
219
+ input,
220
+ select,
221
+ textarea {
222
+ font: inherit;
223
+ padding: 0.5rem 0.65rem;
224
+ border: 1px solid var(--line);
225
+ border-radius: 7px;
226
+ background: var(--bg);
227
+ color: inherit;
228
+ }
229
+
230
+ input:focus-visible,
231
+ select:focus-visible,
232
+ textarea:focus-visible,
233
+ button:focus-visible {
234
+ outline: 2px solid var(--accent);
235
+ outline-offset: 1px;
236
+ }
237
+
238
+ button {
239
+ font: inherit;
240
+ font-weight: 600;
241
+ padding: 0.55rem 1.1rem;
242
+ border-radius: 7px;
243
+ border: 1px solid var(--accent);
244
+ background: var(--accent);
245
+ color: var(--accent-ink);
246
+ cursor: pointer;
247
+ justify-self: start;
248
+ }
249
+
250
+ button:hover:not(:disabled) {
251
+ filter: brightness(1.12);
252
+ }
253
+
254
+ button:disabled {
255
+ opacity: 0.45;
256
+ cursor: not-allowed;
257
+ }
258
+
259
+ button.secondary {
260
+ background: transparent;
261
+ color: var(--accent);
262
+ }
263
+
264
+ button.danger {
265
+ background: var(--danger);
266
+ border-color: var(--danger);
267
+ }
268
+
269
+ .inline-form {
270
+ display: flex;
271
+ gap: 0.6rem;
272
+ align-items: end;
273
+ flex-wrap: wrap;
274
+ }
275
+
276
+ .inline-form label {
277
+ flex: 1;
278
+ min-width: 12rem;
279
+ }
280
+
281
+ .error {
282
+ color: var(--danger);
283
+ font-size: 0.9rem;
284
+ }
285
+
286
+ .hint {
287
+ color: var(--muted);
288
+ font-size: 0.85rem;
289
+ }
290
+
291
+ /* ── session pages ───────────────────────────────────────────────── */
292
+
293
+ .session-header {
294
+ display: flex;
295
+ align-items: center;
296
+ gap: 0.75rem;
297
+ flex-wrap: wrap;
298
+ margin-bottom: 0.75rem;
299
+ }
300
+
301
+ .session-header h1 {
302
+ margin: 0;
303
+ }
304
+
305
+ .badge {
306
+ display: inline-block;
307
+ padding: 0.15rem 0.6rem;
308
+ border-radius: 99px;
309
+ font-size: 0.8rem;
310
+ font-weight: 600;
311
+ border: 1px solid var(--line);
312
+ background: var(--code-bg);
313
+ }
314
+
315
+ .badge.live {
316
+ background: #e8f3ee;
317
+ border-color: #bcd9cc;
318
+ color: var(--accent);
319
+ }
320
+
321
+ .badge.done {
322
+ background: var(--accent);
323
+ border-color: var(--accent);
324
+ color: var(--accent-ink);
325
+ }
326
+
327
+ .badge.cut {
328
+ background: #f8e9e7;
329
+ border-color: #e4c1bc;
330
+ color: var(--danger);
331
+ }
332
+
333
+ .badge.waiting {
334
+ background: #fff4d8;
335
+ border-color: #e5cb8d;
336
+ color: #805a08;
337
+ }
338
+
339
+ /* ── journey timeline ──────────────────────────────────────────── */
340
+
341
+ .timeline {
342
+ list-style: none;
343
+ display: flex;
344
+ flex-wrap: wrap;
345
+ gap: 0.35rem 0;
346
+ margin: 1rem 0;
347
+ padding: 0;
348
+ font-size: 0.85rem;
349
+ }
350
+
351
+ .timeline li {
352
+ display: flex;
353
+ align-items: center;
354
+ color: var(--muted);
355
+ white-space: nowrap;
356
+ }
357
+
358
+ .timeline li::before {
359
+ content: '';
360
+ width: 0.55rem;
361
+ height: 0.55rem;
362
+ border-radius: 50%;
363
+ margin-right: 0.4rem;
364
+ border: 2px solid var(--line);
365
+ background: var(--surface);
366
+ }
367
+
368
+ .timeline li + li {
369
+ margin-left: 0.35rem;
370
+ padding-left: 0.85rem;
371
+ background: linear-gradient(var(--line), var(--line)) no-repeat left center /
372
+ 0.5rem 2px;
373
+ }
374
+
375
+ .timeline li.done {
376
+ color: var(--ink);
377
+ }
378
+
379
+ .timeline li.done::before {
380
+ background: var(--accent);
381
+ border-color: var(--accent);
382
+ }
383
+
384
+ .timeline li.current {
385
+ color: var(--accent);
386
+ font-weight: 600;
387
+ }
388
+
389
+ .timeline li.current::before {
390
+ border-color: var(--accent);
391
+ background: var(--surface);
392
+ animation: pulse 1.4s ease-in-out infinite;
393
+ }
394
+
395
+ @keyframes pulse {
396
+ 50% {
397
+ background: var(--accent);
398
+ }
399
+ }
400
+
401
+ .facts {
402
+ display: grid;
403
+ grid-template-columns: max-content 1fr;
404
+ gap: 0.25rem 1rem;
405
+ margin: 1rem 0;
406
+ font-size: 0.95rem;
407
+ }
408
+
409
+ .facts dt {
410
+ color: var(--muted);
411
+ }
412
+
413
+ .facts dd {
414
+ margin: 0;
415
+ }
416
+
417
+ /* ── counter ─────────────────────────────────────────────────────────────── */
418
+
419
+ .counter-panel {
420
+ display: grid;
421
+ justify-items: center;
422
+ gap: 1.25rem;
423
+ margin: 1.5rem 0 0.75rem;
424
+ padding: 2rem;
425
+ border: 1px solid var(--line);
426
+ border-radius: 10px;
427
+ background: var(--surface);
428
+ }
429
+
430
+ .counter-value {
431
+ min-width: 5ch;
432
+ color: var(--ink);
433
+ font-size: clamp(3.5rem, 12vw, 6rem);
434
+ font-weight: 700;
435
+ font-variant-numeric: tabular-nums;
436
+ line-height: 1;
437
+ text-align: center;
438
+ }
439
+
440
+ .counter-actions {
441
+ display: flex;
442
+ gap: 0.75rem;
443
+ }
444
+
445
+ .counter-actions button {
446
+ min-width: 5rem;
447
+ justify-self: auto;
448
+ font-size: 1.15rem;
449
+ }
450
+
451
+ /* ── connection pill ─────────────────────────────────────────────── */
452
+
453
+ .conn {
454
+ display: inline-flex;
455
+ align-items: center;
456
+ gap: 0.35rem;
457
+ font-size: 0.78rem;
458
+ color: var(--muted);
459
+ font-variant-numeric: tabular-nums;
460
+ }
461
+
462
+ .conn::before {
463
+ content: '';
464
+ width: 0.5rem;
465
+ height: 0.5rem;
466
+ border-radius: 50%;
467
+ background: var(--line);
468
+ }
469
+
470
+ .conn.live::before {
471
+ background: #1a8a5f;
472
+ }
473
+
474
+ .conn.connecting::before {
475
+ background: #c98a1b;
476
+ animation: blink 1s steps(2, start) infinite;
477
+ }
478
+
479
+ .conn.closed::before {
480
+ background: var(--danger);
481
+ }
482
+
483
+ /* ── activity feed ───────────────────────────────────────────────── */
484
+
485
+ .feed {
486
+ list-style: none;
487
+ margin: 0.75rem 0;
488
+ padding: 0;
489
+ border: 1px solid var(--line);
490
+ border-radius: 10px;
491
+ background: var(--surface);
492
+ overflow: hidden;
493
+ }
494
+
495
+ .feed li {
496
+ display: flex;
497
+ gap: 0.75rem;
498
+ align-items: baseline;
499
+ padding: 0.5rem 0.9rem;
500
+ border-top: 1px solid var(--line);
501
+ font-size: 0.88rem;
502
+ }
503
+
504
+ .feed li:first-child {
505
+ border-top: none;
506
+ }
507
+
508
+ .feed .idx {
509
+ color: var(--muted);
510
+ min-width: 2.5rem;
511
+ }
512
+
513
+ .feed .type {
514
+ font-weight: 600;
515
+ }
516
+
517
+ .feed .payload {
518
+ color: var(--muted);
519
+ overflow: hidden;
520
+ text-overflow: ellipsis;
521
+ white-space: nowrap;
522
+ flex: 1;
523
+ }
524
+
525
+ .feed time {
526
+ color: var(--muted);
527
+ margin-left: auto;
528
+ font-variant-numeric: tabular-nums;
529
+ }
530
+
531
+ .frontier {
532
+ color: var(--muted);
533
+ font-size: 0.85rem;
534
+ margin-top: 0.5rem;
535
+ }
536
+
537
+ .activity-status {
538
+ margin: -0.15rem 0 0.65rem;
539
+ padding: 0.65rem 0.8rem;
540
+ border-left: 3px solid #d5a72f;
541
+ background: #fff9e8;
542
+ color: #6d5721;
543
+ font-size: 0.88rem;
544
+ }
545
+
546
+ /* ── recovery lab ───────────────────────────────────────────────── */
547
+
548
+ .timeout-callout {
549
+ margin: 1.25rem 0;
550
+ padding: 1rem 1.1rem;
551
+ border: 1px solid #e5cb8d;
552
+ border-radius: 10px;
553
+ background: #fff9e8;
554
+ }
555
+
556
+ .timeout-callout h2 {
557
+ margin-top: 0;
558
+ }
559
+
560
+ .proof {
561
+ padding: 0.65rem 0.8rem;
562
+ border-left: 3px solid var(--accent);
563
+ background: #e8f3ee;
564
+ font-size: 0.9rem;
565
+ }
566
+
567
+ /* ── chat room ───────────────────────────────────────────────────── */
568
+
569
+ .chat-page {
570
+ display: grid;
571
+ grid-template-rows: auto minmax(0, 1fr);
572
+ min-width: 0;
573
+ min-height: 0;
574
+ height: 100%;
575
+ background: var(--surface);
576
+ }
577
+
578
+ .chat-page-header {
579
+ min-height: 4rem;
580
+ margin: 0;
581
+ padding: 0.65rem 1rem;
582
+ border-bottom: 1px solid var(--line);
583
+ background: var(--surface);
584
+ flex-wrap: nowrap;
585
+ }
586
+
587
+ .chat-page-title {
588
+ min-width: 0;
589
+ margin-right: auto;
590
+ }
591
+
592
+ .chat-page-title h1 {
593
+ margin: 0;
594
+ font-size: 1.05rem;
595
+ line-height: 1.3;
596
+ }
597
+
598
+ .chat-page-title code {
599
+ font-size: 0.78em;
600
+ }
601
+
602
+ .chat-header-meta {
603
+ display: flex;
604
+ align-items: center;
605
+ gap: 0.45rem;
606
+ flex-wrap: wrap;
607
+ }
608
+
609
+ .identity-field.chat-identity {
610
+ display: grid;
611
+ grid-template-columns: auto minmax(5rem, 8rem);
612
+ align-items: center;
613
+ gap: 0.45rem;
614
+ min-width: 0;
615
+ max-width: none;
616
+ margin: 0;
617
+ color: var(--muted);
618
+ font-size: 0.75rem;
619
+ white-space: nowrap;
620
+ }
621
+
622
+ .identity-field.chat-identity input {
623
+ min-width: 0;
624
+ padding: 0.35rem 0.5rem;
625
+ }
626
+
627
+ .chat-workspace {
628
+ position: relative;
629
+ display: grid;
630
+ grid-template-columns: minmax(0, 1fr) minmax(18rem, 22rem);
631
+ min-width: 0;
632
+ min-height: 0;
633
+ overflow: hidden;
634
+ }
635
+
636
+ .chat {
637
+ display: grid;
638
+ grid-template-rows: minmax(0, 1fr) auto;
639
+ min-width: 0;
640
+ min-height: 0;
641
+ overflow: hidden;
642
+ background: var(--surface);
643
+ }
644
+
645
+ .chat-scroll {
646
+ min-height: 0;
647
+ overflow-y: auto;
648
+ overscroll-behavior: contain;
649
+ scrollbar-gutter: stable;
650
+ padding: 1rem clamp(0.75rem, 3vw, 2rem) 2rem;
651
+ }
652
+
653
+ .chat-scroll-content {
654
+ min-height: 100%;
655
+ }
656
+
657
+ .chat-empty {
658
+ min-height: 100%;
659
+ display: grid;
660
+ place-content: center;
661
+ margin: 0;
662
+ text-align: center;
663
+ }
664
+
665
+ .chat-transcript {
666
+ list-style: none;
667
+ width: min(100%, 56rem);
668
+ margin: 0 auto;
669
+ padding: 0;
670
+ display: grid;
671
+ }
672
+
673
+ .msg {
674
+ display: grid;
675
+ grid-template-columns: 2.5rem minmax(0, 1fr);
676
+ gap: 0.65rem;
677
+ width: 100%;
678
+ max-width: none;
679
+ padding: 0.08rem 0.65rem;
680
+ border-radius: 6px;
681
+ }
682
+
683
+ .msg.group-start {
684
+ margin-top: 0.75rem;
685
+ padding-top: 0.25rem;
686
+ }
687
+
688
+ .msg:first-child {
689
+ margin-top: 0;
690
+ }
691
+
692
+ .msg:hover,
693
+ .msg:focus-within {
694
+ background: #f7f5f1;
695
+ }
696
+
697
+ .msg-gutter {
698
+ display: grid;
699
+ place-items: start center;
700
+ min-width: 0;
701
+ padding-top: 0.05rem;
702
+ }
703
+
704
+ .msg-avatar {
705
+ display: grid;
706
+ place-items: center;
707
+ width: 2.25rem;
708
+ height: 2.25rem;
709
+ border-radius: 0.55rem;
710
+ background: #e8f3ee;
711
+ color: var(--accent);
712
+ font-size: 0.86rem;
713
+ font-weight: 800;
714
+ }
715
+
716
+ .msg.agent .msg-avatar {
717
+ background: #e8eef9;
718
+ color: #3874c8;
719
+ }
720
+
721
+ .msg-compact-time {
722
+ padding-top: 0.25rem;
723
+ color: var(--muted);
724
+ font-size: 0.62rem;
725
+ font-variant-numeric: tabular-nums;
726
+ line-height: 1.2;
727
+ opacity: 0;
728
+ text-align: center;
729
+ white-space: nowrap;
730
+ }
731
+
732
+ .msg:hover .msg-compact-time,
733
+ .msg:focus-within .msg-compact-time {
734
+ opacity: 1;
735
+ }
736
+
737
+ .msg-body {
738
+ min-width: 0;
739
+ }
740
+
741
+ .msg header {
742
+ display: flex;
743
+ align-items: baseline;
744
+ gap: 0.5rem;
745
+ margin-bottom: 0.05rem;
746
+ }
747
+
748
+ .msg-author {
749
+ font-size: 0.86rem;
750
+ font-weight: 750;
751
+ }
752
+
753
+ .msg header time {
754
+ color: var(--muted);
755
+ font-size: 0.72rem;
756
+ font-variant-numeric: tabular-nums;
757
+ }
758
+
759
+ .msg-text {
760
+ margin: 0;
761
+ max-width: 70ch;
762
+ padding: 0;
763
+ white-space: pre-wrap;
764
+ overflow-wrap: anywhere;
765
+ }
766
+
767
+ .msg.agent .msg-author {
768
+ color: #3874c8;
769
+ }
770
+
771
+ .mention {
772
+ background: #e8f3ee;
773
+ color: var(--accent);
774
+ border-radius: 4px;
775
+ padding: 0 0.15em;
776
+ font-weight: 600;
777
+ }
778
+
779
+ .presence {
780
+ min-width: 0;
781
+ min-height: 1.2rem;
782
+ margin: 0;
783
+ overflow: hidden;
784
+ color: var(--muted);
785
+ font-size: 0.82rem;
786
+ font-style: italic;
787
+ text-overflow: ellipsis;
788
+ white-space: nowrap;
789
+ }
790
+
791
+ .chat-presence-row {
792
+ min-height: 2rem;
793
+ margin: 0.25rem auto 0;
794
+ display: flex;
795
+ align-items: center;
796
+ justify-content: space-between;
797
+ gap: 0.75rem;
798
+ }
799
+
800
+ .chat-presence-row button {
801
+ flex: 0 0 auto;
802
+ white-space: nowrap;
803
+ }
804
+
805
+ .chat-agent-error {
806
+ margin: 0 auto 0.65rem;
807
+ padding: 0.65rem 0.75rem;
808
+ border: 1px solid #e4c1bc;
809
+ border-radius: 8px;
810
+ background: #fff5f3;
811
+ display: flex;
812
+ align-items: center;
813
+ justify-content: space-between;
814
+ gap: 0.75rem;
815
+ }
816
+
817
+ .chat-agent-error p {
818
+ margin: 0;
819
+ color: var(--danger);
820
+ font-size: 0.82rem;
821
+ white-space: pre-wrap;
822
+ }
823
+
824
+ .chat-send-error {
825
+ margin: 0 auto 0.5rem;
826
+ }
827
+
828
+ .agent-stream-trigger {
829
+ display: flex;
830
+ align-items: center;
831
+ gap: 0.45rem;
832
+ margin-top: 0.24rem;
833
+ padding: 0;
834
+ border: 0;
835
+ background: transparent;
836
+ color: var(--muted);
837
+ font-size: 0.69rem;
838
+ font-weight: 500;
839
+ }
840
+
841
+ .agent-stream-trigger span:last-child {
842
+ color: var(--accent);
843
+ }
844
+
845
+ .agent-stream-trigger:hover:not(:disabled) {
846
+ filter: none;
847
+ color: var(--ink);
848
+ }
849
+
850
+ .composer {
851
+ position: relative;
852
+ display: flex;
853
+ flex-direction: column;
854
+ gap: 0;
855
+ min-width: 0;
856
+ min-height: 7.5rem;
857
+ padding: 0;
858
+ overflow: visible;
859
+ border: 1px solid #a8a39a;
860
+ border-radius: 11px;
861
+ background: var(--surface);
862
+ margin: 0;
863
+ box-shadow: 0 1px 2px rgb(26 25 23 / 5%);
864
+ cursor: text;
865
+ transition:
866
+ border-color 120ms ease,
867
+ box-shadow 120ms ease;
868
+ }
869
+
870
+ .composer:focus-within {
871
+ border-color: var(--ink);
872
+ box-shadow:
873
+ 0 0 0 1px var(--ink),
874
+ 0 3px 10px rgb(26 25 23 / 7%);
875
+ }
876
+
877
+ .composer-input-surface {
878
+ min-width: 0;
879
+ padding: 0.85rem 0.9rem 0.35rem;
880
+ cursor: text;
881
+ }
882
+
883
+ .composer textarea {
884
+ display: block;
885
+ width: 100%;
886
+ min-width: 0;
887
+ min-height: 4.25rem;
888
+ max-height: min(12rem, 30dvh);
889
+ margin: 0;
890
+ padding: 0;
891
+ resize: none;
892
+ overflow-y: hidden;
893
+ border: 0;
894
+ border-radius: 0;
895
+ outline: 0;
896
+ background: var(--surface);
897
+ font-size: 1rem;
898
+ line-height: 1.45;
899
+ }
900
+
901
+ .composer textarea:focus-visible {
902
+ outline: 0;
903
+ }
904
+
905
+ .composer-toolbar {
906
+ display: flex;
907
+ align-items: center;
908
+ gap: 0.65rem;
909
+ min-width: 0;
910
+ padding: 0.45rem 0.5rem 0.5rem 0.65rem;
911
+ cursor: text;
912
+ }
913
+
914
+ .composer-mode-group {
915
+ display: flex;
916
+ align-items: center;
917
+ flex: 1 1 auto;
918
+ gap: 0.5rem;
919
+ min-width: 0;
920
+ }
921
+
922
+ .composer-mode-selector {
923
+ display: inline-flex;
924
+ align-items: center;
925
+ gap: 0.42rem;
926
+ min-height: 2.15rem;
927
+ padding: 0.28rem 0.58rem;
928
+ border: 1px solid var(--line);
929
+ border-radius: 7px;
930
+ background: #f7f5f1;
931
+ color: var(--ink);
932
+ cursor: pointer;
933
+ font-size: 0.78rem;
934
+ font-weight: 650;
935
+ line-height: 1;
936
+ white-space: nowrap;
937
+ }
938
+
939
+ .composer-mode-selector:hover {
940
+ border-color: #bdb7ac;
941
+ background: var(--code-bg);
942
+ }
943
+
944
+ .composer-mode-selector:has(input:focus-visible) {
945
+ outline: 2px solid var(--accent);
946
+ outline-offset: 1px;
947
+ }
948
+
949
+ .composer-mode-selector:has(input:disabled) {
950
+ opacity: 0.5;
951
+ cursor: not-allowed;
952
+ }
953
+
954
+ .composer-mode-selector input {
955
+ width: 0.95rem;
956
+ height: 0.95rem;
957
+ margin: 0;
958
+ padding: 0;
959
+ accent-color: var(--accent);
960
+ cursor: inherit;
961
+ }
962
+
963
+ .composer-mode-selector input:focus-visible {
964
+ outline: 0;
965
+ }
966
+
967
+ .composer-mode-description {
968
+ min-width: 0;
969
+ overflow: hidden;
970
+ color: var(--muted);
971
+ font-size: 0.72rem;
972
+ text-overflow: ellipsis;
973
+ white-space: nowrap;
974
+ }
975
+
976
+ .composer-key-hint {
977
+ margin-left: auto;
978
+ color: var(--muted);
979
+ font-size: 0.68rem;
980
+ white-space: nowrap;
981
+ }
982
+
983
+ .composer-send {
984
+ display: inline-flex;
985
+ align-items: center;
986
+ justify-content: center;
987
+ gap: 0.4rem;
988
+ min-height: 2.15rem;
989
+ flex: 0 0 auto;
990
+ margin: 0;
991
+ padding: 0.38rem 0.72rem;
992
+ justify-self: auto;
993
+ cursor: pointer;
994
+ }
995
+
996
+ .composer-send span:last-child {
997
+ font-size: 1rem;
998
+ line-height: 1;
999
+ }
1000
+
1001
+ .chat-composer-dock {
1002
+ border-top: 1px solid var(--line);
1003
+ padding: 0.7rem clamp(0.75rem, 3vw, 2rem)
1004
+ calc(0.35rem + env(safe-area-inset-bottom));
1005
+ background: var(--surface);
1006
+ box-shadow: 0 -8px 22px rgb(56 48 35 / 5%);
1007
+ }
1008
+
1009
+ .chat-composer-dock > * {
1010
+ width: min(100%, 56rem);
1011
+ margin-right: auto;
1012
+ margin-left: auto;
1013
+ }
1014
+
1015
+ .mention-popover {
1016
+ position: absolute;
1017
+ bottom: calc(100% + 0.35rem);
1018
+ left: 0;
1019
+ z-index: 10;
1020
+ list-style: none;
1021
+ margin: 0;
1022
+ padding: 0.25rem;
1023
+ min-width: 12rem;
1024
+ background: var(--surface);
1025
+ border: 1px solid var(--line);
1026
+ border-radius: 8px;
1027
+ box-shadow: 0 6px 20px rgb(26 25 23 / 0.08);
1028
+ }
1029
+
1030
+ .mention-popover button {
1031
+ display: block;
1032
+ width: 100%;
1033
+ text-align: left;
1034
+ background: none;
1035
+ border: none;
1036
+ color: inherit;
1037
+ font-weight: 500;
1038
+ padding: 0.35rem 0.6rem;
1039
+ border-radius: 6px;
1040
+ }
1041
+
1042
+ .mention-popover button.active,
1043
+ .mention-popover button:hover {
1044
+ background: var(--code-bg);
1045
+ color: var(--accent);
1046
+ }
1047
+
1048
+ .chat-sidebar {
1049
+ min-width: 0;
1050
+ min-height: 0;
1051
+ margin: 0;
1052
+ overflow: hidden;
1053
+ border: 0;
1054
+ border-left: 1px solid var(--line);
1055
+ border-radius: 0;
1056
+ background: #f7f5f1;
1057
+ }
1058
+
1059
+ .chat-sidebar-toggle {
1060
+ display: none;
1061
+ width: 100%;
1062
+ border: 0;
1063
+ border-radius: 0;
1064
+ background: transparent;
1065
+ color: var(--ink);
1066
+ }
1067
+
1068
+ .chat-sidebar-body {
1069
+ height: 100%;
1070
+ padding: 0.9rem 1rem 2rem;
1071
+ overflow-y: auto;
1072
+ overscroll-behavior: contain;
1073
+ }
1074
+
1075
+ .chat-sidebar-body > section > h2 {
1076
+ margin: 1.3rem 0 0.5rem;
1077
+ font-size: 0.9rem;
1078
+ }
1079
+
1080
+ .chat-sidebar .feed {
1081
+ font-size: 0.78rem;
1082
+ }
1083
+
1084
+ .chat-sidebar .feed li {
1085
+ display: grid;
1086
+ grid-template-columns: auto minmax(0, 1fr);
1087
+ gap: 0.1rem 0.5rem;
1088
+ padding: 0.45rem 0.55rem;
1089
+ }
1090
+
1091
+ .chat-sidebar .feed .idx {
1092
+ min-width: 0;
1093
+ }
1094
+
1095
+ .chat-sidebar .feed .payload,
1096
+ .chat-sidebar .feed time {
1097
+ grid-column: 1 / -1;
1098
+ }
1099
+
1100
+ .chat-sidebar .feed time {
1101
+ margin-left: 0;
1102
+ }
1103
+
1104
+ /* The projected UIMessage stays live while this modal sheet is open. */
1105
+ .agent-stream-drawer {
1106
+ position: fixed;
1107
+ inset: 0 0 0 auto;
1108
+ width: min(34rem, 100vw);
1109
+ max-width: none;
1110
+ height: 100dvh;
1111
+ max-height: none;
1112
+ margin: 0 0 0 auto;
1113
+ padding: 0;
1114
+ overflow: hidden;
1115
+ border: 0;
1116
+ border-left: 1px solid var(--line);
1117
+ background: var(--surface);
1118
+ color: var(--ink);
1119
+ box-shadow: -18px 0 45px rgb(26 25 23 / 14%);
1120
+ }
1121
+
1122
+ .agent-stream-drawer::backdrop {
1123
+ background: rgb(26 25 23 / 28%);
1124
+ backdrop-filter: blur(2px);
1125
+ }
1126
+
1127
+ .agent-stream-drawer[open] {
1128
+ animation: drawer-in 180ms ease-out;
1129
+ }
1130
+
1131
+ .agent-stream-drawer-shell {
1132
+ display: grid;
1133
+ grid-template-rows: auto minmax(0, 1fr);
1134
+ height: 100%;
1135
+ }
1136
+
1137
+ .agent-stream-drawer-header {
1138
+ display: flex;
1139
+ align-items: flex-start;
1140
+ justify-content: space-between;
1141
+ gap: 1rem;
1142
+ padding: 1rem 1.1rem;
1143
+ border-bottom: 1px solid var(--line);
1144
+ background: var(--surface);
1145
+ }
1146
+
1147
+ .agent-stream-drawer-header h2 {
1148
+ margin: 0.08rem 0 0.15rem;
1149
+ font-size: 1.15rem;
1150
+ }
1151
+
1152
+ .agent-stream-drawer-header p:last-child {
1153
+ margin: 0;
1154
+ color: var(--muted);
1155
+ font-size: 0.78rem;
1156
+ }
1157
+
1158
+ .agent-stream-close {
1159
+ flex: 0 0 auto;
1160
+ }
1161
+
1162
+ .agent-stream-drawer-body {
1163
+ min-height: 0;
1164
+ padding: 1rem 1.1rem 2rem;
1165
+ overflow-y: auto;
1166
+ overscroll-behavior: contain;
1167
+ }
1168
+
1169
+ .agent-stream-identity {
1170
+ display: flex;
1171
+ align-items: center;
1172
+ gap: 0.55rem;
1173
+ min-width: 0;
1174
+ }
1175
+
1176
+ .agent-stream-identity code {
1177
+ min-width: 0;
1178
+ overflow: hidden;
1179
+ color: var(--muted);
1180
+ text-overflow: ellipsis;
1181
+ white-space: nowrap;
1182
+ }
1183
+
1184
+ .agent-stream-section {
1185
+ margin-top: 1.25rem;
1186
+ }
1187
+
1188
+ .agent-stream-section:first-of-type {
1189
+ margin-top: 1rem;
1190
+ }
1191
+
1192
+ .agent-stream-section h3 {
1193
+ margin: 0 0 0.25rem;
1194
+ font-size: 0.9rem;
1195
+ }
1196
+
1197
+ .agent-stream-parts,
1198
+ .agent-stream-generations {
1199
+ display: grid;
1200
+ gap: 0.6rem;
1201
+ margin-top: 0.65rem;
1202
+ }
1203
+
1204
+ .agent-stream-step {
1205
+ display: flex;
1206
+ align-items: center;
1207
+ gap: 0.6rem;
1208
+ color: var(--muted);
1209
+ font-size: 0.7rem;
1210
+ font-weight: 700;
1211
+ letter-spacing: 0.06em;
1212
+ text-transform: uppercase;
1213
+ }
1214
+
1215
+ .agent-stream-step::before,
1216
+ .agent-stream-step::after {
1217
+ content: '';
1218
+ height: 1px;
1219
+ flex: 1;
1220
+ background: var(--line);
1221
+ }
1222
+
1223
+ .agent-stream-part,
1224
+ .agent-stream-generation {
1225
+ min-width: 0;
1226
+ padding: 0.7rem;
1227
+ border: 1px solid var(--line);
1228
+ border-radius: 8px;
1229
+ background: var(--bg);
1230
+ }
1231
+
1232
+ .agent-stream-part.reasoning {
1233
+ border-color: #d8cbea;
1234
+ background: #fbf8ff;
1235
+ }
1236
+
1237
+ .agent-stream-part.tool {
1238
+ border-color: #bcd9cc;
1239
+ background: #f5fbf8;
1240
+ }
1241
+
1242
+ .agent-stream-part > header,
1243
+ .agent-stream-generation > header {
1244
+ display: flex;
1245
+ align-items: baseline;
1246
+ justify-content: space-between;
1247
+ gap: 0.65rem;
1248
+ margin: 0 0 0.45rem;
1249
+ font-size: 0.76rem;
1250
+ font-weight: 700;
1251
+ }
1252
+
1253
+ .agent-stream-part-state,
1254
+ .agent-stream-generation > header span {
1255
+ color: var(--muted);
1256
+ font-size: 0.68rem;
1257
+ font-weight: 500;
1258
+ }
1259
+
1260
+ .agent-stream-part p {
1261
+ margin: 0;
1262
+ white-space: pre-wrap;
1263
+ }
1264
+
1265
+ .agent-stream-part details,
1266
+ .agent-stream-generation details {
1267
+ margin-top: 0.6rem;
1268
+ }
1269
+
1270
+ .agent-stream-part summary,
1271
+ .agent-stream-generation summary,
1272
+ .agent-stream-raw summary {
1273
+ color: var(--muted);
1274
+ cursor: pointer;
1275
+ font-size: 0.74rem;
1276
+ font-weight: 650;
1277
+ }
1278
+
1279
+ .agent-stream-part pre,
1280
+ .agent-stream-generation pre,
1281
+ .agent-stream-raw pre,
1282
+ .agent-stream-value pre {
1283
+ max-height: 18rem;
1284
+ margin: 0.4rem 0 0;
1285
+ padding: 0.55rem;
1286
+ overflow: auto;
1287
+ border-radius: 6px;
1288
+ background: var(--code-bg);
1289
+ font-size: 0.68rem;
1290
+ white-space: pre-wrap;
1291
+ word-break: break-word;
1292
+ }
1293
+
1294
+ .agent-stream-value + .agent-stream-value {
1295
+ margin-top: 0.6rem;
1296
+ }
1297
+
1298
+ .agent-stream-value > span {
1299
+ color: var(--muted);
1300
+ font-size: 0.68rem;
1301
+ font-weight: 700;
1302
+ letter-spacing: 0.05em;
1303
+ text-transform: uppercase;
1304
+ }
1305
+
1306
+ .agent-stream-generation dl {
1307
+ display: grid;
1308
+ grid-template-columns: auto minmax(0, 1fr);
1309
+ gap: 0.25rem 0.75rem;
1310
+ margin: 0;
1311
+ font-size: 0.74rem;
1312
+ }
1313
+
1314
+ .agent-stream-generation dt {
1315
+ color: var(--muted);
1316
+ }
1317
+
1318
+ .agent-stream-generation dd {
1319
+ min-width: 0;
1320
+ margin: 0;
1321
+ overflow-wrap: anywhere;
1322
+ }
1323
+
1324
+ .agent-stream-empty {
1325
+ margin: 1rem 0;
1326
+ padding: 1rem;
1327
+ border-radius: 8px;
1328
+ background: var(--code-bg);
1329
+ color: var(--muted);
1330
+ text-align: center;
1331
+ }
1332
+
1333
+ .agent-stream-raw {
1334
+ margin-top: 1.25rem;
1335
+ padding-top: 0.85rem;
1336
+ border-top: 1px solid var(--line);
1337
+ }
1338
+
1339
+ @keyframes drawer-in {
1340
+ from {
1341
+ opacity: 0;
1342
+ transform: translateX(1.5rem);
1343
+ }
1344
+ }
1345
+
1346
+ @media (prefers-reduced-motion: reduce) {
1347
+ .agent-stream-drawer[open] {
1348
+ animation: none;
1349
+ }
1350
+ }
1351
+
1352
+ @media (max-width: 780px) {
1353
+ .chat-page-header {
1354
+ align-items: center;
1355
+ flex-wrap: wrap;
1356
+ }
1357
+
1358
+ .chat-page-title {
1359
+ flex: 1;
1360
+ }
1361
+
1362
+ .chat-header-meta {
1363
+ order: 3;
1364
+ width: 100%;
1365
+ overflow-x: auto;
1366
+ flex-wrap: nowrap;
1367
+ }
1368
+
1369
+ .chat-workspace {
1370
+ grid-template-columns: minmax(0, 1fr);
1371
+ grid-template-rows: minmax(0, 1fr);
1372
+ }
1373
+
1374
+ .chat-scroll {
1375
+ padding-top: 3.75rem;
1376
+ }
1377
+
1378
+ .chat-sidebar {
1379
+ position: absolute;
1380
+ z-index: 20;
1381
+ top: 0.55rem;
1382
+ right: 0.65rem;
1383
+ width: min(20rem, calc(100% - 1.3rem));
1384
+ min-height: auto;
1385
+ overflow: visible;
1386
+ border: 1px solid var(--line);
1387
+ border-radius: 8px;
1388
+ background: var(--surface);
1389
+ box-shadow: 0 8px 26px rgb(26 25 23 / 12%);
1390
+ }
1391
+
1392
+ .chat-sidebar-toggle {
1393
+ display: flex;
1394
+ align-items: center;
1395
+ justify-content: space-between;
1396
+ gap: 0.75rem;
1397
+ padding: 0.55rem 0.8rem;
1398
+ cursor: pointer;
1399
+ font-size: 0.82rem;
1400
+ font-weight: 700;
1401
+ }
1402
+
1403
+ .chat-sidebar-toggle:hover:not(:disabled) {
1404
+ filter: none;
1405
+ }
1406
+
1407
+ .chat-sidebar:not(.open) > .chat-sidebar-body {
1408
+ display: none;
1409
+ }
1410
+
1411
+ .chat-sidebar.open .chat-sidebar-body {
1412
+ height: auto;
1413
+ max-height: min(62dvh, 30rem);
1414
+ padding-top: 0.5rem;
1415
+ overflow-y: auto;
1416
+ }
1417
+
1418
+ .composer-key-hint {
1419
+ display: none;
1420
+ }
1421
+ }
1422
+
1423
+ @media (hover: none) {
1424
+ .msg-compact-time {
1425
+ opacity: 0.7;
1426
+ }
1427
+ }
1428
+
1429
+ @media (max-width: 520px) {
1430
+ .chat-page-header {
1431
+ gap: 0.45rem;
1432
+ padding: 0.5rem 0.65rem;
1433
+ }
1434
+
1435
+ .chat-page-title .eyebrow,
1436
+ .identity-field.chat-identity > span {
1437
+ display: none;
1438
+ }
1439
+
1440
+ .identity-field.chat-identity {
1441
+ grid-template-columns: minmax(4.5rem, 7rem);
1442
+ }
1443
+
1444
+ .chat-scroll {
1445
+ padding: 3.75rem 0.3rem 1rem;
1446
+ }
1447
+
1448
+ .msg {
1449
+ grid-template-columns: 2.15rem minmax(0, 1fr);
1450
+ gap: 0.5rem;
1451
+ padding-right: 0.45rem;
1452
+ padding-left: 0.45rem;
1453
+ }
1454
+
1455
+ .msg-avatar {
1456
+ width: 2rem;
1457
+ height: 2rem;
1458
+ }
1459
+
1460
+ .chat-composer-dock {
1461
+ padding-right: 0.65rem;
1462
+ padding-left: 0.65rem;
1463
+ }
1464
+
1465
+ .composer-input-surface {
1466
+ padding: 0.75rem 0.75rem 0.3rem;
1467
+ }
1468
+
1469
+ .composer-toolbar {
1470
+ gap: 0.45rem;
1471
+ padding-right: 0.4rem;
1472
+ padding-left: 0.5rem;
1473
+ }
1474
+
1475
+ .composer-mode-description {
1476
+ display: none;
1477
+ }
1478
+
1479
+ .agent-stream-drawer {
1480
+ width: 100vw;
1481
+ }
1482
+ }
1483
+
1484
+ @keyframes blink {
1485
+ to {
1486
+ visibility: hidden;
1487
+ }
1488
+ }
1489
+
1490
+ /* ── durable agent ──────────────────────────────────────────────── */
1491
+
1492
+ .agent-conversation {
1493
+ display: grid;
1494
+ overflow: hidden;
1495
+ margin: 1rem 0;
1496
+ border: 1px solid var(--line);
1497
+ border-radius: 12px;
1498
+ background: var(--surface);
1499
+ }
1500
+
1501
+ .agent-transcript {
1502
+ display: grid;
1503
+ gap: 1rem;
1504
+ min-height: 10rem;
1505
+ padding: 1rem;
1506
+ }
1507
+
1508
+ .agent-empty {
1509
+ align-self: center;
1510
+ color: var(--muted);
1511
+ text-align: center;
1512
+ }
1513
+
1514
+ .agent-message {
1515
+ display: grid;
1516
+ grid-template-columns: 4rem minmax(0, 1fr);
1517
+ gap: 0.75rem;
1518
+ align-items: start;
1519
+ }
1520
+
1521
+ .agent-message.user > div {
1522
+ padding: 0.7rem 0.85rem;
1523
+ border-radius: 9px;
1524
+ background: var(--code-bg);
1525
+ }
1526
+
1527
+ .agent-message p:first-child {
1528
+ margin-top: 0;
1529
+ }
1530
+
1531
+ .agent-message p:last-child {
1532
+ margin-bottom: 0;
1533
+ }
1534
+
1535
+ .agent-role {
1536
+ padding-top: 0;
1537
+ color: var(--muted);
1538
+ font-size: 0.75rem;
1539
+ font-weight: 700;
1540
+ letter-spacing: 0.06em;
1541
+ text-transform: uppercase;
1542
+ }
1543
+
1544
+ .agent-message.user .agent-role {
1545
+ padding-top: 0.65rem;
1546
+ }
1547
+
1548
+ .agent-thinking {
1549
+ display: flex;
1550
+ gap: 0.45rem;
1551
+ align-items: center;
1552
+ min-height: 1.5rem;
1553
+ margin: 0.55rem 0 0;
1554
+ color: var(--muted);
1555
+ font-size: 0.9rem;
1556
+ }
1557
+
1558
+ .agent-thinking > span {
1559
+ width: 0.5rem;
1560
+ height: 0.5rem;
1561
+ border-radius: 50%;
1562
+ background: var(--accent);
1563
+ animation: agent-thinking 1s ease-in-out infinite alternate;
1564
+ }
1565
+
1566
+ @keyframes agent-thinking {
1567
+ to {
1568
+ opacity: 0.3;
1569
+ transform: scale(0.72);
1570
+ }
1571
+ }
1572
+
1573
+ .tool-card {
1574
+ display: grid;
1575
+ gap: 0.45rem;
1576
+ margin: 0.7rem 0;
1577
+ padding: 0.75rem 0.85rem;
1578
+ border: 1px solid var(--line);
1579
+ border-left: 3px solid var(--accent);
1580
+ border-radius: 8px;
1581
+ background: var(--bg);
1582
+ }
1583
+
1584
+ .tool-card.approval-requested,
1585
+ .tool-card.approval-responded,
1586
+ .tool-card.output-denied {
1587
+ border-left-color: #c98a1b;
1588
+ }
1589
+
1590
+ .tool-card > div {
1591
+ display: flex;
1592
+ gap: 0.6rem;
1593
+ align-items: baseline;
1594
+ justify-content: space-between;
1595
+ }
1596
+
1597
+ .tool-card span {
1598
+ color: var(--muted);
1599
+ font-size: 0.78rem;
1600
+ }
1601
+
1602
+ .tool-card > code {
1603
+ width: fit-content;
1604
+ color: var(--muted);
1605
+ font-size: 0.78rem;
1606
+ }
1607
+
1608
+ .tool-card pre {
1609
+ overflow-x: auto;
1610
+ margin: 0;
1611
+ color: var(--muted);
1612
+ font-size: 0.75rem;
1613
+ white-space: pre-wrap;
1614
+ }
1615
+
1616
+ .approval-card {
1617
+ display: flex;
1618
+ gap: 1.25rem;
1619
+ align-items: center;
1620
+ justify-content: space-between;
1621
+ margin: 0 1rem 1rem;
1622
+ padding: 1rem 1.1rem;
1623
+ border: 1px solid #e5cb8d;
1624
+ border-radius: 10px;
1625
+ background: #fffaec;
1626
+ }
1627
+
1628
+ .approval-card h2 {
1629
+ margin: 0.15rem 0;
1630
+ }
1631
+
1632
+ .approval-card p:last-child {
1633
+ color: var(--muted);
1634
+ font-size: 0.9rem;
1635
+ }
1636
+
1637
+ .approval-actions,
1638
+ .agent-form-actions {
1639
+ display: flex;
1640
+ gap: 0.55rem;
1641
+ flex-wrap: wrap;
1642
+ }
1643
+
1644
+ .approval-actions {
1645
+ flex: 0 0 auto;
1646
+ }
1647
+
1648
+ .agent-form {
1649
+ margin: 0;
1650
+ padding: 1rem;
1651
+ border: 0;
1652
+ border-top: 1px solid var(--line);
1653
+ border-radius: 0;
1654
+ background: var(--surface);
1655
+ }
1656
+
1657
+ .agent-form textarea {
1658
+ resize: vertical;
1659
+ }
1660
+
1661
+ .agent-new .agent-transcript {
1662
+ min-height: 7rem;
1663
+ }
1664
+
1665
+ .agent-new-error {
1666
+ margin: 0;
1667
+ padding: 0 1rem 1rem;
1668
+ }
1669
+
1670
+ .agent-generation-error {
1671
+ margin: 0;
1672
+ padding: 1rem;
1673
+ border-top: 1px solid var(--line);
1674
+ white-space: pre-wrap;
1675
+ }
1676
+
1677
+ @media (max-width: 680px) {
1678
+ .agent-message {
1679
+ grid-template-columns: 1fr;
1680
+ gap: 0.2rem;
1681
+ }
1682
+
1683
+ .agent-role,
1684
+ .agent-message.user .agent-role {
1685
+ padding-top: 0;
1686
+ }
1687
+
1688
+ .approval-card {
1689
+ align-items: stretch;
1690
+ flex-direction: column;
1691
+ }
1692
+ }
1693
+
1694
+ /* ── multiplayer document ──────────────────────────────────────── */
1695
+
1696
+ .document-picker {
1697
+ grid-template-columns: max-content max-content minmax(12rem, 1fr) max-content;
1698
+ align-items: end;
1699
+ }
1700
+
1701
+ .document-picker .hint {
1702
+ align-self: center;
1703
+ padding-bottom: 0.55rem;
1704
+ }
1705
+
1706
+ .document-header {
1707
+ justify-content: flex-end;
1708
+ }
1709
+
1710
+ .document-header > div:first-child {
1711
+ margin-right: auto;
1712
+ }
1713
+
1714
+ .document-header h1 {
1715
+ margin-top: 0.1rem;
1716
+ }
1717
+
1718
+ .eyebrow {
1719
+ margin: 0;
1720
+ color: var(--muted);
1721
+ font-size: 0.75rem;
1722
+ font-weight: 700;
1723
+ letter-spacing: 0.08em;
1724
+ text-transform: uppercase;
1725
+ }
1726
+
1727
+ button.compact {
1728
+ padding: 0.32rem 0.7rem;
1729
+ font-size: 0.82rem;
1730
+ }
1731
+
1732
+ .editor-toolbar {
1733
+ display: flex;
1734
+ gap: 1rem;
1735
+ align-items: end;
1736
+ justify-content: space-between;
1737
+ margin: 1.25rem 0 0.65rem;
1738
+ }
1739
+
1740
+ .identity-field {
1741
+ min-width: 10rem;
1742
+ max-width: 14rem;
1743
+ }
1744
+
1745
+ .identity-field input {
1746
+ background: var(--surface);
1747
+ }
1748
+
1749
+ .collaborators {
1750
+ display: flex;
1751
+ gap: 0.4rem 0.7rem;
1752
+ align-items: center;
1753
+ justify-content: flex-end;
1754
+ flex-wrap: wrap;
1755
+ min-height: 1.8rem;
1756
+ }
1757
+
1758
+ .collaborator {
1759
+ display: inline-flex;
1760
+ align-items: center;
1761
+ gap: 0.35rem;
1762
+ color: var(--muted);
1763
+ font-size: 0.8rem;
1764
+ white-space: nowrap;
1765
+ }
1766
+
1767
+ .collaborator-dot {
1768
+ width: 0.62rem;
1769
+ height: 0.62rem;
1770
+ border-radius: 50%;
1771
+ background: var(--collaborator-color);
1772
+ }
1773
+
1774
+ .document-editor {
1775
+ overflow: hidden;
1776
+ border: 1px solid var(--line);
1777
+ border-radius: 12px;
1778
+ background: var(--surface);
1779
+ box-shadow: 0 12px 35px rgb(56 48 35 / 7%);
1780
+ }
1781
+
1782
+ .document-title {
1783
+ display: block;
1784
+ width: 100%;
1785
+ border: 0;
1786
+ border-radius: 0;
1787
+ background: var(--surface);
1788
+ }
1789
+
1790
+ .document-title:focus-visible {
1791
+ outline: 0;
1792
+ }
1793
+
1794
+ .document-title {
1795
+ padding: 1.5rem 1.7rem 0.8rem;
1796
+ font-size: 1.7rem;
1797
+ font-weight: 700;
1798
+ letter-spacing: -0.02em;
1799
+ }
1800
+
1801
+ .document-body {
1802
+ min-height: 24rem;
1803
+ border-top: 1px solid var(--line);
1804
+ background: var(--surface);
1805
+ }
1806
+
1807
+ .document-title::placeholder,
1808
+ .document-body .cm-placeholder {
1809
+ color: #aaa59c;
1810
+ }
1811
+
1812
+ /* Out of flow: an in-flow placeholder makes a peer's caret at
1813
+ position 0 park at the end of the hint text instead of the line
1814
+ start. */
1815
+ .document-body .cm-placeholder {
1816
+ position: absolute;
1817
+ pointer-events: none;
1818
+ }
1819
+
1820
+ /* y-codemirror ships hover-only name labels (opacity 0) in serif;
1821
+ always-on is the point of having names, and the caret dot is
1822
+ redundant once the label is permanent. */
1823
+ .document-body .cm-ySelectionInfo {
1824
+ opacity: 1;
1825
+ font-family: inherit;
1826
+ border-radius: 3px 3px 3px 0;
1827
+ padding: 0 4px;
1828
+ }
1829
+
1830
+ .document-body .cm-ySelectionCaretDot {
1831
+ display: none;
1832
+ }
1833
+
1834
+ .document-body .cm-editor {
1835
+ min-height: 24rem;
1836
+ color: var(--ink);
1837
+ background: var(--surface);
1838
+ font-size: 0.95rem;
1839
+ }
1840
+
1841
+ .document-body .cm-editor.cm-focused {
1842
+ outline: 0;
1843
+ }
1844
+
1845
+ .document-body .cm-scroller {
1846
+ min-height: 24rem;
1847
+ line-height: 1.65;
1848
+ }
1849
+
1850
+ .document-body .cm-content {
1851
+ padding: 1rem 0.75rem 1.5rem;
1852
+ caret-color: var(--accent);
1853
+ }
1854
+
1855
+ .document-body .cm-gutters {
1856
+ border-right: 1px solid var(--line);
1857
+ color: #aaa59c;
1858
+ background: var(--bg);
1859
+ }
1860
+
1861
+ .document-body .cm-activeLine,
1862
+ .document-body .cm-activeLineGutter {
1863
+ background: #f6f4ef;
1864
+ }
1865
+
1866
+ .document-body .cm-selectionBackground,
1867
+ .document-body .cm-content ::selection {
1868
+ background: #cde2da !important;
1869
+ }
1870
+
1871
+ .editor-status {
1872
+ display: flex;
1873
+ gap: 0.8rem;
1874
+ align-items: center;
1875
+ min-height: 2.5rem;
1876
+ padding: 0.45rem 0.8rem;
1877
+ border-top: 1px solid var(--line);
1878
+ color: var(--muted);
1879
+ background: var(--bg);
1880
+ font-size: 0.78rem;
1881
+ }
1882
+
1883
+ .editor-status button {
1884
+ margin-left: auto;
1885
+ }
1886
+
1887
+ .sync-state {
1888
+ display: inline-flex;
1889
+ align-items: center;
1890
+ gap: 0.35rem;
1891
+ }
1892
+
1893
+ .sync-state::before {
1894
+ content: '';
1895
+ width: 0.48rem;
1896
+ height: 0.48rem;
1897
+ border-radius: 50%;
1898
+ background: var(--accent);
1899
+ }
1900
+
1901
+ .sync-state.saving::before {
1902
+ background: #c98a1b;
1903
+ animation: blink 1s steps(2, start) infinite;
1904
+ }
1905
+
1906
+ .sync-state.error::before {
1907
+ background: var(--danger);
1908
+ }
1909
+
1910
+ /* ── multiplayer canvas ──────────────────────────────── */
1911
+
1912
+ .canvas-toolbar {
1913
+ display: flex;
1914
+ gap: 1rem;
1915
+ align-items: end;
1916
+ justify-content: space-between;
1917
+ margin: 1.25rem 0 0.65rem;
1918
+ min-height: 1.8rem;
1919
+ }
1920
+
1921
+ .canvas-toolbar .collaborators {
1922
+ padding-bottom: 0.55rem;
1923
+ }
1924
+
1925
+ .canvas-stage {
1926
+ position: relative;
1927
+ overflow: hidden;
1928
+ border: 1px solid var(--line);
1929
+ border-radius: 12px;
1930
+ background: var(--surface);
1931
+ box-shadow: 0 12px 35px rgb(56 48 35 / 7%);
1932
+ }
1933
+
1934
+ .canvas-stage.historical {
1935
+ border-color: #e5cb8d;
1936
+ background: #fffdf6;
1937
+ }
1938
+
1939
+ .canvas-stage.historical .canvas-svg {
1940
+ pointer-events: none;
1941
+ }
1942
+
1943
+ .canvas-svg {
1944
+ display: block;
1945
+ width: 100%;
1946
+ aspect-ratio: 16 / 9;
1947
+ touch-action: none;
1948
+ user-select: none;
1949
+ cursor: crosshair;
1950
+ }
1951
+
1952
+ .canvas-shape {
1953
+ fill-opacity: 0.55;
1954
+ stroke-width: 1.5;
1955
+ cursor: grab;
1956
+ }
1957
+
1958
+ .canvas-shape.dragging {
1959
+ fill-opacity: 0.75;
1960
+ stroke-width: 2;
1961
+ cursor: grabbing;
1962
+ }
1963
+
1964
+ .canvas-shape.ghost {
1965
+ fill-opacity: 0.25;
1966
+ stroke-width: 2;
1967
+ stroke-dasharray: 5 4;
1968
+ }
1969
+
1970
+ .canvas-cursor {
1971
+ pointer-events: none;
1972
+ }
1973
+
1974
+ .canvas-cursor text {
1975
+ font-size: 11px;
1976
+ font-weight: 600;
1977
+ paint-order: stroke;
1978
+ stroke: var(--surface);
1979
+ stroke-width: 3;
1980
+ }
1981
+
1982
+ /* Fixed slot in both modes — toggling replay must not shift layout.
1983
+ The button rides inside it, hidden-not-removed when live. */
1984
+ .canvas-status {
1985
+ margin: 0;
1986
+ padding: 0.35rem 0.9rem;
1987
+ border-top: 1px solid var(--line);
1988
+ background: var(--bg);
1989
+ color: var(--muted);
1990
+ font-size: 0.85rem;
1991
+ display: flex;
1992
+ align-items: center;
1993
+ gap: 0.8rem;
1994
+ }
1995
+
1996
+ .canvas-status-text {
1997
+ flex: 1;
1998
+ white-space: nowrap;
1999
+ overflow: hidden;
2000
+ text-overflow: ellipsis;
2001
+ }
2002
+
2003
+ .canvas-status.replaying {
2004
+ border-top-color: #e5cb8d;
2005
+ background: #fff9e8;
2006
+ color: #6d5721;
2007
+ }
2008
+
2009
+ .canvas-scrubber {
2010
+ display: flex;
2011
+ gap: 0.8rem;
2012
+ align-items: center;
2013
+ margin: 0.9rem 0 0.25rem;
2014
+ }
2015
+
2016
+ .canvas-scrubber input[type='range'] {
2017
+ flex: 1;
2018
+ padding: 0;
2019
+ border: none;
2020
+ background: none;
2021
+ accent-color: var(--accent);
2022
+ }
2023
+
2024
+ /* The slider flexes, so the hint must hold its width or the thumb
2025
+ jumps under the pointer as digits change mid-scrub. */
2026
+ .canvas-scrubber .hint {
2027
+ white-space: nowrap;
2028
+ font-variant-numeric: tabular-nums;
2029
+ min-width: 10.5rem;
2030
+ }
2031
+
2032
+ .canvas-back-to-live:disabled {
2033
+ visibility: hidden;
2034
+ }
2035
+
2036
+ @media (max-width: 680px) {
2037
+ .site-header nav {
2038
+ gap: 0.7rem;
2039
+ font-size: 0.9rem;
2040
+ }
2041
+
2042
+ .canvas-toolbar {
2043
+ align-items: stretch;
2044
+ flex-direction: column;
2045
+ gap: 0.4rem;
2046
+ }
2047
+
2048
+ .document-picker {
2049
+ grid-template-columns: 1fr;
2050
+ }
2051
+
2052
+ .document-picker .hint {
2053
+ display: none;
2054
+ }
2055
+
2056
+ .editor-toolbar {
2057
+ align-items: stretch;
2058
+ flex-direction: column;
2059
+ }
2060
+
2061
+ .collaborators {
2062
+ justify-content: flex-start;
2063
+ }
2064
+
2065
+ .document-title {
2066
+ font-size: 1.35rem;
2067
+ }
2068
+
2069
+ .document-body,
2070
+ .document-body .cm-editor,
2071
+ .document-body .cm-scroller {
2072
+ min-height: 20rem;
2073
+ }
2074
+
2075
+ .document-feed time {
2076
+ display: none;
2077
+ }
2078
+ }