bosun 0.26.3

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 (122) hide show
  1. package/.env.example +918 -0
  2. package/LICENSE +190 -0
  3. package/README.md +98 -0
  4. package/agent-endpoint.mjs +918 -0
  5. package/agent-hook-bridge.mjs +230 -0
  6. package/agent-hooks.mjs +1188 -0
  7. package/agent-pool.mjs +2403 -0
  8. package/agent-prompts.mjs +689 -0
  9. package/agent-sdk.mjs +141 -0
  10. package/anomaly-detector.mjs +1195 -0
  11. package/autofix.mjs +1294 -0
  12. package/bosun.config.example.json +115 -0
  13. package/bosun.schema.json +465 -0
  14. package/claude-shell.mjs +708 -0
  15. package/cli.mjs +1028 -0
  16. package/codex-config.mjs +1274 -0
  17. package/codex-model-profiles.mjs +135 -0
  18. package/codex-shell.mjs +762 -0
  19. package/compat.mjs +286 -0
  20. package/config-doctor.mjs +613 -0
  21. package/config.mjs +1724 -0
  22. package/conflict-resolver.mjs +248 -0
  23. package/container-runner.mjs +450 -0
  24. package/copilot-shell.mjs +827 -0
  25. package/daemon-restart-policy.mjs +56 -0
  26. package/diff-stats.mjs +282 -0
  27. package/error-detector.mjs +829 -0
  28. package/fetch-runtime.mjs +34 -0
  29. package/fleet-coordinator.mjs +838 -0
  30. package/get-telegram-chat-id.mjs +71 -0
  31. package/git-safety.mjs +170 -0
  32. package/github-reconciler.mjs +403 -0
  33. package/hook-profiles.mjs +651 -0
  34. package/kanban-adapter.mjs +4491 -0
  35. package/lib/logger.mjs +645 -0
  36. package/maintenance.mjs +828 -0
  37. package/merge-strategy.mjs +1171 -0
  38. package/monitor.mjs +12237 -0
  39. package/package.json +209 -0
  40. package/postinstall.mjs +187 -0
  41. package/pr-cleanup-daemon.mjs +978 -0
  42. package/preflight.mjs +408 -0
  43. package/prepublish-check.mjs +90 -0
  44. package/presence.mjs +328 -0
  45. package/primary-agent.mjs +290 -0
  46. package/publish.mjs +241 -0
  47. package/repo-root.mjs +29 -0
  48. package/restart-controller.mjs +100 -0
  49. package/review-agent.mjs +557 -0
  50. package/rotate-agent-logs.sh +133 -0
  51. package/sdk-conflict-resolver.mjs +973 -0
  52. package/session-tracker.mjs +880 -0
  53. package/setup.mjs +3946 -0
  54. package/shared-knowledge.mjs +410 -0
  55. package/shared-state-manager.mjs +841 -0
  56. package/shared-workspace-cli.mjs +199 -0
  57. package/shared-workspace-registry.mjs +537 -0
  58. package/shared-workspaces.json +18 -0
  59. package/startup-service.mjs +1070 -0
  60. package/sync-engine.mjs +1063 -0
  61. package/task-archiver.mjs +801 -0
  62. package/task-assessment.mjs +550 -0
  63. package/task-claims.mjs +924 -0
  64. package/task-complexity.mjs +581 -0
  65. package/task-executor.mjs +5111 -0
  66. package/task-store.mjs +753 -0
  67. package/telegram-bot.mjs +9683 -0
  68. package/telegram-sentinel.mjs +2010 -0
  69. package/ui/app.js +867 -0
  70. package/ui/app.legacy.js +1464 -0
  71. package/ui/app.monolith.js +2488 -0
  72. package/ui/components/charts.js +226 -0
  73. package/ui/components/chat-view.js +567 -0
  74. package/ui/components/command-palette.js +587 -0
  75. package/ui/components/diff-viewer.js +190 -0
  76. package/ui/components/forms.js +357 -0
  77. package/ui/components/kanban-board.js +451 -0
  78. package/ui/components/session-list.js +305 -0
  79. package/ui/components/shared.js +525 -0
  80. package/ui/demo.html +640 -0
  81. package/ui/index.html +70 -0
  82. package/ui/modules/api.js +297 -0
  83. package/ui/modules/icons.js +461 -0
  84. package/ui/modules/router.js +81 -0
  85. package/ui/modules/settings-schema.js +261 -0
  86. package/ui/modules/state.js +679 -0
  87. package/ui/modules/telegram.js +331 -0
  88. package/ui/modules/utils.js +270 -0
  89. package/ui/styles/animations.css +140 -0
  90. package/ui/styles/base.css +98 -0
  91. package/ui/styles/components.css +2032 -0
  92. package/ui/styles/kanban.css +286 -0
  93. package/ui/styles/layout.css +810 -0
  94. package/ui/styles/sessions.css +841 -0
  95. package/ui/styles/variables.css +188 -0
  96. package/ui/styles.css +141 -0
  97. package/ui/styles.monolith.css +1046 -0
  98. package/ui/tabs/agents.js +1417 -0
  99. package/ui/tabs/chat.js +75 -0
  100. package/ui/tabs/control.js +892 -0
  101. package/ui/tabs/dashboard.js +515 -0
  102. package/ui/tabs/infra.js +537 -0
  103. package/ui/tabs/logs.js +783 -0
  104. package/ui/tabs/settings.js +1509 -0
  105. package/ui/tabs/tasks.js +1385 -0
  106. package/ui-server.mjs +4084 -0
  107. package/update-check.mjs +471 -0
  108. package/utils.mjs +172 -0
  109. package/ve-kanban.mjs +654 -0
  110. package/ve-kanban.ps1 +1365 -0
  111. package/ve-kanban.sh +18 -0
  112. package/ve-orchestrator.mjs +340 -0
  113. package/ve-orchestrator.ps1 +6546 -0
  114. package/ve-orchestrator.sh +18 -0
  115. package/vibe-kanban-wrapper.mjs +41 -0
  116. package/vk-error-resolver.mjs +470 -0
  117. package/vk-log-stream.mjs +914 -0
  118. package/whatsapp-channel.mjs +520 -0
  119. package/workspace-monitor.mjs +581 -0
  120. package/workspace-reaper.mjs +405 -0
  121. package/workspace-registry.mjs +238 -0
  122. package/worktree-manager.mjs +1266 -0
@@ -0,0 +1,2032 @@
1
+ /* ─── Component Styles — Mission Control ─── */
2
+
3
+ /* ─── Cards ─── */
4
+ .card {
5
+ background: var(--bg-card);
6
+ background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent 70%);
7
+ border-radius: var(--radius-lg);
8
+ padding: var(--space-md);
9
+ border: 1px solid var(--border);
10
+ box-shadow: var(--shadow-sm);
11
+ margin-bottom: var(--space-md, 12px);
12
+ transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
13
+ position: relative;
14
+ overflow: hidden;
15
+ }
16
+
17
+ .card:hover {
18
+ background: var(--bg-card-hover);
19
+ border-color: var(--border-strong);
20
+ box-shadow: var(--shadow-md);
21
+ }
22
+
23
+ .card-title {
24
+ font-size: 15px;
25
+ font-weight: 600;
26
+ margin-bottom: 12px;
27
+ color: var(--text-primary);
28
+ line-height: 1.35;
29
+ position: relative;
30
+ }
31
+
32
+ .card-subtitle {
33
+ font-size: 13px;
34
+ font-weight: 600;
35
+ margin-bottom: 8px;
36
+ color: var(--text-secondary);
37
+ line-height: 1.4;
38
+ position: relative;
39
+ }
40
+
41
+ /* ─── Stat Cards ─── */
42
+ .stats-grid {
43
+ display: grid;
44
+ grid-template-columns: repeat(2, 1fr);
45
+ gap: 10px;
46
+ margin-bottom: 12px;
47
+ }
48
+
49
+ .stat-card {
50
+ background: var(--bg-card);
51
+ border-radius: var(--radius-md);
52
+ padding: 16px 12px;
53
+ text-align: center;
54
+ border: 1px solid var(--border);
55
+ position: relative;
56
+ overflow: hidden;
57
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast);
58
+ }
59
+
60
+ .stat-card:hover {
61
+ border-color: var(--border-strong);
62
+ background: var(--bg-card-hover);
63
+ box-shadow: var(--shadow-md);
64
+ }
65
+
66
+ .stat-value {
67
+ font-size: 28px;
68
+ font-weight: 700;
69
+ line-height: 1.2;
70
+ letter-spacing: -0.03em;
71
+ position: relative;
72
+ animation: counter-up 0.4s ease both;
73
+ }
74
+
75
+ .stat-label {
76
+ font-size: 11px;
77
+ font-weight: 500;
78
+ color: var(--text-secondary);
79
+ margin-top: 4px;
80
+ text-transform: uppercase;
81
+ letter-spacing: 0.06em;
82
+ position: relative;
83
+ }
84
+
85
+ .stat-trend {
86
+ font-size: 11px;
87
+ font-weight: 600;
88
+ margin-top: 4px;
89
+ position: relative;
90
+ }
91
+
92
+ /* ─── Badges ─── */
93
+ .badge {
94
+ display: inline-flex;
95
+ align-items: center;
96
+ padding: 3px 10px;
97
+ border-radius: var(--radius-full);
98
+ font-size: 11px;
99
+ font-weight: 600;
100
+ line-height: 1.2;
101
+ white-space: nowrap;
102
+ border: 1px solid transparent;
103
+ }
104
+
105
+ .badge-todo {
106
+ background: rgba(139, 148, 158, 0.15);
107
+ color: var(--color-todo);
108
+ border-color: rgba(139, 148, 158, 0.25);
109
+ }
110
+ .badge-inprogress {
111
+ background: rgba(88, 166, 255, 0.18);
112
+ color: var(--color-inprogress);
113
+ border-color: rgba(88, 166, 255, 0.35);
114
+ }
115
+ .badge-inreview {
116
+ background: rgba(210, 153, 34, 0.18);
117
+ color: var(--color-inreview);
118
+ border-color: rgba(210, 153, 34, 0.35);
119
+ }
120
+ .badge-draft {
121
+ background: rgba(245, 158, 11, 0.16);
122
+ color: var(--color-warning, #f59e0b);
123
+ border-color: rgba(245, 158, 11, 0.35);
124
+ }
125
+ .badge-done {
126
+ background: rgba(46, 160, 67, 0.18);
127
+ color: var(--color-done);
128
+ border-color: rgba(46, 160, 67, 0.35);
129
+ }
130
+ .badge-error {
131
+ background: rgba(248, 81, 73, 0.18);
132
+ color: var(--color-error);
133
+ border-color: rgba(248, 81, 73, 0.35);
134
+ }
135
+ .badge-cancelled {
136
+ background: rgba(110, 118, 129, 0.18);
137
+ color: var(--color-cancelled);
138
+ border-color: rgba(110, 118, 129, 0.3);
139
+ }
140
+
141
+ .badge-critical {
142
+ background: rgba(248, 81, 73, 0.18);
143
+ color: var(--color-critical);
144
+ border-color: rgba(248, 81, 73, 0.35);
145
+ }
146
+ .badge-high {
147
+ background: rgba(210, 153, 34, 0.18);
148
+ color: var(--color-high);
149
+ border-color: rgba(210, 153, 34, 0.35);
150
+ }
151
+ .badge-medium {
152
+ background: rgba(88, 166, 255, 0.18);
153
+ color: var(--color-medium);
154
+ border-color: rgba(88, 166, 255, 0.35);
155
+ }
156
+ .badge-low {
157
+ background: rgba(139, 148, 158, 0.15);
158
+ color: var(--color-low);
159
+ border-color: rgba(139, 148, 158, 0.25);
160
+ }
161
+
162
+ .badge-info {
163
+ background: rgba(88, 166, 255, 0.18);
164
+ color: var(--color-inprogress);
165
+ border-color: rgba(88, 166, 255, 0.35);
166
+ }
167
+ .badge-warning {
168
+ background: rgba(210, 153, 34, 0.18);
169
+ color: var(--color-inreview);
170
+ border-color: rgba(210, 153, 34, 0.35);
171
+ }
172
+ .badge-log {
173
+ background: rgba(139, 148, 158, 0.12);
174
+ color: var(--text-secondary);
175
+ border-color: rgba(139, 148, 158, 0.2);
176
+ }
177
+
178
+ /* ─── Chips / Filters ─── */
179
+ .chip-group {
180
+ display: flex;
181
+ gap: 6px;
182
+ flex-wrap: wrap;
183
+ margin-bottom: 12px;
184
+ }
185
+
186
+ .chip {
187
+ padding: 6px 14px;
188
+ border-radius: var(--radius-full);
189
+ font-size: 12px;
190
+ font-weight: 600;
191
+ border: 1px solid var(--border);
192
+ background: var(--bg-card);
193
+ color: var(--text-secondary);
194
+ cursor: pointer;
195
+ transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), transform 0.15s ease;
196
+ min-height: 32px;
197
+ display: inline-flex;
198
+ align-items: center;
199
+ }
200
+
201
+ .chip:active {
202
+ transform: scale(0.95);
203
+ }
204
+
205
+ .chip:hover {
206
+ background: var(--bg-card-hover);
207
+ border-color: var(--border-strong);
208
+ }
209
+
210
+ .chip:focus-visible {
211
+ outline: 2px solid var(--accent);
212
+ outline-offset: 2px;
213
+ }
214
+
215
+ .chip.active {
216
+ background: var(--accent-subtle);
217
+ color: var(--accent);
218
+ border-color: var(--accent);
219
+ }
220
+
221
+ /* ─── Tags ─── */
222
+ .tag-row {
223
+ display: flex;
224
+ gap: 6px;
225
+ flex-wrap: wrap;
226
+ margin-top: 6px;
227
+ }
228
+
229
+ .tag-chip {
230
+ display: inline-flex;
231
+ align-items: center;
232
+ padding: 2px 8px;
233
+ font-size: 11px;
234
+ font-weight: 600;
235
+ border-radius: var(--radius-full);
236
+ background: rgba(56, 189, 248, 0.15);
237
+ color: #38bdf8;
238
+ border: 1px solid rgba(56, 189, 248, 0.3);
239
+ }
240
+
241
+ /* ─── Buttons ─── */
242
+ .btn {
243
+ display: inline-flex;
244
+ align-items: center;
245
+ justify-content: center;
246
+ gap: 6px;
247
+ padding: 10px 16px;
248
+ border-radius: var(--radius-md);
249
+ font-size: 13px;
250
+ font-weight: 600;
251
+ font-family: var(--font-ui);
252
+ line-height: 1.1;
253
+ border: none;
254
+ cursor: pointer;
255
+ transition: transform 0.15s ease, opacity 0.15s ease, background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
256
+ min-height: 44px;
257
+ -webkit-tap-highlight-color: transparent;
258
+ position: relative;
259
+ overflow: hidden;
260
+ }
261
+
262
+ .btn:disabled,
263
+ .btn[disabled] {
264
+ opacity: 0.55;
265
+ cursor: not-allowed;
266
+ box-shadow: none;
267
+ transform: none;
268
+ }
269
+
270
+ .btn:disabled:hover,
271
+ .btn[disabled]:hover {
272
+ transform: none;
273
+ }
274
+
275
+ .btn:active {
276
+ transform: scale(0.97);
277
+ opacity: 0.85;
278
+ }
279
+
280
+ .btn:focus-visible {
281
+ outline: 2px solid var(--accent);
282
+ outline-offset: 2px;
283
+ }
284
+
285
+ .btn-primary {
286
+ background: var(--accent);
287
+ color: var(--accent-text);
288
+ box-shadow: var(--shadow-sm);
289
+ }
290
+
291
+ .btn-primary:hover {
292
+ background: var(--accent-hover);
293
+ box-shadow: var(--shadow-md);
294
+ }
295
+
296
+ .btn-secondary {
297
+ background: var(--bg-card);
298
+ color: var(--text-primary);
299
+ border: 1px solid var(--border);
300
+ }
301
+
302
+ .btn-secondary:hover {
303
+ border-color: var(--border-strong);
304
+ background: var(--bg-card-hover);
305
+ box-shadow: var(--shadow-sm);
306
+ }
307
+
308
+ .btn-ghost {
309
+ background: transparent;
310
+ color: var(--text-secondary);
311
+ padding: 8px 12px;
312
+ }
313
+
314
+ .btn-ghost:hover {
315
+ background: var(--bg-card-hover);
316
+ }
317
+
318
+ .btn-danger {
319
+ background: rgba(248, 81, 73, 0.12);
320
+ color: var(--color-error);
321
+ border: 1px solid rgba(248, 81, 73, 0.25);
322
+ }
323
+
324
+ .btn-danger:hover {
325
+ background: rgba(248, 81, 73, 0.18);
326
+ }
327
+
328
+ @media (hover: hover) {
329
+ .btn:hover:not(:disabled) {
330
+ transform: translateY(-1px);
331
+ }
332
+
333
+ .btn:active:not(:disabled) {
334
+ transform: translateY(0) scale(0.97);
335
+ }
336
+ }
337
+
338
+ .btn-sm {
339
+ padding: 6px 12px;
340
+ font-size: 12px;
341
+ min-height: 32px;
342
+ }
343
+
344
+ .btn-block {
345
+ width: 100%;
346
+ }
347
+
348
+ .btn-row {
349
+ display: flex;
350
+ flex-wrap: wrap;
351
+ gap: 8px;
352
+ }
353
+
354
+ /* ─── Inputs ─── */
355
+ .input {
356
+ width: 100%;
357
+ padding: 10px 14px;
358
+ border-radius: var(--radius-md);
359
+ border: 1px solid var(--border);
360
+ background: var(--bg-input);
361
+ color: var(--text-primary);
362
+ font-size: 14px;
363
+ font-family: inherit;
364
+ line-height: 1.4;
365
+ min-height: 44px;
366
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
367
+ outline: none;
368
+ }
369
+
370
+ .input:focus {
371
+ border-color: var(--accent);
372
+ box-shadow: 0 0 0 3px var(--accent-subtle), var(--shadow-glow-sm);
373
+ }
374
+
375
+ .input-error {
376
+ border-color: rgba(248, 113, 113, 0.6);
377
+ box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.15);
378
+ }
379
+
380
+ .input::placeholder {
381
+ color: var(--text-hint);
382
+ }
383
+
384
+ textarea.input {
385
+ min-height: 80px;
386
+ resize: vertical;
387
+ }
388
+
389
+ select.input {
390
+ appearance: none;
391
+ cursor: pointer;
392
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%239ca3b8' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E");
393
+ background-repeat: no-repeat;
394
+ background-position: right 12px center;
395
+ padding-right: 32px;
396
+ }
397
+
398
+ .input-row {
399
+ display: flex;
400
+ gap: 8px;
401
+ margin-bottom: 10px;
402
+ flex-wrap: wrap;
403
+ align-items: center;
404
+ }
405
+
406
+ .input-row .input {
407
+ flex: 1;
408
+ }
409
+
410
+ .form-label {
411
+ font-size: 11px;
412
+ font-weight: 600;
413
+ color: var(--text-hint);
414
+ text-transform: uppercase;
415
+ letter-spacing: 0.08em;
416
+ margin-bottom: 6px;
417
+ }
418
+
419
+ .form-hint {
420
+ font-size: 12px;
421
+ color: var(--text-secondary);
422
+ margin-top: 4px;
423
+ }
424
+
425
+ .form-hint.error {
426
+ color: var(--color-error);
427
+ }
428
+
429
+ .form-hint.success {
430
+ color: var(--color-done);
431
+ }
432
+
433
+ .field-group {
434
+ display: flex;
435
+ flex-direction: column;
436
+ gap: 4px;
437
+ margin-bottom: 10px;
438
+ }
439
+
440
+ .range-row {
441
+ display: flex;
442
+ align-items: center;
443
+ gap: 10px;
444
+ margin-bottom: 10px;
445
+ }
446
+
447
+ .range-row input[type="range"] {
448
+ flex: 1;
449
+ accent-color: var(--accent);
450
+ height: 4px;
451
+ }
452
+
453
+ /* ─── Task Cards ─── */
454
+ .task-card {
455
+ background: var(--bg-card);
456
+ border-radius: var(--radius-md);
457
+ padding: 14px;
458
+ border: 1px solid var(--border);
459
+ margin-bottom: 8px;
460
+ transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
461
+ border-left: 3px solid transparent;
462
+ position: relative;
463
+ }
464
+
465
+ .task-card:active {
466
+ background: var(--bg-card-hover);
467
+ }
468
+
469
+ .task-card:hover {
470
+ border-color: var(--border-strong);
471
+ box-shadow: var(--shadow-sm);
472
+ }
473
+
474
+ .task-card-header {
475
+ display: flex;
476
+ justify-content: space-between;
477
+ align-items: flex-start;
478
+ gap: 8px;
479
+ margin-bottom: 6px;
480
+ }
481
+
482
+ .task-card-title {
483
+ font-size: 14px;
484
+ font-weight: 600;
485
+ line-height: 1.3;
486
+ }
487
+
488
+ .task-card-meta {
489
+ font-size: 12px;
490
+ color: var(--text-secondary);
491
+ margin-bottom: 8px;
492
+ line-height: 1.4;
493
+ }
494
+
495
+ /* ─── Progress Bar ─── */
496
+ .progress-bar {
497
+ height: 6px;
498
+ background: #21262d;
499
+ border-radius: var(--radius-full);
500
+ overflow: hidden;
501
+ margin-bottom: 8px;
502
+ position: relative;
503
+ }
504
+
505
+ .progress-bar-fill {
506
+ height: 100%;
507
+ background: var(--gradient-progress);
508
+ border-radius: var(--radius-full);
509
+ transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
510
+ position: relative;
511
+ }
512
+
513
+ /* ─── Donut Chart ─── */
514
+ .donut-wrap {
515
+ display: flex;
516
+ justify-content: center;
517
+ align-items: center;
518
+ padding: 8px 0;
519
+ }
520
+
521
+ .donut-legend {
522
+ display: flex;
523
+ flex-wrap: wrap;
524
+ gap: 12px;
525
+ justify-content: center;
526
+ margin-top: 8px;
527
+ }
528
+
529
+ .donut-legend-item {
530
+ display: flex;
531
+ align-items: center;
532
+ gap: 4px;
533
+ font-size: 11px;
534
+ color: var(--text-secondary);
535
+ }
536
+
537
+ .donut-legend-swatch {
538
+ width: 8px;
539
+ height: 8px;
540
+ border-radius: 50%;
541
+ }
542
+
543
+ /* ─── Segmented Control ─── */
544
+ .segmented-control {
545
+ display: inline-flex;
546
+ background: var(--bg-card);
547
+ border: 1px solid var(--border);
548
+ border-radius: var(--radius-full);
549
+ padding: 3px;
550
+ gap: 2px;
551
+ margin-bottom: 10px;
552
+ }
553
+
554
+ .segmented-btn {
555
+ padding: 6px 14px;
556
+ border-radius: var(--radius-full);
557
+ border: none;
558
+ background: transparent;
559
+ color: var(--text-secondary);
560
+ font-size: 12px;
561
+ font-weight: 600;
562
+ cursor: pointer;
563
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
564
+ min-height: 32px;
565
+ }
566
+
567
+ .segmented-btn:focus-visible {
568
+ outline: 2px solid var(--accent);
569
+ outline-offset: 2px;
570
+ }
571
+
572
+ .segmented-btn.active {
573
+ background: var(--accent);
574
+ color: var(--accent-text);
575
+ box-shadow: var(--shadow-sm);
576
+ }
577
+
578
+ /* ─── Log Box (Terminal) ─── */
579
+ .log-box {
580
+ background: var(--bg-primary);
581
+ color: var(--text-primary);
582
+ padding: 12px;
583
+ border-radius: var(--radius-md);
584
+ font-family: "IBM Plex Mono", "JetBrains Mono", "SF Mono", "Fira Code", monospace;
585
+ font-size: 11px;
586
+ line-height: 1.5;
587
+ max-height: 300px;
588
+ overflow: auto;
589
+ white-space: pre-wrap;
590
+ word-break: break-all;
591
+ border: 1px solid var(--border);
592
+ box-shadow: inset 0 0 20px rgba(1, 4, 9, 0.4);
593
+ }
594
+
595
+ /* ─── Skeleton Loader ─── */
596
+ .skeleton {
597
+ background: linear-gradient(90deg, var(--bg-card) 25%, rgba(240,246,252,0.06) 50%, var(--bg-card) 75%);
598
+ background-size: 200% 100%;
599
+ border-radius: var(--radius-md);
600
+ animation: shimmer 1.5s ease-in-out infinite;
601
+ min-height: 20px;
602
+ }
603
+
604
+ .skeleton-card {
605
+ height: 80px;
606
+ margin-bottom: 8px;
607
+ }
608
+
609
+ .skeleton-stat {
610
+ height: 70px;
611
+ }
612
+
613
+ .skeleton-text {
614
+ height: 14px;
615
+ margin-bottom: 8px;
616
+ border-radius: var(--radius-sm);
617
+ }
618
+
619
+ .skeleton-text.w-60 {
620
+ width: 60%;
621
+ }
622
+ .skeleton-text.w-40 {
623
+ width: 40%;
624
+ }
625
+ .skeleton-text.w-80 {
626
+ width: 80%;
627
+ }
628
+
629
+ /* ─── Modal ─── */
630
+ .modal-overlay {
631
+ position: fixed;
632
+ inset: 0;
633
+ background: var(--backdrop);
634
+ backdrop-filter: var(--backdrop-blur);
635
+ -webkit-backdrop-filter: var(--backdrop-blur);
636
+ z-index: 2000;
637
+ display: flex;
638
+ align-items: flex-end;
639
+ justify-content: center;
640
+ animation: fadeIn 0.2s ease;
641
+ }
642
+
643
+ .modal-content {
644
+ background: var(--bg-elevated);
645
+ border-radius: var(--radius-xl) var(--radius-xl) 0 0;
646
+ border: 1px solid var(--border);
647
+ border-bottom: none;
648
+ width: 100%;
649
+ max-width: 500px;
650
+ max-height: 92vh;
651
+ overflow-y: auto;
652
+ padding: 20px 16px;
653
+ padding-bottom: calc(20px + var(--safe-bottom));
654
+ animation: springUp 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
655
+ box-shadow: 0 -10px 30px rgba(1, 4, 9, 0.4);
656
+ }
657
+
658
+ .modal-handle {
659
+ width: 36px;
660
+ height: 4px;
661
+ background: var(--border-strong);
662
+ border-radius: var(--radius-full);
663
+ margin: 0 auto 16px;
664
+ }
665
+
666
+ .modal-title {
667
+ font-size: 20px;
668
+ font-weight: 700;
669
+ margin-bottom: 16px;
670
+ letter-spacing: -0.02em;
671
+ }
672
+
673
+ /* ─── Modal header with close button ─── */
674
+ .modal-header {
675
+ position: relative;
676
+ display: flex;
677
+ flex-direction: column;
678
+ align-items: center;
679
+ }
680
+
681
+ .modal-header .modal-handle {
682
+ margin-bottom: 12px;
683
+ }
684
+
685
+ .modal-header .modal-title {
686
+ width: 100%;
687
+ padding-right: 36px;
688
+ text-align: left;
689
+ }
690
+
691
+ .modal-close-btn {
692
+ position: absolute;
693
+ top: 0;
694
+ right: 0;
695
+ width: 32px;
696
+ height: 32px;
697
+ display: flex;
698
+ align-items: center;
699
+ justify-content: center;
700
+ border: none;
701
+ background: var(--glass-bg, rgba(255,255,255,0.06));
702
+ border-radius: var(--radius-full, 50%);
703
+ color: var(--text-secondary);
704
+ cursor: pointer;
705
+ transition: background 0.15s ease, color 0.15s ease;
706
+ padding: 0;
707
+ }
708
+
709
+ .modal-close-btn:hover {
710
+ background: var(--bg-card-hover, rgba(255,255,255,0.12));
711
+ color: var(--text-bright);
712
+ }
713
+
714
+ .modal-close-btn svg {
715
+ width: 16px;
716
+ height: 16px;
717
+ }
718
+
719
+ /* ─── Toast ─── */
720
+ .toast-container {
721
+ position: fixed;
722
+ top: 12px;
723
+ left: 50%;
724
+ transform: translateX(-50%);
725
+ z-index: 10000;
726
+ display: flex;
727
+ flex-direction: column;
728
+ gap: 8px;
729
+ pointer-events: none;
730
+ max-width: calc(100vw - 32px);
731
+ }
732
+
733
+ .toast {
734
+ pointer-events: auto;
735
+ padding: 10px 16px;
736
+ border-radius: 10px;
737
+ font-size: 13px;
738
+ font-weight: 500;
739
+ color: #fff;
740
+ backdrop-filter: blur(12px);
741
+ box-shadow: 0 4px 16px rgba(0,0,0,0.3);
742
+ animation: toastIn 0.3s ease, toastOut 0.3s ease 2.7s forwards;
743
+ display: flex;
744
+ align-items: center;
745
+ gap: 8px;
746
+ max-width: 100%;
747
+ }
748
+
749
+ .toast-success {
750
+ background: rgba(46,204,113,0.9);
751
+ }
752
+ .toast-error {
753
+ background: rgba(231,76,60,0.9);
754
+ }
755
+ .toast-info {
756
+ background: rgba(91,110,174,0.9);
757
+ }
758
+ .toast-warning {
759
+ background: rgba(245,166,35,0.9);
760
+ }
761
+
762
+ @keyframes toastIn {
763
+ from { opacity: 0; transform: translateY(-20px) scale(0.95); }
764
+ to { opacity: 1; transform: translateY(0) scale(1); }
765
+ }
766
+ @keyframes toastOut {
767
+ from { opacity: 1; transform: translateY(0); }
768
+ to { opacity: 0; transform: translateY(-10px); }
769
+ }
770
+
771
+ /* ─── Collapsible Section ─── */
772
+ .collapsible-header {
773
+ display: flex;
774
+ align-items: center;
775
+ justify-content: space-between;
776
+ padding: 12px 0;
777
+ cursor: pointer;
778
+ border: none;
779
+ background: none;
780
+ width: 100%;
781
+ color: var(--text-primary);
782
+ font-size: 15px;
783
+ font-weight: 600;
784
+ -webkit-tap-highlight-color: transparent;
785
+ }
786
+
787
+ .collapsible-header svg {
788
+ transition: transform 0.2s ease;
789
+ }
790
+
791
+ .collapsible-header.open svg {
792
+ transform: rotate(180deg);
793
+ }
794
+
795
+ .collapsible-body {
796
+ overflow: hidden;
797
+ max-height: 0;
798
+ transition: max-height 0.3s ease;
799
+ }
800
+
801
+ .collapsible-body.open {
802
+ max-height: 2000px;
803
+ }
804
+
805
+ /* ─── Pill ─── */
806
+ .pill {
807
+ display: inline-flex;
808
+ align-items: center;
809
+ padding: 4px 10px;
810
+ border-radius: var(--radius-full);
811
+ font-size: 11px;
812
+ font-weight: 600;
813
+ background: var(--bg-secondary);
814
+ color: var(--text-secondary);
815
+ border: 1px solid var(--border);
816
+ }
817
+
818
+ /* ─── Pull to Refresh ─── */
819
+ .ptr-spinner {
820
+ display: flex;
821
+ justify-content: center;
822
+ padding: 12px 0;
823
+ }
824
+
825
+ .ptr-spinner-icon {
826
+ width: 24px;
827
+ height: 24px;
828
+ border: 2px solid var(--border);
829
+ border-top-color: var(--accent);
830
+ border-radius: 50%;
831
+ animation: spin 0.8s linear infinite;
832
+ }
833
+
834
+ /* ─── Desktop Refresh Button ─── */
835
+ .ptr-desktop-refresh {
836
+ position: absolute;
837
+ top: 8px;
838
+ right: 8px;
839
+ width: 32px;
840
+ height: 32px;
841
+ display: flex;
842
+ align-items: center;
843
+ justify-content: center;
844
+ border: 1px solid var(--border);
845
+ background: var(--bg-card);
846
+ border-radius: var(--radius-full, 50%);
847
+ color: var(--text-secondary);
848
+ cursor: pointer;
849
+ z-index: 10;
850
+ transition: background 0.15s ease, color 0.15s ease, transform 0.2s ease;
851
+ padding: 0;
852
+ }
853
+
854
+ .ptr-desktop-refresh:hover {
855
+ background: var(--bg-card-hover);
856
+ color: var(--accent);
857
+ }
858
+
859
+ .ptr-desktop-refresh:active {
860
+ transform: scale(0.9);
861
+ }
862
+
863
+ .ptr-desktop-refresh svg {
864
+ width: 16px;
865
+ height: 16px;
866
+ }
867
+
868
+ .ptr-desktop-refresh.spinning svg {
869
+ animation: spin 0.8s linear infinite;
870
+ }
871
+
872
+ .pull-to-refresh-container {
873
+ position: relative;
874
+ }
875
+
876
+ /* ─── Cards need breathing room ─── */
877
+ .card + .card {
878
+ margin-top: 12px;
879
+ }
880
+
881
+ /* ─── Misc ─── */
882
+ .meta-text {
883
+ font-size: 12px;
884
+ color: var(--text-hint);
885
+ }
886
+
887
+ /* ─── Pager ─── */
888
+ .pager {
889
+ display: flex;
890
+ justify-content: space-between;
891
+ align-items: center;
892
+ gap: 8px;
893
+ margin-top: 12px;
894
+ }
895
+
896
+ .pager-info {
897
+ font-size: 12px;
898
+ color: var(--text-secondary);
899
+ font-weight: 600;
900
+ }
901
+
902
+ /* ─── Empty State ─── */
903
+ .empty-state {
904
+ display: flex;
905
+ flex-direction: column;
906
+ align-items: center;
907
+ justify-content: center;
908
+ padding: 40px 20px;
909
+ text-align: center;
910
+ }
911
+
912
+ .empty-state-icon {
913
+ font-size: 48px;
914
+ margin-bottom: 16px;
915
+ opacity: 0.4;
916
+ filter: grayscale(0.3);
917
+ }
918
+
919
+ .empty-state-title {
920
+ font-size: 16px;
921
+ font-weight: 600;
922
+ color: var(--text-primary);
923
+ margin-bottom: 8px;
924
+ }
925
+
926
+ .empty-state-description {
927
+ font-size: 13px;
928
+ color: var(--text-secondary);
929
+ max-width: 280px;
930
+ line-height: 1.5;
931
+ }
932
+
933
+ /* ─── List Item ─── */
934
+ .list-item {
935
+ display: flex;
936
+ align-items: center;
937
+ padding: 12px 0;
938
+ border-bottom: 1px solid var(--border);
939
+ gap: 12px;
940
+ }
941
+
942
+ .list-item:last-child {
943
+ border-bottom: none;
944
+ }
945
+
946
+ .list-item-content {
947
+ flex: 1;
948
+ min-width: 0;
949
+ }
950
+
951
+ .list-item-trailing {
952
+ flex-shrink: 0;
953
+ color: var(--text-hint);
954
+ }
955
+
956
+ /* ─── Avatar ─── */
957
+ .avatar {
958
+ width: 40px;
959
+ height: 40px;
960
+ border-radius: 50%;
961
+ display: flex;
962
+ align-items: center;
963
+ justify-content: center;
964
+ background: var(--gradient-accent);
965
+ color: var(--accent-text);
966
+ font-size: 14px;
967
+ font-weight: 600;
968
+ flex-shrink: 0;
969
+ box-shadow: var(--shadow-glow-sm);
970
+ }
971
+
972
+ .avatar-initials {
973
+ text-transform: uppercase;
974
+ }
975
+
976
+ /* ─── Divider ─── */
977
+ .divider {
978
+ height: 1px;
979
+ background: var(--border);
980
+ margin: 12px 0;
981
+ }
982
+
983
+ .divider-label {
984
+ display: flex;
985
+ align-items: center;
986
+ gap: 12px;
987
+ color: var(--text-hint);
988
+ font-size: 11px;
989
+ font-weight: 600;
990
+ text-transform: uppercase;
991
+ letter-spacing: 0.05em;
992
+ margin: 16px 0 8px;
993
+ }
994
+
995
+ .divider-label::before,
996
+ .divider-label::after {
997
+ content: "";
998
+ flex: 1;
999
+ height: 1px;
1000
+ background: var(--border);
1001
+ }
1002
+
1003
+ /* ─── Search Input ─── */
1004
+ .search-input-wrap {
1005
+ position: relative;
1006
+ margin-bottom: 12px;
1007
+ }
1008
+
1009
+ .search-input-wrap .input,
1010
+ .search-input-wrap .search-input {
1011
+ padding-left: 36px;
1012
+ padding-right: 36px;
1013
+ }
1014
+
1015
+ .search-input-icon {
1016
+ position: absolute;
1017
+ left: 12px;
1018
+ top: 50%;
1019
+ transform: translateY(-50%);
1020
+ color: var(--text-hint);
1021
+ pointer-events: none;
1022
+ width: 16px;
1023
+ height: 16px;
1024
+ }
1025
+
1026
+ .search-input-clear {
1027
+ position: absolute;
1028
+ right: 12px;
1029
+ top: 50%;
1030
+ transform: translateY(-50%);
1031
+ color: var(--text-hint);
1032
+ cursor: pointer;
1033
+ border: none;
1034
+ background: none;
1035
+ padding: 4px;
1036
+ display: flex;
1037
+ align-items: center;
1038
+ justify-content: center;
1039
+ }
1040
+
1041
+ /* ─── Toggle Switch ─── */
1042
+ .toggle {
1043
+ position: relative;
1044
+ width: 44px;
1045
+ height: 24px;
1046
+ border-radius: 12px;
1047
+ background: var(--border, rgba(255,255,255,0.15));
1048
+ transition: background 0.2s ease;
1049
+ cursor: pointer;
1050
+ flex-shrink: 0;
1051
+ }
1052
+ .toggle-on {
1053
+ background: var(--accent, #5b6eae) !important;
1054
+ }
1055
+ .toggle-thumb {
1056
+ position: absolute;
1057
+ top: 2px;
1058
+ left: 2px;
1059
+ width: 20px;
1060
+ height: 20px;
1061
+ border-radius: 50%;
1062
+ background: #fff;
1063
+ box-shadow: 0 1px 3px rgba(0,0,0,0.3);
1064
+ transition: transform 0.2s ease;
1065
+ }
1066
+ .toggle-on .toggle-thumb {
1067
+ transform: translateX(20px);
1068
+ }
1069
+ .toggle-wrap {
1070
+ display: flex;
1071
+ align-items: center;
1072
+ gap: 10px;
1073
+ cursor: pointer;
1074
+ }
1075
+ .toggle-wrap.disabled {
1076
+ opacity: 0.5;
1077
+ pointer-events: none;
1078
+ }
1079
+ .toggle-label {
1080
+ font-size: 14px;
1081
+ color: var(--text-primary, #fff);
1082
+ }
1083
+
1084
+ /* ─── Stepper ─── */
1085
+ .stepper {
1086
+ display: inline-flex;
1087
+ align-items: center;
1088
+ gap: 0;
1089
+ border-radius: var(--radius-md);
1090
+ border: 1px solid var(--border);
1091
+ overflow: hidden;
1092
+ }
1093
+
1094
+ .stepper-btn {
1095
+ width: 36px;
1096
+ height: 36px;
1097
+ border: none;
1098
+ background: var(--bg-surface);
1099
+ color: var(--text-primary);
1100
+ font-size: 18px;
1101
+ font-weight: 600;
1102
+ cursor: pointer;
1103
+ display: flex;
1104
+ align-items: center;
1105
+ justify-content: center;
1106
+ transition: background var(--transition-fast);
1107
+ }
1108
+
1109
+ .stepper-btn:active {
1110
+ background: var(--bg-card-hover);
1111
+ }
1112
+
1113
+ .stepper-value {
1114
+ width: 48px;
1115
+ text-align: center;
1116
+ font-size: 14px;
1117
+ font-weight: 600;
1118
+ color: var(--text-primary);
1119
+ background: var(--bg-input);
1120
+ border-left: 1px solid var(--border);
1121
+ border-right: 1px solid var(--border);
1122
+ line-height: 36px;
1123
+ }
1124
+
1125
+ /* ─── Section Header (Telegram-style) ─── */
1126
+ .section-header {
1127
+ font-size: 13px;
1128
+ font-weight: 600;
1129
+ color: var(--header-text);
1130
+ text-transform: uppercase;
1131
+ letter-spacing: 0.03em;
1132
+ padding: 8px 0 4px;
1133
+ margin-bottom: 4px;
1134
+ }
1135
+
1136
+ /* ─── Settings Section ─── */
1137
+ .settings-section {
1138
+ background: var(--bg-card);
1139
+ border-radius: var(--radius-lg);
1140
+ border: 1px solid var(--border);
1141
+ padding: 0;
1142
+ margin-bottom: 16px;
1143
+ overflow: hidden;
1144
+ box-shadow: var(--shadow-sm);
1145
+ }
1146
+
1147
+ .settings-section .list-item {
1148
+ padding: 14px 16px;
1149
+ margin: 0;
1150
+ }
1151
+
1152
+ .settings-section .list-item:not(:last-child) {
1153
+ border-bottom: 1px solid var(--border);
1154
+ }
1155
+
1156
+ /* ─── Quick Actions Grid ─── */
1157
+ .quick-actions-grid {
1158
+ display: grid;
1159
+ grid-template-columns: repeat(3, 1fr);
1160
+ gap: 8px;
1161
+ margin-bottom: 12px;
1162
+ }
1163
+
1164
+ /* ─── Quick Action Sent Animation ─── */
1165
+ .quick-action-sent {
1166
+ animation: quickActionPulse 0.3s ease;
1167
+ }
1168
+ @keyframes quickActionPulse {
1169
+ 0% { transform: scale(1); }
1170
+ 50% { transform: scale(0.92); opacity: 0.7; }
1171
+ 100% { transform: scale(1); }
1172
+ }
1173
+
1174
+ /* ─── Action Card ─── */
1175
+ .action-card {
1176
+ display: flex;
1177
+ flex-direction: column;
1178
+ align-items: center;
1179
+ justify-content: center;
1180
+ gap: 6px;
1181
+ padding: 16px 8px;
1182
+ background: var(--bg-card);
1183
+ border-radius: var(--radius-md);
1184
+ border: 1px solid var(--border);
1185
+ cursor: pointer;
1186
+ transition: background var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
1187
+ -webkit-tap-highlight-color: transparent;
1188
+ font-size: 11px;
1189
+ font-weight: 500;
1190
+ color: var(--text-secondary);
1191
+ text-align: center;
1192
+ }
1193
+
1194
+ .action-card:active {
1195
+ transform: scale(0.95);
1196
+ background: var(--bg-card-hover);
1197
+ }
1198
+
1199
+ .action-card:hover {
1200
+ border-color: var(--border-strong);
1201
+ background: var(--bg-card-hover);
1202
+ }
1203
+
1204
+ .action-card:focus-visible {
1205
+ outline: 2px solid var(--accent);
1206
+ outline-offset: 2px;
1207
+ }
1208
+
1209
+ .action-card svg {
1210
+ width: 24px;
1211
+ height: 24px;
1212
+ color: var(--accent);
1213
+ filter: none;
1214
+ }
1215
+
1216
+ /* ─── Utility Classes ─── */
1217
+ .gap-sm {
1218
+ gap: 6px;
1219
+ }
1220
+ .gap-md {
1221
+ gap: 10px;
1222
+ }
1223
+ .mb-sm {
1224
+ margin-bottom: 6px;
1225
+ }
1226
+ .mb-md {
1227
+ margin-bottom: 12px;
1228
+ }
1229
+ .mb-lg {
1230
+ margin-bottom: 16px;
1231
+ }
1232
+ .mt-sm {
1233
+ margin-top: 6px;
1234
+ }
1235
+ .mt-md {
1236
+ margin-top: 12px;
1237
+ }
1238
+
1239
+ .flex-between {
1240
+ display: flex;
1241
+ justify-content: space-between;
1242
+ align-items: center;
1243
+ }
1244
+
1245
+ .text-center {
1246
+ text-align: center;
1247
+ }
1248
+ .text-right {
1249
+ text-align: right;
1250
+ }
1251
+
1252
+ .hidden {
1253
+ display: none !important;
1254
+ }
1255
+
1256
+ .flex-col {
1257
+ display: flex;
1258
+ flex-direction: column;
1259
+ }
1260
+
1261
+ .flex-row {
1262
+ display: flex;
1263
+ flex-direction: row;
1264
+ align-items: center;
1265
+ }
1266
+
1267
+ .flex-wrap {
1268
+ flex-wrap: wrap;
1269
+ }
1270
+ .flex-1 {
1271
+ flex: 1;
1272
+ }
1273
+
1274
+ /* ─── Status Dot ─── */
1275
+ .status-dot {
1276
+ display: inline-block;
1277
+ width: 8px;
1278
+ height: 8px;
1279
+ border-radius: 50%;
1280
+ margin-right: 6px;
1281
+ flex-shrink: 0;
1282
+ vertical-align: middle;
1283
+ }
1284
+
1285
+ /* ─── Agent Slot Grid ─── */
1286
+ .slot-grid {
1287
+ display: grid;
1288
+ grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
1289
+ gap: 8px;
1290
+ }
1291
+
1292
+ .slot-cell {
1293
+ display: flex;
1294
+ flex-direction: column;
1295
+ align-items: center;
1296
+ justify-content: center;
1297
+ gap: 4px;
1298
+ padding: 10px 4px;
1299
+ border-radius: var(--radius-md);
1300
+ border: 1px solid var(--border);
1301
+ cursor: default;
1302
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
1303
+ background: var(--bg-card);
1304
+ position: relative;
1305
+ }
1306
+
1307
+ .slot-cell[onClick] {
1308
+ cursor: pointer;
1309
+ }
1310
+
1311
+ .slot-cell:active {
1312
+ transform: scale(0.95);
1313
+ }
1314
+
1315
+ .slot-label {
1316
+ font-size: 11px;
1317
+ font-weight: 600;
1318
+ color: var(--text-secondary);
1319
+ }
1320
+
1321
+ .slot-idle {
1322
+ background: var(--bg-card);
1323
+ border-color: var(--border);
1324
+ opacity: 0.6;
1325
+ }
1326
+
1327
+ .slot-busy,
1328
+ .slot-running {
1329
+ background: rgba(88, 166, 255, 0.12);
1330
+ border-color: rgba(88, 166, 255, 0.4);
1331
+ animation: glowPulse 2s ease-in-out infinite;
1332
+ }
1333
+
1334
+ .slot-error {
1335
+ background: rgba(248, 81, 73, 0.12);
1336
+ border-color: rgba(248, 81, 73, 0.4);
1337
+ }
1338
+
1339
+ .slot-done {
1340
+ background: rgba(46, 160, 67, 0.12);
1341
+ border-color: rgba(46, 160, 67, 0.4);
1342
+ }
1343
+
1344
+ @keyframes slot-pulse {
1345
+ 0%, 100% { opacity: 1; }
1346
+ 50% { opacity: 0.7; }
1347
+ }
1348
+
1349
+ /* ─── Agent Progress Bar ─── */
1350
+ .agent-progress-bar {
1351
+ height: 4px;
1352
+ background: #21262d;
1353
+ border-radius: var(--radius-full);
1354
+ overflow: hidden;
1355
+ }
1356
+
1357
+ .agent-progress-bar-fill {
1358
+ height: 100%;
1359
+ background: var(--gradient-progress, linear-gradient(90deg, #6366f1, #818cf8));
1360
+ border-radius: var(--radius-full);
1361
+ width: 100%;
1362
+ }
1363
+
1364
+ .agent-progress-pulse {
1365
+ animation: agent-progress-indeterminate 1.5s ease-in-out infinite;
1366
+ }
1367
+
1368
+ @keyframes agent-progress-indeterminate {
1369
+ 0% { transform: translateX(-100%); }
1370
+ 100% { transform: translateX(100%); }
1371
+ }
1372
+
1373
+ /* ─── Agent Duration Indicator ─── */
1374
+ .agent-duration {
1375
+ font-size: 11px;
1376
+ color: var(--text-hint);
1377
+ font-variant-numeric: tabular-nums;
1378
+ }
1379
+
1380
+ /* ─── Workspace Viewer ─── */
1381
+ .workspace-viewer {
1382
+ background: var(--bg-card);
1383
+ border-radius: var(--radius-lg, 12px);
1384
+ overflow: hidden;
1385
+ border: 1px solid var(--border);
1386
+ }
1387
+
1388
+ .workspace-log {
1389
+ background: var(--bg-primary);
1390
+ color: var(--text-primary);
1391
+ font-family: "IBM Plex Mono", "JetBrains Mono", "Fira Code", monospace;
1392
+ font-size: 12px;
1393
+ line-height: 1.5;
1394
+ padding: 12px;
1395
+ max-height: 400px;
1396
+ overflow-y: auto;
1397
+ white-space: pre-wrap;
1398
+ word-break: break-all;
1399
+ box-shadow: inset 0 0 20px rgba(1, 4, 9, 0.4);
1400
+ }
1401
+
1402
+ .workspace-header {
1403
+ padding: 12px 16px;
1404
+ display: flex;
1405
+ align-items: center;
1406
+ justify-content: space-between;
1407
+ border-bottom: 1px solid var(--border);
1408
+ }
1409
+
1410
+ .workspace-controls {
1411
+ display: flex;
1412
+ gap: 8px;
1413
+ padding: 12px;
1414
+ border-top: 1px solid var(--border);
1415
+ }
1416
+
1417
+ .workspace-controls .input {
1418
+ flex: 1;
1419
+ }
1420
+
1421
+ .workspace-tabs {
1422
+ margin: 12px 16px 0;
1423
+ }
1424
+
1425
+ .workspace-context .card {
1426
+ background: var(--bg-card);
1427
+ border: 1px solid var(--border);
1428
+ }
1429
+
1430
+ .workspace-diff {
1431
+ font-size: 11px;
1432
+ margin: 8px 0 0;
1433
+ white-space: pre-wrap;
1434
+ color: var(--text-secondary);
1435
+ overflow-x: auto;
1436
+ }
1437
+
1438
+ .mono {
1439
+ font-family: "IBM Plex Mono", "JetBrains Mono", "Fira Code", monospace;
1440
+ font-size: 12px;
1441
+ }
1442
+
1443
+ .branch-row {
1444
+ width: 100%;
1445
+ text-align: left;
1446
+ background: var(--bg-card);
1447
+ border: 1px solid var(--border);
1448
+ border-radius: var(--radius-sm);
1449
+ padding: 8px 10px;
1450
+ margin-bottom: 6px;
1451
+ display: flex;
1452
+ flex-direction: column;
1453
+ gap: 4px;
1454
+ cursor: pointer;
1455
+ color: var(--text-primary);
1456
+ font: inherit;
1457
+ outline: none;
1458
+ transition: background var(--transition-fast), border-color var(--transition-fast);
1459
+ }
1460
+
1461
+ .branch-row:hover {
1462
+ background: var(--bg-card-hover);
1463
+ border-color: var(--border-strong);
1464
+ }
1465
+
1466
+ .branch-name {
1467
+ font-weight: 600;
1468
+ font-size: 13px;
1469
+ }
1470
+
1471
+ .branch-raw {
1472
+ font-size: 11px;
1473
+ color: var(--text-hint);
1474
+ }
1475
+
1476
+ /* ─── Dispatch Card ─── */
1477
+ .dispatch-section {
1478
+ display: flex;
1479
+ flex-direction: column;
1480
+ gap: 8px;
1481
+ }
1482
+
1483
+ .dispatch-section .input-row {
1484
+ margin-bottom: 0;
1485
+ }
1486
+
1487
+ /* ─── Responsive ─── */
1488
+ @media (max-width: 380px) {
1489
+ .stats-grid {
1490
+ grid-template-columns: repeat(2, 1fr);
1491
+ gap: 6px;
1492
+ }
1493
+
1494
+ .stat-value {
1495
+ font-size: 20px;
1496
+ }
1497
+ }
1498
+
1499
+ @media (min-width: 600px) {
1500
+ .stats-grid {
1501
+ grid-template-columns: repeat(4, 1fr);
1502
+ }
1503
+
1504
+ .modal-content {
1505
+ border-radius: var(--radius-xl);
1506
+ margin-bottom: 24px;
1507
+ }
1508
+
1509
+ .modal-overlay {
1510
+ align-items: center;
1511
+ }
1512
+ }
1513
+
1514
+ @media (min-width: 768px) {
1515
+ .card {
1516
+ padding: 20px;
1517
+ margin-bottom: 16px;
1518
+ }
1519
+
1520
+ .stat-card {
1521
+ padding: 18px 16px;
1522
+ }
1523
+
1524
+ .stats-grid {
1525
+ gap: 12px;
1526
+ margin-bottom: 16px;
1527
+ }
1528
+
1529
+ .task-card {
1530
+ padding: 18px;
1531
+ margin-bottom: 12px;
1532
+ }
1533
+
1534
+ .list-item {
1535
+ padding: 14px 0;
1536
+ }
1537
+
1538
+ .empty-state {
1539
+ padding: 60px 24px;
1540
+ }
1541
+
1542
+ .modal-content {
1543
+ max-width: 600px;
1544
+ }
1545
+
1546
+ .chip {
1547
+ padding: 8px 16px;
1548
+ font-size: 13px;
1549
+ }
1550
+
1551
+ .search-input-wrap {
1552
+ max-width: 480px;
1553
+ }
1554
+
1555
+ .slot-grid {
1556
+ grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
1557
+ gap: 10px;
1558
+ }
1559
+
1560
+ .quick-actions-grid {
1561
+ grid-template-columns: repeat(6, 1fr);
1562
+ }
1563
+ }
1564
+
1565
+ /* ─── Quick Action Buttons ─── */
1566
+ .quick-action-btn {
1567
+ display: flex;
1568
+ flex-direction: column;
1569
+ align-items: center;
1570
+ justify-content: center;
1571
+ gap: var(--space-xs, 4px);
1572
+ padding: var(--space-md, 14px) var(--space-sm, 8px);
1573
+ background: var(--glass-bg);
1574
+ backdrop-filter: blur(8px);
1575
+ -webkit-backdrop-filter: blur(8px);
1576
+ border-radius: var(--radius-md);
1577
+ border: 1px solid var(--glass-border);
1578
+ cursor: pointer;
1579
+ transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
1580
+ -webkit-tap-highlight-color: transparent;
1581
+ font-family: inherit;
1582
+ }
1583
+
1584
+ .quick-action-btn:active {
1585
+ transform: scale(0.93);
1586
+ background: var(--bg-card-hover);
1587
+ }
1588
+
1589
+ .quick-action-btn:hover {
1590
+ box-shadow: var(--shadow-glow-sm);
1591
+ border-color: var(--border-glow);
1592
+ }
1593
+
1594
+ .quick-action-btn:focus-visible {
1595
+ outline: 2px solid var(--accent);
1596
+ outline-offset: 2px;
1597
+ }
1598
+
1599
+ .quick-action-icon {
1600
+ font-size: 22px;
1601
+ line-height: 1;
1602
+ }
1603
+
1604
+ .quick-action-label {
1605
+ font-size: 11px;
1606
+ font-weight: 600;
1607
+ color: var(--text-secondary);
1608
+ white-space: nowrap;
1609
+ }
1610
+
1611
+ /* ─── Command History Dropdown ─── */
1612
+ .cmd-history-dropdown {
1613
+ position: absolute;
1614
+ top: 100%;
1615
+ left: 0;
1616
+ right: 0;
1617
+ background: var(--bg-elevated);
1618
+ backdrop-filter: blur(20px);
1619
+ -webkit-backdrop-filter: blur(20px);
1620
+ border: 1px solid var(--glass-border);
1621
+ border-radius: var(--radius-md);
1622
+ box-shadow: var(--shadow-lg), var(--shadow-glow-sm);
1623
+ z-index: 50;
1624
+ max-height: 200px;
1625
+ overflow-y: auto;
1626
+ margin-top: 4px;
1627
+ }
1628
+
1629
+ .cmd-history-item {
1630
+ display: block;
1631
+ width: 100%;
1632
+ padding: 10px 14px;
1633
+ border: none;
1634
+ background: none;
1635
+ color: var(--text-primary);
1636
+ font-size: 13px;
1637
+ font-family: 'SF Mono', 'Fira Code', monospace;
1638
+ text-align: left;
1639
+ cursor: pointer;
1640
+ transition: background var(--transition-fast);
1641
+ }
1642
+
1643
+ .cmd-history-item:hover {
1644
+ background: var(--accent-subtle);
1645
+ }
1646
+
1647
+ .cmd-history-item:not(:last-child) {
1648
+ border-bottom: 1px solid var(--glass-border);
1649
+ }
1650
+
1651
+ /* ─── Health Dot (Infra) ─── */
1652
+ .health-dot {
1653
+ display: inline-block;
1654
+ width: 8px;
1655
+ height: 8px;
1656
+ border-radius: 50%;
1657
+ flex-shrink: 0;
1658
+ vertical-align: middle;
1659
+ }
1660
+
1661
+ /* ─── Task Card States ─── */
1662
+ .task-card-selected {
1663
+ border-color: var(--accent);
1664
+ background: rgba(99, 102, 241, 0.06);
1665
+ box-shadow: var(--shadow-glow-sm);
1666
+ }
1667
+
1668
+ .task-card-expanded {
1669
+ border-color: var(--border-strong);
1670
+ }
1671
+
1672
+ .task-card-enter {
1673
+ animation: fadeSlideUp 0.2s ease;
1674
+ }
1675
+
1676
+ .task-checkbox {
1677
+ width: 18px;
1678
+ height: 18px;
1679
+ flex-shrink: 0;
1680
+ margin-right: var(--space-sm, 8px);
1681
+ cursor: pointer;
1682
+ }
1683
+
1684
+ /* ─── Batch Action Bar ─── */
1685
+ .batch-action-bar {
1686
+ background: var(--glass-bg);
1687
+ backdrop-filter: blur(12px);
1688
+ -webkit-backdrop-filter: blur(12px);
1689
+ border-radius: var(--radius-md);
1690
+ padding: var(--space-sm, 8px) var(--space-md, 12px);
1691
+ align-items: center;
1692
+ border: 1px solid var(--glass-border);
1693
+ }
1694
+
1695
+ /* ─── Sticky Search ─── */
1696
+ .sticky-search {
1697
+ position: sticky;
1698
+ top: 0;
1699
+ z-index: 20;
1700
+ background: var(--bg-primary);
1701
+ padding: 8px 0 12px;
1702
+ margin-bottom: var(--space-sm, 8px);
1703
+ border-bottom: 1px solid var(--border);
1704
+ backdrop-filter: blur(10px);
1705
+ }
1706
+
1707
+ .sticky-search-row {
1708
+ display: flex;
1709
+ align-items: center;
1710
+ gap: 8px;
1711
+ flex-wrap: wrap;
1712
+ }
1713
+
1714
+ .sticky-search-main {
1715
+ flex: 1;
1716
+ min-width: 200px;
1717
+ position: relative;
1718
+ display: flex;
1719
+ align-items: center;
1720
+ gap: 6px;
1721
+ }
1722
+
1723
+ .export-wrap {
1724
+ position: relative;
1725
+ }
1726
+
1727
+ .filter-summary {
1728
+ display: flex;
1729
+ align-items: center;
1730
+ justify-content: space-between;
1731
+ gap: 8px;
1732
+ flex-wrap: wrap;
1733
+ color: var(--text-hint);
1734
+ font-size: 11px;
1735
+ }
1736
+
1737
+ .filter-summary-text {
1738
+ display: flex;
1739
+ align-items: center;
1740
+ gap: 6px;
1741
+ flex-wrap: wrap;
1742
+ color: var(--text-secondary);
1743
+ }
1744
+
1745
+ .filter-summary-actions {
1746
+ display: flex;
1747
+ align-items: center;
1748
+ gap: 6px;
1749
+ }
1750
+
1751
+ /* ─── Sticky Controls ─── */
1752
+ .sticky-controls {
1753
+ position: sticky;
1754
+ top: calc(var(--header-height) + 8px);
1755
+ z-index: 20;
1756
+ background: var(--bg-secondary);
1757
+ padding: 8px 0 10px;
1758
+ margin-bottom: 8px;
1759
+ border-bottom: 1px solid var(--border);
1760
+ backdrop-filter: blur(10px);
1761
+ }
1762
+
1763
+ /* ─── Control Unit (sticky) ─── */
1764
+ .control-unit-card {
1765
+ position: sticky;
1766
+ top: 0;
1767
+ z-index: 18;
1768
+ background: var(--bg-card);
1769
+ }
1770
+
1771
+ .control-unit-body {
1772
+ display: flex;
1773
+ flex-direction: column;
1774
+ gap: 10px;
1775
+ }
1776
+
1777
+ .control-unit-meta {
1778
+ display: flex;
1779
+ flex-wrap: wrap;
1780
+ gap: 6px 12px;
1781
+ font-size: 12px;
1782
+ color: var(--text-secondary);
1783
+ }
1784
+
1785
+ .control-unit-meta strong {
1786
+ color: var(--text-bright);
1787
+ font-weight: 600;
1788
+ }
1789
+
1790
+ .control-unit-actions {
1791
+ display: flex;
1792
+ flex-wrap: wrap;
1793
+ gap: 8px;
1794
+ }
1795
+
1796
+ @media (min-width: 768px) {
1797
+ .control-unit-body {
1798
+ flex-direction: row;
1799
+ align-items: center;
1800
+ justify-content: space-between;
1801
+ }
1802
+ }
1803
+
1804
+ /* ─── Toggle Label ─── */
1805
+ .toggle-label {
1806
+ display: inline-flex;
1807
+ align-items: center;
1808
+ gap: var(--space-xs, 4px);
1809
+ cursor: pointer;
1810
+ user-select: none;
1811
+ white-space: nowrap;
1812
+ }
1813
+
1814
+ /* ─── Settings Row ─── */
1815
+ .settings-row {
1816
+ display: flex;
1817
+ align-items: center;
1818
+ gap: var(--space-md, 12px);
1819
+ }
1820
+
1821
+ /* ─── Log Box Small ─── */
1822
+ .log-box-sm {
1823
+ max-height: 120px;
1824
+ font-size: 10px;
1825
+ }
1826
+
1827
+ /* ─── Worktree Detail ─── */
1828
+ .wt-detail {
1829
+ padding: var(--space-sm, 8px) 0;
1830
+ }
1831
+
1832
+ /* ─── ListItem extensions ─── */
1833
+ .list-item-body {
1834
+ flex: 1;
1835
+ min-width: 0;
1836
+ }
1837
+
1838
+ .list-item-title {
1839
+ font-size: 14px;
1840
+ font-weight: 600;
1841
+ color: var(--text-primary);
1842
+ line-height: 1.4;
1843
+ }
1844
+
1845
+ .list-item-subtitle {
1846
+ font-size: 12px;
1847
+ color: var(--text-secondary);
1848
+ margin-top: 1px;
1849
+ line-height: 1.4;
1850
+ }
1851
+
1852
+ .list-item-clickable {
1853
+ cursor: pointer;
1854
+ transition: background var(--transition-fast);
1855
+ }
1856
+
1857
+ .list-item-clickable:active {
1858
+ background: var(--bg-card-hover);
1859
+ }
1860
+
1861
+ .list-item-icon {
1862
+ width: 20px;
1863
+ height: 20px;
1864
+ color: var(--text-secondary);
1865
+ flex-shrink: 0;
1866
+ }
1867
+
1868
+ /* ─── Toast extensions ─── */
1869
+ .toast-message {
1870
+ flex: 1;
1871
+ }
1872
+
1873
+ .toast-close {
1874
+ border: none;
1875
+ background: none;
1876
+ color: rgba(255,255,255,0.7);
1877
+ font-size: 18px;
1878
+ cursor: pointer;
1879
+ padding: 0 0 0 8px;
1880
+ line-height: 1;
1881
+ }
1882
+
1883
+ .toast-close:hover {
1884
+ color: #fff;
1885
+ }
1886
+
1887
+ /* ─── Spinner ─── */
1888
+ @keyframes spin { to { transform: rotate(360deg); } }
1889
+ .spinner { animation: spin 0.8s linear infinite; }
1890
+ .btn-loading {
1891
+ position: relative;
1892
+ pointer-events: none;
1893
+ opacity: 0.7;
1894
+ }
1895
+ .btn-loading .spinner {
1896
+ display: inline-block;
1897
+ vertical-align: middle;
1898
+ }
1899
+
1900
+ /* ─── Stat trend colors ─── */
1901
+ .stat-trend.up,
1902
+ .stat-trend-up {
1903
+ color: var(--accent-success, var(--color-done));
1904
+ }
1905
+
1906
+ .stat-trend.down,
1907
+ .stat-trend-down {
1908
+ color: var(--accent-error, var(--color-error));
1909
+ }
1910
+
1911
+ /* ─── Input small variant ─── */
1912
+ .input-sm {
1913
+ min-height: 36px;
1914
+ padding: 6px 10px;
1915
+ font-size: 13px;
1916
+ }
1917
+
1918
+ /* ─── Modal swipe-to-dismiss ─── */
1919
+ .modal-content {
1920
+ transition: transform 0.3s cubic-bezier(0.2, 0, 0, 1), opacity 0.3s ease;
1921
+ will-change: transform, opacity;
1922
+ touch-action: pan-x;
1923
+ }
1924
+
1925
+ .modal-content.modal-dragging {
1926
+ transition: none;
1927
+ overflow-y: hidden;
1928
+ }
1929
+
1930
+ /* ─── ConfirmDialog ─── */
1931
+ .confirm-dialog {
1932
+ background: var(--bg-elevated);
1933
+ backdrop-filter: blur(24px);
1934
+ -webkit-backdrop-filter: blur(24px);
1935
+ border-radius: var(--radius-xl);
1936
+ border: 1px solid var(--glass-border);
1937
+ width: calc(100% - 48px);
1938
+ max-width: 340px;
1939
+ padding: 24px;
1940
+ animation: scaleIn 0.2s ease;
1941
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
1942
+ text-align: center;
1943
+ margin: auto;
1944
+ }
1945
+
1946
+ .confirm-dialog-title {
1947
+ font-size: 18px;
1948
+ font-weight: 700;
1949
+ margin-bottom: 8px;
1950
+ color: var(--text-primary);
1951
+ }
1952
+
1953
+ .confirm-dialog-message {
1954
+ font-size: 14px;
1955
+ color: var(--text-secondary);
1956
+ line-height: 1.5;
1957
+ margin-bottom: 20px;
1958
+ }
1959
+
1960
+ .confirm-dialog-actions {
1961
+ display: flex;
1962
+ gap: 10px;
1963
+ justify-content: center;
1964
+ }
1965
+
1966
+ .confirm-dialog-actions .btn {
1967
+ flex: 1;
1968
+ min-height: 40px;
1969
+ border-radius: var(--radius-md);
1970
+ font-weight: 600;
1971
+ font-size: 14px;
1972
+ cursor: pointer;
1973
+ border: none;
1974
+ }
1975
+
1976
+ .confirm-dialog-actions .btn-secondary {
1977
+ background: var(--glass-bg);
1978
+ color: var(--text-primary);
1979
+ border: 1px solid var(--glass-border);
1980
+ }
1981
+
1982
+ .confirm-dialog-actions .btn-destructive {
1983
+ background: var(--destructive);
1984
+ color: #fff;
1985
+ }
1986
+
1987
+ /* ─── Toggle disabled ─── */
1988
+ .toggle-wrap.disabled {
1989
+ opacity: 0.4;
1990
+ cursor: not-allowed;
1991
+ pointer-events: none;
1992
+ }
1993
+
1994
+ .toggle.disabled {
1995
+ opacity: 0.4;
1996
+ cursor: not-allowed;
1997
+ }
1998
+
1999
+ /* ─── SegmentedControl disabled ─── */
2000
+ .segmented-control.disabled {
2001
+ opacity: 0.4;
2002
+ pointer-events: none;
2003
+ }
2004
+
2005
+ .segmented-control.disabled .segmented-btn {
2006
+ cursor: not-allowed;
2007
+ }
2008
+
2009
+ /* ─── Stepper disabled ─── */
2010
+ .stepper.disabled {
2011
+ opacity: 0.4;
2012
+ pointer-events: none;
2013
+ }
2014
+
2015
+ .stepper.disabled .stepper-btn {
2016
+ cursor: not-allowed;
2017
+ color: var(--text-hint);
2018
+ }
2019
+
2020
+ .stepper-wrap.disabled {
2021
+ opacity: 0.4;
2022
+ }
2023
+
2024
+ /* ─── SearchInput disabled ─── */
2025
+ .search-input-wrap.disabled {
2026
+ opacity: 0.4;
2027
+ pointer-events: none;
2028
+ }
2029
+
2030
+ .search-input-wrap.disabled .search-input {
2031
+ cursor: not-allowed;
2032
+ }