@hybridlabor-api/bdb-synapse 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +173 -0
  3. package/bin/synapse +0 -0
  4. package/cmd/rubriceval/main.go +308 -0
  5. package/cmd/synapse/main.go +280 -0
  6. package/cmd/synapse/main_test.go +16 -0
  7. package/go.mod +7 -0
  8. package/go.sum +6 -0
  9. package/internal/adapter/adapter.go +1117 -0
  10. package/internal/adapter/adapter_test.go +518 -0
  11. package/internal/adapter/agy/adapter.go +193 -0
  12. package/internal/adapter/claudecode/adapter.go +415 -0
  13. package/internal/adapter/claudecode/adapter_test.go +260 -0
  14. package/internal/adapter/claudecode/agents.go +387 -0
  15. package/internal/adapter/claudecode/agents_test.go +480 -0
  16. package/internal/adapter/claudecode/summary_inputs_test.go +19 -0
  17. package/internal/adapter/codex/adapter.go +919 -0
  18. package/internal/adapter/codex/adapter_test.go +920 -0
  19. package/internal/adapter/codex/agents.go +401 -0
  20. package/internal/adapter/codex/agents_test.go +610 -0
  21. package/internal/adapter/codex/summary_inputs_test.go +20 -0
  22. package/internal/adapter/pi/adapter.go +483 -0
  23. package/internal/adapter/pi/adapter_test.go +517 -0
  24. package/internal/citymap/builder.go +1124 -0
  25. package/internal/citymap/builder_test.go +818 -0
  26. package/internal/judge/cache.go +180 -0
  27. package/internal/judge/cli.go +240 -0
  28. package/internal/judge/cli_test.go +68 -0
  29. package/internal/judge/fresh_summary_test.go +37 -0
  30. package/internal/judge/input.go +233 -0
  31. package/internal/judge/judge.go +416 -0
  32. package/internal/judge/judge_test.go +288 -0
  33. package/internal/judge/prompt.go +129 -0
  34. package/internal/judge/rubric.go +275 -0
  35. package/internal/judge/rubric_test.go +642 -0
  36. package/internal/model/agent.go +63 -0
  37. package/internal/model/agent_schema_test.go +86 -0
  38. package/internal/model/agent_test.go +64 -0
  39. package/internal/model/model.go +175 -0
  40. package/internal/model/report.go +166 -0
  41. package/internal/model/stats.go +151 -0
  42. package/internal/model/stats_test.go +89 -0
  43. package/internal/model/trace_schema_test.go +67 -0
  44. package/internal/server/analyze.go +286 -0
  45. package/internal/server/analyze_test.go +297 -0
  46. package/internal/server/codex_index_test.go +40 -0
  47. package/internal/server/hardening_test.go +147 -0
  48. package/internal/server/reportindex.go +91 -0
  49. package/internal/server/reportindex_test.go +116 -0
  50. package/internal/server/server.go +1099 -0
  51. package/internal/server/server_test.go +1389 -0
  52. package/internal/server/static/assets/fraunces-latin-ext-standard-italic-CGbN9UgK.woff2 +0 -0
  53. package/internal/server/static/assets/fraunces-latin-ext-standard-normal-CJcjJNj7.woff2 +0 -0
  54. package/internal/server/static/assets/fraunces-latin-standard-italic-lSdLDfvT.woff2 +0 -0
  55. package/internal/server/static/assets/fraunces-latin-standard-normal-DihXLNYH.woff2 +0 -0
  56. package/internal/server/static/assets/fraunces-vietnamese-standard-italic-DxWqP7Ku.woff2 +0 -0
  57. package/internal/server/static/assets/fraunces-vietnamese-standard-normal-Czevyj-6.woff2 +0 -0
  58. package/internal/server/static/assets/index-BNoY_BiB.css +1 -0
  59. package/internal/server/static/assets/index-C_adLrJr.js +3 -0
  60. package/internal/server/static/assets/react-gcHzaSmV.js +10 -0
  61. package/internal/server/static/assets/schibsted-grotesk-latin-ext-wght-normal-hsMS0n0O.woff2 +0 -0
  62. package/internal/server/static/assets/schibsted-grotesk-latin-wght-normal-Bb8VGrTG.woff2 +0 -0
  63. package/internal/server/static/assets/three-DnGjZfD1.js +4012 -0
  64. package/internal/server/static/index.html +26 -0
  65. package/internal/server/tracestore.go +173 -0
  66. package/internal/server/tracestore_test.go +51 -0
  67. package/internal/textutil/truncate.go +30 -0
  68. package/internal/textutil/truncate_test.go +39 -0
  69. package/package.json +35 -0
  70. package/web/e2e/agent-lens.spec.ts +688 -0
  71. package/web/index.html +23 -0
  72. package/web/package-lock.json +1933 -0
  73. package/web/package.json +33 -0
  74. package/web/playwright.config.ts +24 -0
  75. package/web/src/App.tsx +876 -0
  76. package/web/src/api/client.ts +74 -0
  77. package/web/src/main.tsx +12 -0
  78. package/web/src/playback/recorder.ts +160 -0
  79. package/web/src/playback/reducer.ts +91 -0
  80. package/web/src/scene/CityScene.tsx +638 -0
  81. package/web/src/scene/TreeScene.tsx +656 -0
  82. package/web/src/scene/dirLabels.ts +145 -0
  83. package/web/src/scene/sceneUtils.ts +144 -0
  84. package/web/src/scene/textures.ts +60 -0
  85. package/web/src/scene/trail.ts +79 -0
  86. package/web/src/scene/treeLayout.ts +169 -0
  87. package/web/src/state/filters.ts +40 -0
  88. package/web/src/state/store.ts +83 -0
  89. package/web/src/styles.css +2565 -0
  90. package/web/src/types.ts +315 -0
  91. package/web/src/ui/AgentsPanel.tsx +376 -0
  92. package/web/src/ui/Dock.tsx +104 -0
  93. package/web/src/ui/Hud.tsx +335 -0
  94. package/web/src/ui/Inspector.tsx +107 -0
  95. package/web/src/ui/LogoMark.tsx +38 -0
  96. package/web/src/ui/ReportPanel.tsx +491 -0
  97. package/web/src/ui/SessionRail.tsx +316 -0
  98. package/web/src/ui/Timeline.tsx +458 -0
  99. package/web/src/ui/ViewPanel.tsx +45 -0
  100. package/web/src/ui/shortcuts.ts +4 -0
  101. package/web/tsconfig.json +21 -0
  102. package/web/vite.config.ts +28 -0
@@ -0,0 +1,2565 @@
1
+ /* mindwalk — nocturnal observatory.
2
+ Light is data: only touch states and trails may glow. */
3
+
4
+ :root {
5
+ color-scheme: dark;
6
+
7
+ --sky: oklch(0.19 0.016 258);
8
+ --panel: oklch(0.245 0.014 256);
9
+ --panel-raised: oklch(0.285 0.014 254);
10
+ --hairline: oklch(0.37 0.014 254);
11
+ --hairline-strong: oklch(0.46 0.016 252);
12
+
13
+ --ink: oklch(0.91 0.014 88);
14
+ --muted: oklch(0.72 0.02 252);
15
+ --faint: oklch(0.63 0.02 252);
16
+
17
+ /* type scale: two UI sizes (1.2 step), display sizes for the stage */
18
+ --text-xs: 0.75rem;
19
+ --text-sm: 0.9rem;
20
+ --text-lg: 1.35rem;
21
+
22
+ /* the light scale (touch states: what the scene and HUD glow with) */
23
+ --moss: oklch(0.78 0.11 131);
24
+ --moon: oklch(0.83 0.07 250);
25
+ --amber: oklch(0.79 0.13 68);
26
+ --ember: oklch(0.73 0.16 52);
27
+ --pine: oklch(0.72 0.09 155);
28
+ --alarm: oklch(0.7 0.16 32);
29
+
30
+ /* timeline action spectrum: cool = observation, warm = mutation;
31
+ chroma tracks importance so edits outshine the background hum */
32
+ --act-search: oklch(0.74 0.09 192);
33
+ --act-read: oklch(0.8 0.07 242);
34
+ --act-edit: oklch(0.8 0.16 75);
35
+ --act-verify: oklch(0.75 0.13 145);
36
+ --act-exec: oklch(0.58 0.02 255);
37
+ --mark-compaction: oklch(0.66 0.2 32);
38
+ --mark-subagent: oklch(0.74 0.09 300);
39
+
40
+ --font-display: "Fraunces Variable", "Songti SC", "Noto Serif SC", serif;
41
+ --font-body: "Schibsted Grotesk Variable", "PingFang SC", "Hiragino Sans GB",
42
+ "Noto Sans SC", system-ui, sans-serif;
43
+
44
+ color: var(--ink);
45
+ background: var(--sky);
46
+ font-family: var(--font-body);
47
+ font-size: 15px;
48
+ line-height: 1.5;
49
+ font-synthesis: none;
50
+ text-rendering: optimizeLegibility;
51
+ -webkit-font-smoothing: antialiased;
52
+ }
53
+
54
+ * {
55
+ box-sizing: border-box;
56
+ }
57
+
58
+ body {
59
+ margin: 0;
60
+ min-width: 320px;
61
+ min-height: 100vh;
62
+ overflow: hidden;
63
+ }
64
+
65
+ button,
66
+ input {
67
+ font: inherit;
68
+ color: inherit;
69
+ }
70
+
71
+ button {
72
+ cursor: pointer;
73
+ border: 0;
74
+ background: none;
75
+ padding: 0;
76
+ }
77
+
78
+ h1,
79
+ h2,
80
+ h3,
81
+ p,
82
+ dl,
83
+ dd {
84
+ margin: 0;
85
+ }
86
+
87
+ ::selection {
88
+ background: oklch(0.79 0.13 68 / 0.35);
89
+ }
90
+
91
+ :focus-visible {
92
+ outline: 1.5px solid var(--amber);
93
+ outline-offset: 2px;
94
+ }
95
+
96
+ /* ---------- frame ---------- */
97
+
98
+ .app-frame {
99
+ display: flex;
100
+ width: 100vw;
101
+ height: 100vh;
102
+ height: 100dvh;
103
+ overflow: hidden;
104
+ background: var(--sky);
105
+ }
106
+
107
+ .stage {
108
+ flex: 1;
109
+ min-width: 0;
110
+ display: flex;
111
+ flex-direction: column;
112
+ }
113
+
114
+ .viewport {
115
+ position: relative;
116
+ flex: 1;
117
+ min-height: 0;
118
+ }
119
+
120
+ .city-scene {
121
+ position: absolute;
122
+ inset: 0;
123
+ }
124
+
125
+ .city-scene canvas {
126
+ display: block;
127
+ }
128
+
129
+ /* ---------- session rail ---------- */
130
+
131
+ .session-rail {
132
+ flex: none;
133
+ width: 292px;
134
+ display: flex;
135
+ flex-direction: column;
136
+ background: var(--panel);
137
+ border-right: 1px solid var(--hairline);
138
+ transition: margin 0.28s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s;
139
+ }
140
+
141
+ /* slide out by margin so the rail's content never reflows mid-transition;
142
+ visibility drops it from the tab order once hidden */
143
+ .session-rail.collapsed {
144
+ margin-left: -293px;
145
+ visibility: hidden;
146
+ transition: margin 0.28s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s 0.28s;
147
+ }
148
+
149
+ .rail-head {
150
+ display: flex;
151
+ align-items: baseline;
152
+ justify-content: space-between;
153
+ padding: 20px 18px 14px;
154
+ }
155
+
156
+ .wordmark {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ gap: 8px;
160
+ font-family: var(--font-display);
161
+ font-style: italic;
162
+ font-weight: 480;
163
+ font-size: 1.5rem;
164
+ letter-spacing: 0.01em;
165
+ line-height: 1;
166
+ }
167
+
168
+ /* the mark's tile is the night sky; a hairline keeps it a window, not a hole */
169
+ .wordmark svg {
170
+ flex: none;
171
+ border-radius: 5px;
172
+ box-shadow: 0 0 0 1px var(--hairline);
173
+ }
174
+
175
+ .wordmark .spark {
176
+ color: var(--amber);
177
+ }
178
+
179
+ .rail-head-actions {
180
+ display: flex;
181
+ gap: 2px;
182
+ }
183
+
184
+ .rail-head .icon-btn {
185
+ transform: translateY(2px);
186
+ }
187
+
188
+ /* reopens the rail once it has slid away; sits where the wordmark was */
189
+ .rail-expand {
190
+ position: absolute;
191
+ top: 20px;
192
+ left: 24px;
193
+ z-index: 5;
194
+ display: inline-flex;
195
+ align-items: center;
196
+ justify-content: center;
197
+ width: 30px;
198
+ height: 30px;
199
+ border: 1px solid var(--hairline-strong);
200
+ border-radius: 4px;
201
+ background: var(--panel);
202
+ color: var(--muted);
203
+ }
204
+
205
+ .rail-expand:hover {
206
+ color: var(--ink);
207
+ background: var(--panel-raised);
208
+ }
209
+
210
+ /* search + filter chips form one control zone above the list */
211
+ .rail-controls {
212
+ display: grid;
213
+ gap: 9px;
214
+ margin: 0 18px 10px;
215
+ padding-bottom: 10px;
216
+ border-bottom: 1px solid var(--hairline);
217
+ }
218
+
219
+ .rail-filter {
220
+ display: flex;
221
+ align-items: center;
222
+ gap: 8px;
223
+ color: var(--faint);
224
+ }
225
+
226
+ .rail-filter input {
227
+ flex: 1;
228
+ min-width: 0;
229
+ border: 0;
230
+ background: none;
231
+ color: var(--ink);
232
+ font-size: var(--text-sm);
233
+ }
234
+
235
+ .rail-filter input::placeholder {
236
+ color: var(--faint);
237
+ }
238
+
239
+ .rail-filter input:focus {
240
+ outline: none;
241
+ }
242
+
243
+ .rail-chips {
244
+ display: flex;
245
+ flex-wrap: wrap;
246
+ align-items: center;
247
+ gap: 6px;
248
+ }
249
+
250
+ .chip {
251
+ padding: 3px 10px;
252
+ border: 1px solid var(--hairline-strong);
253
+ border-radius: 999px;
254
+ color: var(--muted);
255
+ font-size: var(--text-xs);
256
+ font-weight: 560;
257
+ letter-spacing: 0.04em;
258
+ }
259
+
260
+ .chip:hover {
261
+ color: var(--ink);
262
+ background: var(--panel-raised);
263
+ }
264
+
265
+ .chip.active {
266
+ color: oklch(0.95 0.02 88);
267
+ background: var(--panel-raised);
268
+ border-color: var(--muted);
269
+ }
270
+
271
+ /* empty-session visibility: a quiet utility, styled like the refresh icon
272
+ rather than a peer of the source chips */
273
+ .eye-toggle {
274
+ display: inline-flex;
275
+ align-items: center;
276
+ justify-content: center;
277
+ width: 24px;
278
+ height: 24px;
279
+ margin-left: auto;
280
+ border-radius: 4px;
281
+ color: var(--faint);
282
+ }
283
+
284
+ .eye-toggle:hover {
285
+ color: var(--ink);
286
+ background: var(--panel-raised);
287
+ }
288
+
289
+ .eye-toggle.showing {
290
+ color: oklch(0.95 0.02 88);
291
+ background: var(--panel-raised);
292
+ }
293
+
294
+ .session-list {
295
+ flex: 1;
296
+ overflow-y: auto;
297
+ padding: 4px 10px 12px;
298
+ scrollbar-width: thin;
299
+ scrollbar-color: var(--hairline) transparent;
300
+ }
301
+
302
+ .session-row {
303
+ position: relative;
304
+ width: 100%;
305
+ display: grid;
306
+ gap: 4px;
307
+ padding: 10px 10px 10px 14px;
308
+ border-radius: 4px;
309
+ text-align: left;
310
+ }
311
+
312
+ .session-row::before {
313
+ content: "";
314
+ position: absolute;
315
+ left: 0;
316
+ top: 12px;
317
+ bottom: 12px;
318
+ width: 2px;
319
+ border-radius: 2px;
320
+ background: transparent;
321
+ }
322
+
323
+ .session-row:hover {
324
+ background: oklch(0.285 0.014 254 / 0.6);
325
+ }
326
+
327
+ .session-row.active {
328
+ background: var(--panel-raised);
329
+ }
330
+
331
+ .session-row.active::before {
332
+ background: var(--amber);
333
+ box-shadow: 0 0 8px oklch(0.79 0.13 68 / 0.55);
334
+ }
335
+
336
+ .session-title {
337
+ font-size: var(--text-sm);
338
+ font-weight: 560;
339
+ line-height: 1.4;
340
+ overflow-wrap: anywhere;
341
+ display: -webkit-box;
342
+ -webkit-line-clamp: 2;
343
+ -webkit-box-orient: vertical;
344
+ overflow: hidden;
345
+ color: var(--ink);
346
+ }
347
+
348
+ .session-row.active .session-title {
349
+ color: oklch(0.95 0.02 88);
350
+ }
351
+
352
+ /* one fixed line: dot + text, ellipsized — row height never depends on
353
+ how long the branch name happens to be */
354
+ .session-meta {
355
+ display: flex;
356
+ align-items: center;
357
+ gap: 7px;
358
+ min-width: 0;
359
+ color: var(--faint);
360
+ font-size: var(--text-xs);
361
+ letter-spacing: 0.02em;
362
+ font-variant-numeric: tabular-nums;
363
+ }
364
+
365
+ .session-row.active .session-meta {
366
+ color: var(--muted);
367
+ }
368
+
369
+ .session-meta-text {
370
+ min-width: 0;
371
+ white-space: nowrap;
372
+ overflow: hidden;
373
+ text-overflow: ellipsis;
374
+ }
375
+
376
+ /* rail-head map popover: the one entry point for opening any repository map */
377
+ .rail-map {
378
+ position: relative;
379
+ }
380
+
381
+ .rail-map-pop {
382
+ position: absolute;
383
+ top: calc(100% + 6px);
384
+ left: 0;
385
+ z-index: 20;
386
+ display: grid;
387
+ /* minmax(0, …) keeps the track at the popover width — the form's intrinsic
388
+ width (input default size + button) is wider and would overflow it */
389
+ grid-template-columns: minmax(0, 1fr);
390
+ gap: 6px;
391
+ padding: 8px;
392
+ width: 240px;
393
+ border: 1px solid var(--hairline-strong);
394
+ border-radius: 6px;
395
+ background: var(--panel-raised);
396
+ box-shadow: 0 8px 24px oklch(0 0 0 / 0.4);
397
+ }
398
+
399
+ /* primary choice: the active session's repo, name + full path visible */
400
+ .rail-map-primary {
401
+ display: flex;
402
+ align-items: center;
403
+ gap: 9px;
404
+ width: 100%;
405
+ padding: 8px 9px;
406
+ text-align: left;
407
+ color: var(--muted);
408
+ border: 1px solid var(--hairline-strong);
409
+ border-radius: 4px;
410
+ }
411
+
412
+ .rail-map-primary:hover {
413
+ color: var(--ink);
414
+ background: var(--panel);
415
+ }
416
+
417
+ .rail-map-primary-text {
418
+ display: grid;
419
+ gap: 1px;
420
+ min-width: 0;
421
+ }
422
+
423
+ .rail-map-primary-name {
424
+ color: var(--ink);
425
+ font-size: var(--text-sm);
426
+ font-weight: 560;
427
+ }
428
+
429
+ .rail-map-primary-path {
430
+ font-size: var(--text-xs);
431
+ color: var(--faint);
432
+ overflow: hidden;
433
+ white-space: nowrap;
434
+ text-overflow: ellipsis;
435
+ direction: rtl; /* keep the tail of long paths visible */
436
+ text-align: left;
437
+ }
438
+
439
+ .rail-map-divider {
440
+ display: flex;
441
+ align-items: center;
442
+ gap: 8px;
443
+ margin: 2px 0;
444
+ color: var(--faint);
445
+ font-size: var(--text-xs);
446
+ letter-spacing: 0.04em;
447
+ }
448
+
449
+ .rail-map-divider::before,
450
+ .rail-map-divider::after {
451
+ content: "";
452
+ flex: 1;
453
+ height: 1px;
454
+ background: var(--hairline);
455
+ }
456
+
457
+ .rail-map-label {
458
+ color: var(--faint);
459
+ font-size: var(--text-xs);
460
+ letter-spacing: 0.08em;
461
+ text-transform: uppercase;
462
+ }
463
+
464
+ .rail-map-form {
465
+ display: flex;
466
+ gap: 6px;
467
+ }
468
+
469
+ .rail-map-input {
470
+ flex: 1;
471
+ min-width: 0;
472
+ padding: 6px 8px;
473
+ color: var(--ink);
474
+ font-size: var(--text-sm);
475
+ background: var(--panel);
476
+ border: 1px solid var(--hairline-strong);
477
+ border-radius: 4px;
478
+ }
479
+
480
+ .rail-map-input::placeholder {
481
+ color: var(--faint);
482
+ }
483
+
484
+ .rail-map-input:focus {
485
+ outline: none;
486
+ border-color: var(--muted);
487
+ }
488
+
489
+ .rail-map-go {
490
+ padding: 6px 11px;
491
+ color: var(--ink);
492
+ font-size: var(--text-xs);
493
+ font-weight: 560;
494
+ border: 1px solid var(--hairline-strong);
495
+ border-radius: 4px;
496
+ }
497
+
498
+ .rail-map-go:hover:not(:disabled) {
499
+ background: var(--panel);
500
+ }
501
+
502
+ .rail-map-go:disabled {
503
+ opacity: 0.4;
504
+ }
505
+
506
+ .rail-foot {
507
+ padding: 10px 18px 14px;
508
+ border-top: 1px solid var(--hairline);
509
+ color: var(--faint);
510
+ font-size: var(--text-xs);
511
+ letter-spacing: 0.08em;
512
+ text-transform: uppercase;
513
+ font-variant-numeric: tabular-nums;
514
+ }
515
+
516
+ /* ---------- HUD ---------- */
517
+
518
+ .hud {
519
+ position: absolute;
520
+ inset: 0;
521
+ pointer-events: none;
522
+ padding: 20px 24px;
523
+ display: flex;
524
+ align-items: flex-start;
525
+ justify-content: space-between;
526
+ gap: 24px;
527
+ }
528
+
529
+ .hud-left {
530
+ min-width: 0;
531
+ transition: margin-left 0.28s cubic-bezier(0.16, 1, 0.3, 1);
532
+ }
533
+
534
+ /* clear the floating expand button */
535
+ .rail-collapsed .hud-left {
536
+ margin-left: 42px;
537
+ }
538
+
539
+ .hud-repo {
540
+ font-family: var(--font-display);
541
+ font-weight: 540;
542
+ font-size: 1.6rem;
543
+ line-height: 1.1;
544
+ letter-spacing: 0.005em;
545
+ }
546
+
547
+ .hud-title-line {
548
+ display: flex;
549
+ align-items: center;
550
+ flex-wrap: wrap;
551
+ gap: 8px 12px;
552
+ }
553
+
554
+ .hud-lens {
555
+ display: inline-flex;
556
+ align-items: center;
557
+ gap: 6px;
558
+ padding: 3px 8px;
559
+ border: 1px solid var(--hairline-strong);
560
+ border-radius: 999px;
561
+ background: oklch(0.245 0.014 256 / 0.86);
562
+ color: var(--ink);
563
+ font-size: var(--text-xs);
564
+ font-weight: 560;
565
+ letter-spacing: 0.02em;
566
+ pointer-events: auto;
567
+ }
568
+
569
+ .hud-lens:hover:not(:disabled),
570
+ .hud-agent-link:hover:not(:disabled) {
571
+ color: var(--ink);
572
+ border-color: var(--amber);
573
+ }
574
+
575
+ .hud-lens:disabled,
576
+ .hud-agent-link:disabled {
577
+ cursor: default;
578
+ }
579
+
580
+ .hud-lens span {
581
+ color: var(--amber);
582
+ font-size: 0.67rem;
583
+ letter-spacing: 0.1em;
584
+ text-transform: uppercase;
585
+ }
586
+
587
+ .hud-commit {
588
+ display: flex;
589
+ align-items: center;
590
+ gap: 8px;
591
+ margin-top: 5px;
592
+ color: var(--muted);
593
+ font-size: var(--text-sm);
594
+ font-variant-numeric: tabular-nums;
595
+ }
596
+
597
+ .hud-commit .dirty {
598
+ color: var(--ember);
599
+ }
600
+
601
+ /* spectrum: scene legend and live tally in one instrument row */
602
+ .spectrum {
603
+ display: flex;
604
+ flex-wrap: wrap;
605
+ gap: 3px 18px;
606
+ margin-top: 18px;
607
+ font-size: var(--text-xs);
608
+ letter-spacing: 0.03em;
609
+ font-variant-numeric: tabular-nums;
610
+ /* the HUD swallows pointer events; stats opt back in for their tooltips */
611
+ pointer-events: auto;
612
+ }
613
+
614
+ .spectrum-stat {
615
+ display: flex;
616
+ align-items: center;
617
+ gap: 7px;
618
+ }
619
+
620
+ .spectrum-label {
621
+ color: var(--faint);
622
+ text-transform: uppercase;
623
+ letter-spacing: 0.1em;
624
+ text-decoration: underline dotted oklch(0.63 0.02 252 / 0.5);
625
+ text-underline-offset: 3px;
626
+ }
627
+
628
+ .spectrum-stat strong {
629
+ font-size: var(--text-sm);
630
+ font-weight: 560;
631
+ color: var(--ink);
632
+ }
633
+
634
+ .hud-quiet {
635
+ display: flex;
636
+ flex-wrap: wrap;
637
+ gap: 3px 14px;
638
+ margin-top: 7px;
639
+ color: var(--faint);
640
+ font-size: var(--text-xs);
641
+ letter-spacing: 0.04em;
642
+ font-variant-numeric: tabular-nums;
643
+ pointer-events: auto;
644
+ }
645
+
646
+ .hud-agent-link {
647
+ color: inherit;
648
+ border-bottom: 1px dotted var(--hairline-strong);
649
+ }
650
+
651
+ /* review: the one row allowed to raise its voice — ember marks "worth a
652
+ second look", pine marks the reassuring counter-signal */
653
+ .hud-review {
654
+ display: flex;
655
+ flex-wrap: wrap;
656
+ align-items: baseline;
657
+ gap: 3px 14px;
658
+ margin-top: 8px;
659
+ font-size: var(--text-xs);
660
+ letter-spacing: 0.04em;
661
+ font-variant-numeric: tabular-nums;
662
+ pointer-events: auto;
663
+ }
664
+
665
+ .review-label {
666
+ color: var(--faint);
667
+ text-transform: uppercase;
668
+ letter-spacing: 0.1em;
669
+ }
670
+
671
+ .hud-review .warn {
672
+ color: var(--ember);
673
+ }
674
+
675
+ .hud-review .ok {
676
+ color: var(--pine);
677
+ }
678
+
679
+ .churn-toggle {
680
+ font-size: inherit;
681
+ letter-spacing: inherit;
682
+ text-decoration: underline dotted oklch(0.73 0.16 52 / 0.6);
683
+ text-underline-offset: 3px;
684
+ }
685
+
686
+ .churn-toggle:hover,
687
+ .churn-toggle.open {
688
+ color: oklch(0.82 0.16 52);
689
+ }
690
+
691
+ /* drill-down under the review row: which files, how many edits each */
692
+ .churn-panel {
693
+ display: grid;
694
+ width: max-content;
695
+ min-width: 240px;
696
+ max-width: 340px;
697
+ margin-top: 8px;
698
+ padding: 5px;
699
+ border: 1px solid var(--hairline-strong);
700
+ border-radius: 5px;
701
+ background: oklch(0.245 0.014 256 / 0.97);
702
+ pointer-events: auto;
703
+ }
704
+
705
+ .churn-row {
706
+ display: flex;
707
+ align-items: baseline;
708
+ justify-content: space-between;
709
+ gap: 14px;
710
+ padding: 5px 8px;
711
+ border-radius: 3px;
712
+ text-align: left;
713
+ font-size: var(--text-xs);
714
+ color: var(--muted);
715
+ font-variant-numeric: tabular-nums;
716
+ }
717
+
718
+ .churn-row:hover {
719
+ background: var(--panel-raised);
720
+ color: var(--ink);
721
+ }
722
+
723
+ .churn-path {
724
+ direction: rtl; /* ellipsize the head: the tail of a path carries the name */
725
+ text-align: left;
726
+ white-space: nowrap;
727
+ overflow: hidden;
728
+ text-overflow: ellipsis;
729
+ unicode-bidi: plaintext;
730
+ }
731
+
732
+ .churn-count {
733
+ flex: none;
734
+ color: var(--faint);
735
+ }
736
+
737
+ .churn-row:hover .churn-count {
738
+ color: var(--muted);
739
+ }
740
+
741
+ .churn-more {
742
+ padding: 4px 8px 3px;
743
+ color: var(--faint);
744
+ font-size: var(--text-xs);
745
+ }
746
+
747
+ /* instant hover definitions — native title is too slow for an instrument */
748
+ [data-hint] {
749
+ position: relative;
750
+ cursor: help;
751
+ }
752
+
753
+ [data-hint]::after {
754
+ content: attr(data-hint);
755
+ position: absolute;
756
+ top: calc(100% + 7px);
757
+ left: 0;
758
+ z-index: 40;
759
+ width: max-content;
760
+ max-width: 250px;
761
+ padding: 6px 10px;
762
+ border: 1px solid var(--hairline-strong);
763
+ border-radius: 4px;
764
+ background: var(--panel-raised);
765
+ color: var(--ink);
766
+ font-size: var(--text-xs);
767
+ font-weight: 420;
768
+ letter-spacing: 0.01em;
769
+ line-height: 1.45;
770
+ text-transform: none;
771
+ opacity: 0;
772
+ visibility: hidden;
773
+ pointer-events: none;
774
+ transition: opacity 0.12s ease-out;
775
+ }
776
+
777
+ [data-hint]:hover::after {
778
+ opacity: 1;
779
+ visibility: visible;
780
+ }
781
+
782
+ .hud-right {
783
+ display: grid;
784
+ gap: 10px;
785
+ justify-items: end;
786
+ }
787
+
788
+ .legend-dot {
789
+ width: 8px;
790
+ height: 8px;
791
+ border-radius: 50%;
792
+ }
793
+
794
+ .legend-dot.hit {
795
+ background: var(--moss);
796
+ box-shadow: 0 0 7px oklch(0.78 0.11 131 / 0.8);
797
+ }
798
+
799
+ .legend-dot.read {
800
+ background: var(--moon);
801
+ box-shadow: 0 0 7px oklch(0.83 0.07 250 / 0.8);
802
+ }
803
+
804
+ .legend-dot.edit {
805
+ background: var(--amber);
806
+ box-shadow: 0 0 7px oklch(0.79 0.13 68 / 0.8);
807
+ }
808
+
809
+ .legend-dot.unvisited {
810
+ background: oklch(0.5 0.014 254);
811
+ }
812
+
813
+ /* hollow, matching the wireframe ghost leaves in the scene */
814
+ .legend-dot.ghost {
815
+ background: transparent;
816
+ border: 1px solid oklch(0.55 0.014 254);
817
+ }
818
+
819
+ /* ---------- scene hover tip ---------- */
820
+
821
+ /* imperatively driven by the scenes: one line, follows the pointer */
822
+ .scene-tip {
823
+ position: absolute;
824
+ z-index: 30;
825
+ display: none;
826
+ max-width: 380px;
827
+ padding: 5px 9px;
828
+ border: 1px solid var(--hairline-strong);
829
+ border-radius: 4px;
830
+ background: oklch(0.245 0.014 256 / 0.97);
831
+ color: var(--ink);
832
+ font-size: var(--text-xs);
833
+ letter-spacing: 0.01em;
834
+ line-height: 1.4;
835
+ white-space: nowrap;
836
+ overflow: hidden;
837
+ text-overflow: ellipsis;
838
+ pointer-events: none;
839
+ font-variant-numeric: tabular-nums;
840
+ }
841
+
842
+ .scene-tip .dim {
843
+ color: var(--muted);
844
+ }
845
+
846
+ /* ---------- dock panel shell (inspector + evaluation content) ---------- */
847
+
848
+ .dock-panel {
849
+ /* the .dock container owns placement (below the view toggle, above the
850
+ transport); the panel fills its column */
851
+ width: 308px;
852
+ max-height: 100%;
853
+ display: flex;
854
+ flex-direction: column;
855
+ overflow-x: hidden;
856
+ overflow-y: auto;
857
+ background: oklch(0.245 0.014 256 / 0.96);
858
+ border: 1px solid var(--hairline);
859
+ border-radius: 6px;
860
+ scrollbar-width: thin;
861
+ scrollbar-color: var(--hairline) transparent;
862
+ }
863
+
864
+ @media (prefers-reduced-motion: no-preference) {
865
+ .dock-panel {
866
+ animation: inspector-in 0.28s cubic-bezier(0.16, 1, 0.3, 1);
867
+ }
868
+ }
869
+
870
+ @keyframes inspector-in {
871
+ from {
872
+ opacity: 0;
873
+ transform: translateX(14px);
874
+ }
875
+ to {
876
+ opacity: 1;
877
+ transform: none;
878
+ }
879
+ }
880
+
881
+ .inspector-head {
882
+ display: flex;
883
+ align-items: flex-start;
884
+ justify-content: space-between;
885
+ gap: 10px;
886
+ padding: 14px 16px 12px;
887
+ border-bottom: 1px solid var(--hairline);
888
+ }
889
+
890
+ .inspector-path {
891
+ font-size: var(--text-sm);
892
+ font-weight: 560;
893
+ line-height: 1.45;
894
+ overflow-wrap: anywhere;
895
+ }
896
+
897
+ .inspector-path .dir {
898
+ color: var(--muted);
899
+ font-weight: 420;
900
+ }
901
+
902
+ .ghost-badge {
903
+ display: inline-block;
904
+ margin-top: 6px;
905
+ padding: 2px 8px;
906
+ border: 1px solid var(--hairline-strong);
907
+ border-radius: 999px;
908
+ color: var(--muted);
909
+ font-size: var(--text-xs);
910
+ letter-spacing: 0.08em;
911
+ text-transform: uppercase;
912
+ }
913
+
914
+ .inspector-facts {
915
+ display: grid;
916
+ grid-template-columns: 1fr 1fr;
917
+ padding: 6px 16px 12px;
918
+ border-bottom: 1px solid var(--hairline);
919
+ }
920
+
921
+ .inspector-facts > div {
922
+ display: flex;
923
+ align-items: baseline;
924
+ justify-content: space-between;
925
+ gap: 10px;
926
+ padding: 6px 0;
927
+ }
928
+
929
+ .inspector-facts > div:nth-child(odd) {
930
+ padding-right: 14px;
931
+ border-right: 1px solid var(--hairline);
932
+ }
933
+
934
+ .inspector-facts > div:nth-child(even) {
935
+ padding-left: 14px;
936
+ }
937
+
938
+ .inspector-facts dt {
939
+ color: var(--faint);
940
+ font-size: var(--text-xs);
941
+ letter-spacing: 0.1em;
942
+ text-transform: uppercase;
943
+ }
944
+
945
+ .inspector-facts dd {
946
+ font-size: var(--text-sm);
947
+ font-weight: 560;
948
+ font-variant-numeric: tabular-nums;
949
+ }
950
+
951
+ .inspector-facts dd.touch-hit {
952
+ color: var(--moss);
953
+ }
954
+
955
+ .inspector-facts dd.touch-read {
956
+ color: var(--moon);
957
+ }
958
+
959
+ .inspector-facts dd.touch-edit {
960
+ color: var(--amber);
961
+ }
962
+
963
+ .inspector-history {
964
+ padding: 12px 16px;
965
+ }
966
+
967
+ .eyebrow {
968
+ margin: 0 0 10px;
969
+ color: var(--faint);
970
+ font-size: var(--text-xs);
971
+ font-weight: 560;
972
+ letter-spacing: 0.14em;
973
+ text-transform: uppercase;
974
+ }
975
+
976
+ .history-list {
977
+ display: grid;
978
+ }
979
+
980
+ .history-row {
981
+ display: grid;
982
+ grid-template-columns: 10px max-content 1fr auto auto;
983
+ align-items: center;
984
+ gap: 9px;
985
+ width: 100%;
986
+ padding: 6px 4px;
987
+ border-radius: 3px;
988
+ text-align: left;
989
+ font-size: var(--text-sm);
990
+ color: var(--muted);
991
+ font-variant-numeric: tabular-nums;
992
+ }
993
+
994
+ .history-time {
995
+ color: var(--faint);
996
+ font-size: var(--text-xs);
997
+ }
998
+
999
+ .history-row:hover:not(:disabled) {
1000
+ background: var(--panel-raised);
1001
+ color: var(--ink);
1002
+ }
1003
+
1004
+ .history-row:disabled {
1005
+ opacity: 0.45;
1006
+ cursor: not-allowed;
1007
+ }
1008
+
1009
+ .history-row strong {
1010
+ font-weight: 560;
1011
+ color: var(--faint);
1012
+ }
1013
+
1014
+ .history-row:hover:not(:disabled) strong {
1015
+ color: var(--muted);
1016
+ }
1017
+
1018
+ .history-err {
1019
+ color: var(--alarm);
1020
+ }
1021
+
1022
+ .muted {
1023
+ color: var(--faint);
1024
+ font-size: var(--text-sm);
1025
+ line-height: 1.5;
1026
+ }
1027
+
1028
+ /* ---------- action colors ---------- */
1029
+
1030
+ .action-dot {
1031
+ width: 7px;
1032
+ height: 7px;
1033
+ border-radius: 50%;
1034
+ background: var(--faint);
1035
+ }
1036
+
1037
+ .action-dot.search {
1038
+ background: var(--act-search);
1039
+ }
1040
+
1041
+ .action-dot.read {
1042
+ background: var(--act-read);
1043
+ }
1044
+
1045
+ .action-dot.edit {
1046
+ background: var(--act-edit);
1047
+ }
1048
+
1049
+ .action-dot.verify {
1050
+ background: var(--act-verify);
1051
+ }
1052
+
1053
+ .action-dot.exec {
1054
+ background: var(--act-exec);
1055
+ }
1056
+
1057
+ /* ---------- deck (timeline) ---------- */
1058
+
1059
+ .deck {
1060
+ flex: none;
1061
+ display: flex;
1062
+ flex-direction: column;
1063
+ gap: 6px;
1064
+ padding: 12px 22px 10px;
1065
+ background: var(--panel);
1066
+ border-top: 1px solid var(--hairline);
1067
+ }
1068
+
1069
+ /* band one is the instrument row: full-width strip, then position dial and
1070
+ transport anchored right — scrub on the left, numbers and controls where
1071
+ the hand rests. dial and transport sit tight as one group; the strip keeps
1072
+ its distance */
1073
+ .deck-main {
1074
+ display: flex;
1075
+ align-items: center;
1076
+ gap: 12px;
1077
+ }
1078
+
1079
+ .deck-main .strip {
1080
+ margin-right: 10px;
1081
+ }
1082
+
1083
+ /* band two is the caption line: what the playhead is on, then the key */
1084
+ .deck-foot {
1085
+ display: flex;
1086
+ align-items: center;
1087
+ gap: 26px;
1088
+ }
1089
+
1090
+ .transport {
1091
+ display: flex;
1092
+ align-items: center;
1093
+ gap: 6px;
1094
+ }
1095
+
1096
+ .icon-btn {
1097
+ display: inline-flex;
1098
+ align-items: center;
1099
+ justify-content: center;
1100
+ width: 30px;
1101
+ height: 30px;
1102
+ border-radius: 4px;
1103
+ color: var(--muted);
1104
+ }
1105
+
1106
+ .icon-btn:hover:not(:disabled) {
1107
+ color: var(--ink);
1108
+ background: var(--panel-raised);
1109
+ }
1110
+
1111
+ .icon-btn:disabled {
1112
+ opacity: 0.45;
1113
+ cursor: not-allowed;
1114
+ }
1115
+
1116
+ .icon-btn.recording {
1117
+ color: var(--warm, #e0a458);
1118
+ }
1119
+
1120
+ .spin {
1121
+ animation: spin 0.9s linear infinite;
1122
+ }
1123
+
1124
+ @keyframes spin {
1125
+ from {
1126
+ transform: rotate(0deg);
1127
+ }
1128
+ to {
1129
+ transform: rotate(360deg);
1130
+ }
1131
+ }
1132
+
1133
+ /* icon-only and fixed-width: the cluster is right-anchored, so a Play/Pause
1134
+ label swap would shift every button beside it */
1135
+ .play-btn {
1136
+ display: inline-flex;
1137
+ align-items: center;
1138
+ justify-content: center;
1139
+ width: 38px;
1140
+ height: 30px;
1141
+ border: 1px solid var(--hairline-strong);
1142
+ border-radius: 4px;
1143
+ color: var(--ink);
1144
+ }
1145
+
1146
+ /* triangle glyphs sit optically left of center; nudge right */
1147
+ .play-btn .play-glyph {
1148
+ transform: translateX(1px);
1149
+ }
1150
+
1151
+ .play-btn:hover {
1152
+ border-color: var(--muted);
1153
+ background: var(--panel-raised);
1154
+ }
1155
+
1156
+ /* everything past the three core keys lives behind ⋯ */
1157
+ .transport-more {
1158
+ position: relative;
1159
+ display: inline-flex;
1160
+ }
1161
+
1162
+ .icon-btn.open {
1163
+ color: var(--ink);
1164
+ background: var(--panel-raised);
1165
+ }
1166
+
1167
+ /* engaged speed shown in place of the ⋯ glyph so 16× is never invisible */
1168
+ .more-speed {
1169
+ color: oklch(0.95 0.02 88);
1170
+ font-size: var(--text-xs);
1171
+ font-weight: 560;
1172
+ letter-spacing: 0.04em;
1173
+ font-variant-numeric: tabular-nums;
1174
+ }
1175
+
1176
+ /* same card recipe as .dock-pop, anchored above the trigger */
1177
+ .transport-pop {
1178
+ position: absolute;
1179
+ bottom: calc(100% + 8px);
1180
+ right: 0;
1181
+ z-index: 20;
1182
+ min-width: 172px;
1183
+ padding: 8px;
1184
+ display: grid;
1185
+ gap: 3px;
1186
+ border: 1px solid var(--hairline-strong);
1187
+ border-radius: 6px;
1188
+ background: var(--panel-raised);
1189
+ box-shadow: 0 8px 24px oklch(0 0 0 / 0.4);
1190
+ animation: pop-rise 0.14s ease-out;
1191
+ }
1192
+
1193
+ @keyframes pop-rise {
1194
+ from {
1195
+ opacity: 0;
1196
+ transform: translateY(4px);
1197
+ }
1198
+ to {
1199
+ opacity: 1;
1200
+ transform: translateY(0);
1201
+ }
1202
+ }
1203
+
1204
+ .pop-speed {
1205
+ display: flex;
1206
+ align-items: center;
1207
+ justify-content: space-between;
1208
+ gap: 12px;
1209
+ padding: 2px 8px 8px;
1210
+ margin-bottom: 3px;
1211
+ border-bottom: 1px solid var(--hairline);
1212
+ }
1213
+
1214
+ .pop-speed-label {
1215
+ color: var(--muted);
1216
+ font-size: var(--text-sm);
1217
+ }
1218
+
1219
+ .pop-speed-chips {
1220
+ display: inline-flex;
1221
+ gap: 2px;
1222
+ }
1223
+
1224
+ .pop-chip {
1225
+ min-width: 26px;
1226
+ height: 22px;
1227
+ padding: 0 5px;
1228
+ border-radius: 3px;
1229
+ color: var(--muted);
1230
+ font-size: var(--text-xs);
1231
+ font-weight: 560;
1232
+ letter-spacing: 0.04em;
1233
+ font-variant-numeric: tabular-nums;
1234
+ }
1235
+
1236
+ .pop-chip:hover {
1237
+ color: var(--ink);
1238
+ background: var(--panel);
1239
+ }
1240
+
1241
+ .pop-chip.engaged {
1242
+ color: oklch(0.95 0.02 88);
1243
+ background: var(--panel);
1244
+ box-shadow: inset 0 0 0 1px var(--hairline-strong);
1245
+ }
1246
+
1247
+ .pop-item {
1248
+ display: flex;
1249
+ align-items: center;
1250
+ gap: 8px;
1251
+ padding: 6px 8px;
1252
+ border-radius: 4px;
1253
+ text-align: left;
1254
+ color: var(--muted);
1255
+ font-size: var(--text-sm);
1256
+ }
1257
+
1258
+ .pop-item:hover {
1259
+ color: var(--ink);
1260
+ background: var(--panel);
1261
+ }
1262
+
1263
+ .pop-item kbd {
1264
+ margin-left: auto;
1265
+ padding: 1px 5px;
1266
+ border: 1px solid var(--hairline);
1267
+ border-radius: 3px;
1268
+ color: var(--faint);
1269
+ font-family: inherit;
1270
+ font-size: 0.62rem;
1271
+ letter-spacing: 0.06em;
1272
+ }
1273
+
1274
+ .transport > button:disabled,
1275
+ .transport-more > button:disabled {
1276
+ opacity: 0.45;
1277
+ cursor: default;
1278
+ pointer-events: none;
1279
+ }
1280
+
1281
+ .strip {
1282
+ position: relative;
1283
+ flex: 1;
1284
+ height: 46px;
1285
+ min-width: 0;
1286
+ }
1287
+
1288
+ .strip-marks {
1289
+ position: absolute;
1290
+ top: 0;
1291
+ left: 0;
1292
+ right: 0;
1293
+ height: 10px;
1294
+ /* marks are clickable jump targets, but the row itself must not block the slider */
1295
+ pointer-events: none;
1296
+ }
1297
+
1298
+ .strip-mark {
1299
+ position: absolute;
1300
+ top: 1px;
1301
+ width: 7px;
1302
+ height: 7px;
1303
+ transform: translateX(-50%) rotate(45deg);
1304
+ border: 1px solid var(--mark-compaction);
1305
+ background: transparent;
1306
+ pointer-events: auto;
1307
+ cursor: pointer;
1308
+ transition: transform 0.12s ease-out;
1309
+ }
1310
+
1311
+ .strip-mark:hover {
1312
+ transform: translateX(-50%) rotate(45deg) scale(1.5);
1313
+ }
1314
+
1315
+ .strip-mark:disabled {
1316
+ cursor: default;
1317
+ opacity: 0.45;
1318
+ pointer-events: none;
1319
+ }
1320
+
1321
+ .strip-mark.subagent {
1322
+ border-color: var(--mark-subagent);
1323
+ border-radius: 50%;
1324
+ }
1325
+
1326
+ /* user turns are frequent: a quiet prompt chevron — "an instruction was
1327
+ typed here" — never a peer of compaction diamonds. the box is an
1328
+ invisible 11px click target; the glyph is drawn by ::after. */
1329
+ .strip-mark.user-message {
1330
+ top: 0;
1331
+ width: 11px;
1332
+ height: 10px;
1333
+ border: 0;
1334
+ border-radius: 0;
1335
+ transform: translateX(-50%);
1336
+ }
1337
+
1338
+ .strip-mark.user-message::after {
1339
+ content: "";
1340
+ position: absolute;
1341
+ left: 3px;
1342
+ top: 2.5px;
1343
+ width: 4px;
1344
+ height: 4px;
1345
+ border: 1.5px solid var(--faint);
1346
+ border-left: 0;
1347
+ border-bottom: 0;
1348
+ transform: rotate(45deg);
1349
+ }
1350
+
1351
+ .strip-mark.user-message:hover {
1352
+ transform: translateX(-50%) scale(1.5);
1353
+ }
1354
+
1355
+ .strip-mark.user-message:hover::after {
1356
+ border-color: var(--ink);
1357
+ }
1358
+
1359
+ .strip-bars {
1360
+ position: absolute;
1361
+ left: 0;
1362
+ right: 0;
1363
+ top: 12px;
1364
+ bottom: 12px;
1365
+ display: flex;
1366
+ align-items: flex-end;
1367
+ gap: 1px;
1368
+ border-bottom: 1px solid var(--hairline-strong);
1369
+ }
1370
+
1371
+ .strip-bar {
1372
+ flex: 1;
1373
+ min-width: 0;
1374
+ border-radius: 1px 1px 0 0;
1375
+ background: var(--faint);
1376
+ opacity: 0.85;
1377
+ }
1378
+
1379
+ .strip-bar.search {
1380
+ background: var(--act-search);
1381
+ }
1382
+
1383
+ .strip-bar.read {
1384
+ background: var(--act-read);
1385
+ }
1386
+
1387
+ .strip-bar.edit {
1388
+ background: var(--act-edit);
1389
+ }
1390
+
1391
+ .strip-bar.verify {
1392
+ background: var(--act-verify);
1393
+ }
1394
+
1395
+ .strip-bar.exec {
1396
+ background: var(--act-exec);
1397
+ }
1398
+
1399
+ .strip-playhead {
1400
+ position: absolute;
1401
+ top: 10px;
1402
+ bottom: 0;
1403
+ width: 1.5px;
1404
+ background: var(--ink);
1405
+ transform: translateX(-50%);
1406
+ pointer-events: none;
1407
+ }
1408
+
1409
+ .strip-playhead::after {
1410
+ content: "";
1411
+ position: absolute;
1412
+ bottom: -2px;
1413
+ left: 50%;
1414
+ width: 5px;
1415
+ height: 5px;
1416
+ transform: translate(-50%, 0) rotate(45deg);
1417
+ background: var(--ink);
1418
+ }
1419
+
1420
+ .strip-input {
1421
+ position: absolute;
1422
+ inset: 8px 0 0;
1423
+ width: 100%;
1424
+ margin: 0;
1425
+ opacity: 0;
1426
+ cursor: ew-resize;
1427
+ }
1428
+
1429
+ /* position dial: event index, hairline, wall clock on one baseline — the
1430
+ same height and rhythm as the buttons beside it. right-aligned inside a
1431
+ min-width so ticking digits grow into the reserve, not into the strip */
1432
+ .deck-pos {
1433
+ display: flex;
1434
+ align-items: baseline;
1435
+ gap: 12px;
1436
+ font-variant-numeric: tabular-nums;
1437
+ }
1438
+
1439
+ .deck-pos-count {
1440
+ color: var(--ink);
1441
+ font-size: var(--text-sm);
1442
+ letter-spacing: 0.04em;
1443
+ text-align: right;
1444
+ }
1445
+
1446
+ .deck-pos-clock {
1447
+ color: var(--faint);
1448
+ font-size: var(--text-xs);
1449
+ letter-spacing: 0.06em;
1450
+ }
1451
+
1452
+ .readout-now {
1453
+ flex: 1;
1454
+ min-width: 0;
1455
+ display: flex;
1456
+ align-items: center;
1457
+ gap: 8px;
1458
+ font-size: var(--text-sm);
1459
+ white-space: nowrap;
1460
+ }
1461
+
1462
+ .readout-tool {
1463
+ font-weight: 560;
1464
+ flex: none;
1465
+ }
1466
+
1467
+ .readout-now .err {
1468
+ flex: none;
1469
+ color: var(--alarm);
1470
+ font-size: var(--text-xs);
1471
+ letter-spacing: 0.08em;
1472
+ text-transform: uppercase;
1473
+ }
1474
+
1475
+ .readout-summary {
1476
+ color: var(--muted);
1477
+ line-height: 1.4;
1478
+ overflow: hidden;
1479
+ text-overflow: ellipsis;
1480
+ }
1481
+
1482
+ /* full key for the strip: bar colors, then the mark shapes above them;
1483
+ the two groups separate by distance alone */
1484
+ .deck-legend {
1485
+ flex: none;
1486
+ display: flex;
1487
+ align-items: center;
1488
+ gap: 22px;
1489
+ color: var(--faint);
1490
+ font-size: 0.68rem;
1491
+ letter-spacing: 0.07em;
1492
+ white-space: nowrap;
1493
+ }
1494
+
1495
+ .legend-group {
1496
+ display: inline-flex;
1497
+ align-items: center;
1498
+ gap: 11px;
1499
+ }
1500
+
1501
+ .legend-item {
1502
+ display: inline-flex;
1503
+ align-items: center;
1504
+ gap: 5px;
1505
+ }
1506
+
1507
+ .deck-legend .action-dot {
1508
+ width: 5px;
1509
+ height: 5px;
1510
+ }
1511
+
1512
+ /* glyphs mirror the strip-mark shapes so the key reads one-to-one */
1513
+ .legend-glyph {
1514
+ display: inline-block;
1515
+ flex: none;
1516
+ }
1517
+
1518
+ .legend-glyph.compaction {
1519
+ width: 6px;
1520
+ height: 6px;
1521
+ border: 1px solid var(--mark-compaction);
1522
+ transform: rotate(45deg);
1523
+ }
1524
+
1525
+ .legend-glyph.subagent {
1526
+ width: 6px;
1527
+ height: 6px;
1528
+ border: 1px solid var(--mark-subagent);
1529
+ border-radius: 50%;
1530
+ }
1531
+
1532
+ .legend-glyph.user-message {
1533
+ width: 4px;
1534
+ height: 4px;
1535
+ border: 1.5px solid var(--faint);
1536
+ border-left: 0;
1537
+ border-bottom: 0;
1538
+ transform: rotate(45deg);
1539
+ margin-right: 2px;
1540
+ }
1541
+
1542
+ /* ---------- toast ---------- */
1543
+
1544
+ .toast {
1545
+ position: absolute;
1546
+ top: 18px;
1547
+ left: 50%;
1548
+ transform: translateX(-50%);
1549
+ padding: 8px 14px;
1550
+ border: 1px solid var(--hairline-strong);
1551
+ border-radius: 4px;
1552
+ background: var(--panel-raised);
1553
+ color: var(--muted);
1554
+ font-size: var(--text-sm);
1555
+ pointer-events: none;
1556
+ }
1557
+
1558
+ .toast.error {
1559
+ color: var(--alarm);
1560
+ border-color: oklch(0.7 0.16 32 / 0.5);
1561
+ }
1562
+
1563
+ /* ---------- empty state ---------- */
1564
+
1565
+ .empty-stage {
1566
+ position: absolute;
1567
+ inset: 0;
1568
+ display: grid;
1569
+ place-items: center;
1570
+ pointer-events: none;
1571
+ }
1572
+
1573
+ .empty-stage .card {
1574
+ text-align: center;
1575
+ color: var(--muted);
1576
+ max-width: 340px;
1577
+ line-height: 1.6;
1578
+ font-size: var(--text-sm);
1579
+ }
1580
+
1581
+ .empty-stage .card h2 {
1582
+ font-family: var(--font-display);
1583
+ font-style: italic;
1584
+ font-weight: 480;
1585
+ font-size: var(--text-lg);
1586
+ margin-bottom: 8px;
1587
+ color: var(--ink);
1588
+ }
1589
+
1590
+ /* ---------- responsive ---------- */
1591
+
1592
+ @media (max-width: 900px) {
1593
+ .app-frame {
1594
+ flex-direction: column;
1595
+ }
1596
+
1597
+ .session-rail {
1598
+ width: auto;
1599
+ height: 224px;
1600
+ border-right: 0;
1601
+ border-bottom: 1px solid var(--hairline);
1602
+ }
1603
+
1604
+ /* the rail is a top bar here, so it slides up instead of left */
1605
+ .session-rail.collapsed {
1606
+ margin-left: 0;
1607
+ margin-top: -225px;
1608
+ }
1609
+
1610
+ .rail-expand {
1611
+ top: 14px;
1612
+ left: 16px;
1613
+ }
1614
+
1615
+ .rail-head {
1616
+ padding: 12px 16px 8px;
1617
+ }
1618
+
1619
+ .hud {
1620
+ padding: 14px 16px;
1621
+ }
1622
+
1623
+ .hud-repo {
1624
+ font-size: 1.2rem;
1625
+ }
1626
+
1627
+ .dock {
1628
+ /* bottom sheet on narrow screens, pinned to the visual viewport so it
1629
+ never floats over the HUD readout */
1630
+ position: fixed;
1631
+ top: auto;
1632
+ right: 12px;
1633
+ bottom: 12px;
1634
+ left: 12px;
1635
+ z-index: 30;
1636
+ flex-direction: row-reverse;
1637
+ align-items: flex-end;
1638
+ }
1639
+
1640
+ .dock-panel {
1641
+ position: static;
1642
+ flex: 1;
1643
+ min-width: 0;
1644
+ width: auto;
1645
+ max-height: 46vh;
1646
+ }
1647
+
1648
+ .deck-pos {
1649
+ display: none;
1650
+ }
1651
+ }
1652
+
1653
+ /* the key is reference material; below this the caption line belongs to the summary */
1654
+ @media (max-width: 1180px) {
1655
+ .deck-legend {
1656
+ display: none;
1657
+ }
1658
+ }
1659
+
1660
+ @media (prefers-reduced-motion: reduce) {
1661
+ * {
1662
+ transition-duration: 0.01ms !important;
1663
+ animation-duration: 0.01ms !important;
1664
+ }
1665
+ }
1666
+
1667
+ /* ---------- dock: the right-edge home of session-depth panels ---------- */
1668
+
1669
+ .dock {
1670
+ position: absolute;
1671
+ top: 20px; /* level with the HUD readout's first line */
1672
+ right: 20px;
1673
+ bottom: 20px;
1674
+ display: flex;
1675
+ align-items: flex-start;
1676
+ gap: 10px;
1677
+ pointer-events: none;
1678
+ }
1679
+
1680
+ .dock > * {
1681
+ pointer-events: auto;
1682
+ }
1683
+
1684
+ .dock-side {
1685
+ position: relative;
1686
+ display: flex;
1687
+ align-items: flex-start;
1688
+ }
1689
+
1690
+ .dock-strip {
1691
+ display: grid;
1692
+ gap: 6px;
1693
+ padding: 6px;
1694
+ border: 1px solid var(--hairline);
1695
+ border-radius: 6px;
1696
+ background: oklch(0.245 0.014 256 / 0.92);
1697
+ }
1698
+
1699
+ .dock-strip-group {
1700
+ display: grid;
1701
+ gap: 6px;
1702
+ }
1703
+
1704
+ .dock-strip-divider {
1705
+ height: 1px;
1706
+ margin: 2px 3px;
1707
+ background: var(--hairline);
1708
+ }
1709
+
1710
+ /* pop: a compact card anchored beside the strip; coexists with an open
1711
+ sheet so a view tweak never steals the report */
1712
+ .dock-pop {
1713
+ position: absolute;
1714
+ top: 0;
1715
+ right: calc(100% + 10px); /* left of the whole dock: sheet or strip */
1716
+ z-index: 20;
1717
+ min-width: 148px;
1718
+ padding: 8px;
1719
+ border: 1px solid var(--hairline-strong);
1720
+ border-radius: 6px;
1721
+ background: var(--panel-raised);
1722
+ box-shadow: 0 8px 24px oklch(0 0 0 / 0.4);
1723
+ }
1724
+
1725
+ .view-pop {
1726
+ display: grid;
1727
+ gap: 3px;
1728
+ }
1729
+
1730
+ .view-row {
1731
+ display: flex;
1732
+ align-items: center;
1733
+ gap: 8px;
1734
+ padding: 6px 8px;
1735
+ border-radius: 4px;
1736
+ text-align: left;
1737
+ color: var(--muted);
1738
+ font-size: var(--text-sm);
1739
+ }
1740
+
1741
+ .view-row:hover:not(:disabled) {
1742
+ color: var(--ink);
1743
+ background: var(--panel);
1744
+ }
1745
+
1746
+ .view-row.active {
1747
+ color: var(--ink);
1748
+ background: var(--panel);
1749
+ box-shadow: inset 0 0 0 1px var(--hairline-strong);
1750
+ }
1751
+
1752
+ .view-row:disabled {
1753
+ opacity: 0.5;
1754
+ }
1755
+
1756
+ .view-note {
1757
+ display: flex;
1758
+ align-items: center;
1759
+ justify-content: space-between;
1760
+ gap: 8px;
1761
+ margin: 4px 2px 0;
1762
+ padding-top: 6px;
1763
+ border-top: 1px solid var(--hairline);
1764
+ color: var(--faint);
1765
+ font-size: var(--text-xs);
1766
+ }
1767
+
1768
+ .view-key {
1769
+ padding: 0 5px;
1770
+ border: 1px solid var(--hairline-strong);
1771
+ border-radius: 3px;
1772
+ font-size: var(--text-xs);
1773
+ color: var(--muted);
1774
+ }
1775
+
1776
+ .dock-strip button {
1777
+ position: relative;
1778
+ display: grid;
1779
+ place-items: center;
1780
+ width: 30px;
1781
+ height: 30px;
1782
+ border-radius: 4px;
1783
+ color: var(--muted);
1784
+ }
1785
+
1786
+ .dock-strip button:hover {
1787
+ color: var(--ink);
1788
+ background: var(--panel-raised);
1789
+ }
1790
+
1791
+ .dock-strip button.active {
1792
+ color: var(--ink);
1793
+ background: var(--panel-raised);
1794
+ box-shadow: inset 0 0 0 1px var(--hairline-strong);
1795
+ }
1796
+
1797
+ .dock-strip [data-hint]::after {
1798
+ top: 50%;
1799
+ left: auto;
1800
+ right: calc(100% + 8px);
1801
+ transform: translateY(-50%);
1802
+ }
1803
+
1804
+ .dock-dot {
1805
+ position: absolute;
1806
+ top: 4px;
1807
+ right: 4px;
1808
+ width: 6px;
1809
+ height: 6px;
1810
+ border-radius: 999px;
1811
+ }
1812
+
1813
+ .dock-dot-running {
1814
+ background: var(--moon);
1815
+ animation: report-pulse 1.4s ease-in-out infinite;
1816
+ }
1817
+
1818
+ .dock-dot-done {
1819
+ background: var(--pine);
1820
+ }
1821
+
1822
+ .dock-dot-stale {
1823
+ background: var(--amber);
1824
+ }
1825
+
1826
+ .dock-dot-failed {
1827
+ background: var(--alarm);
1828
+ }
1829
+
1830
+ @keyframes report-pulse {
1831
+ 0%,
1832
+ 100% {
1833
+ opacity: 1;
1834
+ }
1835
+ 50% {
1836
+ opacity: 0.35;
1837
+ }
1838
+ }
1839
+
1840
+ .dock-note {
1841
+ padding: 14px 16px;
1842
+ color: var(--muted);
1843
+ font-size: var(--text-sm);
1844
+ line-height: 1.55;
1845
+ }
1846
+
1847
+ /* agent lens picker: actor identity is typographic; color is reserved for
1848
+ availability and the single current-lens signature */
1849
+ .agents-head-note {
1850
+ margin-top: 3px;
1851
+ color: var(--faint);
1852
+ font-size: var(--text-xs);
1853
+ }
1854
+
1855
+ .agent-list {
1856
+ display: grid;
1857
+ gap: 4px;
1858
+ padding: 10px;
1859
+ }
1860
+
1861
+ .agent-row {
1862
+ position: relative;
1863
+ width: 100%;
1864
+ border-radius: 4px;
1865
+ color: var(--muted);
1866
+ }
1867
+
1868
+ .agent-row-select {
1869
+ display: grid;
1870
+ grid-template-columns: 16px minmax(0, 1fr);
1871
+ gap: 8px;
1872
+ width: 100%;
1873
+ padding: 9px 10px 9px 12px;
1874
+ border-radius: inherit;
1875
+ color: inherit;
1876
+ text-align: left;
1877
+ }
1878
+
1879
+ .agent-row > .agent-row-select {
1880
+ padding-right: 34px;
1881
+ }
1882
+
1883
+ .agent-row:hover:not(:disabled) {
1884
+ color: var(--ink);
1885
+ background: var(--panel-raised);
1886
+ }
1887
+
1888
+ .agent-row.active {
1889
+ color: var(--ink);
1890
+ background: var(--panel-raised);
1891
+ box-shadow: inset 0 0 0 1px var(--hairline-strong);
1892
+ }
1893
+
1894
+ .agent-row:disabled,
1895
+ .agent-row.disabled {
1896
+ opacity: 0.76;
1897
+ }
1898
+
1899
+ .agent-row:disabled,
1900
+ .agent-row-select:disabled {
1901
+ cursor: not-allowed;
1902
+ }
1903
+
1904
+ .agent-row-icon {
1905
+ display: grid;
1906
+ place-items: center;
1907
+ min-height: 19px;
1908
+ color: var(--faint);
1909
+ }
1910
+
1911
+ .agent-row-copy {
1912
+ min-width: 0;
1913
+ display: grid;
1914
+ gap: 2px;
1915
+ }
1916
+
1917
+ .agent-row-primary {
1918
+ min-width: 0;
1919
+ display: flex;
1920
+ align-items: center;
1921
+ justify-content: space-between;
1922
+ gap: 10px;
1923
+ }
1924
+
1925
+ .agent-row-title {
1926
+ min-width: 0;
1927
+ display: flex;
1928
+ align-items: center;
1929
+ gap: 7px;
1930
+ font-size: var(--text-sm);
1931
+ font-weight: 560;
1932
+ line-height: 1.35;
1933
+ overflow-wrap: anywhere;
1934
+ }
1935
+
1936
+ .agent-current {
1937
+ flex: none;
1938
+ padding: 1px 6px;
1939
+ border: 1px solid var(--amber);
1940
+ border-radius: 999px;
1941
+ color: var(--amber);
1942
+ font-size: 0.65rem;
1943
+ font-weight: 560;
1944
+ letter-spacing: 0.07em;
1945
+ line-height: 1.45;
1946
+ text-transform: uppercase;
1947
+ }
1948
+
1949
+ .agent-row-count,
1950
+ .agent-row-secondary {
1951
+ color: var(--faint);
1952
+ font-size: var(--text-xs);
1953
+ line-height: 1.4;
1954
+ }
1955
+
1956
+ .agent-row-count {
1957
+ flex: none;
1958
+ text-align: right;
1959
+ font-variant-numeric: tabular-nums;
1960
+ }
1961
+
1962
+ .agent-status-missing {
1963
+ color: var(--amber);
1964
+ }
1965
+
1966
+ .agent-status-unavailable {
1967
+ color: var(--alarm);
1968
+ }
1969
+
1970
+ .agent-row-secondary {
1971
+ min-width: 0;
1972
+ overflow: hidden;
1973
+ color: var(--muted);
1974
+ text-overflow: ellipsis;
1975
+ white-space: nowrap;
1976
+ }
1977
+
1978
+ .agent-row-detail-trigger {
1979
+ position: absolute;
1980
+ right: 8px;
1981
+ bottom: 8px;
1982
+ display: grid;
1983
+ place-items: center;
1984
+ width: 20px;
1985
+ height: 20px;
1986
+ border-radius: 3px;
1987
+ color: var(--faint);
1988
+ }
1989
+
1990
+ .agent-row-detail-trigger:hover,
1991
+ .agent-row-detail-trigger[aria-pressed="true"] {
1992
+ color: var(--ink);
1993
+ background: var(--panel);
1994
+ }
1995
+
1996
+ .agent-detail-popover {
1997
+ position: fixed;
1998
+ z-index: 30;
1999
+ display: grid;
2000
+ gap: 8px;
2001
+ padding: 12px;
2002
+ border: 1px solid var(--hairline-strong);
2003
+ border-radius: 6px;
2004
+ background: oklch(0.225 0.014 256 / 0.99);
2005
+ box-shadow: 0 8px 24px oklch(0 0 0 / 0.4);
2006
+ color: var(--muted);
2007
+ font-size: var(--text-xs);
2008
+ line-height: 1.5;
2009
+ overflow-wrap: anywhere;
2010
+ }
2011
+
2012
+ .agent-detail-popover.preview {
2013
+ overflow: hidden;
2014
+ pointer-events: none;
2015
+ }
2016
+
2017
+ .agent-detail-popover.pinned {
2018
+ overflow-y: auto;
2019
+ pointer-events: auto;
2020
+ }
2021
+
2022
+ .agent-detail-head {
2023
+ display: flex;
2024
+ align-items: flex-start;
2025
+ justify-content: space-between;
2026
+ gap: 12px;
2027
+ }
2028
+
2029
+ .agent-detail-head > span {
2030
+ display: flex;
2031
+ align-items: baseline;
2032
+ gap: 8px;
2033
+ min-width: 0;
2034
+ }
2035
+
2036
+ .agent-detail-head strong,
2037
+ .agent-detail-instruction {
2038
+ color: var(--ink);
2039
+ }
2040
+
2041
+ .agent-detail-head strong {
2042
+ font-size: var(--text-sm);
2043
+ font-weight: 560;
2044
+ }
2045
+
2046
+ .agent-detail-close {
2047
+ flex: none;
2048
+ display: grid;
2049
+ place-items: center;
2050
+ width: 22px;
2051
+ height: 22px;
2052
+ border-radius: 3px;
2053
+ color: var(--faint);
2054
+ }
2055
+
2056
+ .agent-detail-close:hover {
2057
+ color: var(--ink);
2058
+ background: var(--panel-raised);
2059
+ }
2060
+
2061
+ .agent-detail-instruction,
2062
+ .agent-detail-meta {
2063
+ min-width: 0;
2064
+ }
2065
+
2066
+ .agents-empty,
2067
+ .agents-state {
2068
+ display: flex;
2069
+ align-items: center;
2070
+ gap: 7px;
2071
+ padding: 9px 10px;
2072
+ color: var(--faint);
2073
+ font-size: var(--text-xs);
2074
+ }
2075
+
2076
+ .agents-state {
2077
+ margin: 0 10px 10px;
2078
+ border-top: 1px solid var(--hairline);
2079
+ }
2080
+
2081
+ .agent-list .agents-state {
2082
+ margin: 0;
2083
+ }
2084
+
2085
+ .agents-error {
2086
+ display: grid;
2087
+ gap: 9px;
2088
+ margin: 0 10px 10px;
2089
+ padding: 10px;
2090
+ border: 1px solid oklch(0.7 0.16 32 / 0.45);
2091
+ border-radius: 4px;
2092
+ background: oklch(0.7 0.16 32 / 0.08);
2093
+ color: var(--muted);
2094
+ font-size: var(--text-xs);
2095
+ line-height: 1.45;
2096
+ }
2097
+
2098
+ .agents-error.row-local {
2099
+ margin: -1px 10px 4px 34px;
2100
+ }
2101
+
2102
+ .agents-error > span,
2103
+ .agents-retry {
2104
+ display: flex;
2105
+ align-items: flex-start;
2106
+ gap: 7px;
2107
+ }
2108
+
2109
+ .agents-error > span svg,
2110
+ .agents-retry svg {
2111
+ flex: none;
2112
+ margin-top: 1px;
2113
+ }
2114
+
2115
+ .agents-error > span svg {
2116
+ color: var(--alarm);
2117
+ }
2118
+
2119
+ .agents-retry {
2120
+ width: max-content;
2121
+ align-items: center;
2122
+ padding: 4px 8px;
2123
+ border: 1px solid var(--hairline-strong);
2124
+ border-radius: 4px;
2125
+ color: var(--ink);
2126
+ }
2127
+
2128
+ .agents-retry:hover {
2129
+ background: var(--panel-raised);
2130
+ }
2131
+
2132
+ .agents-retry:disabled {
2133
+ cursor: default;
2134
+ opacity: 0.45;
2135
+ }
2136
+
2137
+ .report-panel .report-meta {
2138
+ margin-top: 4px;
2139
+ color: var(--faint);
2140
+ font-size: var(--text-xs);
2141
+ }
2142
+
2143
+ .report-note {
2144
+ padding: 14px 16px;
2145
+ color: var(--muted);
2146
+ font-size: var(--text-sm);
2147
+ line-height: 1.55;
2148
+ display: grid;
2149
+ gap: 10px;
2150
+ }
2151
+
2152
+ .report-note code {
2153
+ color: var(--ink);
2154
+ }
2155
+
2156
+ .report-running {
2157
+ color: var(--moon);
2158
+ font-weight: 560;
2159
+ }
2160
+
2161
+ .report-error {
2162
+ display: inline-flex;
2163
+ align-items: center;
2164
+ gap: 6px;
2165
+ color: var(--alarm);
2166
+ font-weight: 560;
2167
+ }
2168
+
2169
+ .report-error-detail {
2170
+ color: var(--faint);
2171
+ font-size: var(--text-xs);
2172
+ overflow-wrap: anywhere;
2173
+ }
2174
+
2175
+ .report-run {
2176
+ display: inline-flex;
2177
+ align-items: center;
2178
+ justify-content: center;
2179
+ gap: 7px;
2180
+ padding: 7px 12px;
2181
+ font-size: var(--text-sm);
2182
+ font-weight: 560;
2183
+ color: var(--ink);
2184
+ border: 1px solid var(--hairline-strong);
2185
+ border-radius: 4px;
2186
+ }
2187
+
2188
+ .report-run:hover {
2189
+ background: var(--panel-raised);
2190
+ }
2191
+
2192
+ .report-cost {
2193
+ color: var(--faint);
2194
+ font-size: var(--text-xs);
2195
+ }
2196
+
2197
+ .report-picker {
2198
+ display: flex;
2199
+ flex-wrap: wrap;
2200
+ gap: 6px;
2201
+ min-width: 0;
2202
+ }
2203
+
2204
+ .report-picker select {
2205
+ max-width: 100%;
2206
+ appearance: none;
2207
+ padding: 4px 8px;
2208
+ font-size: var(--text-xs);
2209
+ font-family: inherit;
2210
+ color: var(--muted);
2211
+ background: transparent;
2212
+ border: 1px solid var(--hairline-strong);
2213
+ border-radius: 3px;
2214
+ cursor: pointer;
2215
+ }
2216
+
2217
+ .report-picker select:hover {
2218
+ color: var(--ink);
2219
+ background: var(--panel-raised);
2220
+ }
2221
+
2222
+ .report-stale-actions {
2223
+ display: flex;
2224
+ flex-wrap: wrap;
2225
+ align-items: center;
2226
+ gap: 6px;
2227
+ }
2228
+
2229
+ .report-body {
2230
+ display: grid;
2231
+ gap: 2px;
2232
+ padding-bottom: 10px;
2233
+ }
2234
+
2235
+ /* one controls block at the top owns judge choice, re-evaluation, and the
2236
+ staleness note — the report below it is pure content */
2237
+ .report-controls {
2238
+ display: flex;
2239
+ flex-direction: column;
2240
+ gap: 7px;
2241
+ padding: 10px 16px 0;
2242
+ }
2243
+
2244
+ .report-stale-note {
2245
+ color: var(--amber);
2246
+ font-size: var(--text-xs);
2247
+ line-height: 1.4;
2248
+ }
2249
+
2250
+ .report-rerun {
2251
+ display: inline-flex;
2252
+ align-items: center;
2253
+ gap: 5px;
2254
+ flex-shrink: 0;
2255
+ padding: 3px 8px;
2256
+ font-size: var(--text-xs);
2257
+ font-weight: 560;
2258
+ color: var(--muted);
2259
+ border: 1px solid var(--hairline-strong);
2260
+ border-radius: 3px;
2261
+ }
2262
+
2263
+ .report-rerun:hover {
2264
+ color: var(--ink);
2265
+ background: var(--panel-raised);
2266
+ }
2267
+
2268
+ .report-task {
2269
+ padding: 12px 16px 2px;
2270
+ color: var(--ink);
2271
+ font-size: var(--text-sm);
2272
+ line-height: 1.55;
2273
+ }
2274
+
2275
+ .report-dimension {
2276
+ padding: 12px 16px 2px;
2277
+ }
2278
+
2279
+ .report-dimension-head {
2280
+ display: flex;
2281
+ align-items: center;
2282
+ justify-content: space-between;
2283
+ gap: 10px;
2284
+ margin-bottom: 6px;
2285
+ }
2286
+
2287
+ .report-dimension-name {
2288
+ color: var(--faint);
2289
+ font-size: var(--text-xs);
2290
+ font-weight: 560;
2291
+ letter-spacing: 0.14em;
2292
+ text-transform: uppercase;
2293
+ }
2294
+
2295
+ .verdict {
2296
+ padding: 1px 8px;
2297
+ border-radius: 999px;
2298
+ border: 1px solid var(--hairline-strong);
2299
+ font-size: var(--text-xs);
2300
+ font-weight: 560;
2301
+ letter-spacing: 0.04em;
2302
+ }
2303
+
2304
+ .verdict-good {
2305
+ color: var(--pine);
2306
+ }
2307
+
2308
+ .verdict-warning {
2309
+ color: var(--amber);
2310
+ }
2311
+
2312
+ .verdict-problem {
2313
+ color: var(--alarm);
2314
+ }
2315
+
2316
+ .verdict-insufficient-data {
2317
+ color: var(--faint);
2318
+ }
2319
+
2320
+ .report-finding {
2321
+ display: grid;
2322
+ grid-template-columns: 10px 1fr;
2323
+ align-items: baseline;
2324
+ gap: 8px;
2325
+ width: 100%;
2326
+ padding: 5px 4px;
2327
+ border-radius: 3px;
2328
+ text-align: left;
2329
+ color: var(--muted);
2330
+ font-size: var(--text-sm);
2331
+ line-height: 1.5;
2332
+ }
2333
+
2334
+ .report-finding:not(:disabled):hover {
2335
+ color: var(--ink);
2336
+ background: var(--panel-raised);
2337
+ }
2338
+
2339
+ .report-finding:disabled {
2340
+ cursor: default;
2341
+ }
2342
+
2343
+ .report-finding:disabled,
2344
+ .report-moment:disabled {
2345
+ opacity: 0.45;
2346
+ cursor: not-allowed;
2347
+ }
2348
+
2349
+ .severity-dot {
2350
+ width: 7px;
2351
+ height: 7px;
2352
+ border-radius: 999px;
2353
+ transform: translateY(-1px);
2354
+ }
2355
+
2356
+ .severity-dot.sev-info {
2357
+ background: var(--faint);
2358
+ }
2359
+
2360
+ .severity-dot.sev-warning {
2361
+ background: var(--amber);
2362
+ }
2363
+
2364
+ .severity-dot.sev-problem {
2365
+ background: var(--alarm);
2366
+ }
2367
+
2368
+ .report-claim {
2369
+ overflow-wrap: anywhere;
2370
+ }
2371
+
2372
+ /* task-accounting layer: criteria reuse the dimension pattern; only the
2373
+ task grouping chrome and coverage metadata are new. Coverage is metadata,
2374
+ not state — it stays on neutral tokens, no new status colors. */
2375
+
2376
+ /* chapter heads split the report into its two layers — Tasks (accounting)
2377
+ and Process (dimensions) — one rank above plain section eyebrows: their
2378
+ own ruled row, generous space above, tight below. */
2379
+ /* chapter heads are the panel's top type rank: ink, tracked wide, no rule —
2380
+ the report separates by type and spacing, not by lines */
2381
+ .report-chapter {
2382
+ margin: 0;
2383
+ padding: 20px 16px 4px;
2384
+ color: var(--ink);
2385
+ font-size: var(--text-sm);
2386
+ font-weight: 620;
2387
+ letter-spacing: 0.12em;
2388
+ text-transform: uppercase;
2389
+ }
2390
+
2391
+ .report-rubric-note {
2392
+ padding: 8px 16px;
2393
+ color: var(--faint);
2394
+ font-size: var(--text-xs);
2395
+ line-height: 1.5;
2396
+ }
2397
+
2398
+ /* CJK sentences never drop below --text-sm; --text-xs is reserved for latin
2399
+ labels, badges, and eyebrows */
2400
+ .report-rubric-hint {
2401
+ padding: 8px 16px 0;
2402
+ color: var(--muted);
2403
+ font-size: var(--text-sm);
2404
+ line-height: 1.5;
2405
+ }
2406
+
2407
+ /* spacing ranks the boundaries: chapter > task > criterion > finding.
2408
+ Criteria inside a task sit tighter than free-standing dimensions. */
2409
+ .report-criterion {
2410
+ padding: 8px 16px 6px;
2411
+ }
2412
+
2413
+ .report-criterion .report-dimension-head {
2414
+ margin-bottom: 4px;
2415
+ }
2416
+
2417
+ .rubric-task-head {
2418
+ display: flex;
2419
+ align-items: center;
2420
+ gap: 8px;
2421
+ width: 100%;
2422
+ padding: 16px 16px 0;
2423
+ text-align: left;
2424
+ }
2425
+
2426
+ .rubric-task-head:not(:disabled):hover .rubric-task-title {
2427
+ text-decoration: underline;
2428
+ text-decoration-color: var(--hairline-strong);
2429
+ text-underline-offset: 3px;
2430
+ }
2431
+
2432
+ .rubric-task-head:disabled {
2433
+ cursor: default;
2434
+ }
2435
+
2436
+ .rubric-task-title {
2437
+ color: var(--ink);
2438
+ font-size: var(--text-sm);
2439
+ font-weight: 560;
2440
+ }
2441
+
2442
+ /* the type tag trails the title's last character so a wrapped title keeps
2443
+ its tag attached; severity dots on findings stay the panel's only dots */
2444
+ .rubric-task-type {
2445
+ margin-left: 8px;
2446
+ color: var(--faint);
2447
+ font-size: var(--text-xs);
2448
+ font-weight: 400;
2449
+ letter-spacing: 0.06em;
2450
+ }
2451
+
2452
+ .report-criterion-name {
2453
+ color: var(--muted);
2454
+ font-size: var(--text-sm);
2455
+ font-weight: 560;
2456
+ overflow-wrap: anywhere;
2457
+ }
2458
+
2459
+ .report-criterion-badges {
2460
+ display: inline-flex;
2461
+ align-items: center;
2462
+ gap: 6px;
2463
+ flex-shrink: 0;
2464
+ }
2465
+
2466
+ .coverage-badge {
2467
+ padding: 1px 7px;
2468
+ border: 1px solid var(--hairline);
2469
+ border-radius: 999px;
2470
+ color: var(--faint);
2471
+ font-size: var(--text-xs);
2472
+ }
2473
+
2474
+ /* the scorer's note closes the rubric block: labeled so it reads as rubric
2475
+ metadata, hairlined so it does not run into the Process chapter below.
2476
+ The label stays an xs eyebrow; the note body is CJK prose and holds sm. */
2477
+ .report-rubric-footnote {
2478
+ padding: 14px 16px 2px;
2479
+ color: var(--muted);
2480
+ font-size: var(--text-sm);
2481
+ line-height: 1.55;
2482
+ }
2483
+
2484
+ .report-rubric-footnote .eyebrow {
2485
+ margin-bottom: 4px;
2486
+ }
2487
+
2488
+ .report-moment {
2489
+ display: grid;
2490
+ grid-template-columns: max-content 1fr;
2491
+ align-items: baseline;
2492
+ gap: 9px;
2493
+ width: 100%;
2494
+ padding: 5px 4px;
2495
+ border-radius: 3px;
2496
+ text-align: left;
2497
+ color: var(--muted);
2498
+ font-size: var(--text-sm);
2499
+ line-height: 1.5;
2500
+ }
2501
+
2502
+ .report-moment:hover:not(:disabled) {
2503
+ color: var(--ink);
2504
+ background: var(--panel-raised);
2505
+ }
2506
+
2507
+ .report-moment strong {
2508
+ font-variant-numeric: tabular-nums;
2509
+ }
2510
+
2511
+ /* the judge's overview joins the lede right under the task summary — the
2512
+ report reads summary-first, itemized layers after */
2513
+ .report-narrative {
2514
+ padding: 0 16px 12px;
2515
+ color: var(--muted);
2516
+ font-size: var(--text-sm);
2517
+ line-height: 1.6;
2518
+ }
2519
+
2520
+ /* moments + narrative share the dimensions' side padding so the report
2521
+ reads as one column */
2522
+ .report-section {
2523
+ padding: 10px 16px 6px;
2524
+ }
2525
+
2526
+
2527
+ /* rail evaluation badges: the list mirrors judge state without extra clicks */
2528
+
2529
+ .rail-eval {
2530
+ display: inline-flex;
2531
+ align-items: center;
2532
+ gap: 5px;
2533
+ flex-shrink: 0;
2534
+ margin-left: auto;
2535
+ font-size: var(--text-xs);
2536
+ letter-spacing: 0.04em;
2537
+ }
2538
+
2539
+ .rail-eval::before {
2540
+ content: "";
2541
+ width: 6px;
2542
+ height: 6px;
2543
+ border-radius: 999px;
2544
+ }
2545
+
2546
+ .rail-eval-running {
2547
+ color: var(--moon);
2548
+ }
2549
+
2550
+ .rail-eval-running::before {
2551
+ background: var(--moon);
2552
+ animation: report-pulse 1.4s ease-in-out infinite;
2553
+ }
2554
+
2555
+ .rail-eval-done::before {
2556
+ background: var(--pine);
2557
+ }
2558
+
2559
+ .rail-eval-stale::before {
2560
+ background: var(--amber);
2561
+ }
2562
+
2563
+ .rail-eval-failed::before {
2564
+ background: var(--alarm);
2565
+ }