taskplane 0.1.5 → 0.1.7

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.
@@ -1,924 +1,1108 @@
1
- /* ─── Reset & Base ─────────────────────────────────────────────────────── */
2
-
3
- *,
4
- *::before,
5
- *::after {
6
- box-sizing: border-box;
7
- margin: 0;
8
- padding: 0;
9
- }
10
-
11
- :root {
12
- --bg: #0d1117;
13
- --bg-surface: #161b22;
14
- --bg-surface-hover: #1c2129;
15
- --bg-inset: #0d1117;
16
- --border: #30363d;
17
- --border-subtle: #21262d;
18
- --text: #e6edf3;
19
- --text-muted: #8b949e;
20
- --text-faint: #484f58;
21
- --accent: #58a6ff;
22
- --accent-dim: #1f6feb;
23
- --green: #3fb950;
24
- --green-dim: #238636;
25
- --red: #f85149;
26
- --red-dim: #da3633;
27
- --yellow: #d29922;
28
- --yellow-dim: #9e6a03;
29
- --cyan: #39d2c0;
30
- --magenta: #bc8cff;
31
- --font-mono: "JetBrains Mono", "Fira Code", "Cascadia Code", "SF Mono", Consolas, monospace;
32
- --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
33
- --radius: 8px;
34
- --radius-sm: 4px;
35
- }
36
-
37
- html { font-size: 14px; }
38
-
39
- body {
40
- font-family: var(--font-sans);
41
- background: var(--bg);
42
- color: var(--text);
43
- min-height: 100vh;
44
- overflow-x: hidden;
45
- }
46
-
47
- /* ─── Layout Shell ─────────────────────────────────────────────────────── */
48
-
49
- .dashboard {
50
- display: grid;
51
- grid-template-rows: auto auto 1fr auto;
52
- min-height: 100vh;
53
- padding: 16px 20px;
54
- gap: 12px;
55
- max-width: 1600px;
56
- margin: 0 auto;
57
- }
58
-
59
- /* ─── Header ───────────────────────────────────────────────────────────── */
60
-
61
- .header {
62
- display: flex;
63
- align-items: center;
64
- gap: 16px;
65
- flex-wrap: wrap;
66
- }
67
-
68
- .header-title {
69
- font-size: 1.35rem;
70
- font-weight: 700;
71
- letter-spacing: -0.02em;
72
- white-space: nowrap;
73
- }
74
-
75
- .header-badge {
76
- display: inline-flex;
77
- align-items: center;
78
- gap: 6px;
79
- font-family: var(--font-mono);
80
- font-size: 0.8rem;
81
- padding: 3px 10px;
82
- border-radius: 12px;
83
- font-weight: 500;
84
- }
85
-
86
- .badge-batch {
87
- background: var(--bg-surface);
88
- border: 1px solid var(--border);
89
- color: var(--accent);
90
- }
91
-
92
- .badge-phase {
93
- font-weight: 600;
94
- text-transform: uppercase;
95
- letter-spacing: 0.05em;
96
- font-size: 0.7rem;
97
- }
98
-
99
- .phase-executing { background: var(--accent-dim); color: #fff; }
100
- .phase-merging { background: #1a3a5c; color: var(--accent); }
101
- .phase-completed { background: var(--green-dim); color: #fff; }
102
- .phase-paused { background: var(--yellow-dim); color: #fff; }
103
- .phase-stopped,
104
- .phase-aborted { background: var(--red-dim); color: #fff; }
105
- .phase-failed { background: var(--red-dim); color: #fff; }
106
-
107
- .header-meta {
108
- margin-left: auto;
109
- display: flex;
110
- align-items: center;
111
- gap: 12px;
112
- color: var(--text-muted);
113
- font-size: 0.8rem;
114
- }
115
-
116
- .connection-dot {
117
- width: 8px;
118
- height: 8px;
119
- border-radius: 50%;
120
- display: inline-block;
121
- }
122
-
123
- .connection-dot.connected { background: var(--green); }
124
- .connection-dot.disconnected { background: var(--red); }
125
-
126
- /* ─── Summary Bar ──────────────────────────────────────────────────────── */
127
-
128
- .summary-bar {
129
- display: flex;
130
- align-items: center;
131
- gap: 16px;
132
- padding: 12px 16px;
133
- background: var(--bg-surface);
134
- border: 1px solid var(--border);
135
- border-radius: var(--radius);
136
- flex-wrap: wrap;
137
- }
138
-
139
- .summary-progress {
140
- display: flex;
141
- align-items: center;
142
- gap: 10px;
143
- flex-shrink: 0;
144
- }
145
-
146
- .progress-bar-bg {
147
- width: 280px;
148
- height: 18px;
149
- background: var(--bg-inset);
150
- border-radius: 4px;
151
- overflow: hidden;
152
- display: flex;
153
- position: relative;
154
- }
155
-
156
- /* Individual wave segment within the segmented bar */
157
- .wave-seg {
158
- position: relative;
159
- height: 100%;
160
- overflow: hidden;
161
- border-right: 1px solid var(--bg-deeper, rgba(0,0,0,0.3));
162
- }
163
- .wave-seg:last-child { border-right: none; }
164
-
165
- /* The filled portion within each segment */
166
- .wave-seg-fill {
167
- height: 100%;
168
- transition: width 0.5s ease, background-color 0.5s ease;
169
- }
170
- .wave-seg-fill.pct-0 { background: transparent; }
171
- .wave-seg-fill.pct-low { background: var(--yellow); }
172
- .wave-seg-fill.pct-mid { background: var(--cyan); }
173
- .wave-seg-fill.pct-hi { background: var(--green); }
174
-
175
- /* Wave label centered in each segment */
176
- .wave-seg-label {
177
- position: absolute;
178
- top: 0; left: 0; right: 0; bottom: 0;
179
- display: flex;
180
- align-items: center;
181
- justify-content: center;
182
- font-size: 0.6rem;
183
- font-weight: 700;
184
- letter-spacing: 0.03em;
185
- color: rgba(255,255,255,0.85);
186
- pointer-events: none;
187
- text-shadow: 0 1px 2px rgba(0,0,0,0.6);
188
- }
189
-
190
- /* Highlight the active wave segment */
191
- .wave-seg-current { box-shadow: inset 0 0 0 1px var(--accent); }
192
-
193
- /* Future waves: visible but subdued */
194
- .wave-seg-future {
195
- background: rgba(139,148,158,0.25);
196
- }
197
- .wave-seg-future .wave-seg-label {
198
- color: rgba(255,255,255,0.55);
199
- text-shadow: none;
200
- }
201
-
202
- /* Legacy single-bar fill (still used by per-task progress bars) */
203
- .progress-bar-fill {
204
- height: 100%;
205
- border-radius: 4px;
206
- transition: width 0.5s ease, background-color 0.5s ease;
207
- }
208
- .progress-bar-fill.pct-0 { background: var(--text-faint); }
209
- .progress-bar-fill.pct-low { background: var(--yellow); }
210
- .progress-bar-fill.pct-mid { background: var(--cyan); }
211
- .progress-bar-fill.pct-hi { background: var(--green); }
212
-
213
- .summary-pct {
214
- font-family: var(--font-mono);
215
- font-size: 0.95rem;
216
- font-weight: 600;
217
- min-width: 38px;
218
- }
219
-
220
- .summary-counts {
221
- display: flex;
222
- gap: 10px;
223
- font-family: var(--font-mono);
224
- font-size: 0.85rem;
225
- }
226
-
227
- .count-chip {
228
- display: inline-flex;
229
- align-items: center;
230
- gap: 4px;
231
- padding: 2px 10px;
232
- border-radius: 10px;
233
- font-weight: 500;
234
- margin-right: 4px;
235
- }
236
- .count-num { font-variant-numeric: tabular-nums; }
237
- .count-icon { font-size: 0.85em; opacity: 0.9; }
238
- .count-total { color: var(--text-faint); margin-left: 2px; }
239
-
240
- .count-succeeded { background: rgba(63,185,80,0.15); color: var(--green); }
241
- .count-running { background: rgba(88,166,255,0.15); color: var(--accent); }
242
- .count-failed { background: rgba(248,81,73,0.15); color: var(--red); }
243
- .count-stalled { background: rgba(210,153,34,0.15); color: var(--yellow); }
244
- .count-pending { background: rgba(139,148,158,0.1); color: var(--text-muted); }
245
-
246
- .summary-elapsed {
247
- color: var(--text-muted);
248
- font-size: 0.8rem;
249
- font-family: var(--font-mono);
250
- }
251
-
252
- .summary-waves {
253
- display: flex;
254
- align-items: center;
255
- gap: 6px;
256
- font-size: 0.8rem;
257
- }
258
-
259
- .wave-chip {
260
- padding: 2px 8px;
261
- border-radius: 10px;
262
- font-family: var(--font-mono);
263
- font-size: 0.75rem;
264
- font-weight: 500;
265
- border: 1px solid var(--border);
266
- color: var(--text-muted);
267
- }
268
-
269
- .wave-chip.current {
270
- border-color: var(--accent-dim);
271
- background: rgba(88,166,255,0.12);
272
- color: var(--accent);
273
- font-weight: 700;
274
- }
275
-
276
- .wave-chip.done {
277
- border-color: var(--green-dim);
278
- background: rgba(63,185,80,0.12);
279
- color: var(--green);
280
- }
281
-
282
- /* ─── Content ──────────────────────────────────────────────────────────── */
283
-
284
- .content {
285
- display: flex;
286
- flex-direction: column;
287
- gap: 12px;
288
- min-height: 0;
289
- }
290
-
291
- /* ─── Panels (shared) ──────────────────────────────────────────────────── */
292
-
293
- .panel {
294
- background: var(--bg-surface);
295
- border: 1px solid var(--border);
296
- border-radius: var(--radius);
297
- overflow: hidden;
298
- display: flex;
299
- flex-direction: column;
300
- }
301
-
302
- .panel-header {
303
- padding: 10px 14px;
304
- font-size: 0.75rem;
305
- font-weight: 600;
306
- text-transform: uppercase;
307
- letter-spacing: 0.06em;
308
- color: var(--text-muted);
309
- border-bottom: 1px solid var(--border);
310
- background: var(--bg-surface);
311
- }
312
-
313
- .panel-body {
314
- padding: 0;
315
- flex: 1;
316
- overflow-y: auto;
317
- }
318
-
319
- .empty-state {
320
- padding: 24px;
321
- text-align: center;
322
- color: var(--text-faint);
323
- font-size: 0.85rem;
324
- }
325
-
326
- /* ─── Lane Group (lane header + nested task rows) ──────────────────────── */
327
-
328
- .lane-group {
329
- border-bottom: 1px solid var(--border);
330
- }
331
-
332
- .lane-group:last-child { border-bottom: none; }
333
-
334
- .lane-header {
335
- display: grid;
336
- grid-template-columns: 36px 1fr auto;
337
- align-items: center;
338
- gap: 12px;
339
- padding: 10px 14px;
340
- background: var(--bg-inset);
341
- border-bottom: 1px solid var(--border-subtle);
342
- }
343
-
344
- .lane-num {
345
- font-family: var(--font-mono);
346
- font-size: 1rem;
347
- font-weight: 700;
348
- color: var(--text-muted);
349
- text-align: center;
350
- }
351
-
352
- .lane-meta {
353
- display: flex;
354
- align-items: center;
355
- gap: 10px;
356
- min-width: 0;
357
- }
358
-
359
- .lane-session {
360
- font-family: var(--font-mono);
361
- font-size: 0.82rem;
362
- color: var(--accent);
363
- white-space: nowrap;
364
- }
365
-
366
- .lane-branch {
367
- font-size: 0.72rem;
368
- color: var(--text-muted);
369
- white-space: nowrap;
370
- overflow: hidden;
371
- text-overflow: ellipsis;
372
- }
373
-
374
- .lane-right {
375
- display: flex;
376
- align-items: center;
377
- gap: 10px;
378
- }
379
-
380
- .tmux-dot {
381
- width: 8px;
382
- height: 8px;
383
- border-radius: 50%;
384
- flex-shrink: 0;
385
- }
386
-
387
- .tmux-dot.alive { background: var(--green); }
388
- .tmux-dot.dead { background: var(--red); opacity: 0.6; }
389
-
390
- .tmux-view-btn {
391
- font-family: var(--font-sans);
392
- font-size: 0.72rem;
393
- font-weight: 600;
394
- padding: 3px 10px;
395
- border-radius: var(--radius-sm);
396
- background: var(--accent-dim);
397
- border: 1px solid var(--accent-dim);
398
- color: #fff;
399
- cursor: pointer;
400
- white-space: nowrap;
401
- transition: background 0.2s, border-color 0.2s;
402
- }
403
-
404
- .tmux-view-btn:hover {
405
- background: var(--accent);
406
- border-color: var(--accent);
407
- }
408
-
409
- .tmux-cmd {
410
- font-family: var(--font-mono);
411
- font-size: 0.7rem;
412
- padding: 3px 8px;
413
- border-radius: var(--radius-sm);
414
- background: var(--bg);
415
- border: 1px solid var(--border);
416
- color: var(--text);
417
- cursor: pointer;
418
- user-select: all;
419
- white-space: nowrap;
420
- transition: border-color 0.2s, color 0.2s;
421
- }
422
-
423
- .tmux-cmd:hover {
424
- border-color: var(--accent-dim);
425
- color: var(--accent);
426
- }
427
-
428
- .tmux-cmd.copied {
429
- border-color: var(--green-dim);
430
- color: var(--green);
431
- }
432
-
433
- .tmux-cmd.dead-session {
434
- color: var(--text-muted);
435
- cursor: default;
436
- }
437
-
438
- /* ─── Task Row (inside lane group) ─────────────────────────────────────── */
439
-
440
- .task-row {
441
- display: grid;
442
- grid-template-columns: 36px 100px 90px 80px 200px 1fr;
443
- align-items: center;
444
- gap: 8px;
445
- padding: 8px 14px;
446
- border-bottom: 1px solid var(--border-subtle);
447
- transition: background 0.15s;
448
- }
449
-
450
- .task-row:last-child { border-bottom: none; }
451
- .task-row:hover { background: var(--bg-surface-hover); }
452
-
453
- .task-icon {
454
- text-align: center;
455
- }
456
-
457
- .task-id {
458
- font-family: var(--font-mono);
459
- font-weight: 600;
460
- font-size: 0.85rem;
461
- }
462
-
463
- .task-duration {
464
- font-family: var(--font-mono);
465
- font-size: 0.8rem;
466
- color: var(--text-muted);
467
- }
468
-
469
- .task-step {
470
- font-size: 0.8rem;
471
- color: var(--text-muted);
472
- white-space: nowrap;
473
- overflow: hidden;
474
- text-overflow: ellipsis;
475
- }
476
-
477
- .task-iter {
478
- font-family: var(--font-mono);
479
- font-size: 0.7rem;
480
- color: var(--text-faint);
481
- margin-left: 6px;
482
- }
483
-
484
- /* Status badges */
485
- .status-badge {
486
- display: inline-flex;
487
- align-items: center;
488
- gap: 4px;
489
- font-family: var(--font-mono);
490
- font-size: 0.75rem;
491
- font-weight: 600;
492
- padding: 2px 8px;
493
- border-radius: 10px;
494
- }
495
-
496
- .status-succeeded { background: rgba(63,185,80,0.15); color: var(--green); }
497
- .status-running { background: rgba(88,166,255,0.15); color: var(--accent); }
498
- .status-failed { background: rgba(248,81,73,0.15); color: var(--red); }
499
- .status-stalled { background: rgba(210,153,34,0.15); color: var(--yellow); }
500
- .status-pending { background: rgba(139,148,158,0.1); color: var(--text-muted); }
501
- .status-skipped { background: rgba(139,148,158,0.1); color: var(--text-faint); }
502
-
503
- .status-dot {
504
- width: 6px;
505
- height: 6px;
506
- border-radius: 50%;
507
- display: inline-block;
508
- }
509
-
510
- .status-dot.succeeded { background: var(--green); }
511
- .status-dot.running { background: var(--accent); }
512
- .status-dot.failed { background: var(--red); }
513
- .status-dot.stalled { background: var(--yellow); }
514
- .status-dot.pending { background: var(--text-faint); }
515
- .status-dot.skipped { background: var(--text-faint); }
516
-
517
- /* Task progress bar (inline) */
518
- .task-progress {
519
- display: flex;
520
- align-items: center;
521
- gap: 8px;
522
- }
523
-
524
- .task-progress-bar {
525
- width: 80px;
526
- height: 6px;
527
- background: var(--bg-inset);
528
- border-radius: 3px;
529
- overflow: hidden;
530
- flex-shrink: 0;
531
- }
532
-
533
- .task-progress-fill {
534
- height: 100%;
535
- border-radius: 3px;
536
- transition: width 0.5s ease;
537
- }
538
-
539
- .task-progress-fill.pct-0 { background: var(--text-faint); }
540
- .task-progress-fill.pct-low { background: var(--yellow); }
541
- .task-progress-fill.pct-mid { background: var(--cyan); }
542
- .task-progress-fill.pct-hi { background: var(--green); }
543
-
544
- .task-progress-text {
545
- font-family: var(--font-mono);
546
- font-size: 0.75rem;
547
- color: var(--text-muted);
548
- min-width: 55px;
549
- }
550
-
551
- /* ─── Merge Agents Table ───────────────────────────────────────────────── */
552
-
553
- .merge-table {
554
- width: 100%;
555
- border-collapse: collapse;
556
- }
557
-
558
- .merge-table th {
559
- text-align: left;
560
- padding: 8px 12px;
561
- font-size: 0.7rem;
562
- font-weight: 600;
563
- text-transform: uppercase;
564
- letter-spacing: 0.05em;
565
- color: var(--text-faint);
566
- border-bottom: 1px solid var(--border);
567
- background: var(--bg-surface);
568
- }
569
-
570
- .merge-table td {
571
- padding: 8px 12px;
572
- border-bottom: 1px solid var(--border-subtle);
573
- font-size: 0.85rem;
574
- }
575
-
576
- .merge-table tr:last-child td { border-bottom: none; }
577
- .merge-table tr:hover td { background: var(--bg-surface-hover); }
578
-
579
- /* ─── Terminal Panel ────────────────────────────────────────────────────── */
580
-
581
- .terminal-panel .panel-header {
582
- display: flex;
583
- align-items: center;
584
- justify-content: space-between;
585
- }
586
-
587
- .terminal-close {
588
- background: none;
589
- border: 1px solid var(--border);
590
- color: var(--text-muted);
591
- font-size: 0.85rem;
592
- cursor: pointer;
593
- padding: 2px 8px;
594
- border-radius: var(--radius-sm);
595
- transition: color 0.2s, border-color 0.2s;
596
- }
597
-
598
- .terminal-close:hover {
599
- color: var(--red);
600
- border-color: var(--red-dim);
601
- }
602
-
603
- .terminal-panel .panel-body {
604
- max-height: 500px;
605
- padding: 0;
606
- background: var(--bg-inset);
607
- overflow-y: auto;
608
- }
609
-
610
- /* ─── Worker Stats (inline in task row) ────────────────────────────────── */
611
-
612
- .worker-stats {
613
- display: flex;
614
- align-items: center;
615
- gap: 10px;
616
- margin-top: 4px;
617
- flex-wrap: wrap;
618
- }
619
-
620
- .worker-stat {
621
- font-family: var(--font-mono);
622
- font-size: 0.7rem;
623
- color: var(--text-muted);
624
- white-space: nowrap;
625
- }
626
-
627
- .worker-last-tool {
628
- color: var(--text-muted);
629
- max-width: 600px;
630
- overflow: hidden;
631
- text-overflow: ellipsis;
632
- }
633
-
634
- /* ─── Conversation Viewer ──────────────────────────────────────────────── */
635
-
636
- .conv-stream {
637
- padding: 12px 16px;
638
- font-family: var(--font-mono);
639
- font-size: 0.82rem;
640
- line-height: 1.6;
641
- white-space: pre-wrap;
642
- word-break: break-word;
643
- }
644
-
645
- .conv-text {
646
- color: var(--text);
647
- }
648
-
649
- .conv-thinking {
650
- color: var(--text-faint);
651
- font-style: italic;
652
- }
653
-
654
- .conv-tool-call {
655
- margin: 8px 0 4px;
656
- padding: 6px 10px;
657
- background: rgba(88,166,255,0.08);
658
- border-left: 3px solid var(--accent-dim);
659
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
660
- }
661
-
662
- .conv-tool-name {
663
- color: var(--accent);
664
- font-weight: 600;
665
- }
666
-
667
- .conv-tool-args {
668
- color: var(--text-muted);
669
- font-size: 0.75rem;
670
- }
671
-
672
- .conv-tool-result {
673
- margin: 0 0 8px;
674
- padding: 6px 10px;
675
- background: var(--bg-inset);
676
- border-left: 3px solid var(--border);
677
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
678
- max-height: 200px;
679
- overflow-y: auto;
680
- }
681
-
682
- .conv-tool-result pre {
683
- margin: 0;
684
- font-size: 0.75rem;
685
- color: var(--text-muted);
686
- white-space: pre-wrap;
687
- }
688
-
689
- .conv-usage {
690
- margin: 6px 0;
691
- padding: 4px 10px;
692
- font-size: 0.7rem;
693
- color: var(--text-faint);
694
- border-top: 1px solid var(--border-subtle);
695
- }
696
-
697
- .conv-empty {
698
- padding: 40px;
699
- text-align: center;
700
- color: var(--text-faint);
701
- }
702
-
703
- /* ─── Errors Panel ─────────────────────────────────────────────────────── */
704
-
705
- .errors-panel .panel-header { color: var(--red); }
706
-
707
- .error-item {
708
- padding: 8px 14px;
709
- font-family: var(--font-mono);
710
- font-size: 0.78rem;
711
- color: var(--red);
712
- border-bottom: 1px solid var(--border-subtle);
713
- display: flex;
714
- align-items: flex-start;
715
- gap: 8px;
716
- }
717
-
718
- .error-item:last-child { border-bottom: none; }
719
- .error-bullet { flex-shrink: 0; margin-top: 2px; }
720
- .error-text { word-break: break-word; }
721
-
722
- /* ─── Footer ───────────────────────────────────────────────────────────── */
723
-
724
- .footer {
725
- display: flex;
726
- align-items: center;
727
- justify-content: space-between;
728
- padding: 8px 4px;
729
- font-size: 0.75rem;
730
- color: var(--text-faint);
731
- }
732
-
733
- /* ─── No Batch State ───────────────────────────────────────────────────── */
734
-
735
- .no-batch {
736
- display: flex;
737
- flex-direction: column;
738
- align-items: center;
739
- justify-content: center;
740
- gap: 12px;
741
- padding: 80px 20px;
742
- text-align: center;
743
- }
744
-
745
- .no-batch-icon { font-size: 3rem; opacity: 0.3; }
746
- .no-batch-title { font-size: 1.1rem; font-weight: 600; color: var(--text-muted); }
747
- .no-batch-hint { font-size: 0.85rem; color: var(--text-faint); font-family: var(--font-mono); }
748
-
749
- /* ─── Responsive ───────────────────────────────────────────────────────── */
750
-
751
- @media (max-width: 900px) {
752
- .task-row {
753
- grid-template-columns: 36px 90px 80px 70px 1fr;
754
- }
755
- .task-row .task-step { display: none; }
756
- .progress-bar-bg { width: 160px; }
757
- }
758
-
759
- /* ─── Scrollbar ────────────────────────────────────────────────────────── */
760
-
761
- ::-webkit-scrollbar { width: 6px; }
762
- ::-webkit-scrollbar-track { background: transparent; }
763
- ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
764
- ::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
765
-
766
- /* ─── Pulse animation ──────────────────────────────────────────────────── */
767
-
768
- @keyframes pulse {
769
- 0%, 100% { opacity: 1; }
770
- 50% { opacity: 0.5; }
771
- }
772
-
773
- .status-running .status-dot { animation: pulse 2s infinite; }
774
-
775
- /* ─── Copy toast ───────────────────────────────────────────────────────── */
776
-
777
- .copy-toast {
778
- position: fixed;
779
- bottom: 20px;
780
- right: 20px;
781
- background: var(--green-dim);
782
- color: #fff;
783
- padding: 8px 16px;
784
- border-radius: var(--radius);
785
- font-size: 0.8rem;
786
- font-family: var(--font-mono);
787
- opacity: 0;
788
- transform: translateY(8px);
789
- transition: opacity 0.2s, transform 0.2s;
790
- pointer-events: none;
791
- z-index: 100;
792
- }
793
-
794
- .copy-toast.visible {
795
- opacity: 1;
796
- transform: translateY(0);
797
- }
798
-
799
- /* ── History Dropdown ────────────────────────────────────────────────────── */
800
-
801
- .history-select {
802
- background: var(--bg-surface);
803
- border: 1px solid var(--border);
804
- color: var(--text-muted);
805
- font-family: var(--font-mono);
806
- font-size: 0.8rem;
807
- padding: 3px 8px;
808
- border-radius: 8px;
809
- cursor: pointer;
810
- max-width: 260px;
811
- }
812
- .history-select:hover {
813
- border-color: var(--accent);
814
- color: var(--text-primary);
815
- }
816
- .history-select:focus {
817
- outline: none;
818
- border-color: var(--accent);
819
- }
820
-
821
- /* ── History Summary Panel ───────────────────────────────────────────────── */
822
-
823
- .history-panel .panel-body {
824
- padding: 16px;
825
- }
826
-
827
- .history-header {
828
- display: flex;
829
- align-items: center;
830
- gap: 16px;
831
- margin-bottom: 16px;
832
- flex-wrap: wrap;
833
- }
834
-
835
- .history-header .batch-id {
836
- font-family: var(--font-mono);
837
- font-size: 1.1rem;
838
- font-weight: 700;
839
- color: var(--accent);
840
- }
841
-
842
- .history-header .batch-status {
843
- font-size: 0.85rem;
844
- padding: 2px 10px;
845
- border-radius: 12px;
846
- font-weight: 600;
847
- }
848
-
849
- .history-header .batch-status.completed { background: rgba(63,185,80,0.15); color: var(--green); }
850
- .history-header .batch-status.partial { background: rgba(210,153,34,0.15); color: var(--yellow); }
851
- .history-header .batch-status.failed { background: rgba(248,81,73,0.15); color: var(--red); }
852
- .history-header .batch-status.aborted { background: rgba(139,148,158,0.15); color: var(--text-muted); }
853
-
854
- .history-header .batch-time {
855
- color: var(--text-muted);
856
- font-size: 0.85rem;
857
- }
858
-
859
- .history-stats {
860
- display: grid;
861
- grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
862
- gap: 12px;
863
- margin-bottom: 16px;
864
- }
865
-
866
- .stat-card {
867
- background: var(--bg-surface);
868
- border: 1px solid var(--border);
869
- border-radius: 8px;
870
- padding: 12px;
871
- text-align: center;
872
- }
873
-
874
- .stat-card .stat-value {
875
- font-family: var(--font-mono);
876
- font-size: 1.3rem;
877
- font-weight: 700;
878
- color: var(--text-primary);
879
- }
880
-
881
- .stat-card .stat-label {
882
- font-size: 0.75rem;
883
- color: var(--text-muted);
884
- margin-top: 2px;
885
- }
886
-
887
- .stat-card.stat-tokens .stat-value {
888
- font-size: 0.95rem;
889
- color: var(--accent);
890
- }
891
-
892
- .history-waves-table,
893
- .history-tasks-table {
894
- width: 100%;
895
- border-collapse: collapse;
896
- margin-bottom: 16px;
897
- }
898
-
899
- .history-waves-table th,
900
- .history-tasks-table th {
901
- text-align: left;
902
- padding: 6px 10px;
903
- border-bottom: 1px solid var(--border);
904
- font-size: 0.75rem;
905
- color: var(--text-muted);
906
- text-transform: uppercase;
907
- letter-spacing: 0.05em;
908
- }
909
-
910
- .history-waves-table td,
911
- .history-tasks-table td {
912
- padding: 6px 10px;
913
- border-bottom: 1px solid rgba(48,54,61,0.3);
914
- font-family: var(--font-mono);
915
- font-size: 0.85rem;
916
- color: var(--text-muted);
917
- }
918
-
919
- .history-section-title {
920
- font-size: 0.9rem;
921
- font-weight: 600;
922
- color: var(--text-primary);
923
- margin: 16px 0 8px;
924
- }
1
+ /* ─── Reset & Base ─────────────────────────────────────────────────────── */
2
+
3
+ *,
4
+ *::before,
5
+ *::after {
6
+ box-sizing: border-box;
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ :root {
12
+ --bg: #0d1117;
13
+ --bg-surface: #161b22;
14
+ --bg-surface-hover: #1c2129;
15
+ --bg-inset: #0d1117;
16
+ --border: #30363d;
17
+ --border-subtle: #21262d;
18
+ --text: #e6edf3;
19
+ --text-muted: #8b949e;
20
+ --text-faint: #484f58;
21
+ --accent: #58a6ff;
22
+ --accent-dim: #1f6feb;
23
+ --green: #3fb950;
24
+ --green-dim: #238636;
25
+ --red: #f85149;
26
+ --red-dim: #da3633;
27
+ --yellow: #d29922;
28
+ --yellow-dim: #9e6a03;
29
+ --cyan: #39d2c0;
30
+ --magenta: #bc8cff;
31
+ --font-mono: "JetBrains Mono", "Fira Code", "Cascadia Code", "SF Mono", Consolas, monospace;
32
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
33
+ --radius: 8px;
34
+ --radius-sm: 4px;
35
+ }
36
+
37
+ html { font-size: 14px; }
38
+
39
+ body {
40
+ font-family: var(--font-sans);
41
+ background: var(--bg);
42
+ color: var(--text);
43
+ min-height: 100vh;
44
+ overflow-x: hidden;
45
+ }
46
+
47
+ /* ─── Layout Shell ─────────────────────────────────────────────────────── */
48
+
49
+ .dashboard {
50
+ display: grid;
51
+ grid-template-rows: auto auto 1fr auto;
52
+ min-height: 100vh;
53
+ padding: 16px 20px;
54
+ gap: 12px;
55
+ max-width: 1600px;
56
+ margin: 0 auto;
57
+ }
58
+
59
+ /* ─── Header ───────────────────────────────────────────────────────────── */
60
+
61
+ .header {
62
+ display: flex;
63
+ align-items: center;
64
+ gap: 16px;
65
+ flex-wrap: wrap;
66
+ }
67
+
68
+ .header-title {
69
+ font-size: 1.35rem;
70
+ font-weight: 700;
71
+ letter-spacing: -0.02em;
72
+ white-space: nowrap;
73
+ }
74
+
75
+ .header-badge {
76
+ display: inline-flex;
77
+ align-items: center;
78
+ gap: 6px;
79
+ font-family: var(--font-mono);
80
+ font-size: 0.8rem;
81
+ padding: 3px 10px;
82
+ border-radius: 12px;
83
+ font-weight: 500;
84
+ }
85
+
86
+ .badge-batch {
87
+ background: var(--bg-surface);
88
+ border: 1px solid var(--border);
89
+ color: var(--accent);
90
+ }
91
+
92
+ .badge-phase {
93
+ font-weight: 600;
94
+ text-transform: uppercase;
95
+ letter-spacing: 0.05em;
96
+ font-size: 0.7rem;
97
+ }
98
+
99
+ .phase-executing { background: var(--accent-dim); color: #fff; }
100
+ .phase-merging { background: #1a3a5c; color: var(--accent); }
101
+ .phase-completed { background: var(--green-dim); color: #fff; }
102
+ .phase-paused { background: var(--yellow-dim); color: #fff; }
103
+ .phase-stopped,
104
+ .phase-aborted { background: var(--red-dim); color: #fff; }
105
+ .phase-failed { background: var(--red-dim); color: #fff; }
106
+
107
+ .header-meta {
108
+ margin-left: auto;
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 12px;
112
+ color: var(--text-muted);
113
+ font-size: 0.8rem;
114
+ }
115
+
116
+ .connection-dot {
117
+ width: 8px;
118
+ height: 8px;
119
+ border-radius: 50%;
120
+ display: inline-block;
121
+ }
122
+
123
+ .connection-dot.connected { background: var(--green); }
124
+ .connection-dot.disconnected { background: var(--red); }
125
+
126
+ /* ─── Summary Bar ──────────────────────────────────────────────────────── */
127
+
128
+ .summary-bar {
129
+ display: flex;
130
+ align-items: center;
131
+ gap: 16px;
132
+ padding: 12px 16px;
133
+ background: var(--bg-surface);
134
+ border: 1px solid var(--border);
135
+ border-radius: var(--radius);
136
+ flex-wrap: wrap;
137
+ }
138
+
139
+ .summary-progress {
140
+ display: flex;
141
+ align-items: center;
142
+ gap: 10px;
143
+ flex-shrink: 0;
144
+ }
145
+
146
+ .progress-bar-bg {
147
+ width: 280px;
148
+ height: 18px;
149
+ background: var(--bg-inset);
150
+ border-radius: 4px;
151
+ overflow: hidden;
152
+ display: flex;
153
+ position: relative;
154
+ }
155
+
156
+ /* Individual wave segment within the segmented bar */
157
+ .wave-seg {
158
+ position: relative;
159
+ height: 100%;
160
+ overflow: hidden;
161
+ border-right: 1px solid var(--bg-deeper, rgba(0,0,0,0.3));
162
+ }
163
+ .wave-seg:last-child { border-right: none; }
164
+
165
+ /* The filled portion within each segment */
166
+ .wave-seg-fill {
167
+ height: 100%;
168
+ transition: width 0.5s ease, background-color 0.5s ease;
169
+ }
170
+ .wave-seg-fill.pct-0 { background: transparent; }
171
+ .wave-seg-fill.pct-low { background: var(--yellow); }
172
+ .wave-seg-fill.pct-mid { background: var(--cyan); }
173
+ .wave-seg-fill.pct-hi { background: var(--green); }
174
+
175
+ /* Wave label centered in each segment */
176
+ .wave-seg-label {
177
+ position: absolute;
178
+ top: 0; left: 0; right: 0; bottom: 0;
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ font-size: 0.6rem;
183
+ font-weight: 700;
184
+ letter-spacing: 0.03em;
185
+ color: rgba(255,255,255,0.85);
186
+ pointer-events: none;
187
+ text-shadow: 0 1px 2px rgba(0,0,0,0.6);
188
+ }
189
+
190
+ /* Highlight the active wave segment */
191
+ .wave-seg-current { box-shadow: inset 0 0 0 1px var(--accent); }
192
+
193
+ /* Future waves: visible but subdued */
194
+ .wave-seg-future {
195
+ background: rgba(139,148,158,0.25);
196
+ }
197
+ .wave-seg-future .wave-seg-label {
198
+ color: rgba(255,255,255,0.55);
199
+ text-shadow: none;
200
+ }
201
+
202
+ /* Legacy single-bar fill (still used by per-task progress bars) */
203
+ .progress-bar-fill {
204
+ height: 100%;
205
+ border-radius: 4px;
206
+ transition: width 0.5s ease, background-color 0.5s ease;
207
+ }
208
+ .progress-bar-fill.pct-0 { background: var(--text-faint); }
209
+ .progress-bar-fill.pct-low { background: var(--yellow); }
210
+ .progress-bar-fill.pct-mid { background: var(--cyan); }
211
+ .progress-bar-fill.pct-hi { background: var(--green); }
212
+
213
+ .summary-pct {
214
+ font-family: var(--font-mono);
215
+ font-size: 0.95rem;
216
+ font-weight: 600;
217
+ min-width: 38px;
218
+ }
219
+
220
+ .summary-counts {
221
+ display: flex;
222
+ gap: 10px;
223
+ font-family: var(--font-mono);
224
+ font-size: 0.85rem;
225
+ }
226
+
227
+ .count-chip {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ gap: 4px;
231
+ padding: 2px 10px;
232
+ border-radius: 10px;
233
+ font-weight: 500;
234
+ margin-right: 4px;
235
+ }
236
+ .count-num { font-variant-numeric: tabular-nums; }
237
+ .count-icon { font-size: 0.85em; opacity: 0.9; }
238
+ .count-total { color: var(--text-faint); margin-left: 2px; }
239
+
240
+ .count-succeeded { background: rgba(63,185,80,0.15); color: var(--green); }
241
+ .count-running { background: rgba(88,166,255,0.15); color: var(--accent); }
242
+ .count-failed { background: rgba(248,81,73,0.15); color: var(--red); }
243
+ .count-stalled { background: rgba(210,153,34,0.15); color: var(--yellow); }
244
+ .count-pending { background: rgba(139,148,158,0.1); color: var(--text-muted); }
245
+
246
+ .summary-elapsed {
247
+ color: var(--text-muted);
248
+ font-size: 0.8rem;
249
+ font-family: var(--font-mono);
250
+ }
251
+
252
+ .summary-waves {
253
+ display: flex;
254
+ align-items: center;
255
+ gap: 6px;
256
+ font-size: 0.8rem;
257
+ }
258
+
259
+ .wave-chip {
260
+ padding: 2px 8px;
261
+ border-radius: 10px;
262
+ font-family: var(--font-mono);
263
+ font-size: 0.75rem;
264
+ font-weight: 500;
265
+ border: 1px solid var(--border);
266
+ color: var(--text-muted);
267
+ }
268
+
269
+ .wave-chip.current {
270
+ border-color: var(--accent-dim);
271
+ background: rgba(88,166,255,0.12);
272
+ color: var(--accent);
273
+ font-weight: 700;
274
+ }
275
+
276
+ .wave-chip.done {
277
+ border-color: var(--green-dim);
278
+ background: rgba(63,185,80,0.12);
279
+ color: var(--green);
280
+ }
281
+
282
+ /* ─── Content ──────────────────────────────────────────────────────────── */
283
+
284
+ .content {
285
+ display: flex;
286
+ flex-direction: column;
287
+ gap: 12px;
288
+ min-height: 0;
289
+ }
290
+
291
+ /* ─── Panels (shared) ──────────────────────────────────────────────────── */
292
+
293
+ .panel {
294
+ background: var(--bg-surface);
295
+ border: 1px solid var(--border);
296
+ border-radius: var(--radius);
297
+ overflow: hidden;
298
+ display: flex;
299
+ flex-direction: column;
300
+ }
301
+
302
+ .panel-header {
303
+ padding: 10px 14px;
304
+ font-size: 0.75rem;
305
+ font-weight: 600;
306
+ text-transform: uppercase;
307
+ letter-spacing: 0.06em;
308
+ color: var(--text-muted);
309
+ border-bottom: 1px solid var(--border);
310
+ background: var(--bg-surface);
311
+ }
312
+
313
+ .panel-body {
314
+ padding: 0;
315
+ flex: 1;
316
+ overflow-y: auto;
317
+ }
318
+
319
+ .empty-state {
320
+ padding: 24px;
321
+ text-align: center;
322
+ color: var(--text-faint);
323
+ font-size: 0.85rem;
324
+ }
325
+
326
+ /* ─── Lane Group (lane header + nested task rows) ──────────────────────── */
327
+
328
+ .lane-group {
329
+ border-bottom: 1px solid var(--border);
330
+ }
331
+
332
+ .lane-group:last-child { border-bottom: none; }
333
+
334
+ .lane-header {
335
+ display: grid;
336
+ grid-template-columns: 36px 1fr auto;
337
+ align-items: center;
338
+ gap: 12px;
339
+ padding: 10px 14px;
340
+ background: var(--bg-inset);
341
+ border-bottom: 1px solid var(--border-subtle);
342
+ }
343
+
344
+ .lane-num {
345
+ font-family: var(--font-mono);
346
+ font-size: 1rem;
347
+ font-weight: 700;
348
+ color: var(--text-muted);
349
+ text-align: center;
350
+ }
351
+
352
+ .lane-meta {
353
+ display: flex;
354
+ align-items: center;
355
+ gap: 10px;
356
+ min-width: 0;
357
+ }
358
+
359
+ .lane-session {
360
+ font-family: var(--font-mono);
361
+ font-size: 0.82rem;
362
+ color: var(--accent);
363
+ white-space: nowrap;
364
+ }
365
+
366
+ .lane-branch {
367
+ font-size: 0.72rem;
368
+ color: var(--text-muted);
369
+ white-space: nowrap;
370
+ overflow: hidden;
371
+ text-overflow: ellipsis;
372
+ }
373
+
374
+ .lane-right {
375
+ display: flex;
376
+ align-items: center;
377
+ gap: 10px;
378
+ }
379
+
380
+ .tmux-dot {
381
+ width: 8px;
382
+ height: 8px;
383
+ border-radius: 50%;
384
+ flex-shrink: 0;
385
+ }
386
+
387
+ .tmux-dot.alive { background: var(--green); }
388
+ .tmux-dot.dead { background: var(--red); opacity: 0.6; }
389
+
390
+ .tmux-view-btn {
391
+ font-family: var(--font-sans);
392
+ font-size: 0.72rem;
393
+ font-weight: 600;
394
+ padding: 3px 10px;
395
+ border-radius: var(--radius-sm);
396
+ background: var(--accent-dim);
397
+ border: 1px solid var(--accent-dim);
398
+ color: #fff;
399
+ cursor: pointer;
400
+ white-space: nowrap;
401
+ transition: background 0.2s, border-color 0.2s;
402
+ }
403
+
404
+ .tmux-view-btn:hover {
405
+ background: var(--accent);
406
+ border-color: var(--accent);
407
+ }
408
+
409
+ .tmux-cmd {
410
+ font-family: var(--font-mono);
411
+ font-size: 0.7rem;
412
+ padding: 3px 8px;
413
+ border-radius: var(--radius-sm);
414
+ background: var(--bg);
415
+ border: 1px solid var(--border);
416
+ color: var(--text);
417
+ cursor: pointer;
418
+ user-select: all;
419
+ white-space: nowrap;
420
+ transition: border-color 0.2s, color 0.2s;
421
+ }
422
+
423
+ .tmux-cmd:hover {
424
+ border-color: var(--accent-dim);
425
+ color: var(--accent);
426
+ }
427
+
428
+ .tmux-cmd.copied {
429
+ border-color: var(--green-dim);
430
+ color: var(--green);
431
+ }
432
+
433
+ .tmux-cmd.dead-session {
434
+ color: var(--text-muted);
435
+ cursor: default;
436
+ }
437
+
438
+ /* ─── Task Row (inside lane group) ─────────────────────────────────────── */
439
+
440
+ .task-row {
441
+ display: grid;
442
+ grid-template-columns: 36px 24px 100px 90px 80px 200px 1fr;
443
+ align-items: center;
444
+ gap: 8px;
445
+ padding: 8px 14px;
446
+ border-bottom: 1px solid var(--border-subtle);
447
+ transition: background 0.15s;
448
+ }
449
+
450
+ .task-row:last-child { border-bottom: none; }
451
+ .task-row:hover { background: var(--bg-surface-hover); }
452
+
453
+ .task-icon {
454
+ text-align: center;
455
+ }
456
+
457
+ .task-id {
458
+ font-family: var(--font-mono);
459
+ font-weight: 600;
460
+ font-size: 0.85rem;
461
+ }
462
+
463
+ .task-duration {
464
+ font-family: var(--font-mono);
465
+ font-size: 0.8rem;
466
+ color: var(--text-muted);
467
+ }
468
+
469
+ .task-step {
470
+ font-size: 0.8rem;
471
+ color: var(--text-muted);
472
+ white-space: nowrap;
473
+ overflow: hidden;
474
+ text-overflow: ellipsis;
475
+ }
476
+
477
+ .task-iter {
478
+ font-family: var(--font-mono);
479
+ font-size: 0.7rem;
480
+ color: var(--text-faint);
481
+ margin-left: 6px;
482
+ }
483
+
484
+ /* Status badges */
485
+ .status-badge {
486
+ display: inline-flex;
487
+ align-items: center;
488
+ gap: 4px;
489
+ font-family: var(--font-mono);
490
+ font-size: 0.75rem;
491
+ font-weight: 600;
492
+ padding: 2px 8px;
493
+ border-radius: 10px;
494
+ }
495
+
496
+ .status-succeeded { background: rgba(63,185,80,0.15); color: var(--green); }
497
+ .status-running { background: rgba(88,166,255,0.15); color: var(--accent); }
498
+ .status-failed { background: rgba(248,81,73,0.15); color: var(--red); }
499
+ .status-stalled { background: rgba(210,153,34,0.15); color: var(--yellow); }
500
+ .status-pending { background: rgba(139,148,158,0.1); color: var(--text-muted); }
501
+ .status-skipped { background: rgba(139,148,158,0.1); color: var(--text-faint); }
502
+
503
+ .status-dot {
504
+ width: 6px;
505
+ height: 6px;
506
+ border-radius: 50%;
507
+ display: inline-block;
508
+ }
509
+
510
+ .status-dot.succeeded { background: var(--green); }
511
+ .status-dot.running { background: var(--accent); }
512
+ .status-dot.failed { background: var(--red); }
513
+ .status-dot.stalled { background: var(--yellow); }
514
+ .status-dot.pending { background: var(--text-faint); }
515
+ .status-dot.skipped { background: var(--text-faint); }
516
+
517
+ /* Task progress bar (inline) */
518
+ .task-progress {
519
+ display: flex;
520
+ align-items: center;
521
+ gap: 8px;
522
+ }
523
+
524
+ .task-progress-bar {
525
+ width: 80px;
526
+ height: 6px;
527
+ background: var(--bg-inset);
528
+ border-radius: 3px;
529
+ overflow: hidden;
530
+ flex-shrink: 0;
531
+ }
532
+
533
+ .task-progress-fill {
534
+ height: 100%;
535
+ border-radius: 3px;
536
+ transition: width 0.5s ease;
537
+ }
538
+
539
+ .task-progress-fill.pct-0 { background: var(--text-faint); }
540
+ .task-progress-fill.pct-low { background: var(--yellow); }
541
+ .task-progress-fill.pct-mid { background: var(--cyan); }
542
+ .task-progress-fill.pct-hi { background: var(--green); }
543
+
544
+ .task-progress-text {
545
+ font-family: var(--font-mono);
546
+ font-size: 0.75rem;
547
+ color: var(--text-muted);
548
+ min-width: 55px;
549
+ }
550
+
551
+ /* ─── Merge Agents Table ───────────────────────────────────────────────── */
552
+
553
+ .merge-table {
554
+ width: 100%;
555
+ border-collapse: collapse;
556
+ }
557
+
558
+ .merge-table th {
559
+ text-align: left;
560
+ padding: 8px 12px;
561
+ font-size: 0.7rem;
562
+ font-weight: 600;
563
+ text-transform: uppercase;
564
+ letter-spacing: 0.05em;
565
+ color: var(--text-faint);
566
+ border-bottom: 1px solid var(--border);
567
+ background: var(--bg-surface);
568
+ }
569
+
570
+ .merge-table td {
571
+ padding: 8px 12px;
572
+ border-bottom: 1px solid var(--border-subtle);
573
+ font-size: 0.85rem;
574
+ }
575
+
576
+ .merge-table tr:last-child td { border-bottom: none; }
577
+ .merge-table tr:hover td { background: var(--bg-surface-hover); }
578
+
579
+ /* ─── Terminal Panel ────────────────────────────────────────────────────── */
580
+
581
+ .terminal-panel .panel-header {
582
+ display: flex;
583
+ align-items: center;
584
+ justify-content: space-between;
585
+ }
586
+
587
+ .terminal-close {
588
+ background: none;
589
+ border: 1px solid var(--border);
590
+ color: var(--text-muted);
591
+ font-size: 0.85rem;
592
+ cursor: pointer;
593
+ padding: 2px 8px;
594
+ border-radius: var(--radius-sm);
595
+ transition: color 0.2s, border-color 0.2s;
596
+ }
597
+
598
+ .terminal-close:hover {
599
+ color: var(--red);
600
+ border-color: var(--red-dim);
601
+ }
602
+
603
+ .terminal-panel .panel-body {
604
+ max-height: 500px;
605
+ padding: 0;
606
+ background: var(--bg-inset);
607
+ overflow-y: auto;
608
+ }
609
+
610
+ /* ─── Worker Stats (inline in task row) ────────────────────────────────── */
611
+
612
+ .worker-stats {
613
+ display: flex;
614
+ align-items: center;
615
+ gap: 10px;
616
+ margin-top: 4px;
617
+ flex-wrap: wrap;
618
+ }
619
+
620
+ .worker-stat {
621
+ font-family: var(--font-mono);
622
+ font-size: 0.7rem;
623
+ color: var(--text-muted);
624
+ white-space: nowrap;
625
+ }
626
+
627
+ .worker-last-tool {
628
+ color: var(--text-muted);
629
+ max-width: 600px;
630
+ overflow: hidden;
631
+ text-overflow: ellipsis;
632
+ }
633
+
634
+ /* ─── Conversation Viewer ──────────────────────────────────────────────── */
635
+
636
+ .conv-stream {
637
+ padding: 12px 16px;
638
+ font-family: var(--font-mono);
639
+ font-size: 0.82rem;
640
+ line-height: 1.6;
641
+ white-space: pre-wrap;
642
+ word-break: break-word;
643
+ }
644
+
645
+ .conv-text {
646
+ color: var(--text);
647
+ }
648
+
649
+ .conv-thinking {
650
+ color: var(--text-faint);
651
+ font-style: italic;
652
+ }
653
+
654
+ .conv-tool-call {
655
+ margin: 8px 0 4px;
656
+ padding: 6px 10px;
657
+ background: rgba(88,166,255,0.08);
658
+ border-left: 3px solid var(--accent-dim);
659
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
660
+ }
661
+
662
+ .conv-tool-name {
663
+ color: var(--accent);
664
+ font-weight: 600;
665
+ }
666
+
667
+ .conv-tool-args {
668
+ color: var(--text-muted);
669
+ font-size: 0.75rem;
670
+ }
671
+
672
+ .conv-tool-result {
673
+ margin: 0 0 8px;
674
+ padding: 6px 10px;
675
+ background: var(--bg-inset);
676
+ border-left: 3px solid var(--border);
677
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
678
+ max-height: 200px;
679
+ overflow-y: auto;
680
+ }
681
+
682
+ .conv-tool-result pre {
683
+ margin: 0;
684
+ font-size: 0.75rem;
685
+ color: var(--text-muted);
686
+ white-space: pre-wrap;
687
+ }
688
+
689
+ .conv-usage {
690
+ margin: 6px 0;
691
+ padding: 4px 10px;
692
+ font-size: 0.7rem;
693
+ color: var(--text-faint);
694
+ border-top: 1px solid var(--border-subtle);
695
+ }
696
+
697
+ .conv-empty {
698
+ padding: 40px;
699
+ text-align: center;
700
+ color: var(--text-faint);
701
+ }
702
+
703
+ /* ─── Viewer Eye Button (task row) ─────────────────────────────────────── */
704
+
705
+ .task-actions {
706
+ display: flex;
707
+ align-items: center;
708
+ justify-content: center;
709
+ }
710
+
711
+ .viewer-eye-btn {
712
+ background: none;
713
+ border: none;
714
+ cursor: pointer;
715
+ font-size: 0.75rem;
716
+ padding: 2px;
717
+ border-radius: var(--radius-sm);
718
+ opacity: 0.35;
719
+ transition: opacity 0.2s, background 0.2s;
720
+ line-height: 1;
721
+ }
722
+
723
+ .viewer-eye-btn:hover {
724
+ opacity: 0.8;
725
+ background: rgba(88,166,255,0.1);
726
+ }
727
+
728
+ .viewer-eye-btn.active {
729
+ opacity: 1;
730
+ background: rgba(88,166,255,0.15);
731
+ }
732
+
733
+ .tmux-view-btn.active {
734
+ background: var(--accent);
735
+ border-color: var(--accent);
736
+ }
737
+
738
+ /* ─── Viewer Controls (auto-scroll checkbox + close) ───────────────────── */
739
+
740
+ .terminal-controls {
741
+ display: flex;
742
+ align-items: center;
743
+ gap: 12px;
744
+ }
745
+
746
+ .auto-scroll-label {
747
+ display: flex;
748
+ align-items: center;
749
+ gap: 6px;
750
+ cursor: pointer;
751
+ font-size: 0.75rem;
752
+ color: var(--text-muted);
753
+ user-select: none;
754
+ white-space: nowrap;
755
+ }
756
+
757
+ .auto-scroll-label input[type="checkbox"] {
758
+ appearance: none;
759
+ -webkit-appearance: none;
760
+ width: 14px;
761
+ height: 14px;
762
+ border: 1px solid var(--border);
763
+ border-radius: 3px;
764
+ background: var(--bg-inset);
765
+ cursor: pointer;
766
+ position: relative;
767
+ flex-shrink: 0;
768
+ }
769
+
770
+ .auto-scroll-label input[type="checkbox"]:checked {
771
+ background: var(--accent-dim);
772
+ border-color: var(--accent);
773
+ }
774
+
775
+ .auto-scroll-label input[type="checkbox"]:checked::after {
776
+ content: '✓';
777
+ position: absolute;
778
+ top: -1px;
779
+ left: 2px;
780
+ font-size: 11px;
781
+ color: #fff;
782
+ }
783
+
784
+ /* ─── STATUS.md Rendered Content ───────────────────────────────────────── */
785
+
786
+ .status-md-content {
787
+ padding: 12px 16px;
788
+ font-family: var(--font-sans);
789
+ font-size: 0.85rem;
790
+ line-height: 1.6;
791
+ }
792
+
793
+ .status-md-h1 {
794
+ font-size: 1.15rem;
795
+ font-weight: 700;
796
+ color: var(--text);
797
+ margin: 16px 0 8px;
798
+ padding-bottom: 4px;
799
+ border-bottom: 1px solid var(--border-subtle);
800
+ }
801
+
802
+ .status-md-h1:first-child { margin-top: 0; }
803
+
804
+ .status-md-h2 {
805
+ font-size: 1rem;
806
+ font-weight: 600;
807
+ color: var(--text);
808
+ margin: 14px 0 6px;
809
+ }
810
+
811
+ .status-md-h3 {
812
+ font-size: 0.9rem;
813
+ font-weight: 600;
814
+ color: var(--text-muted);
815
+ margin: 12px 0 4px;
816
+ }
817
+
818
+ .status-md-h4 {
819
+ font-size: 0.85rem;
820
+ font-weight: 600;
821
+ color: var(--text-muted);
822
+ margin: 10px 0 4px;
823
+ }
824
+
825
+ .status-md-check {
826
+ display: flex;
827
+ align-items: flex-start;
828
+ gap: 8px;
829
+ padding: 3px 8px;
830
+ border-radius: var(--radius-sm);
831
+ border-left: 2px solid transparent;
832
+ transition: background 0.2s, border-color 0.2s;
833
+ }
834
+
835
+ .status-md-check.checked {
836
+ color: var(--text-muted);
837
+ }
838
+
839
+ .status-md-check.checked .check-box {
840
+ color: var(--green);
841
+ }
842
+
843
+ .status-md-check.unchecked {
844
+ color: var(--text);
845
+ }
846
+
847
+ .status-md-check.unchecked .check-box {
848
+ color: var(--text-faint);
849
+ }
850
+
851
+ .check-box {
852
+ flex-shrink: 0;
853
+ font-size: 0.85rem;
854
+ line-height: 1.6;
855
+ }
856
+
857
+ /* Progress frontier highlight — only when tracking is active */
858
+ .status-md-content.tracking .status-md-check.last-checked {
859
+ border-left-color: var(--accent);
860
+ background: rgba(88, 166, 255, 0.06);
861
+ }
862
+
863
+ .status-md-li {
864
+ padding: 2px 8px;
865
+ color: var(--text);
866
+ }
867
+
868
+ .status-md-text {
869
+ padding: 2px 8px;
870
+ color: var(--text);
871
+ }
872
+
873
+ .status-md-spacer {
874
+ height: 8px;
875
+ }
876
+
877
+ .status-md-code {
878
+ font-family: var(--font-mono);
879
+ font-size: 0.8rem;
880
+ padding: 1px 5px;
881
+ background: var(--bg-surface);
882
+ border: 1px solid var(--border-subtle);
883
+ border-radius: 3px;
884
+ color: var(--accent);
885
+ }
886
+
887
+ /* ─── Errors Panel ─────────────────────────────────────────────────────── */
888
+
889
+ .errors-panel .panel-header { color: var(--red); }
890
+
891
+ .error-item {
892
+ padding: 8px 14px;
893
+ font-family: var(--font-mono);
894
+ font-size: 0.78rem;
895
+ color: var(--red);
896
+ border-bottom: 1px solid var(--border-subtle);
897
+ display: flex;
898
+ align-items: flex-start;
899
+ gap: 8px;
900
+ }
901
+
902
+ .error-item:last-child { border-bottom: none; }
903
+ .error-bullet { flex-shrink: 0; margin-top: 2px; }
904
+ .error-text { word-break: break-word; }
905
+
906
+ /* ─── Footer ───────────────────────────────────────────────────────────── */
907
+
908
+ .footer {
909
+ display: flex;
910
+ align-items: center;
911
+ justify-content: space-between;
912
+ padding: 8px 4px;
913
+ font-size: 0.75rem;
914
+ color: var(--text-faint);
915
+ }
916
+
917
+ /* ─── No Batch State ───────────────────────────────────────────────────── */
918
+
919
+ .no-batch {
920
+ display: flex;
921
+ flex-direction: column;
922
+ align-items: center;
923
+ justify-content: center;
924
+ gap: 12px;
925
+ padding: 80px 20px;
926
+ text-align: center;
927
+ }
928
+
929
+ .no-batch-icon { font-size: 3rem; opacity: 0.3; }
930
+ .no-batch-title { font-size: 1.1rem; font-weight: 600; color: var(--text-muted); }
931
+ .no-batch-hint { font-size: 0.85rem; color: var(--text-faint); font-family: var(--font-mono); }
932
+
933
+ /* ─── Responsive ───────────────────────────────────────────────────────── */
934
+
935
+ @media (max-width: 900px) {
936
+ .task-row {
937
+ grid-template-columns: 36px 24px 90px 80px 70px 1fr;
938
+ }
939
+ .task-row .task-step { display: none; }
940
+ .progress-bar-bg { width: 160px; }
941
+ }
942
+
943
+ /* ─── Scrollbar ────────────────────────────────────────────────────────── */
944
+
945
+ ::-webkit-scrollbar { width: 6px; }
946
+ ::-webkit-scrollbar-track { background: transparent; }
947
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
948
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
949
+
950
+ /* ─── Pulse animation ──────────────────────────────────────────────────── */
951
+
952
+ @keyframes pulse {
953
+ 0%, 100% { opacity: 1; }
954
+ 50% { opacity: 0.5; }
955
+ }
956
+
957
+ .status-running .status-dot { animation: pulse 2s infinite; }
958
+
959
+ /* ─── Copy toast ───────────────────────────────────────────────────────── */
960
+
961
+ .copy-toast {
962
+ position: fixed;
963
+ bottom: 20px;
964
+ right: 20px;
965
+ background: var(--green-dim);
966
+ color: #fff;
967
+ padding: 8px 16px;
968
+ border-radius: var(--radius);
969
+ font-size: 0.8rem;
970
+ font-family: var(--font-mono);
971
+ opacity: 0;
972
+ transform: translateY(8px);
973
+ transition: opacity 0.2s, transform 0.2s;
974
+ pointer-events: none;
975
+ z-index: 100;
976
+ }
977
+
978
+ .copy-toast.visible {
979
+ opacity: 1;
980
+ transform: translateY(0);
981
+ }
982
+
983
+ /* ── History Dropdown ────────────────────────────────────────────────────── */
984
+
985
+ .history-select {
986
+ background: var(--bg-surface);
987
+ border: 1px solid var(--border);
988
+ color: var(--text-muted);
989
+ font-family: var(--font-mono);
990
+ font-size: 0.8rem;
991
+ padding: 3px 8px;
992
+ border-radius: 8px;
993
+ cursor: pointer;
994
+ max-width: 260px;
995
+ }
996
+ .history-select:hover {
997
+ border-color: var(--accent);
998
+ color: var(--text-primary);
999
+ }
1000
+ .history-select:focus {
1001
+ outline: none;
1002
+ border-color: var(--accent);
1003
+ }
1004
+
1005
+ /* ── History Summary Panel ───────────────────────────────────────────────── */
1006
+
1007
+ .history-panel .panel-body {
1008
+ padding: 16px;
1009
+ }
1010
+
1011
+ .history-header {
1012
+ display: flex;
1013
+ align-items: center;
1014
+ gap: 16px;
1015
+ margin-bottom: 16px;
1016
+ flex-wrap: wrap;
1017
+ }
1018
+
1019
+ .history-header .batch-id {
1020
+ font-family: var(--font-mono);
1021
+ font-size: 1.1rem;
1022
+ font-weight: 700;
1023
+ color: var(--accent);
1024
+ }
1025
+
1026
+ .history-header .batch-status {
1027
+ font-size: 0.85rem;
1028
+ padding: 2px 10px;
1029
+ border-radius: 12px;
1030
+ font-weight: 600;
1031
+ }
1032
+
1033
+ .history-header .batch-status.completed { background: rgba(63,185,80,0.15); color: var(--green); }
1034
+ .history-header .batch-status.partial { background: rgba(210,153,34,0.15); color: var(--yellow); }
1035
+ .history-header .batch-status.failed { background: rgba(248,81,73,0.15); color: var(--red); }
1036
+ .history-header .batch-status.aborted { background: rgba(139,148,158,0.15); color: var(--text-muted); }
1037
+
1038
+ .history-header .batch-time {
1039
+ color: var(--text-muted);
1040
+ font-size: 0.85rem;
1041
+ }
1042
+
1043
+ .history-stats {
1044
+ display: grid;
1045
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
1046
+ gap: 12px;
1047
+ margin-bottom: 16px;
1048
+ }
1049
+
1050
+ .stat-card {
1051
+ background: var(--bg-surface);
1052
+ border: 1px solid var(--border);
1053
+ border-radius: 8px;
1054
+ padding: 12px;
1055
+ text-align: center;
1056
+ }
1057
+
1058
+ .stat-card .stat-value {
1059
+ font-family: var(--font-mono);
1060
+ font-size: 1.3rem;
1061
+ font-weight: 700;
1062
+ color: var(--text-primary);
1063
+ }
1064
+
1065
+ .stat-card .stat-label {
1066
+ font-size: 0.75rem;
1067
+ color: var(--text-muted);
1068
+ margin-top: 2px;
1069
+ }
1070
+
1071
+ .stat-card.stat-tokens .stat-value {
1072
+ font-size: 0.95rem;
1073
+ color: var(--accent);
1074
+ }
1075
+
1076
+ .history-waves-table,
1077
+ .history-tasks-table {
1078
+ width: 100%;
1079
+ border-collapse: collapse;
1080
+ margin-bottom: 16px;
1081
+ }
1082
+
1083
+ .history-waves-table th,
1084
+ .history-tasks-table th {
1085
+ text-align: left;
1086
+ padding: 6px 10px;
1087
+ border-bottom: 1px solid var(--border);
1088
+ font-size: 0.75rem;
1089
+ color: var(--text-muted);
1090
+ text-transform: uppercase;
1091
+ letter-spacing: 0.05em;
1092
+ }
1093
+
1094
+ .history-waves-table td,
1095
+ .history-tasks-table td {
1096
+ padding: 6px 10px;
1097
+ border-bottom: 1px solid rgba(48,54,61,0.3);
1098
+ font-family: var(--font-mono);
1099
+ font-size: 0.85rem;
1100
+ color: var(--text-muted);
1101
+ }
1102
+
1103
+ .history-section-title {
1104
+ font-size: 0.9rem;
1105
+ font-weight: 600;
1106
+ color: var(--text-primary);
1107
+ margin: 16px 0 8px;
1108
+ }