@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,809 @@
1
+ /* ─── Layout: Header, Main Content, Bottom Nav, FAB — Mission Control ─── */
2
+
3
+ /* ─── Header ─── */
4
+ .app-header {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: space-between;
8
+ height: var(--header-height);
9
+ padding: 0 20px;
10
+ padding-top: var(--content-safe-top);
11
+ background: var(--bg-secondary);
12
+ border-bottom: 1px solid var(--border);
13
+ box-shadow: var(--shadow-inset);
14
+ flex-shrink: 0;
15
+ z-index: 10;
16
+ position: relative;
17
+ }
18
+
19
+ .app-header::after {
20
+ content: none;
21
+ }
22
+
23
+ .app-header-left {
24
+ display: flex;
25
+ align-items: center;
26
+ gap: 10px;
27
+ }
28
+
29
+ .app-header-titles {
30
+ display: flex;
31
+ flex-direction: column;
32
+ gap: 2px;
33
+ }
34
+
35
+ .app-header-logo {
36
+ width: 28px;
37
+ height: 28px;
38
+ border-radius: 8px;
39
+ background: var(--gradient-accent);
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ box-shadow: var(--shadow-sm);
44
+ flex-shrink: 0;
45
+ }
46
+
47
+ .app-header-logo svg {
48
+ width: 16px;
49
+ height: 16px;
50
+ color: #041016;
51
+ }
52
+
53
+ .app-header-title {
54
+ font-size: 17px;
55
+ font-weight: 700;
56
+ letter-spacing: -0.03em;
57
+ color: var(--text-bright);
58
+ }
59
+
60
+ .app-header-subtitle {
61
+ font-size: 12px;
62
+ font-weight: 500;
63
+ color: var(--text-secondary);
64
+ }
65
+
66
+ .app-header-hint {
67
+ font-size: 11px;
68
+ color: var(--text-hint);
69
+ }
70
+
71
+ .app-header-user {
72
+ font-size: 12px;
73
+ color: var(--text-secondary);
74
+ }
75
+
76
+ .header-actions {
77
+ display: flex;
78
+ align-items: center;
79
+ gap: 8px;
80
+ }
81
+
82
+ /* ─── Connection Pill ─── */
83
+ .connection-pill {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ gap: 6px;
87
+ padding: 4px 12px;
88
+ border-radius: var(--radius-full);
89
+ font-size: 11px;
90
+ font-weight: 600;
91
+ background: var(--bg-card);
92
+ border: 1px solid var(--border);
93
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
94
+ }
95
+
96
+ .connection-pill.connected {
97
+ border-color: rgba(46, 160, 67, 0.4);
98
+ color: var(--color-done);
99
+ box-shadow: 0 0 12px rgba(46, 160, 67, 0.2);
100
+ }
101
+
102
+ .connection-pill.disconnected {
103
+ border-color: rgba(248, 81, 73, 0.45);
104
+ color: var(--color-error);
105
+ }
106
+
107
+ .connection-dot {
108
+ width: 6px;
109
+ height: 6px;
110
+ border-radius: 50%;
111
+ background: currentColor;
112
+ animation: pulse-dot 2s infinite;
113
+ position: relative;
114
+ }
115
+
116
+ .connection-pill.connected .connection-dot::after {
117
+ content: "";
118
+ position: absolute;
119
+ inset: -3px;
120
+ border-radius: 50%;
121
+ border: 1.5px solid currentColor;
122
+ opacity: 0;
123
+ animation: pulseRing 2s ease-out infinite;
124
+ }
125
+
126
+ @keyframes pulseRing {
127
+ 0% { transform: scale(0.8); opacity: 0.6; }
128
+ 100% { transform: scale(2); opacity: 0; }
129
+ }
130
+
131
+ /* ─── Main Content ─── */
132
+ .main-content {
133
+ flex: 1;
134
+ min-height: 0;
135
+ overflow-y: auto;
136
+ overflow-x: hidden;
137
+ scrollbar-gutter: stable;
138
+ padding: 16px 16px 20px;
139
+ padding-bottom: calc(var(--nav-height) + var(--safe-bottom) + 20px);
140
+ -webkit-overflow-scrolling: touch;
141
+ scroll-behavior: smooth;
142
+ touch-action: pan-y;
143
+ position: relative;
144
+ z-index: 1;
145
+ }
146
+
147
+ /* ─── Tab Panel ─── */
148
+ .tab-panel {
149
+ display: none;
150
+ animation: fadeIn 0.25s ease;
151
+ }
152
+
153
+ .tab-panel.active {
154
+ display: block;
155
+ }
156
+
157
+ /* Staggered card entrance */
158
+ .main-content > * {
159
+ animation: cardReveal 0.25s cubic-bezier(0.4, 0, 0.2, 1) both;
160
+ }
161
+ .main-content > *:nth-child(1) { animation-delay: 0s; }
162
+ .main-content > *:nth-child(2) { animation-delay: 0.05s; }
163
+ .main-content > *:nth-child(3) { animation-delay: 0.1s; }
164
+ .main-content > *:nth-child(4) { animation-delay: 0.15s; }
165
+ .main-content > *:nth-child(5) { animation-delay: 0.2s; }
166
+ .main-content > *:nth-child(6) { animation-delay: 0.25s; }
167
+ .main-content > *:nth-child(7) { animation-delay: 0.3s; }
168
+ .main-content > *:nth-child(8) { animation-delay: 0.35s; }
169
+
170
+ @keyframes cardReveal {
171
+ from { opacity: 0; transform: translateY(10px); }
172
+ to { opacity: 1; transform: translateY(0); }
173
+ }
174
+
175
+ /* ─── Bottom Navigation — Floating Pill ─── */
176
+ .bottom-nav {
177
+ position: fixed;
178
+ bottom: calc(12px + var(--safe-bottom));
179
+ left: 16px;
180
+ right: 16px;
181
+ height: var(--nav-height);
182
+ background: var(--bg-secondary);
183
+ border: 1px solid var(--border);
184
+ border-radius: var(--radius-xl);
185
+ display: flex;
186
+ align-items: center;
187
+ justify-content: space-around;
188
+ z-index: 100;
189
+ box-shadow: var(--shadow-md);
190
+ animation: navSlideUp 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s both;
191
+ }
192
+
193
+ @keyframes navSlideUp {
194
+ from { opacity: 0; transform: translateY(20px); }
195
+ to { opacity: 1; transform: translateY(0); }
196
+ }
197
+
198
+ .nav-item {
199
+ display: flex;
200
+ flex-direction: column;
201
+ align-items: center;
202
+ justify-content: center;
203
+ gap: 3px;
204
+ padding: 8px 0;
205
+ min-width: 48px;
206
+ min-height: 44px;
207
+ border: none;
208
+ background: none;
209
+ color: var(--text-hint);
210
+ font-size: 10px;
211
+ font-weight: 500;
212
+ cursor: pointer;
213
+ transition: color 0.2s ease, transform 0.15s ease;
214
+ -webkit-tap-highlight-color: transparent;
215
+ position: relative;
216
+ border-radius: var(--radius-md);
217
+ }
218
+
219
+ .nav-item:active {
220
+ transform: scale(0.9);
221
+ }
222
+
223
+ .nav-item:focus-visible {
224
+ outline: 2px solid var(--accent);
225
+ outline-offset: 2px;
226
+ }
227
+
228
+ .nav-item.active {
229
+ color: var(--accent);
230
+ }
231
+
232
+ .nav-item.active::before {
233
+ content: "";
234
+ position: absolute;
235
+ inset: 4px;
236
+ border-radius: var(--radius-md);
237
+ background: rgba(88, 166, 255, 0.18);
238
+ z-index: -1;
239
+ animation: scaleIn 0.2s ease;
240
+ }
241
+
242
+ .nav-item.active svg {
243
+ transform: scale(1.05);
244
+ filter: none;
245
+ }
246
+
247
+ .nav-item svg {
248
+ width: 22px;
249
+ height: 22px;
250
+ transition: transform 0.2s ease, filter 0.2s ease;
251
+ }
252
+
253
+ .nav-label {
254
+ line-height: 1;
255
+ }
256
+
257
+ /* ─── FAB ─── */
258
+ .fab {
259
+ position: fixed;
260
+ right: 16px;
261
+ bottom: calc(var(--nav-height) + var(--safe-bottom) + 28px);
262
+ width: 52px;
263
+ height: 52px;
264
+ border-radius: var(--radius-lg);
265
+ background: var(--accent);
266
+ color: white;
267
+ border: none;
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: center;
271
+ box-shadow: var(--shadow-lg);
272
+ cursor: pointer;
273
+ z-index: 50;
274
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
275
+ }
276
+
277
+ .fab:active {
278
+ transform: scale(0.9);
279
+ }
280
+
281
+ .fab:hover {
282
+ box-shadow: var(--shadow-xl);
283
+ }
284
+
285
+ .fab svg {
286
+ width: 24px;
287
+ height: 24px;
288
+ }
289
+
290
+ .scroll-top {
291
+ position: fixed;
292
+ left: 16px;
293
+ bottom: calc(var(--nav-height) + var(--safe-bottom) + 20px);
294
+ padding: 8px 12px;
295
+ border-radius: var(--radius-full);
296
+ border: 1px solid var(--border);
297
+ background: var(--bg-secondary);
298
+ color: var(--text-bright);
299
+ font-size: 12px;
300
+ font-weight: 600;
301
+ box-shadow: var(--shadow-md);
302
+ cursor: pointer;
303
+ z-index: 60;
304
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
305
+ }
306
+
307
+ .scroll-top:active {
308
+ transform: scale(0.95);
309
+ }
310
+
311
+ .scroll-top:hover {
312
+ box-shadow: var(--shadow-lg);
313
+ }
314
+
315
+ /* ─── Responsive ─── */
316
+ @media (max-width: 380px) {
317
+ .nav-label {
318
+ font-size: 9px;
319
+ }
320
+ }
321
+
322
+ @media (max-width: 360px) {
323
+ .app-header-hint {
324
+ display: none;
325
+ }
326
+ }
327
+
328
+ @media (min-width: 768px) {
329
+ .main-content {
330
+ max-width: 960px;
331
+ width: 100%;
332
+ margin-left: auto;
333
+ margin-right: auto;
334
+ padding: 24px;
335
+ padding-bottom: calc(var(--nav-height) + var(--safe-bottom) + 24px);
336
+ }
337
+
338
+ .app-header {
339
+ height: 60px;
340
+ }
341
+
342
+ .bottom-nav {
343
+ left: 50%;
344
+ right: auto;
345
+ width: 480px;
346
+ transform: translateX(-50%);
347
+ animation: navSlideUpDesktop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s both;
348
+ }
349
+
350
+ @keyframes navSlideUpDesktop {
351
+ from { opacity: 0; transform: translateX(-50%) translateY(20px); }
352
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
353
+ }
354
+
355
+ .nav-item {
356
+ min-width: 64px;
357
+ gap: 4px;
358
+ }
359
+
360
+ .nav-label {
361
+ font-size: 11px;
362
+ font-weight: 600;
363
+ }
364
+ }
365
+
366
+ /* ─── Desktop Shell: Sidebar + Session Rail ─── */
367
+ .app-shell {
368
+ min-height: 100%;
369
+ display: flex;
370
+ flex-direction: column;
371
+ position: relative;
372
+ z-index: 1;
373
+ }
374
+
375
+ .app-main {
376
+ display: flex;
377
+ flex-direction: column;
378
+ min-height: 0;
379
+ flex: 1;
380
+ }
381
+
382
+ .main-panel {
383
+ display: flex;
384
+ flex-direction: column;
385
+ min-height: 0;
386
+ flex: 1;
387
+ background: var(--gradient-surface);
388
+ border: 1px solid var(--border);
389
+ border-radius: var(--radius-xl);
390
+ box-shadow: var(--shadow-lg);
391
+ overflow: hidden;
392
+ }
393
+
394
+ .sidebar,
395
+ .session-rail {
396
+ display: none;
397
+ }
398
+
399
+ .inspector {
400
+ display: none;
401
+ }
402
+
403
+ @media (min-width: 1200px) {
404
+ body {
405
+ overflow: hidden;
406
+ }
407
+
408
+ .app-shell {
409
+ display: grid;
410
+ grid-template-columns: var(--sidebar-width) var(--rail-width) minmax(0, 1fr);
411
+ grid-template-rows: 1fr;
412
+ grid-template-areas: "sidebar rail main";
413
+ gap: var(--shell-gap);
414
+ padding: var(--shell-gap);
415
+ height: var(--viewport-stable-height);
416
+ }
417
+
418
+ .app-shell[data-has-rail="false"] {
419
+ grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
420
+ grid-template-areas: "sidebar main";
421
+ }
422
+
423
+ .app-shell[data-has-inspector="true"] {
424
+ grid-template-columns: var(--sidebar-width) var(--rail-width) minmax(0, 1fr) var(--inspector-width);
425
+ grid-template-areas: "sidebar rail main inspector";
426
+ }
427
+
428
+ .app-shell[data-has-rail="false"][data-has-inspector="true"] {
429
+ grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--inspector-width);
430
+ grid-template-areas: "sidebar main inspector";
431
+ }
432
+
433
+ .sidebar {
434
+ display: flex;
435
+ flex-direction: column;
436
+ grid-area: sidebar;
437
+ background: var(--bg-secondary);
438
+ border: 1px solid var(--border);
439
+ border-radius: var(--radius-lg);
440
+ padding: 16px 12px;
441
+ gap: 16px;
442
+ box-shadow: var(--shadow-md);
443
+ }
444
+
445
+ .session-rail {
446
+ display: flex;
447
+ flex-direction: column;
448
+ grid-area: rail;
449
+ background: var(--bg-secondary);
450
+ border: 1px solid var(--border);
451
+ border-radius: var(--radius-lg);
452
+ padding: 12px;
453
+ min-height: 0;
454
+ box-shadow: var(--shadow-md);
455
+ }
456
+
457
+ .app-main {
458
+ grid-area: main;
459
+ min-height: 0;
460
+ border-radius: var(--radius-lg);
461
+ overflow: hidden;
462
+ }
463
+
464
+ .inspector {
465
+ display: flex;
466
+ flex-direction: column;
467
+ grid-area: inspector;
468
+ background: var(--bg-secondary);
469
+ border: 1px solid var(--border);
470
+ border-radius: var(--radius-lg);
471
+ padding: 12px;
472
+ gap: 12px;
473
+ min-height: 0;
474
+ box-shadow: var(--shadow-md);
475
+ }
476
+
477
+ .app-header {
478
+ border-radius: var(--radius-lg);
479
+ border: 1px solid var(--border);
480
+ margin-bottom: var(--space-md);
481
+ position: sticky;
482
+ top: 0;
483
+ backdrop-filter: blur(12px);
484
+ z-index: 5;
485
+ }
486
+
487
+ .main-content {
488
+ padding: 20px 24px 32px;
489
+ padding-bottom: 32px;
490
+ max-width: var(--content-max);
491
+ margin: 0 auto;
492
+ }
493
+
494
+ .bottom-nav {
495
+ display: none;
496
+ }
497
+
498
+ .scroll-top {
499
+ left: auto;
500
+ right: 32px;
501
+ bottom: 32px;
502
+ }
503
+ }
504
+
505
+ /* ─── Sidebar styling ─── */
506
+ .sidebar-brand {
507
+ display: flex;
508
+ align-items: center;
509
+ gap: 10px;
510
+ }
511
+
512
+ .sidebar-logo {
513
+ width: 40px;
514
+ height: 40px;
515
+ border-radius: 14px;
516
+ background: var(--gradient-accent);
517
+ display: flex;
518
+ align-items: center;
519
+ justify-content: center;
520
+ color: #041016;
521
+ box-shadow: var(--shadow-glow-sm);
522
+ }
523
+
524
+ .sidebar-logo svg {
525
+ width: 20px;
526
+ height: 20px;
527
+ }
528
+
529
+ .sidebar-title {
530
+ font-size: 14px;
531
+ font-weight: 700;
532
+ color: var(--text-bright);
533
+ }
534
+
535
+ .sidebar-subtitle {
536
+ font-size: 11px;
537
+ color: var(--text-secondary);
538
+ }
539
+
540
+ .sidebar-actions {
541
+ display: flex;
542
+ flex-direction: column;
543
+ gap: 8px;
544
+ }
545
+
546
+ .sidebar-nav {
547
+ display: flex;
548
+ flex-direction: column;
549
+ gap: 6px;
550
+ flex: 1;
551
+ }
552
+
553
+ .sidebar-nav-item {
554
+ display: flex;
555
+ flex-direction: column;
556
+ align-items: center;
557
+ justify-content: center;
558
+ gap: 4px;
559
+ padding: 10px 6px;
560
+ border-radius: 14px;
561
+ background: transparent;
562
+ border: none;
563
+ color: var(--text-hint);
564
+ font-size: 10px;
565
+ font-weight: 600;
566
+ cursor: pointer;
567
+ transition: background var(--transition-fast), color var(--transition-fast), transform 0.2s ease;
568
+ }
569
+
570
+ .sidebar-nav-item svg {
571
+ width: 20px;
572
+ height: 20px;
573
+ }
574
+
575
+ .sidebar-nav-item span {
576
+ font-size: 10px;
577
+ letter-spacing: 0.02em;
578
+ }
579
+
580
+ .sidebar-nav-item:hover {
581
+ background: rgba(76, 201, 240, 0.12);
582
+ color: var(--text-bright);
583
+ }
584
+
585
+ .sidebar-nav-item:focus-visible {
586
+ outline: 2px solid var(--accent);
587
+ outline-offset: 2px;
588
+ }
589
+
590
+ .sidebar-nav-item.active {
591
+ background: rgba(76, 201, 240, 0.2);
592
+ color: var(--accent);
593
+ box-shadow: inset 0 0 0 1px rgba(76, 201, 240, 0.35);
594
+ }
595
+
596
+ .sidebar-footer {
597
+ border-top: 1px solid var(--border);
598
+ padding-top: 12px;
599
+ font-size: 11px;
600
+ color: var(--text-secondary);
601
+ display: flex;
602
+ flex-direction: column;
603
+ gap: 6px;
604
+ }
605
+
606
+ .sidebar-status {
607
+ display: inline-flex;
608
+ align-items: center;
609
+ gap: 6px;
610
+ }
611
+
612
+ .sidebar-status-dot {
613
+ width: 8px;
614
+ height: 8px;
615
+ border-radius: 50%;
616
+ background: var(--color-error);
617
+ box-shadow: 0 0 10px rgba(248, 113, 113, 0.4);
618
+ }
619
+
620
+ .sidebar-status.online .sidebar-status-dot {
621
+ background: var(--color-done);
622
+ box-shadow: 0 0 10px rgba(52, 211, 153, 0.4);
623
+ }
624
+
625
+ .sidebar-user {
626
+ font-size: 10px;
627
+ color: var(--text-hint);
628
+ }
629
+
630
+ /* ─── Session rail tweaks ─── */
631
+ .session-rail .session-list {
632
+ background: transparent;
633
+ border: none;
634
+ box-shadow: none;
635
+ flex: 1;
636
+ min-height: 0;
637
+ }
638
+
639
+ .session-rail .session-list-header {
640
+ padding: 8px 4px 12px;
641
+ border-bottom: 1px solid var(--border);
642
+ }
643
+
644
+ .session-rail .session-search {
645
+ padding: 8px 4px 10px;
646
+ }
647
+
648
+ .session-rail .session-list-scroll {
649
+ max-height: none;
650
+ }
651
+
652
+ .rail-header {
653
+ display: flex;
654
+ align-items: baseline;
655
+ justify-content: space-between;
656
+ gap: 8px;
657
+ padding: 4px 2px 10px;
658
+ border-bottom: 1px solid var(--border);
659
+ margin-bottom: 8px;
660
+ }
661
+
662
+ .rail-title {
663
+ font-size: 13px;
664
+ font-weight: 600;
665
+ color: var(--text-bright);
666
+ }
667
+
668
+ .rail-meta {
669
+ font-size: 11px;
670
+ color: var(--text-hint);
671
+ }
672
+
673
+ /* ─── Inspector styling ─── */
674
+ .inspector-section {
675
+ background: var(--glass-bg);
676
+ border: 1px solid var(--glass-border);
677
+ border-radius: var(--radius-lg);
678
+ padding: 12px;
679
+ display: flex;
680
+ flex-direction: column;
681
+ gap: 8px;
682
+ min-height: 0;
683
+ }
684
+
685
+ .inspector-title {
686
+ font-size: 12px;
687
+ font-weight: 600;
688
+ text-transform: uppercase;
689
+ letter-spacing: 0.08em;
690
+ color: var(--text-hint);
691
+ }
692
+
693
+ .inspector-kv {
694
+ display: flex;
695
+ justify-content: space-between;
696
+ gap: 8px;
697
+ font-size: 12px;
698
+ color: var(--text-secondary);
699
+ }
700
+
701
+ .inspector-kv strong {
702
+ color: var(--text-bright);
703
+ font-weight: 600;
704
+ }
705
+
706
+ .inspector-empty {
707
+ padding: 16px 0;
708
+ text-align: center;
709
+ color: var(--text-secondary);
710
+ font-size: 12px;
711
+ }
712
+
713
+ .inspector-scroll {
714
+ overflow-y: auto;
715
+ min-height: 120px;
716
+ max-height: 320px;
717
+ }
718
+
719
+ @media (min-width: 1200px) {
720
+ .app-shell[data-has-rail="true"] .main-content {
721
+ max-width: none;
722
+ }
723
+ }
724
+
725
+ .inspector-log-line {
726
+ font-family: var(--font-mono);
727
+ font-size: 11px;
728
+ line-height: 1.4;
729
+ padding: 6px 8px;
730
+ border-radius: 10px;
731
+ background: rgba(15, 23, 42, 0.35);
732
+ border: 1px solid rgba(148, 163, 184, 0.18);
733
+ color: var(--text-secondary);
734
+ margin-bottom: 6px;
735
+ word-break: break-word;
736
+ }
737
+
738
+ .inspector-log-line.warn {
739
+ border-color: rgba(245, 158, 11, 0.35);
740
+ color: rgba(245, 158, 11, 0.95);
741
+ background: rgba(245, 158, 11, 0.1);
742
+ }
743
+
744
+ .inspector-log-line.error {
745
+ border-color: rgba(248, 113, 113, 0.4);
746
+ color: rgba(248, 113, 113, 0.95);
747
+ background: rgba(248, 113, 113, 0.12);
748
+ }
749
+
750
+ body.is-resizing,
751
+ body.is-resizing * {
752
+ cursor: col-resize !important;
753
+ user-select: none;
754
+ }
755
+
756
+ @media (min-width: 1200px) {
757
+ .session-rail,
758
+ .inspector {
759
+ position: relative;
760
+ }
761
+
762
+ .rail-resizer,
763
+ .inspector-resizer {
764
+ position: absolute;
765
+ top: 12px;
766
+ bottom: 12px;
767
+ width: 14px;
768
+ z-index: 20;
769
+ cursor: col-resize;
770
+ }
771
+
772
+ .rail-resizer {
773
+ right: -7px;
774
+ }
775
+
776
+ .inspector-resizer {
777
+ left: -7px;
778
+ }
779
+
780
+ .rail-resizer::after,
781
+ .inspector-resizer::after {
782
+ content: "";
783
+ position: absolute;
784
+ top: 0;
785
+ bottom: 0;
786
+ width: 2px;
787
+ left: 6px;
788
+ background: rgba(148, 163, 184, 0.35);
789
+ opacity: 0;
790
+ transition: opacity var(--transition-fast), background var(--transition-fast);
791
+ }
792
+
793
+ .session-rail:hover .rail-resizer::after,
794
+ .inspector:hover .inspector-resizer::after {
795
+ opacity: 1;
796
+ }
797
+
798
+ .rail-resizer:hover::after,
799
+ .inspector-resizer:hover::after {
800
+ background: rgba(76, 201, 240, 0.7);
801
+ }
802
+ }
803
+
804
+ @media (min-width: 1200px) {
805
+ .inspector .diff-viewer {
806
+ max-height: 260px;
807
+ overflow-y: auto;
808
+ }
809
+ }