@virtengine/openfleet 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/.env.example +914 -0
  2. package/LICENSE +190 -0
  3. package/README.md +500 -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/claude-shell.mjs +708 -0
  13. package/cli.mjs +906 -0
  14. package/codex-config.mjs +1274 -0
  15. package/codex-model-profiles.mjs +135 -0
  16. package/codex-shell.mjs +762 -0
  17. package/config-doctor.mjs +613 -0
  18. package/config.mjs +1720 -0
  19. package/conflict-resolver.mjs +248 -0
  20. package/container-runner.mjs +450 -0
  21. package/copilot-shell.mjs +827 -0
  22. package/daemon-restart-policy.mjs +56 -0
  23. package/diff-stats.mjs +282 -0
  24. package/error-detector.mjs +829 -0
  25. package/fetch-runtime.mjs +34 -0
  26. package/fleet-coordinator.mjs +838 -0
  27. package/get-telegram-chat-id.mjs +71 -0
  28. package/git-safety.mjs +170 -0
  29. package/github-reconciler.mjs +403 -0
  30. package/hook-profiles.mjs +651 -0
  31. package/kanban-adapter.mjs +4491 -0
  32. package/lib/logger.mjs +645 -0
  33. package/maintenance.mjs +828 -0
  34. package/merge-strategy.mjs +1171 -0
  35. package/monitor.mjs +12207 -0
  36. package/openfleet.config.example.json +115 -0
  37. package/openfleet.schema.json +465 -0
  38. package/package.json +203 -0
  39. package/postinstall.mjs +187 -0
  40. package/pr-cleanup-daemon.mjs +978 -0
  41. package/preflight.mjs +408 -0
  42. package/prepublish-check.mjs +90 -0
  43. package/presence.mjs +328 -0
  44. package/primary-agent.mjs +282 -0
  45. package/publish.mjs +151 -0
  46. package/repo-root.mjs +29 -0
  47. package/restart-controller.mjs +100 -0
  48. package/review-agent.mjs +557 -0
  49. package/rotate-agent-logs.sh +133 -0
  50. package/sdk-conflict-resolver.mjs +973 -0
  51. package/session-tracker.mjs +880 -0
  52. package/setup.mjs +3937 -0
  53. package/shared-knowledge.mjs +410 -0
  54. package/shared-state-manager.mjs +841 -0
  55. package/shared-workspace-cli.mjs +199 -0
  56. package/shared-workspace-registry.mjs +537 -0
  57. package/shared-workspaces.json +18 -0
  58. package/startup-service.mjs +1070 -0
  59. package/sync-engine.mjs +1063 -0
  60. package/task-archiver.mjs +801 -0
  61. package/task-assessment.mjs +550 -0
  62. package/task-claims.mjs +924 -0
  63. package/task-complexity.mjs +581 -0
  64. package/task-executor.mjs +5111 -0
  65. package/task-store.mjs +753 -0
  66. package/telegram-bot.mjs +9281 -0
  67. package/telegram-sentinel.mjs +2010 -0
  68. package/ui/app.js +867 -0
  69. package/ui/app.legacy.js +1464 -0
  70. package/ui/app.monolith.js +2488 -0
  71. package/ui/components/charts.js +226 -0
  72. package/ui/components/chat-view.js +567 -0
  73. package/ui/components/command-palette.js +587 -0
  74. package/ui/components/diff-viewer.js +190 -0
  75. package/ui/components/forms.js +327 -0
  76. package/ui/components/kanban-board.js +451 -0
  77. package/ui/components/session-list.js +305 -0
  78. package/ui/components/shared.js +473 -0
  79. package/ui/index.html +70 -0
  80. package/ui/modules/api.js +297 -0
  81. package/ui/modules/icons.js +461 -0
  82. package/ui/modules/router.js +81 -0
  83. package/ui/modules/settings-schema.js +261 -0
  84. package/ui/modules/state.js +679 -0
  85. package/ui/modules/telegram.js +331 -0
  86. package/ui/modules/utils.js +270 -0
  87. package/ui/styles/animations.css +140 -0
  88. package/ui/styles/base.css +98 -0
  89. package/ui/styles/components.css +1915 -0
  90. package/ui/styles/kanban.css +286 -0
  91. package/ui/styles/layout.css +809 -0
  92. package/ui/styles/sessions.css +827 -0
  93. package/ui/styles/variables.css +188 -0
  94. package/ui/styles.css +141 -0
  95. package/ui/styles.monolith.css +1046 -0
  96. package/ui/tabs/agents.js +1417 -0
  97. package/ui/tabs/chat.js +74 -0
  98. package/ui/tabs/control.js +887 -0
  99. package/ui/tabs/dashboard.js +515 -0
  100. package/ui/tabs/infra.js +537 -0
  101. package/ui/tabs/logs.js +783 -0
  102. package/ui/tabs/settings.js +1487 -0
  103. package/ui/tabs/tasks.js +1385 -0
  104. package/ui-server.mjs +4073 -0
  105. package/update-check.mjs +465 -0
  106. package/utils.mjs +172 -0
  107. package/ve-kanban.mjs +654 -0
  108. package/ve-kanban.ps1 +1365 -0
  109. package/ve-kanban.sh +18 -0
  110. package/ve-orchestrator.mjs +340 -0
  111. package/ve-orchestrator.ps1 +6546 -0
  112. package/ve-orchestrator.sh +18 -0
  113. package/vibe-kanban-wrapper.mjs +41 -0
  114. package/vk-error-resolver.mjs +470 -0
  115. package/vk-log-stream.mjs +914 -0
  116. package/whatsapp-channel.mjs +520 -0
  117. package/workspace-monitor.mjs +581 -0
  118. package/workspace-reaper.mjs +405 -0
  119. package/workspace-registry.mjs +238 -0
  120. package/worktree-manager.mjs +1266 -0
@@ -0,0 +1,1915 @@
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: 200;
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
+ /* ─── Toast ─── */
674
+ .toast-container {
675
+ position: fixed;
676
+ top: 12px;
677
+ left: 16px;
678
+ right: 16px;
679
+ z-index: 300;
680
+ display: flex;
681
+ flex-direction: column;
682
+ gap: 8px;
683
+ pointer-events: none;
684
+ }
685
+
686
+ .toast {
687
+ background: var(--bg-elevated);
688
+ color: var(--text-primary);
689
+ border-radius: var(--radius-md);
690
+ padding: 12px 16px;
691
+ font-size: 13px;
692
+ font-weight: 500;
693
+ box-shadow: var(--shadow-lg);
694
+ border: 1px solid var(--border);
695
+ animation: slideDown 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
696
+ pointer-events: auto;
697
+ }
698
+
699
+ .toast-success {
700
+ border-left: 3px solid var(--color-done);
701
+ box-shadow: var(--shadow-lg);
702
+ }
703
+ .toast-error {
704
+ border-left: 3px solid var(--color-error);
705
+ box-shadow: var(--shadow-lg);
706
+ }
707
+ .toast-info {
708
+ border-left: 3px solid var(--color-inprogress);
709
+ box-shadow: var(--shadow-lg);
710
+ }
711
+
712
+ /* ─── Collapsible Section ─── */
713
+ .collapsible-header {
714
+ display: flex;
715
+ align-items: center;
716
+ justify-content: space-between;
717
+ padding: 12px 0;
718
+ cursor: pointer;
719
+ border: none;
720
+ background: none;
721
+ width: 100%;
722
+ color: var(--text-primary);
723
+ font-size: 15px;
724
+ font-weight: 600;
725
+ -webkit-tap-highlight-color: transparent;
726
+ }
727
+
728
+ .collapsible-header svg {
729
+ transition: transform 0.2s ease;
730
+ }
731
+
732
+ .collapsible-header.open svg {
733
+ transform: rotate(180deg);
734
+ }
735
+
736
+ .collapsible-body {
737
+ overflow: hidden;
738
+ max-height: 0;
739
+ transition: max-height 0.3s ease;
740
+ }
741
+
742
+ .collapsible-body.open {
743
+ max-height: 2000px;
744
+ }
745
+
746
+ /* ─── Pill ─── */
747
+ .pill {
748
+ display: inline-flex;
749
+ align-items: center;
750
+ padding: 4px 10px;
751
+ border-radius: var(--radius-full);
752
+ font-size: 11px;
753
+ font-weight: 600;
754
+ background: var(--bg-secondary);
755
+ color: var(--text-secondary);
756
+ border: 1px solid var(--border);
757
+ }
758
+
759
+ /* ─── Pull to Refresh ─── */
760
+ .ptr-spinner {
761
+ display: flex;
762
+ justify-content: center;
763
+ padding: 12px 0;
764
+ }
765
+
766
+ .ptr-spinner-icon {
767
+ width: 24px;
768
+ height: 24px;
769
+ border: 2px solid var(--border);
770
+ border-top-color: var(--accent);
771
+ border-radius: 50%;
772
+ animation: spin 0.8s linear infinite;
773
+ }
774
+
775
+ /* ─── Misc ─── */
776
+ .meta-text {
777
+ font-size: 12px;
778
+ color: var(--text-hint);
779
+ }
780
+
781
+ /* ─── Pager ─── */
782
+ .pager {
783
+ display: flex;
784
+ justify-content: space-between;
785
+ align-items: center;
786
+ gap: 8px;
787
+ margin-top: 12px;
788
+ }
789
+
790
+ .pager-info {
791
+ font-size: 12px;
792
+ color: var(--text-secondary);
793
+ font-weight: 600;
794
+ }
795
+
796
+ /* ─── Empty State ─── */
797
+ .empty-state {
798
+ display: flex;
799
+ flex-direction: column;
800
+ align-items: center;
801
+ justify-content: center;
802
+ padding: 40px 20px;
803
+ text-align: center;
804
+ }
805
+
806
+ .empty-state-icon {
807
+ font-size: 48px;
808
+ margin-bottom: 16px;
809
+ opacity: 0.4;
810
+ filter: grayscale(0.3);
811
+ }
812
+
813
+ .empty-state-title {
814
+ font-size: 16px;
815
+ font-weight: 600;
816
+ color: var(--text-primary);
817
+ margin-bottom: 8px;
818
+ }
819
+
820
+ .empty-state-description {
821
+ font-size: 13px;
822
+ color: var(--text-secondary);
823
+ max-width: 280px;
824
+ line-height: 1.5;
825
+ }
826
+
827
+ /* ─── List Item ─── */
828
+ .list-item {
829
+ display: flex;
830
+ align-items: center;
831
+ padding: 12px 0;
832
+ border-bottom: 1px solid var(--border);
833
+ gap: 12px;
834
+ }
835
+
836
+ .list-item:last-child {
837
+ border-bottom: none;
838
+ }
839
+
840
+ .list-item-content {
841
+ flex: 1;
842
+ min-width: 0;
843
+ }
844
+
845
+ .list-item-trailing {
846
+ flex-shrink: 0;
847
+ color: var(--text-hint);
848
+ }
849
+
850
+ /* ─── Avatar ─── */
851
+ .avatar {
852
+ width: 40px;
853
+ height: 40px;
854
+ border-radius: 50%;
855
+ display: flex;
856
+ align-items: center;
857
+ justify-content: center;
858
+ background: var(--gradient-accent);
859
+ color: var(--accent-text);
860
+ font-size: 14px;
861
+ font-weight: 600;
862
+ flex-shrink: 0;
863
+ box-shadow: var(--shadow-glow-sm);
864
+ }
865
+
866
+ .avatar-initials {
867
+ text-transform: uppercase;
868
+ }
869
+
870
+ /* ─── Divider ─── */
871
+ .divider {
872
+ height: 1px;
873
+ background: var(--border);
874
+ margin: 12px 0;
875
+ }
876
+
877
+ .divider-label {
878
+ display: flex;
879
+ align-items: center;
880
+ gap: 12px;
881
+ color: var(--text-hint);
882
+ font-size: 11px;
883
+ font-weight: 600;
884
+ text-transform: uppercase;
885
+ letter-spacing: 0.05em;
886
+ margin: 16px 0 8px;
887
+ }
888
+
889
+ .divider-label::before,
890
+ .divider-label::after {
891
+ content: "";
892
+ flex: 1;
893
+ height: 1px;
894
+ background: var(--border);
895
+ }
896
+
897
+ /* ─── Search Input ─── */
898
+ .search-input-wrap {
899
+ position: relative;
900
+ margin-bottom: 12px;
901
+ }
902
+
903
+ .search-input-wrap .input,
904
+ .search-input-wrap .search-input {
905
+ padding-left: 36px;
906
+ padding-right: 36px;
907
+ }
908
+
909
+ .search-input-icon {
910
+ position: absolute;
911
+ left: 12px;
912
+ top: 50%;
913
+ transform: translateY(-50%);
914
+ color: var(--text-hint);
915
+ pointer-events: none;
916
+ width: 16px;
917
+ height: 16px;
918
+ }
919
+
920
+ .search-input-clear {
921
+ position: absolute;
922
+ right: 12px;
923
+ top: 50%;
924
+ transform: translateY(-50%);
925
+ color: var(--text-hint);
926
+ cursor: pointer;
927
+ border: none;
928
+ background: none;
929
+ padding: 4px;
930
+ display: flex;
931
+ align-items: center;
932
+ justify-content: center;
933
+ }
934
+
935
+ /* ─── Toggle Switch ─── */
936
+ .toggle {
937
+ position: relative;
938
+ display: inline-flex;
939
+ align-items: center;
940
+ cursor: pointer;
941
+ }
942
+
943
+ .toggle-track {
944
+ width: 44px;
945
+ height: 24px;
946
+ border-radius: 12px;
947
+ background: var(--bg-card);
948
+ border: 1px solid var(--border);
949
+ transition:
950
+ background var(--transition-fast),
951
+ border-color var(--transition-fast),
952
+ box-shadow var(--transition-fast);
953
+ position: relative;
954
+ }
955
+
956
+ .toggle.active .toggle-track {
957
+ background: var(--accent);
958
+ border-color: transparent;
959
+ box-shadow: var(--shadow-sm);
960
+ }
961
+
962
+ .toggle-thumb {
963
+ position: absolute;
964
+ top: 2px;
965
+ left: 2px;
966
+ width: 20px;
967
+ height: 20px;
968
+ border-radius: 50%;
969
+ background: white;
970
+ box-shadow: var(--shadow-sm);
971
+ transition: transform var(--transition-fast);
972
+ }
973
+
974
+ .toggle.active .toggle-thumb {
975
+ transform: translateX(20px);
976
+ }
977
+
978
+ /* ─── Stepper ─── */
979
+ .stepper {
980
+ display: inline-flex;
981
+ align-items: center;
982
+ gap: 0;
983
+ border-radius: var(--radius-md);
984
+ border: 1px solid var(--border);
985
+ overflow: hidden;
986
+ }
987
+
988
+ .stepper-btn {
989
+ width: 36px;
990
+ height: 36px;
991
+ border: none;
992
+ background: var(--bg-surface);
993
+ color: var(--text-primary);
994
+ font-size: 18px;
995
+ font-weight: 600;
996
+ cursor: pointer;
997
+ display: flex;
998
+ align-items: center;
999
+ justify-content: center;
1000
+ transition: background var(--transition-fast);
1001
+ }
1002
+
1003
+ .stepper-btn:active {
1004
+ background: var(--bg-card-hover);
1005
+ }
1006
+
1007
+ .stepper-value {
1008
+ width: 48px;
1009
+ text-align: center;
1010
+ font-size: 14px;
1011
+ font-weight: 600;
1012
+ color: var(--text-primary);
1013
+ background: var(--bg-input);
1014
+ border-left: 1px solid var(--border);
1015
+ border-right: 1px solid var(--border);
1016
+ line-height: 36px;
1017
+ }
1018
+
1019
+ /* ─── Section Header (Telegram-style) ─── */
1020
+ .section-header {
1021
+ font-size: 13px;
1022
+ font-weight: 600;
1023
+ color: var(--header-text);
1024
+ text-transform: uppercase;
1025
+ letter-spacing: 0.03em;
1026
+ padding: 8px 0 4px;
1027
+ margin-bottom: 4px;
1028
+ }
1029
+
1030
+ /* ─── Settings Section ─── */
1031
+ .settings-section {
1032
+ background: var(--bg-card);
1033
+ border-radius: var(--radius-lg);
1034
+ border: 1px solid var(--border);
1035
+ padding: 0;
1036
+ margin-bottom: 16px;
1037
+ overflow: hidden;
1038
+ box-shadow: var(--shadow-sm);
1039
+ }
1040
+
1041
+ .settings-section .list-item {
1042
+ padding: 14px 16px;
1043
+ margin: 0;
1044
+ }
1045
+
1046
+ .settings-section .list-item:not(:last-child) {
1047
+ border-bottom: 1px solid var(--border);
1048
+ }
1049
+
1050
+ /* ─── Quick Actions Grid ─── */
1051
+ .quick-actions-grid {
1052
+ display: grid;
1053
+ grid-template-columns: repeat(3, 1fr);
1054
+ gap: 8px;
1055
+ margin-bottom: 12px;
1056
+ }
1057
+
1058
+ /* ─── Quick Action Sent Animation ─── */
1059
+ .quick-action-sent {
1060
+ animation: quickActionPulse 0.3s ease;
1061
+ }
1062
+ @keyframes quickActionPulse {
1063
+ 0% { transform: scale(1); }
1064
+ 50% { transform: scale(0.92); opacity: 0.7; }
1065
+ 100% { transform: scale(1); }
1066
+ }
1067
+
1068
+ /* ─── Action Card ─── */
1069
+ .action-card {
1070
+ display: flex;
1071
+ flex-direction: column;
1072
+ align-items: center;
1073
+ justify-content: center;
1074
+ gap: 6px;
1075
+ padding: 16px 8px;
1076
+ background: var(--bg-card);
1077
+ border-radius: var(--radius-md);
1078
+ border: 1px solid var(--border);
1079
+ cursor: pointer;
1080
+ transition: background var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
1081
+ -webkit-tap-highlight-color: transparent;
1082
+ font-size: 11px;
1083
+ font-weight: 500;
1084
+ color: var(--text-secondary);
1085
+ text-align: center;
1086
+ }
1087
+
1088
+ .action-card:active {
1089
+ transform: scale(0.95);
1090
+ background: var(--bg-card-hover);
1091
+ }
1092
+
1093
+ .action-card:hover {
1094
+ border-color: var(--border-strong);
1095
+ background: var(--bg-card-hover);
1096
+ }
1097
+
1098
+ .action-card:focus-visible {
1099
+ outline: 2px solid var(--accent);
1100
+ outline-offset: 2px;
1101
+ }
1102
+
1103
+ .action-card svg {
1104
+ width: 24px;
1105
+ height: 24px;
1106
+ color: var(--accent);
1107
+ filter: none;
1108
+ }
1109
+
1110
+ /* ─── Utility Classes ─── */
1111
+ .gap-sm {
1112
+ gap: 6px;
1113
+ }
1114
+ .gap-md {
1115
+ gap: 10px;
1116
+ }
1117
+ .mb-sm {
1118
+ margin-bottom: 6px;
1119
+ }
1120
+ .mb-md {
1121
+ margin-bottom: 12px;
1122
+ }
1123
+ .mb-lg {
1124
+ margin-bottom: 16px;
1125
+ }
1126
+ .mt-sm {
1127
+ margin-top: 6px;
1128
+ }
1129
+ .mt-md {
1130
+ margin-top: 12px;
1131
+ }
1132
+
1133
+ .flex-between {
1134
+ display: flex;
1135
+ justify-content: space-between;
1136
+ align-items: center;
1137
+ }
1138
+
1139
+ .text-center {
1140
+ text-align: center;
1141
+ }
1142
+ .text-right {
1143
+ text-align: right;
1144
+ }
1145
+
1146
+ .hidden {
1147
+ display: none !important;
1148
+ }
1149
+
1150
+ .flex-col {
1151
+ display: flex;
1152
+ flex-direction: column;
1153
+ }
1154
+
1155
+ .flex-row {
1156
+ display: flex;
1157
+ flex-direction: row;
1158
+ align-items: center;
1159
+ }
1160
+
1161
+ .flex-wrap {
1162
+ flex-wrap: wrap;
1163
+ }
1164
+ .flex-1 {
1165
+ flex: 1;
1166
+ }
1167
+
1168
+ /* ─── Status Dot ─── */
1169
+ .status-dot {
1170
+ display: inline-block;
1171
+ width: 8px;
1172
+ height: 8px;
1173
+ border-radius: 50%;
1174
+ margin-right: 6px;
1175
+ flex-shrink: 0;
1176
+ vertical-align: middle;
1177
+ }
1178
+
1179
+ /* ─── Agent Slot Grid ─── */
1180
+ .slot-grid {
1181
+ display: grid;
1182
+ grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
1183
+ gap: 8px;
1184
+ }
1185
+
1186
+ .slot-cell {
1187
+ display: flex;
1188
+ flex-direction: column;
1189
+ align-items: center;
1190
+ justify-content: center;
1191
+ gap: 4px;
1192
+ padding: 10px 4px;
1193
+ border-radius: var(--radius-md);
1194
+ border: 1px solid var(--border);
1195
+ cursor: default;
1196
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
1197
+ background: var(--bg-card);
1198
+ position: relative;
1199
+ }
1200
+
1201
+ .slot-cell[onClick] {
1202
+ cursor: pointer;
1203
+ }
1204
+
1205
+ .slot-cell:active {
1206
+ transform: scale(0.95);
1207
+ }
1208
+
1209
+ .slot-label {
1210
+ font-size: 11px;
1211
+ font-weight: 600;
1212
+ color: var(--text-secondary);
1213
+ }
1214
+
1215
+ .slot-idle {
1216
+ background: var(--bg-card);
1217
+ border-color: var(--border);
1218
+ opacity: 0.6;
1219
+ }
1220
+
1221
+ .slot-busy,
1222
+ .slot-running {
1223
+ background: rgba(88, 166, 255, 0.12);
1224
+ border-color: rgba(88, 166, 255, 0.4);
1225
+ animation: glowPulse 2s ease-in-out infinite;
1226
+ }
1227
+
1228
+ .slot-error {
1229
+ background: rgba(248, 81, 73, 0.12);
1230
+ border-color: rgba(248, 81, 73, 0.4);
1231
+ }
1232
+
1233
+ .slot-done {
1234
+ background: rgba(46, 160, 67, 0.12);
1235
+ border-color: rgba(46, 160, 67, 0.4);
1236
+ }
1237
+
1238
+ @keyframes slot-pulse {
1239
+ 0%, 100% { opacity: 1; }
1240
+ 50% { opacity: 0.7; }
1241
+ }
1242
+
1243
+ /* ─── Agent Progress Bar ─── */
1244
+ .agent-progress-bar {
1245
+ height: 4px;
1246
+ background: #21262d;
1247
+ border-radius: var(--radius-full);
1248
+ overflow: hidden;
1249
+ }
1250
+
1251
+ .agent-progress-bar-fill {
1252
+ height: 100%;
1253
+ background: var(--gradient-progress, linear-gradient(90deg, #6366f1, #818cf8));
1254
+ border-radius: var(--radius-full);
1255
+ width: 100%;
1256
+ }
1257
+
1258
+ .agent-progress-pulse {
1259
+ animation: agent-progress-indeterminate 1.5s ease-in-out infinite;
1260
+ }
1261
+
1262
+ @keyframes agent-progress-indeterminate {
1263
+ 0% { transform: translateX(-100%); }
1264
+ 100% { transform: translateX(100%); }
1265
+ }
1266
+
1267
+ /* ─── Agent Duration Indicator ─── */
1268
+ .agent-duration {
1269
+ font-size: 11px;
1270
+ color: var(--text-hint);
1271
+ font-variant-numeric: tabular-nums;
1272
+ }
1273
+
1274
+ /* ─── Workspace Viewer ─── */
1275
+ .workspace-viewer {
1276
+ background: var(--bg-card);
1277
+ border-radius: var(--radius-lg, 12px);
1278
+ overflow: hidden;
1279
+ border: 1px solid var(--border);
1280
+ }
1281
+
1282
+ .workspace-log {
1283
+ background: var(--bg-primary);
1284
+ color: var(--text-primary);
1285
+ font-family: "IBM Plex Mono", "JetBrains Mono", "Fira Code", monospace;
1286
+ font-size: 12px;
1287
+ line-height: 1.5;
1288
+ padding: 12px;
1289
+ max-height: 400px;
1290
+ overflow-y: auto;
1291
+ white-space: pre-wrap;
1292
+ word-break: break-all;
1293
+ box-shadow: inset 0 0 20px rgba(1, 4, 9, 0.4);
1294
+ }
1295
+
1296
+ .workspace-header {
1297
+ padding: 12px 16px;
1298
+ display: flex;
1299
+ align-items: center;
1300
+ justify-content: space-between;
1301
+ border-bottom: 1px solid var(--border);
1302
+ }
1303
+
1304
+ .workspace-controls {
1305
+ display: flex;
1306
+ gap: 8px;
1307
+ padding: 12px;
1308
+ border-top: 1px solid var(--border);
1309
+ }
1310
+
1311
+ .workspace-controls .input {
1312
+ flex: 1;
1313
+ }
1314
+
1315
+ .workspace-tabs {
1316
+ margin: 12px 16px 0;
1317
+ }
1318
+
1319
+ .workspace-context .card {
1320
+ background: var(--bg-card);
1321
+ border: 1px solid var(--border);
1322
+ }
1323
+
1324
+ .workspace-diff {
1325
+ font-size: 11px;
1326
+ margin: 8px 0 0;
1327
+ white-space: pre-wrap;
1328
+ color: var(--text-secondary);
1329
+ overflow-x: auto;
1330
+ }
1331
+
1332
+ .mono {
1333
+ font-family: "IBM Plex Mono", "JetBrains Mono", "Fira Code", monospace;
1334
+ font-size: 12px;
1335
+ }
1336
+
1337
+ .branch-row {
1338
+ width: 100%;
1339
+ text-align: left;
1340
+ background: var(--bg-card);
1341
+ border: 1px solid var(--border);
1342
+ border-radius: var(--radius-sm);
1343
+ padding: 8px 10px;
1344
+ margin-bottom: 6px;
1345
+ display: flex;
1346
+ flex-direction: column;
1347
+ gap: 4px;
1348
+ cursor: pointer;
1349
+ color: var(--text-primary);
1350
+ font: inherit;
1351
+ outline: none;
1352
+ transition: background var(--transition-fast), border-color var(--transition-fast);
1353
+ }
1354
+
1355
+ .branch-row:hover {
1356
+ background: var(--bg-card-hover);
1357
+ border-color: var(--border-strong);
1358
+ }
1359
+
1360
+ .branch-name {
1361
+ font-weight: 600;
1362
+ font-size: 13px;
1363
+ }
1364
+
1365
+ .branch-raw {
1366
+ font-size: 11px;
1367
+ color: var(--text-hint);
1368
+ }
1369
+
1370
+ /* ─── Dispatch Card ─── */
1371
+ .dispatch-section {
1372
+ display: flex;
1373
+ flex-direction: column;
1374
+ gap: 8px;
1375
+ }
1376
+
1377
+ .dispatch-section .input-row {
1378
+ margin-bottom: 0;
1379
+ }
1380
+
1381
+ /* ─── Responsive ─── */
1382
+ @media (max-width: 380px) {
1383
+ .stats-grid {
1384
+ grid-template-columns: repeat(2, 1fr);
1385
+ gap: 6px;
1386
+ }
1387
+
1388
+ .stat-value {
1389
+ font-size: 20px;
1390
+ }
1391
+ }
1392
+
1393
+ @media (min-width: 600px) {
1394
+ .stats-grid {
1395
+ grid-template-columns: repeat(4, 1fr);
1396
+ }
1397
+
1398
+ .modal-content {
1399
+ border-radius: var(--radius-xl);
1400
+ margin-bottom: 24px;
1401
+ }
1402
+
1403
+ .modal-overlay {
1404
+ align-items: center;
1405
+ }
1406
+ }
1407
+
1408
+ @media (min-width: 768px) {
1409
+ .card {
1410
+ padding: 20px;
1411
+ margin-bottom: 16px;
1412
+ }
1413
+
1414
+ .stat-card {
1415
+ padding: 18px 16px;
1416
+ }
1417
+
1418
+ .stats-grid {
1419
+ gap: 12px;
1420
+ margin-bottom: 16px;
1421
+ }
1422
+
1423
+ .task-card {
1424
+ padding: 18px;
1425
+ margin-bottom: 12px;
1426
+ }
1427
+
1428
+ .list-item {
1429
+ padding: 14px 0;
1430
+ }
1431
+
1432
+ .empty-state {
1433
+ padding: 60px 24px;
1434
+ }
1435
+
1436
+ .modal-content {
1437
+ max-width: 600px;
1438
+ }
1439
+
1440
+ .chip {
1441
+ padding: 8px 16px;
1442
+ font-size: 13px;
1443
+ }
1444
+
1445
+ .search-input-wrap {
1446
+ max-width: 480px;
1447
+ }
1448
+
1449
+ .slot-grid {
1450
+ grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
1451
+ gap: 10px;
1452
+ }
1453
+
1454
+ .quick-actions-grid {
1455
+ grid-template-columns: repeat(6, 1fr);
1456
+ }
1457
+ }
1458
+
1459
+ /* ─── Quick Action Buttons ─── */
1460
+ .quick-action-btn {
1461
+ display: flex;
1462
+ flex-direction: column;
1463
+ align-items: center;
1464
+ justify-content: center;
1465
+ gap: var(--space-xs, 4px);
1466
+ padding: var(--space-md, 14px) var(--space-sm, 8px);
1467
+ background: var(--glass-bg);
1468
+ backdrop-filter: blur(8px);
1469
+ -webkit-backdrop-filter: blur(8px);
1470
+ border-radius: var(--radius-md);
1471
+ border: 1px solid var(--glass-border);
1472
+ cursor: pointer;
1473
+ transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
1474
+ -webkit-tap-highlight-color: transparent;
1475
+ font-family: inherit;
1476
+ }
1477
+
1478
+ .quick-action-btn:active {
1479
+ transform: scale(0.93);
1480
+ background: var(--bg-card-hover);
1481
+ }
1482
+
1483
+ .quick-action-btn:hover {
1484
+ box-shadow: var(--shadow-glow-sm);
1485
+ border-color: var(--border-glow);
1486
+ }
1487
+
1488
+ .quick-action-btn:focus-visible {
1489
+ outline: 2px solid var(--accent);
1490
+ outline-offset: 2px;
1491
+ }
1492
+
1493
+ .quick-action-icon {
1494
+ font-size: 22px;
1495
+ line-height: 1;
1496
+ }
1497
+
1498
+ .quick-action-label {
1499
+ font-size: 11px;
1500
+ font-weight: 600;
1501
+ color: var(--text-secondary);
1502
+ white-space: nowrap;
1503
+ }
1504
+
1505
+ /* ─── Command History Dropdown ─── */
1506
+ .cmd-history-dropdown {
1507
+ position: absolute;
1508
+ top: 100%;
1509
+ left: 0;
1510
+ right: 0;
1511
+ background: var(--bg-elevated);
1512
+ backdrop-filter: blur(20px);
1513
+ -webkit-backdrop-filter: blur(20px);
1514
+ border: 1px solid var(--glass-border);
1515
+ border-radius: var(--radius-md);
1516
+ box-shadow: var(--shadow-lg), var(--shadow-glow-sm);
1517
+ z-index: 50;
1518
+ max-height: 200px;
1519
+ overflow-y: auto;
1520
+ margin-top: 4px;
1521
+ }
1522
+
1523
+ .cmd-history-item {
1524
+ display: block;
1525
+ width: 100%;
1526
+ padding: 10px 14px;
1527
+ border: none;
1528
+ background: none;
1529
+ color: var(--text-primary);
1530
+ font-size: 13px;
1531
+ font-family: 'SF Mono', 'Fira Code', monospace;
1532
+ text-align: left;
1533
+ cursor: pointer;
1534
+ transition: background var(--transition-fast);
1535
+ }
1536
+
1537
+ .cmd-history-item:hover {
1538
+ background: var(--accent-subtle);
1539
+ }
1540
+
1541
+ .cmd-history-item:not(:last-child) {
1542
+ border-bottom: 1px solid var(--glass-border);
1543
+ }
1544
+
1545
+ /* ─── Health Dot (Infra) ─── */
1546
+ .health-dot {
1547
+ display: inline-block;
1548
+ width: 8px;
1549
+ height: 8px;
1550
+ border-radius: 50%;
1551
+ flex-shrink: 0;
1552
+ vertical-align: middle;
1553
+ }
1554
+
1555
+ /* ─── Task Card States ─── */
1556
+ .task-card-selected {
1557
+ border-color: var(--accent);
1558
+ background: rgba(99, 102, 241, 0.06);
1559
+ box-shadow: var(--shadow-glow-sm);
1560
+ }
1561
+
1562
+ .task-card-expanded {
1563
+ border-color: var(--border-strong);
1564
+ }
1565
+
1566
+ .task-card-enter {
1567
+ animation: fadeSlideUp 0.2s ease;
1568
+ }
1569
+
1570
+ .task-checkbox {
1571
+ width: 18px;
1572
+ height: 18px;
1573
+ flex-shrink: 0;
1574
+ margin-right: var(--space-sm, 8px);
1575
+ cursor: pointer;
1576
+ }
1577
+
1578
+ /* ─── Batch Action Bar ─── */
1579
+ .batch-action-bar {
1580
+ background: var(--glass-bg);
1581
+ backdrop-filter: blur(12px);
1582
+ -webkit-backdrop-filter: blur(12px);
1583
+ border-radius: var(--radius-md);
1584
+ padding: var(--space-sm, 8px) var(--space-md, 12px);
1585
+ align-items: center;
1586
+ border: 1px solid var(--glass-border);
1587
+ }
1588
+
1589
+ /* ─── Sticky Search ─── */
1590
+ .sticky-search {
1591
+ position: sticky;
1592
+ top: 0;
1593
+ z-index: 20;
1594
+ background: var(--bg-primary);
1595
+ padding: 8px 0 12px;
1596
+ margin-bottom: var(--space-sm, 8px);
1597
+ border-bottom: 1px solid var(--border);
1598
+ backdrop-filter: blur(10px);
1599
+ }
1600
+
1601
+ .sticky-search-row {
1602
+ display: flex;
1603
+ align-items: center;
1604
+ gap: 8px;
1605
+ flex-wrap: wrap;
1606
+ }
1607
+
1608
+ .sticky-search-main {
1609
+ flex: 1;
1610
+ min-width: 200px;
1611
+ position: relative;
1612
+ display: flex;
1613
+ align-items: center;
1614
+ gap: 6px;
1615
+ }
1616
+
1617
+ .export-wrap {
1618
+ position: relative;
1619
+ }
1620
+
1621
+ .filter-summary {
1622
+ display: flex;
1623
+ align-items: center;
1624
+ justify-content: space-between;
1625
+ gap: 8px;
1626
+ flex-wrap: wrap;
1627
+ color: var(--text-hint);
1628
+ font-size: 11px;
1629
+ }
1630
+
1631
+ .filter-summary-text {
1632
+ display: flex;
1633
+ align-items: center;
1634
+ gap: 6px;
1635
+ flex-wrap: wrap;
1636
+ color: var(--text-secondary);
1637
+ }
1638
+
1639
+ .filter-summary-actions {
1640
+ display: flex;
1641
+ align-items: center;
1642
+ gap: 6px;
1643
+ }
1644
+
1645
+ /* ─── Sticky Controls ─── */
1646
+ .sticky-controls {
1647
+ position: sticky;
1648
+ top: calc(var(--header-height) + 8px);
1649
+ z-index: 20;
1650
+ background: var(--bg-secondary);
1651
+ padding: 8px 0 10px;
1652
+ margin-bottom: 8px;
1653
+ border-bottom: 1px solid var(--border);
1654
+ backdrop-filter: blur(10px);
1655
+ }
1656
+
1657
+ /* ─── Control Unit (sticky) ─── */
1658
+ .control-unit-card {
1659
+ position: sticky;
1660
+ top: 0;
1661
+ z-index: 18;
1662
+ background: var(--bg-card);
1663
+ }
1664
+
1665
+ .control-unit-body {
1666
+ display: flex;
1667
+ flex-direction: column;
1668
+ gap: 10px;
1669
+ }
1670
+
1671
+ .control-unit-meta {
1672
+ display: flex;
1673
+ flex-wrap: wrap;
1674
+ gap: 6px 12px;
1675
+ font-size: 12px;
1676
+ color: var(--text-secondary);
1677
+ }
1678
+
1679
+ .control-unit-meta strong {
1680
+ color: var(--text-bright);
1681
+ font-weight: 600;
1682
+ }
1683
+
1684
+ .control-unit-actions {
1685
+ display: flex;
1686
+ flex-wrap: wrap;
1687
+ gap: 8px;
1688
+ }
1689
+
1690
+ @media (min-width: 768px) {
1691
+ .control-unit-body {
1692
+ flex-direction: row;
1693
+ align-items: center;
1694
+ justify-content: space-between;
1695
+ }
1696
+ }
1697
+
1698
+ /* ─── Toggle Label ─── */
1699
+ .toggle-label {
1700
+ display: inline-flex;
1701
+ align-items: center;
1702
+ gap: var(--space-xs, 4px);
1703
+ cursor: pointer;
1704
+ user-select: none;
1705
+ white-space: nowrap;
1706
+ }
1707
+
1708
+ /* ─── Settings Row ─── */
1709
+ .settings-row {
1710
+ display: flex;
1711
+ align-items: center;
1712
+ gap: var(--space-md, 12px);
1713
+ }
1714
+
1715
+ /* ─── Log Box Small ─── */
1716
+ .log-box-sm {
1717
+ max-height: 120px;
1718
+ font-size: 10px;
1719
+ }
1720
+
1721
+ /* ─── Worktree Detail ─── */
1722
+ .wt-detail {
1723
+ padding: var(--space-sm, 8px) 0;
1724
+ }
1725
+
1726
+ /* ─── ListItem extensions ─── */
1727
+ .list-item-body {
1728
+ flex: 1;
1729
+ min-width: 0;
1730
+ }
1731
+
1732
+ .list-item-title {
1733
+ font-size: 14px;
1734
+ font-weight: 600;
1735
+ color: var(--text-primary);
1736
+ line-height: 1.4;
1737
+ }
1738
+
1739
+ .list-item-subtitle {
1740
+ font-size: 12px;
1741
+ color: var(--text-secondary);
1742
+ margin-top: 1px;
1743
+ line-height: 1.4;
1744
+ }
1745
+
1746
+ .list-item-clickable {
1747
+ cursor: pointer;
1748
+ transition: background var(--transition-fast);
1749
+ }
1750
+
1751
+ .list-item-clickable:active {
1752
+ background: var(--bg-card-hover);
1753
+ }
1754
+
1755
+ .list-item-icon {
1756
+ width: 20px;
1757
+ height: 20px;
1758
+ color: var(--text-secondary);
1759
+ flex-shrink: 0;
1760
+ }
1761
+
1762
+ /* ─── Toast extensions ─── */
1763
+ .toast-message {
1764
+ flex: 1;
1765
+ }
1766
+
1767
+ .toast-close {
1768
+ border: none;
1769
+ background: none;
1770
+ color: var(--text-hint);
1771
+ font-size: 18px;
1772
+ cursor: pointer;
1773
+ padding: 0 0 0 var(--space-sm, 8px);
1774
+ line-height: 1;
1775
+ }
1776
+
1777
+ .toast {
1778
+ display: flex;
1779
+ align-items: center;
1780
+ gap: var(--space-sm, 8px);
1781
+ }
1782
+
1783
+ /* ─── Stat trend colors ─── */
1784
+ .stat-trend.up,
1785
+ .stat-trend-up {
1786
+ color: var(--accent-success, var(--color-done));
1787
+ }
1788
+
1789
+ .stat-trend.down,
1790
+ .stat-trend-down {
1791
+ color: var(--accent-error, var(--color-error));
1792
+ }
1793
+
1794
+ /* ─── Input small variant ─── */
1795
+ .input-sm {
1796
+ min-height: 36px;
1797
+ padding: 6px 10px;
1798
+ font-size: 13px;
1799
+ }
1800
+
1801
+ /* ─── Modal swipe-to-dismiss ─── */
1802
+ .modal-content {
1803
+ transition: transform 0.3s cubic-bezier(0.2, 0, 0, 1), opacity 0.3s ease;
1804
+ will-change: transform, opacity;
1805
+ touch-action: pan-x;
1806
+ }
1807
+
1808
+ .modal-content.modal-dragging {
1809
+ transition: none;
1810
+ overflow-y: hidden;
1811
+ }
1812
+
1813
+ /* ─── ConfirmDialog ─── */
1814
+ .confirm-dialog {
1815
+ background: var(--bg-elevated);
1816
+ backdrop-filter: blur(24px);
1817
+ -webkit-backdrop-filter: blur(24px);
1818
+ border-radius: var(--radius-xl);
1819
+ border: 1px solid var(--glass-border);
1820
+ width: calc(100% - 48px);
1821
+ max-width: 340px;
1822
+ padding: 24px;
1823
+ animation: scaleIn 0.2s ease;
1824
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
1825
+ text-align: center;
1826
+ margin: auto;
1827
+ }
1828
+
1829
+ .confirm-dialog-title {
1830
+ font-size: 18px;
1831
+ font-weight: 700;
1832
+ margin-bottom: 8px;
1833
+ color: var(--text-primary);
1834
+ }
1835
+
1836
+ .confirm-dialog-message {
1837
+ font-size: 14px;
1838
+ color: var(--text-secondary);
1839
+ line-height: 1.5;
1840
+ margin-bottom: 20px;
1841
+ }
1842
+
1843
+ .confirm-dialog-actions {
1844
+ display: flex;
1845
+ gap: 10px;
1846
+ justify-content: center;
1847
+ }
1848
+
1849
+ .confirm-dialog-actions .btn {
1850
+ flex: 1;
1851
+ min-height: 40px;
1852
+ border-radius: var(--radius-md);
1853
+ font-weight: 600;
1854
+ font-size: 14px;
1855
+ cursor: pointer;
1856
+ border: none;
1857
+ }
1858
+
1859
+ .confirm-dialog-actions .btn-secondary {
1860
+ background: var(--glass-bg);
1861
+ color: var(--text-primary);
1862
+ border: 1px solid var(--glass-border);
1863
+ }
1864
+
1865
+ .confirm-dialog-actions .btn-destructive {
1866
+ background: var(--destructive);
1867
+ color: #fff;
1868
+ }
1869
+
1870
+ /* ─── Toggle disabled ─── */
1871
+ .toggle-wrap.disabled {
1872
+ opacity: 0.4;
1873
+ cursor: not-allowed;
1874
+ pointer-events: none;
1875
+ }
1876
+
1877
+ .toggle.disabled {
1878
+ opacity: 0.4;
1879
+ cursor: not-allowed;
1880
+ }
1881
+
1882
+ /* ─── SegmentedControl disabled ─── */
1883
+ .segmented-control.disabled {
1884
+ opacity: 0.4;
1885
+ pointer-events: none;
1886
+ }
1887
+
1888
+ .segmented-control.disabled .segmented-btn {
1889
+ cursor: not-allowed;
1890
+ }
1891
+
1892
+ /* ─── Stepper disabled ─── */
1893
+ .stepper.disabled {
1894
+ opacity: 0.4;
1895
+ pointer-events: none;
1896
+ }
1897
+
1898
+ .stepper.disabled .stepper-btn {
1899
+ cursor: not-allowed;
1900
+ color: var(--text-hint);
1901
+ }
1902
+
1903
+ .stepper-wrap.disabled {
1904
+ opacity: 0.4;
1905
+ }
1906
+
1907
+ /* ─── SearchInput disabled ─── */
1908
+ .search-input-wrap.disabled {
1909
+ opacity: 0.4;
1910
+ pointer-events: none;
1911
+ }
1912
+
1913
+ .search-input-wrap.disabled .search-input {
1914
+ cursor: not-allowed;
1915
+ }