reasonix 0.11.3 → 0.12.8

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.
@@ -0,0 +1,2346 @@
1
+ /*
2
+ * Reasonix dashboard styles. Hand-rolled, no Tailwind — colors line
3
+ * up with src/cli/ui/theme.ts so the web surface reads as the same
4
+ * product as the TUI:
5
+ *
6
+ * gradient (brand wordmark, accent rules) — teal → fuchsia
7
+ * primary cyan → focus / link / accent text
8
+ * accent violet → hover / pill backgrounds
9
+ * slate scale → backgrounds, borders, dim text
10
+ *
11
+ * Variables live in `:root` so future themes (light mode, alt brand)
12
+ * can swap them without touching component selectors.
13
+ */
14
+
15
+ :root {
16
+ /* Brand gradient — lifted verbatim from theme.ts GRADIENT[]. */
17
+ --grad-1: #5eead4; /* teal */
18
+ --grad-2: #67e8f9; /* cyan */
19
+ --grad-3: #7dd3fc; /* sky */
20
+ --grad-4: #93c5fd; /* blue */
21
+ --grad-5: #a5b4fc; /* indigo */
22
+ --grad-6: #c4b5fd; /* violet */
23
+ --grad-7: #d8b4fe; /* purple */
24
+ --grad-8: #f0abfc; /* fuchsia */
25
+
26
+ /* Semantic palette mirrors COLOR{} from theme.ts. */
27
+ --primary: #67e8f9;
28
+ --accent: #c4b5fd;
29
+ --brand: #5eead4;
30
+
31
+ --user: #67e8f9;
32
+ --assistant: #86efac;
33
+ --tool: #fcd34d;
34
+ --tool-err: #fda4af;
35
+ --info: #94a3b8;
36
+ --warn: #fbbf24;
37
+ --err: #f87171;
38
+ --ok: #4ade80;
39
+
40
+ /* Surfaces — terminal-dark background with subtle slate steps. */
41
+ --bg-0: #0a0e14;
42
+ --bg-1: #11161e;
43
+ --bg-2: #161c26;
44
+ --bg-3: #1f2733;
45
+ --bg-hover: rgba(103, 232, 249, 0.08);
46
+
47
+ --fg-0: #e2e8f0; /* slate-200 — body text */
48
+ --fg-1: #cbd5e1; /* slate-300 — primary text */
49
+ --fg-2: #94a3b8; /* slate-400 — secondary */
50
+ --fg-3: #64748b; /* slate-500 — dim */
51
+
52
+ --border: #1e2733;
53
+ --border-focus: var(--primary);
54
+
55
+ --gradient-rule: linear-gradient(
56
+ 90deg,
57
+ var(--grad-1),
58
+ var(--grad-2),
59
+ var(--grad-3),
60
+ var(--grad-4),
61
+ var(--grad-5),
62
+ var(--grad-6),
63
+ var(--grad-7),
64
+ var(--grad-8)
65
+ );
66
+
67
+ --mono: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;
68
+ --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
69
+
70
+ --radius-sm: 4px;
71
+ --radius-md: 6px;
72
+ --radius-lg: 10px;
73
+ }
74
+
75
+ * {
76
+ box-sizing: border-box;
77
+ }
78
+
79
+ html,
80
+ body {
81
+ margin: 0;
82
+ padding: 0;
83
+ background: var(--bg-0);
84
+ color: var(--fg-0);
85
+ font-family: var(--sans);
86
+ font-size: 14px;
87
+ line-height: 1.5;
88
+ height: 100%;
89
+ }
90
+
91
+ /* ---------- Animations ----------
92
+ *
93
+ * Conservative, opacity-led — no horizontal slides because messages
94
+ * land in a scrolling container and any non-y motion fights the
95
+ * auto-scroll. `prefers-reduced-motion` users get instant transitions.
96
+ */
97
+ @keyframes fade-in {
98
+ from {
99
+ opacity: 0;
100
+ transform: translateY(4px);
101
+ }
102
+ to {
103
+ opacity: 1;
104
+ transform: translateY(0);
105
+ }
106
+ }
107
+ @keyframes modal-slide-in {
108
+ from {
109
+ opacity: 0;
110
+ transform: translateY(8px);
111
+ }
112
+ to {
113
+ opacity: 1;
114
+ transform: translateY(0);
115
+ }
116
+ }
117
+ @keyframes toast-slide-in {
118
+ from {
119
+ opacity: 0;
120
+ transform: translateX(20px);
121
+ }
122
+ to {
123
+ opacity: 1;
124
+ transform: translateX(0);
125
+ }
126
+ }
127
+ .chat-msg {
128
+ animation: fade-in 0.18s ease-out;
129
+ }
130
+ .modal-card {
131
+ animation: modal-slide-in 0.20s ease-out;
132
+ }
133
+ @media (prefers-reduced-motion: reduce) {
134
+ .chat-msg,
135
+ .modal-card {
136
+ animation: none;
137
+ }
138
+ }
139
+
140
+ /* ---------- Custom scrollbars ----------
141
+ *
142
+ * Default OS scrollbars look out of place against the dark TUI palette.
143
+ * WebKit (Chrome / Edge / Safari) gets the `::-webkit-scrollbar` route;
144
+ * Firefox uses `scrollbar-color` / `scrollbar-width`. Both render a thin
145
+ * slate thumb on the bg-0 background, with the accent violet on hover.
146
+ */
147
+ *::-webkit-scrollbar {
148
+ width: 10px;
149
+ height: 10px;
150
+ }
151
+ *::-webkit-scrollbar-track {
152
+ background: var(--bg-0);
153
+ }
154
+ *::-webkit-scrollbar-thumb {
155
+ background: var(--bg-3);
156
+ border-radius: 5px;
157
+ /* Border carves the thumb a hair thinner so it doesn't crowd the
158
+ * track; uses bg-0 so it visually merges with the background. */
159
+ border: 2px solid var(--bg-0);
160
+ }
161
+ *::-webkit-scrollbar-thumb:hover {
162
+ background: var(--accent);
163
+ }
164
+ *::-webkit-scrollbar-corner {
165
+ background: var(--bg-0);
166
+ }
167
+ * {
168
+ scrollbar-color: var(--bg-3) var(--bg-0);
169
+ scrollbar-width: thin;
170
+ }
171
+
172
+ #root {
173
+ display: flex;
174
+ height: 100vh;
175
+ }
176
+
177
+ .boot {
178
+ margin: auto;
179
+ color: var(--fg-3);
180
+ font-family: var(--mono);
181
+ }
182
+
183
+ /* ---------- Layout: sidebar + main ---------- */
184
+
185
+ .sidebar {
186
+ width: 220px;
187
+ flex-shrink: 0;
188
+ background: var(--bg-1);
189
+ border-right: 1px solid var(--border);
190
+ display: flex;
191
+ flex-direction: column;
192
+ transition: width 0.18s ease-out;
193
+ }
194
+ .sidebar.collapsed {
195
+ width: 52px;
196
+ }
197
+ .sidebar.collapsed .sidebar-label {
198
+ display: none;
199
+ }
200
+ .sidebar.collapsed .sidebar-header {
201
+ padding: 14px 8px 10px;
202
+ text-align: center;
203
+ }
204
+ .sidebar.collapsed .sidebar-brand {
205
+ font-size: 0;
206
+ }
207
+ .sidebar.collapsed .sidebar-brand .glyph {
208
+ font-size: 18px;
209
+ margin: 0;
210
+ }
211
+ .sidebar.collapsed .tab {
212
+ padding: 9px 0;
213
+ justify-content: center;
214
+ border-left: 2px solid transparent;
215
+ }
216
+ .sidebar.collapsed .tab.active {
217
+ border-left-color: var(--primary);
218
+ }
219
+ .sidebar.collapsed .tab .glyph {
220
+ width: auto;
221
+ font-size: 14px;
222
+ }
223
+ .sidebar.collapsed .sidebar-collapse-toggle {
224
+ padding: 8px 0;
225
+ justify-content: center;
226
+ }
227
+ .sidebar.collapsed .sidebar-footer {
228
+ display: none;
229
+ }
230
+
231
+ .sidebar-collapse-toggle {
232
+ display: flex;
233
+ align-items: center;
234
+ gap: 8px;
235
+ background: transparent;
236
+ border: none;
237
+ border-top: 1px solid var(--border);
238
+ padding: 8px 20px;
239
+ font-family: var(--mono);
240
+ font-size: 11px;
241
+ color: var(--fg-3);
242
+ cursor: pointer;
243
+ width: 100%;
244
+ text-align: left;
245
+ }
246
+ .sidebar-collapse-toggle:hover {
247
+ background: var(--bg-hover);
248
+ color: var(--primary);
249
+ }
250
+
251
+ .sidebar-header {
252
+ padding: 18px 20px 14px;
253
+ border-bottom: 1px solid var(--border);
254
+ }
255
+
256
+ .sidebar-brand {
257
+ font-family: var(--mono);
258
+ font-size: 13px;
259
+ letter-spacing: 0.08em;
260
+ color: var(--fg-2);
261
+ }
262
+
263
+ .sidebar-brand .glyph {
264
+ background: var(--gradient-rule);
265
+ background-clip: text;
266
+ -webkit-background-clip: text;
267
+ color: transparent;
268
+ font-size: 16px;
269
+ font-weight: 700;
270
+ margin-right: 6px;
271
+ }
272
+
273
+ .sidebar-version {
274
+ margin-top: 4px;
275
+ font-size: 11px;
276
+ color: var(--fg-3);
277
+ font-family: var(--mono);
278
+ }
279
+
280
+ .sidebar-mode {
281
+ display: inline-block;
282
+ margin-top: 6px;
283
+ padding: 1px 6px;
284
+ font-size: 10px;
285
+ letter-spacing: 0.06em;
286
+ text-transform: uppercase;
287
+ border-radius: var(--radius-sm);
288
+ background: var(--bg-3);
289
+ color: var(--accent);
290
+ }
291
+
292
+ .sidebar-tabs {
293
+ flex: 1;
294
+ overflow-y: auto;
295
+ padding: 8px 0;
296
+ }
297
+
298
+ .tab {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 10px;
302
+ padding: 8px 20px;
303
+ cursor: pointer;
304
+ color: var(--fg-2);
305
+ font-size: 13px;
306
+ border-left: 2px solid transparent;
307
+ user-select: none;
308
+ }
309
+
310
+ .tab:hover {
311
+ background: var(--bg-hover);
312
+ color: var(--fg-0);
313
+ }
314
+
315
+ .tab.active {
316
+ background: var(--bg-2);
317
+ color: var(--primary);
318
+ border-left-color: var(--primary);
319
+ }
320
+
321
+ .tab-stub {
322
+ opacity: 0.45;
323
+ cursor: not-allowed;
324
+ }
325
+
326
+ .tab-stub:hover {
327
+ background: transparent;
328
+ color: var(--fg-2);
329
+ }
330
+
331
+ .tab .glyph {
332
+ width: 16px;
333
+ font-family: var(--mono);
334
+ text-align: center;
335
+ }
336
+
337
+ .tab .badge {
338
+ margin-left: auto;
339
+ font-size: 10px;
340
+ background: var(--bg-3);
341
+ color: var(--fg-3);
342
+ padding: 1px 6px;
343
+ border-radius: var(--radius-sm);
344
+ }
345
+
346
+ .sidebar-footer {
347
+ padding: 12px 20px;
348
+ font-size: 11px;
349
+ color: var(--fg-3);
350
+ border-top: 1px solid var(--border);
351
+ font-family: var(--mono);
352
+ }
353
+
354
+ .gradient-rule {
355
+ height: 2px;
356
+ background: var(--gradient-rule);
357
+ margin: 0;
358
+ }
359
+
360
+ /* Hamburger that flips the mobile sidebar drawer. Pinned top-left of
361
+ * the main panel; hidden on desktop (sidebar is always visible there). */
362
+ .menu-toggle {
363
+ display: none;
364
+ position: absolute;
365
+ top: 14px;
366
+ left: 14px;
367
+ z-index: 10;
368
+ background: var(--bg-2);
369
+ border: 1px solid var(--border);
370
+ color: var(--fg-1);
371
+ padding: 4px 10px;
372
+ font-family: var(--mono);
373
+ font-size: 16px;
374
+ border-radius: var(--radius-sm);
375
+ cursor: pointer;
376
+ }
377
+ .menu-toggle:hover {
378
+ border-color: var(--primary);
379
+ color: var(--primary);
380
+ }
381
+
382
+ .sidebar-backdrop {
383
+ display: none;
384
+ position: fixed;
385
+ inset: 0;
386
+ background: rgba(10, 14, 20, 0.6);
387
+ z-index: 5;
388
+ }
389
+
390
+ @media (max-width: 800px) {
391
+ .menu-toggle {
392
+ display: block;
393
+ }
394
+ .sidebar {
395
+ position: fixed;
396
+ top: 0;
397
+ bottom: 0;
398
+ left: 0;
399
+ z-index: 8;
400
+ transform: translateX(-100%);
401
+ transition: transform 0.18s ease-out;
402
+ box-shadow: 4px 0 24px rgba(0, 0, 0, 0.4);
403
+ }
404
+ .sidebar.open {
405
+ transform: translateX(0);
406
+ }
407
+ .sidebar.open ~ .sidebar-backdrop {
408
+ display: block;
409
+ }
410
+ .main {
411
+ padding: 60px 16px 16px;
412
+ width: 100%;
413
+ }
414
+ .panel-header {
415
+ flex-direction: column;
416
+ align-items: flex-start;
417
+ gap: 8px;
418
+ }
419
+ .header-pickers {
420
+ margin-left: 0 !important;
421
+ width: 100%;
422
+ }
423
+ .metric-grid {
424
+ grid-template-columns: 1fr 1fr;
425
+ }
426
+ }
427
+
428
+ /* ---------- Main panel ---------- */
429
+
430
+ .main {
431
+ flex: 1;
432
+ overflow-y: auto;
433
+ padding: 28px 36px;
434
+ min-width: 0;
435
+ }
436
+ .main-editor {
437
+ padding: 0;
438
+ overflow: hidden;
439
+ display: flex;
440
+ flex-direction: column;
441
+ }
442
+ .main-editor .editor-shell {
443
+ flex: 1;
444
+ height: auto;
445
+ min-height: 0;
446
+ }
447
+
448
+ .panel-header {
449
+ display: flex;
450
+ align-items: baseline;
451
+ gap: 12px;
452
+ margin-bottom: 20px;
453
+ }
454
+
455
+ .panel-title {
456
+ font-size: 20px;
457
+ font-weight: 600;
458
+ margin: 0;
459
+ }
460
+
461
+ .panel-subtitle {
462
+ color: var(--fg-2);
463
+ font-size: 13px;
464
+ }
465
+
466
+ .section-title {
467
+ font-size: 11px;
468
+ letter-spacing: 0.1em;
469
+ text-transform: uppercase;
470
+ color: var(--fg-3);
471
+ margin: 24px 0 12px;
472
+ }
473
+
474
+ /* ---------- Cards / metric tiles ---------- */
475
+
476
+ .card {
477
+ background: var(--bg-1);
478
+ border: 1px solid var(--border);
479
+ border-radius: var(--radius-md);
480
+ padding: 16px 18px;
481
+ }
482
+
483
+ .card-title {
484
+ font-size: 11px;
485
+ letter-spacing: 0.08em;
486
+ text-transform: uppercase;
487
+ color: var(--fg-3);
488
+ margin-bottom: 6px;
489
+ }
490
+
491
+ .card-value {
492
+ font-family: var(--mono);
493
+ font-size: 22px;
494
+ color: var(--fg-0);
495
+ }
496
+
497
+ .card-value.muted {
498
+ color: var(--fg-3);
499
+ }
500
+
501
+ .card-hint {
502
+ margin-top: 4px;
503
+ font-size: 12px;
504
+ color: var(--fg-2);
505
+ }
506
+
507
+ .metric-grid {
508
+ display: grid;
509
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
510
+ gap: 14px;
511
+ }
512
+
513
+ /* Pill labels — mirror TUI accent bgs. */
514
+ .pill {
515
+ display: inline-block;
516
+ padding: 1px 8px;
517
+ font-size: 11px;
518
+ font-family: var(--mono);
519
+ border-radius: 999px;
520
+ }
521
+
522
+ .pill-primary {
523
+ background: rgba(103, 232, 249, 0.18);
524
+ color: var(--primary);
525
+ }
526
+ .pill-accent {
527
+ background: rgba(196, 181, 253, 0.18);
528
+ color: var(--accent);
529
+ }
530
+ .pill-ok {
531
+ background: rgba(74, 222, 128, 0.18);
532
+ color: var(--ok);
533
+ }
534
+ .pill-warn {
535
+ background: rgba(251, 191, 36, 0.18);
536
+ color: var(--warn);
537
+ }
538
+ .pill-err {
539
+ background: rgba(248, 113, 113, 0.18);
540
+ color: var(--err);
541
+ }
542
+ .pill-dim {
543
+ background: var(--bg-3);
544
+ color: var(--fg-2);
545
+ }
546
+
547
+ /* ---------- Tables ---------- */
548
+
549
+ table {
550
+ width: 100%;
551
+ border-collapse: collapse;
552
+ margin: 8px 0;
553
+ font-family: var(--mono);
554
+ font-size: 13px;
555
+ }
556
+
557
+ thead {
558
+ background: var(--bg-2);
559
+ }
560
+
561
+ th {
562
+ text-align: left;
563
+ font-weight: 500;
564
+ color: var(--fg-3);
565
+ font-size: 11px;
566
+ letter-spacing: 0.06em;
567
+ text-transform: uppercase;
568
+ padding: 10px 12px;
569
+ border-bottom: 1px solid var(--border);
570
+ }
571
+
572
+ td {
573
+ padding: 8px 12px;
574
+ border-bottom: 1px solid var(--border);
575
+ color: var(--fg-1);
576
+ }
577
+
578
+ tr:hover td {
579
+ background: var(--bg-hover);
580
+ }
581
+
582
+ td.numeric,
583
+ th.numeric {
584
+ text-align: right;
585
+ }
586
+
587
+ td.muted {
588
+ color: var(--fg-3);
589
+ }
590
+
591
+ /* ---------- Inputs / buttons ---------- */
592
+
593
+ button,
594
+ .button {
595
+ background: var(--bg-2);
596
+ color: var(--fg-1);
597
+ border: 1px solid var(--border);
598
+ border-radius: var(--radius-sm);
599
+ padding: 6px 12px;
600
+ font-family: var(--sans);
601
+ font-size: 12px;
602
+ cursor: pointer;
603
+ transition: border-color 0.12s, background 0.12s;
604
+ }
605
+
606
+ button:hover,
607
+ .button:hover {
608
+ border-color: var(--primary);
609
+ color: var(--primary);
610
+ }
611
+
612
+ button.primary {
613
+ background: var(--primary);
614
+ color: var(--bg-0);
615
+ border-color: var(--primary);
616
+ font-weight: 500;
617
+ }
618
+
619
+ button.primary:hover {
620
+ background: var(--brand);
621
+ border-color: var(--brand);
622
+ color: var(--bg-0);
623
+ }
624
+
625
+ button.danger {
626
+ border-color: var(--err);
627
+ color: var(--err);
628
+ }
629
+
630
+ button.danger:hover {
631
+ background: rgba(248, 113, 113, 0.12);
632
+ }
633
+
634
+ button:disabled {
635
+ opacity: 0.4;
636
+ cursor: not-allowed;
637
+ }
638
+
639
+ input[type="text"],
640
+ input[type="search"] {
641
+ background: var(--bg-2);
642
+ border: 1px solid var(--border);
643
+ color: var(--fg-0);
644
+ padding: 6px 10px;
645
+ border-radius: var(--radius-sm);
646
+ font-family: var(--mono);
647
+ font-size: 13px;
648
+ width: 100%;
649
+ }
650
+
651
+ input[type="text"]:focus,
652
+ input[type="search"]:focus,
653
+ input[type="password"]:focus {
654
+ border-color: var(--primary);
655
+ outline: none;
656
+ }
657
+
658
+ input[type="password"] {
659
+ background: var(--bg-2);
660
+ border: 1px solid var(--border);
661
+ color: var(--fg-0);
662
+ padding: 6px 10px;
663
+ border-radius: var(--radius-sm);
664
+ font-family: var(--mono);
665
+ font-size: 13px;
666
+ width: 100%;
667
+ }
668
+
669
+ select {
670
+ background: var(--bg-2);
671
+ border: 1px solid var(--border);
672
+ color: var(--fg-0);
673
+ padding: 5px 10px;
674
+ border-radius: var(--radius-sm);
675
+ font-family: var(--sans);
676
+ font-size: 13px;
677
+ cursor: pointer;
678
+ }
679
+ select:focus {
680
+ border-color: var(--primary);
681
+ outline: none;
682
+ }
683
+
684
+ textarea {
685
+ background: var(--bg-2);
686
+ color: var(--fg-0);
687
+ font-family: var(--mono);
688
+ }
689
+ textarea:focus {
690
+ border-color: var(--primary);
691
+ outline: none;
692
+ }
693
+
694
+ .row {
695
+ display: flex;
696
+ gap: 10px;
697
+ align-items: center;
698
+ margin-bottom: 12px;
699
+ }
700
+
701
+ .row > input {
702
+ flex: 1;
703
+ }
704
+
705
+ /* ---------- Markdown rendering (matches TUI markdown.tsx palette) ----------
706
+ *
707
+ * Mapping comes from src/cli/ui/markdown.tsx:
708
+ * H1 → bg #67e8f9 (cyan) text black, bold — pill
709
+ * H2 → bg #c4b5fd (violet) text black, bold — pill
710
+ * H3 → bg #f0abfc (fuchsia) text black, bold — pill
711
+ * inline code → amber text on bg-2
712
+ * code block → bg-1, monospace, soft border
713
+ * blockquote → teal-300 left bar (brand)
714
+ * strong / em → bold / italic
715
+ * tables → bordered, monospace
716
+ * strike → red strikethrough
717
+ * link → cyan underline
718
+ * diff +/- → green / red lines (handled by code-block class)
719
+ */
720
+
721
+ .md {
722
+ color: var(--fg-0);
723
+ font-size: 14px;
724
+ line-height: 1.7;
725
+ }
726
+ .md > *:first-child {
727
+ margin-top: 0;
728
+ }
729
+ .md > *:last-child {
730
+ margin-bottom: 0;
731
+ }
732
+
733
+ .md p {
734
+ margin: 0.5em 0;
735
+ }
736
+
737
+ .md h1,
738
+ .md h2,
739
+ .md h3 {
740
+ display: inline-block;
741
+ padding: 2px 10px;
742
+ margin: 0.8em 0 0.5em;
743
+ border-radius: var(--radius-sm);
744
+ color: #0a0e14;
745
+ font-weight: 700;
746
+ line-height: 1.4;
747
+ }
748
+ .md h1 {
749
+ background: var(--primary);
750
+ font-size: 18px;
751
+ }
752
+ .md h2 {
753
+ background: var(--accent);
754
+ font-size: 16px;
755
+ }
756
+ .md h3 {
757
+ background: var(--grad-8);
758
+ font-size: 14px;
759
+ }
760
+
761
+ .md h4,
762
+ .md h5,
763
+ .md h6 {
764
+ font-weight: 600;
765
+ color: var(--accent);
766
+ font-size: 14px;
767
+ margin: 0.6em 0 0.3em;
768
+ }
769
+
770
+ .md strong {
771
+ color: var(--fg-0);
772
+ font-weight: 700;
773
+ }
774
+ .md em {
775
+ color: var(--fg-0);
776
+ font-style: italic;
777
+ }
778
+ .md del {
779
+ color: var(--err);
780
+ text-decoration: line-through;
781
+ }
782
+
783
+ .md a {
784
+ color: var(--primary);
785
+ text-decoration: none;
786
+ }
787
+ .md a:hover {
788
+ text-decoration: underline;
789
+ }
790
+
791
+ .md code {
792
+ font-family: var(--mono);
793
+ background: var(--bg-2);
794
+ color: var(--tool); /* amber matches TUI inline-code */
795
+ padding: 1px 6px;
796
+ border-radius: var(--radius-sm);
797
+ font-size: 12px;
798
+ }
799
+
800
+ .md pre {
801
+ background: var(--bg-1);
802
+ border: 1px solid var(--border);
803
+ border-radius: var(--radius-md);
804
+ padding: 12px 14px;
805
+ overflow-x: auto;
806
+ margin: 0.6em 0;
807
+ font-family: var(--mono);
808
+ font-size: 12.5px;
809
+ line-height: 1.55;
810
+ color: var(--tool);
811
+ white-space: pre;
812
+ }
813
+ .md pre code {
814
+ background: transparent;
815
+ padding: 0;
816
+ border-radius: 0;
817
+ color: inherit;
818
+ font-size: inherit;
819
+ }
820
+
821
+ /* Diff blocks — rendered by the custom renderer in app.js for
822
+ * SEARCH/REPLACE markers and ``` diff fences. Mirror TUI's
823
+ * markdown.tsx red/green palette so the experience reads as the same
824
+ * tool whether you're in the terminal or the browser. */
825
+ .md .diff-block,
826
+ .diff-block {
827
+ background: var(--bg-1);
828
+ border: 1px solid var(--border);
829
+ border-radius: var(--radius-md);
830
+ padding: 8px 12px;
831
+ margin: 0.6em 0;
832
+ font-family: var(--mono);
833
+ font-size: 12.5px;
834
+ line-height: 1.55;
835
+ overflow-x: auto;
836
+ white-space: pre;
837
+ color: var(--fg-1);
838
+ }
839
+ .diff-line {
840
+ display: block;
841
+ padding: 0 4px;
842
+ }
843
+ .diff-line.ins {
844
+ background: rgba(74, 222, 128, 0.1);
845
+ color: #86efac;
846
+ }
847
+ .diff-line.del {
848
+ background: rgba(248, 113, 113, 0.1);
849
+ color: #fda4af;
850
+ }
851
+ .diff-line.hunk {
852
+ color: var(--accent);
853
+ font-weight: 500;
854
+ }
855
+ .diff-line.meta {
856
+ color: var(--fg-3);
857
+ }
858
+
859
+ /* highlight.js github-dark loads from CDN; we tweak surface colors
860
+ * to merge with our card backgrounds. The theme provides token colors
861
+ * (keyword, string, number, comment etc.) we keep as-is — they read
862
+ * well against bg-1. */
863
+ .md .hljs,
864
+ .hljs {
865
+ background: var(--bg-1) !important;
866
+ color: var(--fg-0);
867
+ padding: 0;
868
+ }
869
+ .md pre code.hljs {
870
+ background: transparent !important;
871
+ }
872
+
873
+ .md ul,
874
+ .md ol {
875
+ margin: 0.4em 0;
876
+ padding-left: 24px;
877
+ }
878
+ .md li {
879
+ margin: 0.15em 0;
880
+ }
881
+ .md ul > li::marker {
882
+ color: var(--brand);
883
+ }
884
+ .md ol > li::marker {
885
+ color: var(--accent);
886
+ font-weight: 600;
887
+ }
888
+
889
+ .md blockquote {
890
+ border-left: 3px solid var(--brand);
891
+ padding: 4px 12px;
892
+ margin: 0.6em 0;
893
+ color: var(--fg-1);
894
+ background: var(--bg-1);
895
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
896
+ }
897
+
898
+ .md table {
899
+ width: auto;
900
+ margin: 0.6em 0;
901
+ border-collapse: collapse;
902
+ font-family: var(--mono);
903
+ font-size: 12.5px;
904
+ }
905
+ .md thead {
906
+ background: var(--bg-2);
907
+ }
908
+ .md th,
909
+ .md td {
910
+ border: 1px solid var(--border);
911
+ padding: 6px 10px;
912
+ text-align: left;
913
+ }
914
+ .md th {
915
+ color: var(--primary);
916
+ font-weight: 600;
917
+ font-size: 11px;
918
+ letter-spacing: 0.04em;
919
+ text-transform: uppercase;
920
+ }
921
+ .md td {
922
+ color: var(--fg-1);
923
+ }
924
+
925
+ .md hr {
926
+ border: none;
927
+ height: 2px;
928
+ background: var(--gradient-rule);
929
+ margin: 1.2em 0;
930
+ opacity: 0.6;
931
+ }
932
+
933
+ .md img {
934
+ max-width: 100%;
935
+ border-radius: var(--radius-sm);
936
+ }
937
+
938
+ /* ---------- Chat panel ---------- */
939
+
940
+ .chat-shell {
941
+ display: flex;
942
+ flex-direction: column;
943
+ height: calc(100vh - 56px);
944
+ }
945
+
946
+ .chat-feed {
947
+ flex: 1;
948
+ overflow-y: auto;
949
+ padding: 4px 4px 16px;
950
+ display: flex;
951
+ flex-direction: column;
952
+ gap: 14px;
953
+ }
954
+
955
+ .chat-msg {
956
+ display: flex;
957
+ gap: 12px;
958
+ align-items: flex-start;
959
+ line-height: 1.6;
960
+ }
961
+
962
+ .chat-msg .glyph {
963
+ width: 22px;
964
+ flex-shrink: 0;
965
+ font-family: var(--mono);
966
+ text-align: center;
967
+ font-size: 14px;
968
+ padding-top: 2px;
969
+ }
970
+
971
+ .chat-msg .body {
972
+ flex: 1;
973
+ min-width: 0;
974
+ }
975
+
976
+ .chat-msg.user .glyph {
977
+ color: var(--user);
978
+ }
979
+ .chat-msg.assistant .glyph {
980
+ color: var(--assistant);
981
+ }
982
+ .chat-msg.tool .glyph {
983
+ color: var(--tool);
984
+ }
985
+ .chat-msg.info .glyph {
986
+ color: var(--info);
987
+ }
988
+ .chat-msg.warning .glyph {
989
+ color: var(--warn);
990
+ }
991
+ .chat-msg.error .glyph {
992
+ color: var(--err);
993
+ }
994
+
995
+ .chat-msg.user .body {
996
+ color: var(--fg-0);
997
+ }
998
+ .chat-msg.assistant .body {
999
+ color: var(--fg-0);
1000
+ }
1001
+ /* Tool-card replaces the simple .body box for role="tool" rows. The
1002
+ * card carries a left accent bar (amber for success), a header with
1003
+ * tool name + path/lang pills, then the kind-specific body (diff for
1004
+ * edit_file, code block for read/write_file, terminal for run_command,
1005
+ * etc). Keeps the visual weight consistent across kinds. */
1006
+ .tool-card {
1007
+ flex: 1;
1008
+ background: var(--bg-1);
1009
+ border: 1px solid var(--border);
1010
+ border-left: 3px solid var(--tool);
1011
+ border-radius: var(--radius-md);
1012
+ padding: 10px 12px;
1013
+ min-width: 0;
1014
+ }
1015
+ .tool-card-head {
1016
+ display: flex;
1017
+ align-items: center;
1018
+ gap: 8px;
1019
+ margin-bottom: 8px;
1020
+ font-family: var(--mono);
1021
+ font-size: 12px;
1022
+ flex-wrap: wrap;
1023
+ }
1024
+ .tool-card-icon {
1025
+ color: var(--tool);
1026
+ font-size: 14px;
1027
+ font-weight: 600;
1028
+ }
1029
+ .tool-card-name {
1030
+ color: var(--accent);
1031
+ font-weight: 500;
1032
+ }
1033
+ .tool-card-path {
1034
+ color: var(--primary);
1035
+ background: var(--bg-2);
1036
+ padding: 1px 8px;
1037
+ border-radius: var(--radius-sm);
1038
+ font-size: 11px;
1039
+ }
1040
+ .tool-card-path-link {
1041
+ cursor: pointer;
1042
+ border: 1px solid transparent;
1043
+ transition: border-color 0.12s, background 0.12s;
1044
+ }
1045
+ .tool-card-path-link:hover {
1046
+ border-color: var(--primary);
1047
+ background: rgba(103, 232, 249, 0.12);
1048
+ }
1049
+ .tool-card pre,
1050
+ .tool-card .md {
1051
+ margin: 0;
1052
+ }
1053
+ .tool-card .md > pre,
1054
+ .tool-card-cmd,
1055
+ .tool-card-output {
1056
+ background: var(--bg-2);
1057
+ border: 1px solid var(--border);
1058
+ border-radius: var(--radius-sm);
1059
+ padding: 8px 10px;
1060
+ font-family: var(--mono);
1061
+ font-size: 12px;
1062
+ line-height: 1.55;
1063
+ max-height: 320px;
1064
+ overflow: auto;
1065
+ }
1066
+ .tool-card .md > pre code {
1067
+ background: transparent;
1068
+ padding: 0;
1069
+ color: inherit;
1070
+ }
1071
+ .tool-card .diff-block {
1072
+ margin: 0;
1073
+ max-height: 320px;
1074
+ }
1075
+ .tool-card-cmd {
1076
+ background: var(--bg-0);
1077
+ white-space: pre;
1078
+ margin: 0 0 6px 0;
1079
+ }
1080
+ .tool-card-prompt {
1081
+ color: var(--fg-3);
1082
+ margin-right: 6px;
1083
+ }
1084
+ .tool-card-output {
1085
+ white-space: pre-wrap;
1086
+ word-break: break-word;
1087
+ color: var(--fg-1);
1088
+ margin: 0;
1089
+ }
1090
+ .tool-card-result {
1091
+ margin-top: 6px;
1092
+ font-size: 11px;
1093
+ color: var(--fg-3);
1094
+ font-family: var(--mono);
1095
+ }
1096
+ .tool-card-args {
1097
+ margin-bottom: 6px;
1098
+ font-size: 11px;
1099
+ }
1100
+ .tool-card-args summary {
1101
+ cursor: pointer;
1102
+ color: var(--fg-2);
1103
+ }
1104
+ .tool-card-args summary:hover {
1105
+ color: var(--primary);
1106
+ }
1107
+ .tool-card-args pre {
1108
+ margin-top: 6px;
1109
+ white-space: pre;
1110
+ }
1111
+
1112
+ .chat-msg .reasoning {
1113
+ margin-top: 6px;
1114
+ padding: 6px 10px;
1115
+ background: var(--bg-1);
1116
+ border-left: 2px solid var(--accent);
1117
+ color: var(--fg-2);
1118
+ font-size: 12px;
1119
+ font-style: italic;
1120
+ white-space: pre-wrap;
1121
+ word-break: break-word;
1122
+ border-radius: var(--radius-sm);
1123
+ }
1124
+
1125
+ .chat-msg .tool-name {
1126
+ color: var(--accent);
1127
+ font-weight: 500;
1128
+ }
1129
+
1130
+ .chat-streaming-cursor {
1131
+ display: inline-block;
1132
+ width: 7px;
1133
+ height: 14px;
1134
+ background: var(--primary);
1135
+ margin-left: 2px;
1136
+ vertical-align: middle;
1137
+ animation: blink 1s steps(1) infinite;
1138
+ }
1139
+
1140
+ @keyframes blink {
1141
+ 50% {
1142
+ opacity: 0;
1143
+ }
1144
+ }
1145
+
1146
+ .chat-input-area {
1147
+ display: flex;
1148
+ gap: 10px;
1149
+ padding-top: 12px;
1150
+ border-top: 1px solid var(--border);
1151
+ flex-shrink: 0;
1152
+ }
1153
+
1154
+ .chat-input-area textarea {
1155
+ flex: 1;
1156
+ background: var(--bg-2);
1157
+ border: 1px solid var(--border);
1158
+ color: var(--fg-0);
1159
+ padding: 8px 12px;
1160
+ border-radius: var(--radius-md);
1161
+ font-family: var(--mono);
1162
+ font-size: 13px;
1163
+ resize: vertical;
1164
+ min-height: 44px;
1165
+ max-height: 200px;
1166
+ }
1167
+
1168
+ .chat-input-area textarea:focus {
1169
+ border-color: var(--primary);
1170
+ outline: none;
1171
+ }
1172
+
1173
+ .chat-input-area textarea:disabled {
1174
+ opacity: 0.5;
1175
+ cursor: not-allowed;
1176
+ }
1177
+
1178
+ .chat-empty {
1179
+ margin: auto;
1180
+ text-align: center;
1181
+ color: var(--fg-3);
1182
+ font-family: var(--mono);
1183
+ font-size: 13px;
1184
+ padding: 40px 20px;
1185
+ }
1186
+
1187
+ .chat-status {
1188
+ display: flex;
1189
+ align-items: center;
1190
+ gap: 8px;
1191
+ margin-bottom: 12px;
1192
+ font-size: 12px;
1193
+ color: var(--fg-2);
1194
+ }
1195
+
1196
+ /* ---------- Chat status bar ----------
1197
+ *
1198
+ * Compact metric strip below the input area. Mirrors the TUI's
1199
+ * StatsPanel (model · ctx · cache · turn $ · session $ · balance) so
1200
+ * the user has the same one-glance read-out without leaving Chat.
1201
+ */
1202
+ .chat-statusbar {
1203
+ display: flex;
1204
+ flex-wrap: wrap;
1205
+ gap: 16px;
1206
+ padding: 8px 4px 0;
1207
+ margin-top: 8px;
1208
+ border-top: 1px solid var(--border);
1209
+ font-family: var(--mono);
1210
+ font-size: 11px;
1211
+ color: var(--fg-2);
1212
+ flex-shrink: 0;
1213
+ }
1214
+ .status-item {
1215
+ display: inline-flex;
1216
+ align-items: center;
1217
+ gap: 6px;
1218
+ }
1219
+ .status-label {
1220
+ color: var(--fg-3);
1221
+ font-size: 10px;
1222
+ letter-spacing: 0.06em;
1223
+ text-transform: uppercase;
1224
+ }
1225
+ .status-bar-mini {
1226
+ display: inline-block;
1227
+ width: 60px;
1228
+ height: 4px;
1229
+ background: var(--bg-3);
1230
+ border-radius: 2px;
1231
+ overflow: hidden;
1232
+ }
1233
+ .status-bar-mini-fill {
1234
+ display: block;
1235
+ height: 100%;
1236
+ background: var(--gradient-rule);
1237
+ }
1238
+ .status-ok {
1239
+ color: var(--ok);
1240
+ }
1241
+ .status-warn {
1242
+ color: var(--warn);
1243
+ }
1244
+ .status-err {
1245
+ color: var(--err);
1246
+ }
1247
+
1248
+ /* ---------- Header pickers (effort / preset / edit-mode) ----------
1249
+ *
1250
+ * Three segmented controls that flow on the chat header right side.
1251
+ * On narrow screens they wrap onto multiple rows. The `accent` variant
1252
+ * paints active segments violet (preset / effort) instead of cyan
1253
+ * (edit-mode), so the three picker groups remain visually distinct.
1254
+ */
1255
+ .header-pickers {
1256
+ display: flex;
1257
+ gap: 8px;
1258
+ flex-wrap: wrap;
1259
+ justify-content: flex-end;
1260
+ }
1261
+
1262
+ .mode-picker {
1263
+ display: inline-flex;
1264
+ border: 1px solid var(--border);
1265
+ border-radius: var(--radius-md);
1266
+ overflow: hidden;
1267
+ background: var(--bg-1);
1268
+ }
1269
+ .mode-btn {
1270
+ background: transparent;
1271
+ border: none;
1272
+ border-radius: 0;
1273
+ padding: 4px 12px;
1274
+ font-family: var(--mono);
1275
+ font-size: 11px;
1276
+ letter-spacing: 0.05em;
1277
+ text-transform: uppercase;
1278
+ color: var(--fg-2);
1279
+ cursor: pointer;
1280
+ transition: color 0.12s, background 0.12s;
1281
+ }
1282
+ .mode-btn + .mode-btn {
1283
+ border-left: 1px solid var(--border);
1284
+ }
1285
+ .mode-btn:hover {
1286
+ background: var(--bg-2);
1287
+ color: var(--fg-0);
1288
+ }
1289
+ .mode-btn.active {
1290
+ background: var(--primary);
1291
+ color: var(--bg-0);
1292
+ font-weight: 600;
1293
+ }
1294
+ .mode-btn.active.accent {
1295
+ background: var(--accent);
1296
+ color: var(--bg-0);
1297
+ }
1298
+ .mode-btn.active.yolo {
1299
+ background: var(--err);
1300
+ color: var(--bg-0);
1301
+ }
1302
+
1303
+ /* ---------- Modal cards (shell / choice / plan / edit-review) ----------
1304
+ *
1305
+ * Mirrors the TUI's ModalCard shape — left-accent border in the modal
1306
+ * kind's color (red shell, magenta choice, cyan plan, green edits)
1307
+ * with an icon, title, optional subtitle, then content + actions. The
1308
+ * card sits above the chat input area, full-width within the chat
1309
+ * column. Styled minimal so it doesn't compete with conversation
1310
+ * content for attention.
1311
+ */
1312
+
1313
+ .modal-card {
1314
+ margin: 12px 0;
1315
+ background: var(--bg-1);
1316
+ border: 1px solid var(--border);
1317
+ border-left: 3px solid var(--accent);
1318
+ border-radius: var(--radius-md);
1319
+ padding: 14px 16px;
1320
+ display: flex;
1321
+ flex-direction: column;
1322
+ gap: 12px;
1323
+ }
1324
+
1325
+ .modal-card-head {
1326
+ display: flex;
1327
+ gap: 12px;
1328
+ align-items: flex-start;
1329
+ }
1330
+
1331
+ .modal-card-icon {
1332
+ font-size: 18px;
1333
+ font-family: var(--mono);
1334
+ line-height: 1.4;
1335
+ }
1336
+
1337
+ .modal-card-title {
1338
+ font-size: 14px;
1339
+ font-weight: 600;
1340
+ color: var(--fg-0);
1341
+ }
1342
+
1343
+ .modal-card-subtitle {
1344
+ font-size: 12px;
1345
+ color: var(--fg-2);
1346
+ margin-top: 2px;
1347
+ }
1348
+
1349
+ .modal-cmd {
1350
+ background: var(--bg-2);
1351
+ border-radius: var(--radius-sm);
1352
+ padding: 8px 12px;
1353
+ font-family: var(--mono);
1354
+ font-size: 13px;
1355
+ }
1356
+ .modal-cmd-prompt {
1357
+ color: var(--fg-3);
1358
+ margin-right: 6px;
1359
+ }
1360
+ .modal-cmd code {
1361
+ color: var(--primary);
1362
+ background: transparent;
1363
+ padding: 0;
1364
+ }
1365
+
1366
+ .modal-actions {
1367
+ display: flex;
1368
+ gap: 8px;
1369
+ flex-wrap: wrap;
1370
+ }
1371
+
1372
+ .modal-choice-row {
1373
+ display: grid;
1374
+ grid-template-columns: 28px 1fr;
1375
+ grid-template-rows: auto auto;
1376
+ gap: 2px 12px;
1377
+ background: transparent;
1378
+ border: 1px solid var(--border);
1379
+ border-radius: var(--radius-sm);
1380
+ padding: 8px 12px;
1381
+ text-align: left;
1382
+ cursor: pointer;
1383
+ transition: border-color 0.12s, background 0.12s;
1384
+ }
1385
+ .modal-choice-row:hover {
1386
+ border-color: var(--accent);
1387
+ background: rgba(196, 181, 253, 0.06);
1388
+ }
1389
+ .modal-choice-row.modal-choice-cancel {
1390
+ margin-top: 4px;
1391
+ border-style: dashed;
1392
+ }
1393
+ .modal-choice-id {
1394
+ grid-row: 1 / 3;
1395
+ align-self: center;
1396
+ font-family: var(--mono);
1397
+ font-size: 14px;
1398
+ color: var(--accent);
1399
+ font-weight: 600;
1400
+ text-align: center;
1401
+ }
1402
+ .modal-choice-title {
1403
+ color: var(--fg-0);
1404
+ font-size: 13px;
1405
+ font-weight: 500;
1406
+ }
1407
+ .modal-choice-summary {
1408
+ color: var(--fg-2);
1409
+ font-size: 12px;
1410
+ grid-column: 2;
1411
+ }
1412
+
1413
+ .modal-custom textarea {
1414
+ width: 100%;
1415
+ background: var(--bg-2);
1416
+ border: 1px solid var(--border);
1417
+ color: var(--fg-0);
1418
+ padding: 8px 12px;
1419
+ border-radius: var(--radius-sm);
1420
+ font-family: var(--mono);
1421
+ font-size: 13px;
1422
+ resize: vertical;
1423
+ min-height: 56px;
1424
+ }
1425
+
1426
+ .modal-plan-body {
1427
+ background: var(--bg-2);
1428
+ border-radius: var(--radius-sm);
1429
+ padding: 12px 14px;
1430
+ max-height: 320px;
1431
+ overflow-y: auto;
1432
+ }
1433
+
1434
+ .modal-edit-preview {
1435
+ background: var(--bg-2);
1436
+ border: 1px solid var(--border);
1437
+ border-radius: var(--radius-sm);
1438
+ padding: 10px 12px;
1439
+ margin: 0;
1440
+ font-family: var(--mono);
1441
+ font-size: 12px;
1442
+ color: var(--fg-1);
1443
+ white-space: pre;
1444
+ overflow-x: auto;
1445
+ max-height: 200px;
1446
+ }
1447
+
1448
+ /* Side-by-side diff for the edit-review modal — left is "before" (red
1449
+ * tint), right is "after" (green tint), context rows render unchanged.
1450
+ * Lines hljs-highlight per the file's language. */
1451
+ .edit-diff-wrap {
1452
+ border: 1px solid var(--border);
1453
+ border-radius: var(--radius-sm);
1454
+ background: var(--bg-2);
1455
+ font-family: var(--mono);
1456
+ font-size: 12px;
1457
+ overflow: hidden;
1458
+ max-height: 60vh;
1459
+ display: flex;
1460
+ flex-direction: column;
1461
+ }
1462
+ .edit-diff-head {
1463
+ display: flex;
1464
+ background: var(--bg-1);
1465
+ border-bottom: 1px solid var(--border);
1466
+ font-size: 11px;
1467
+ text-transform: uppercase;
1468
+ letter-spacing: 0.06em;
1469
+ color: var(--fg-3);
1470
+ flex-shrink: 0;
1471
+ }
1472
+ .edit-diff-side {
1473
+ flex: 1;
1474
+ padding: 6px 12px;
1475
+ }
1476
+ .edit-diff-side + .edit-diff-side {
1477
+ border-left: 1px solid var(--border);
1478
+ }
1479
+ .edit-diff-side-old .edit-diff-marker {
1480
+ color: #f87171;
1481
+ font-weight: 700;
1482
+ margin-right: 4px;
1483
+ }
1484
+ .edit-diff-side-new .edit-diff-marker {
1485
+ color: #86efac;
1486
+ font-weight: 700;
1487
+ margin-right: 4px;
1488
+ }
1489
+ .edit-diff-body {
1490
+ flex: 1;
1491
+ overflow-y: auto;
1492
+ overflow-x: auto;
1493
+ }
1494
+ .edit-diff-row {
1495
+ display: flex;
1496
+ width: 100%;
1497
+ align-items: stretch;
1498
+ min-height: 19px;
1499
+ }
1500
+ .edit-diff-cell {
1501
+ flex: 1;
1502
+ padding: 1px 12px;
1503
+ white-space: pre;
1504
+ overflow-x: auto;
1505
+ border-right: 1px solid var(--border);
1506
+ color: var(--fg-1);
1507
+ line-height: 1.55;
1508
+ }
1509
+ .edit-diff-cell:last-child {
1510
+ border-right: none;
1511
+ }
1512
+ .edit-diff-row-context .edit-diff-cell {
1513
+ background: transparent;
1514
+ color: var(--fg-2);
1515
+ }
1516
+ .edit-diff-row-del .edit-diff-cell-old,
1517
+ .edit-diff-row-change .edit-diff-cell-old {
1518
+ background: rgba(248, 113, 113, 0.12);
1519
+ border-left: 2px solid #f87171;
1520
+ padding-left: 10px;
1521
+ }
1522
+ .edit-diff-row-ins .edit-diff-cell-new,
1523
+ .edit-diff-row-change .edit-diff-cell-new {
1524
+ background: rgba(134, 239, 172, 0.12);
1525
+ border-left: 2px solid #86efac;
1526
+ padding-left: 10px;
1527
+ }
1528
+ .edit-diff-cell-old .edit-diff-empty,
1529
+ .edit-diff-cell-new .edit-diff-empty {
1530
+ display: inline-block;
1531
+ width: 1px;
1532
+ }
1533
+ .edit-diff-row-del .edit-diff-cell-new,
1534
+ .edit-diff-row-ins .edit-diff-cell-old {
1535
+ background: var(--bg-3);
1536
+ opacity: 0.5;
1537
+ }
1538
+ .edit-diff-line {
1539
+ font-family: var(--mono);
1540
+ }
1541
+
1542
+ @media (max-width: 800px) {
1543
+ .edit-diff-row {
1544
+ flex-direction: column;
1545
+ }
1546
+ .edit-diff-cell {
1547
+ border-right: none;
1548
+ border-bottom: 1px solid var(--border);
1549
+ }
1550
+ .edit-diff-head {
1551
+ flex-direction: column;
1552
+ }
1553
+ .edit-diff-side + .edit-diff-side {
1554
+ border-left: none;
1555
+ border-top: 1px solid var(--border);
1556
+ }
1557
+ }
1558
+
1559
+ .muted {
1560
+ color: var(--fg-3);
1561
+ }
1562
+
1563
+ /* ---------- Toast ----------
1564
+ * Ephemeral notifications stacked bottom-right of the viewport. Fired
1565
+ * by save / network success paths instead of inline banners that push
1566
+ * the form around. Auto-dismiss after 3 seconds. */
1567
+ .toast-stack {
1568
+ position: fixed;
1569
+ bottom: 20px;
1570
+ right: 20px;
1571
+ display: flex;
1572
+ flex-direction: column;
1573
+ gap: 8px;
1574
+ z-index: 50;
1575
+ pointer-events: none;
1576
+ }
1577
+ .toast {
1578
+ pointer-events: auto;
1579
+ background: var(--bg-1);
1580
+ border: 1px solid var(--border);
1581
+ border-left: 3px solid var(--ok);
1582
+ border-radius: var(--radius-md);
1583
+ padding: 10px 14px;
1584
+ font-size: 13px;
1585
+ color: var(--fg-0);
1586
+ font-family: var(--sans);
1587
+ min-width: 200px;
1588
+ max-width: 360px;
1589
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
1590
+ animation: toast-slide-in 0.18s ease-out;
1591
+ }
1592
+ .toast.warn {
1593
+ border-left-color: var(--warn);
1594
+ }
1595
+ .toast.err {
1596
+ border-left-color: var(--err);
1597
+ }
1598
+ .toast.info {
1599
+ border-left-color: var(--accent);
1600
+ }
1601
+
1602
+ /* ---------- Error overlay ----------
1603
+ *
1604
+ * Full-screen modal triggered by uncaught exceptions / promise
1605
+ * rejections / Preact render errors. The TUI is unaffected — this
1606
+ * only blocks the browser tab. Includes "Copy details" + a GitHub
1607
+ * issue link prefilled with redacted environment info.
1608
+ */
1609
+ .error-overlay {
1610
+ position: fixed;
1611
+ inset: 0;
1612
+ background: rgba(10, 14, 20, 0.85);
1613
+ backdrop-filter: blur(4px);
1614
+ display: flex;
1615
+ align-items: center;
1616
+ justify-content: center;
1617
+ padding: 32px;
1618
+ z-index: 100;
1619
+ animation: fade-in 0.18s ease-out;
1620
+ }
1621
+ .error-overlay-card {
1622
+ max-width: 720px;
1623
+ width: 100%;
1624
+ max-height: 85vh;
1625
+ overflow-y: auto;
1626
+ background: var(--bg-1);
1627
+ border: 1px solid var(--err);
1628
+ border-left: 4px solid var(--err);
1629
+ border-radius: var(--radius-md);
1630
+ padding: 22px 26px;
1631
+ box-shadow: 0 12px 60px rgba(248, 113, 113, 0.18);
1632
+ }
1633
+ .error-overlay-head {
1634
+ display: flex;
1635
+ gap: 14px;
1636
+ align-items: flex-start;
1637
+ margin-bottom: 16px;
1638
+ }
1639
+ .error-overlay-icon {
1640
+ color: var(--err);
1641
+ font-size: 22px;
1642
+ font-weight: 700;
1643
+ }
1644
+ .error-overlay-title {
1645
+ font-size: 16px;
1646
+ font-weight: 600;
1647
+ color: var(--fg-0);
1648
+ }
1649
+ .error-overlay-subtitle {
1650
+ font-size: 13px;
1651
+ color: var(--fg-2);
1652
+ font-family: var(--mono);
1653
+ margin-top: 4px;
1654
+ word-break: break-word;
1655
+ }
1656
+ .error-overlay-trace {
1657
+ background: var(--bg-2);
1658
+ border: 1px solid var(--border);
1659
+ border-radius: var(--radius-sm);
1660
+ padding: 12px 14px;
1661
+ font-family: var(--mono);
1662
+ font-size: 12px;
1663
+ line-height: 1.55;
1664
+ color: var(--fg-1);
1665
+ white-space: pre-wrap;
1666
+ word-break: break-word;
1667
+ max-height: 280px;
1668
+ overflow-y: auto;
1669
+ margin: 0 0 12px;
1670
+ }
1671
+ .error-overlay-info {
1672
+ font-size: 12px;
1673
+ font-family: var(--mono);
1674
+ color: var(--fg-2);
1675
+ margin-bottom: 12px;
1676
+ }
1677
+ .error-overlay-help {
1678
+ font-size: 13px;
1679
+ color: var(--fg-1);
1680
+ margin-bottom: 18px;
1681
+ line-height: 1.55;
1682
+ }
1683
+ .error-overlay-actions {
1684
+ display: flex;
1685
+ gap: 8px;
1686
+ flex-wrap: wrap;
1687
+ align-items: center;
1688
+ }
1689
+ .error-overlay-actions a.button {
1690
+ display: inline-block;
1691
+ text-decoration: none;
1692
+ background: var(--bg-2);
1693
+ color: var(--fg-1);
1694
+ border: 1px solid var(--border);
1695
+ border-radius: var(--radius-sm);
1696
+ padding: 6px 12px;
1697
+ font-family: var(--sans);
1698
+ font-size: 12px;
1699
+ }
1700
+ .error-overlay-actions a.button:hover {
1701
+ border-color: var(--primary);
1702
+ color: var(--primary);
1703
+ }
1704
+
1705
+ /* ---------- Editor drawer ----------
1706
+ *
1707
+ * Sits to the right of the main panel. Hidden by default (width: 0,
1708
+ * overflow hidden) so its DOM stays mounted and keeps its tab state.
1709
+ * `.open` flips width to ~50% with a slide animation. On narrow
1710
+ * viewports it covers the panel entirely (full-screen overlay).
1711
+ */
1712
+ .editor-drawer-host {
1713
+ flex-shrink: 0;
1714
+ width: 0;
1715
+ overflow: hidden;
1716
+ border-left: 1px solid var(--border);
1717
+ background: var(--bg-0);
1718
+ transition: width 0.2s ease-out;
1719
+ }
1720
+ .editor-drawer-host.open {
1721
+ width: 65%;
1722
+ min-width: 420px;
1723
+ }
1724
+
1725
+ .editor-drawer-head {
1726
+ display: flex;
1727
+ align-items: center;
1728
+ padding: 8px 12px;
1729
+ border-bottom: 1px solid var(--border);
1730
+ background: var(--bg-1);
1731
+ flex-shrink: 0;
1732
+ }
1733
+ .editor-drawer-title {
1734
+ font-family: var(--mono);
1735
+ font-size: 12px;
1736
+ letter-spacing: 0.06em;
1737
+ text-transform: uppercase;
1738
+ color: var(--accent);
1739
+ }
1740
+ .editor-drawer-close {
1741
+ margin-left: auto;
1742
+ background: transparent;
1743
+ border: 1px solid var(--border);
1744
+ color: var(--fg-2);
1745
+ font-size: 18px;
1746
+ line-height: 1;
1747
+ padding: 0 10px;
1748
+ border-radius: var(--radius-sm);
1749
+ cursor: pointer;
1750
+ }
1751
+ .editor-drawer-close:hover {
1752
+ border-color: var(--err);
1753
+ color: var(--err);
1754
+ }
1755
+
1756
+ @media (max-width: 800px) {
1757
+ .editor-drawer-host {
1758
+ position: fixed;
1759
+ top: 0;
1760
+ right: 0;
1761
+ bottom: 0;
1762
+ width: 0;
1763
+ z-index: 7;
1764
+ box-shadow: -4px 0 24px rgba(0, 0, 0, 0.4);
1765
+ }
1766
+ .editor-drawer-host.open {
1767
+ width: 100%;
1768
+ min-width: 0;
1769
+ }
1770
+ }
1771
+
1772
+ /* ---------- Editor panel (CodeMirror multi-tab) ---------- */
1773
+
1774
+ .editor-shell {
1775
+ display: flex;
1776
+ flex-direction: column;
1777
+ height: calc(100vh - 56px);
1778
+ padding: 0;
1779
+ background: var(--bg-0);
1780
+ }
1781
+
1782
+ /* When the editor renders inside the right-side drawer, it follows
1783
+ * the drawer's flex column instead of carrying its own viewport-tied
1784
+ * height. Drawer-host gets `display: flex; flex-direction: column`
1785
+ * via the descendant context. */
1786
+ .editor-drawer-host {
1787
+ display: flex;
1788
+ flex-direction: column;
1789
+ }
1790
+ .editor-drawer-host .editor-shell {
1791
+ flex: 1;
1792
+ height: auto;
1793
+ min-height: 0;
1794
+ }
1795
+ .editor-body {
1796
+ display: flex;
1797
+ flex: 1;
1798
+ min-height: 0;
1799
+ gap: 0;
1800
+ }
1801
+ .editor-side {
1802
+ width: 260px;
1803
+ flex-shrink: 0;
1804
+ display: flex;
1805
+ flex-direction: column;
1806
+ background: var(--bg-1);
1807
+ border-right: 1px solid var(--border);
1808
+ padding: 8px 8px 8px 10px;
1809
+ transition: width 0.15s ease-out;
1810
+ }
1811
+ .editor-side.collapsed {
1812
+ width: 28px;
1813
+ }
1814
+ .editor-side-head {
1815
+ display: flex;
1816
+ align-items: center;
1817
+ gap: 6px;
1818
+ margin-bottom: 8px;
1819
+ padding: 0 2px;
1820
+ }
1821
+ .editor-side-label {
1822
+ font-family: var(--mono);
1823
+ font-size: 10px;
1824
+ letter-spacing: 0.08em;
1825
+ color: var(--fg-3);
1826
+ text-transform: uppercase;
1827
+ }
1828
+ .editor-side-toggle {
1829
+ margin-left: auto;
1830
+ background: transparent;
1831
+ border: 1px solid var(--border);
1832
+ color: var(--fg-3);
1833
+ font-size: 10px;
1834
+ line-height: 1;
1835
+ padding: 3px 6px;
1836
+ border-radius: var(--radius-sm);
1837
+ cursor: pointer;
1838
+ }
1839
+ .editor-side-toggle:hover {
1840
+ border-color: var(--primary);
1841
+ color: var(--primary);
1842
+ }
1843
+ .editor-side.collapsed .editor-side-toggle {
1844
+ margin: 8px auto 0;
1845
+ width: 100%;
1846
+ }
1847
+ .editor-files {
1848
+ flex: 1;
1849
+ overflow-y: auto;
1850
+ border: 1px solid var(--border);
1851
+ border-radius: var(--radius-sm);
1852
+ background: var(--bg-0);
1853
+ }
1854
+ .editor-file {
1855
+ padding: 5px 10px;
1856
+ font-family: var(--mono);
1857
+ font-size: 11.5px;
1858
+ color: var(--fg-2);
1859
+ cursor: pointer;
1860
+ border-left: 2px solid transparent;
1861
+ white-space: nowrap;
1862
+ overflow: hidden;
1863
+ text-overflow: ellipsis;
1864
+ }
1865
+ .editor-file:hover {
1866
+ background: var(--bg-hover);
1867
+ color: var(--fg-0);
1868
+ }
1869
+ .editor-file.open {
1870
+ color: var(--primary);
1871
+ border-left-color: var(--primary);
1872
+ }
1873
+ .editor-tree-folder,
1874
+ .editor-tree-file {
1875
+ display: flex;
1876
+ align-items: center;
1877
+ gap: 4px;
1878
+ font-family: var(--mono);
1879
+ font-size: 11.5px;
1880
+ color: var(--fg-2);
1881
+ cursor: pointer;
1882
+ white-space: nowrap;
1883
+ overflow: hidden;
1884
+ text-overflow: ellipsis;
1885
+ user-select: none;
1886
+ border-left: 2px solid transparent;
1887
+ padding-top: 3px;
1888
+ padding-bottom: 3px;
1889
+ padding-right: 8px;
1890
+ }
1891
+ .editor-tree-folder:hover,
1892
+ .editor-tree-file:hover {
1893
+ background: var(--bg-hover);
1894
+ color: var(--fg-0);
1895
+ }
1896
+ .editor-tree-caret {
1897
+ display: inline-block;
1898
+ width: 12px;
1899
+ font-size: 9px;
1900
+ color: var(--fg-3);
1901
+ flex-shrink: 0;
1902
+ }
1903
+ .editor-tree-name {
1904
+ overflow: hidden;
1905
+ text-overflow: ellipsis;
1906
+ }
1907
+ .editor-tree-folder {
1908
+ color: var(--fg-1);
1909
+ }
1910
+ .editor-tree-file.open {
1911
+ color: var(--primary);
1912
+ border-left-color: var(--primary);
1913
+ }
1914
+
1915
+ .editor-main {
1916
+ flex: 1;
1917
+ display: flex;
1918
+ flex-direction: column;
1919
+ min-width: 0;
1920
+ background: #282c34;
1921
+ }
1922
+ .editor-tabs {
1923
+ display: flex;
1924
+ align-items: stretch;
1925
+ gap: 0;
1926
+ background: var(--bg-1);
1927
+ border-bottom: 1px solid var(--border);
1928
+ overflow-x: auto;
1929
+ flex-wrap: nowrap;
1930
+ flex-shrink: 0;
1931
+ height: 34px;
1932
+ scrollbar-width: thin;
1933
+ }
1934
+ .editor-tabs::-webkit-scrollbar {
1935
+ height: 3px;
1936
+ }
1937
+ .editor-tabs::-webkit-scrollbar-thumb {
1938
+ background: var(--border);
1939
+ }
1940
+ .editor-no-tabs {
1941
+ padding: 9px 14px;
1942
+ color: var(--fg-3);
1943
+ font-size: 12px;
1944
+ font-family: var(--mono);
1945
+ }
1946
+ .editor-tab {
1947
+ display: flex;
1948
+ align-items: center;
1949
+ gap: 6px;
1950
+ padding: 0 10px 0 12px;
1951
+ background: var(--bg-1);
1952
+ border: none;
1953
+ border-right: 1px solid var(--border);
1954
+ border-top: 2px solid transparent;
1955
+ border-bottom: 1px solid var(--border);
1956
+ margin-bottom: -1px;
1957
+ font-family: var(--mono);
1958
+ font-size: 12px;
1959
+ color: var(--fg-3);
1960
+ cursor: pointer;
1961
+ white-space: nowrap;
1962
+ user-select: none;
1963
+ height: 34px;
1964
+ position: relative;
1965
+ }
1966
+ .editor-tab:hover {
1967
+ color: var(--fg-1);
1968
+ background: var(--bg-2);
1969
+ }
1970
+ .editor-tab.active {
1971
+ background: #282c34;
1972
+ color: var(--fg-0);
1973
+ border-top-color: var(--primary);
1974
+ border-bottom-color: #282c34;
1975
+ }
1976
+ .editor-tab-name {
1977
+ max-width: 200px;
1978
+ overflow: hidden;
1979
+ text-overflow: ellipsis;
1980
+ }
1981
+ .editor-tab-dirty {
1982
+ color: var(--accent);
1983
+ font-size: 14px;
1984
+ line-height: 1;
1985
+ width: 12px;
1986
+ text-align: center;
1987
+ }
1988
+ .editor-tab-close {
1989
+ margin-left: 2px;
1990
+ color: var(--fg-3);
1991
+ font-size: 14px;
1992
+ line-height: 1;
1993
+ padding: 1px 5px;
1994
+ border-radius: var(--radius-sm);
1995
+ width: 18px;
1996
+ height: 18px;
1997
+ display: inline-flex;
1998
+ align-items: center;
1999
+ justify-content: center;
2000
+ }
2001
+ .editor-tab-close:hover {
2002
+ background: var(--bg-3);
2003
+ color: var(--err);
2004
+ }
2005
+ .editor-bar {
2006
+ display: flex;
2007
+ align-items: center;
2008
+ gap: 12px;
2009
+ padding: 6px 12px;
2010
+ background: var(--bg-1);
2011
+ border-bottom: 1px solid var(--border);
2012
+ flex-shrink: 0;
2013
+ }
2014
+ .editor-host {
2015
+ flex: 1;
2016
+ overflow: hidden;
2017
+ background: #282c34;
2018
+ border: none;
2019
+ border-radius: 0;
2020
+ min-height: 0;
2021
+ }
2022
+ .editor-host .cm-editor {
2023
+ height: 100%;
2024
+ font-family: var(--mono);
2025
+ font-size: 13px;
2026
+ outline: none;
2027
+ }
2028
+ .editor-host .cm-editor.cm-focused {
2029
+ outline: none;
2030
+ }
2031
+ .editor-host .cm-scroller {
2032
+ font-family: inherit;
2033
+ line-height: 1.55;
2034
+ }
2035
+
2036
+ /* VS Code-style gutter — darker bg, dim line numbers, accent on active */
2037
+ .editor-host .cm-gutters {
2038
+ background: #21252b;
2039
+ border-right: 1px solid #181a1f;
2040
+ color: #495162;
2041
+ }
2042
+ .editor-host .cm-lineNumbers {
2043
+ font-family: var(--mono);
2044
+ font-size: 12px;
2045
+ min-width: 40px;
2046
+ }
2047
+ .editor-host .cm-lineNumbers .cm-gutterElement {
2048
+ padding: 0 12px 0 16px;
2049
+ color: #495162;
2050
+ }
2051
+ .editor-host .cm-activeLineGutter {
2052
+ background: #2c313a;
2053
+ color: #abb2bf;
2054
+ }
2055
+ .editor-host .cm-foldGutter {
2056
+ color: #5c6370;
2057
+ }
2058
+ .editor-host .cm-foldGutter .cm-gutterElement {
2059
+ padding: 0 4px;
2060
+ cursor: pointer;
2061
+ }
2062
+ .editor-host .cm-activeLine {
2063
+ background: rgba(99, 110, 123, 0.1);
2064
+ }
2065
+ .editor-host .cm-selectionBackground,
2066
+ .editor-host .cm-content ::selection {
2067
+ background: #3e4451 !important;
2068
+ }
2069
+ .editor-host .cm-cursor {
2070
+ border-left-color: #61afef;
2071
+ border-left-width: 2px;
2072
+ }
2073
+
2074
+ /* Autocomplete popup — match the dark theme */
2075
+ .cm-tooltip.cm-tooltip-autocomplete {
2076
+ background: #21252b;
2077
+ border: 1px solid #181a1f;
2078
+ border-radius: var(--radius-sm);
2079
+ font-family: var(--mono);
2080
+ font-size: 12px;
2081
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
2082
+ }
2083
+ .cm-tooltip.cm-tooltip-autocomplete > ul > li {
2084
+ padding: 3px 10px;
2085
+ color: #abb2bf;
2086
+ }
2087
+ .cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] {
2088
+ background: var(--primary);
2089
+ color: #1e2127;
2090
+ }
2091
+ .cm-completionLabel {
2092
+ font-family: var(--mono);
2093
+ }
2094
+ .cm-completionDetail {
2095
+ color: #5c6370;
2096
+ font-style: normal;
2097
+ margin-left: 8px;
2098
+ }
2099
+
2100
+ .editor-empty {
2101
+ flex: 1;
2102
+ display: flex;
2103
+ align-items: center;
2104
+ justify-content: center;
2105
+ color: var(--fg-3);
2106
+ font-family: var(--mono);
2107
+ font-size: 13px;
2108
+ background: #282c34;
2109
+ }
2110
+
2111
+ /* Split view — left half source (CodeMirror), right half preview. */
2112
+ .editor-split {
2113
+ flex: 1;
2114
+ display: flex;
2115
+ min-height: 0;
2116
+ overflow: hidden;
2117
+ }
2118
+ .editor-split-pane {
2119
+ flex: 1;
2120
+ min-width: 0;
2121
+ border: none;
2122
+ border-radius: 0;
2123
+ }
2124
+ .editor-split .editor-split-pane + .editor-split-pane {
2125
+ border-left: 1px solid #181a1f;
2126
+ }
2127
+
2128
+ /* Segmented control for Edit / Split / Preview */
2129
+ .view-mode-group {
2130
+ display: inline-flex;
2131
+ background: var(--bg-2);
2132
+ border: 1px solid var(--border);
2133
+ border-radius: var(--radius-sm);
2134
+ overflow: hidden;
2135
+ padding: 0;
2136
+ }
2137
+ .view-mode-group .view-mode {
2138
+ background: transparent;
2139
+ border: none;
2140
+ padding: 3px 10px;
2141
+ font-size: 11px;
2142
+ font-family: var(--mono);
2143
+ color: var(--fg-3);
2144
+ cursor: pointer;
2145
+ border-radius: 0;
2146
+ }
2147
+ .view-mode-group .view-mode:hover {
2148
+ color: var(--fg-1);
2149
+ background: var(--bg-hover);
2150
+ }
2151
+ .view-mode-group .view-mode.active {
2152
+ background: var(--primary);
2153
+ color: #1e2127;
2154
+ }
2155
+
2156
+ /* Markdown preview — render the same .md styles used in chat,
2157
+ * but with scroll and a comfortable max-width so prose doesn't
2158
+ * stretch across the full editor width. */
2159
+ .editor-md-preview {
2160
+ overflow-y: auto;
2161
+ padding: 24px 36px;
2162
+ background: #282c34;
2163
+ color: #abb2bf;
2164
+ font-family: var(--font-sans, system-ui, sans-serif);
2165
+ font-size: 14px;
2166
+ line-height: 1.65;
2167
+ }
2168
+ .editor-md-preview > *:first-child {
2169
+ margin-top: 0;
2170
+ }
2171
+ .editor-md-preview h1,
2172
+ .editor-md-preview h2,
2173
+ .editor-md-preview h3,
2174
+ .editor-md-preview h4 {
2175
+ color: #e5e9f0;
2176
+ margin: 1.4em 0 0.6em;
2177
+ line-height: 1.3;
2178
+ }
2179
+ .editor-md-preview h1 {
2180
+ font-size: 1.8em;
2181
+ border-bottom: 1px solid #3e4451;
2182
+ padding-bottom: 0.3em;
2183
+ }
2184
+ .editor-md-preview h2 {
2185
+ font-size: 1.4em;
2186
+ border-bottom: 1px solid #3e4451;
2187
+ padding-bottom: 0.3em;
2188
+ }
2189
+ .editor-md-preview h3 {
2190
+ font-size: 1.15em;
2191
+ }
2192
+ .editor-md-preview a {
2193
+ color: #61afef;
2194
+ text-decoration: none;
2195
+ }
2196
+ .editor-md-preview a:hover {
2197
+ text-decoration: underline;
2198
+ }
2199
+ .editor-md-preview code {
2200
+ background: #21252b;
2201
+ color: #e06c75;
2202
+ padding: 1px 6px;
2203
+ border-radius: 3px;
2204
+ font-family: var(--mono);
2205
+ font-size: 0.92em;
2206
+ }
2207
+ .editor-md-preview pre {
2208
+ background: #21252b;
2209
+ border: 1px solid #181a1f;
2210
+ border-radius: 4px;
2211
+ padding: 12px 14px;
2212
+ overflow-x: auto;
2213
+ }
2214
+ .editor-md-preview pre code {
2215
+ background: transparent;
2216
+ color: #abb2bf;
2217
+ padding: 0;
2218
+ }
2219
+ .editor-md-preview blockquote {
2220
+ border-left: 3px solid #5c6370;
2221
+ margin: 0.8em 0;
2222
+ padding: 0.2em 0.9em;
2223
+ color: #828997;
2224
+ }
2225
+ .editor-md-preview table {
2226
+ border-collapse: collapse;
2227
+ margin: 0.8em 0;
2228
+ }
2229
+ .editor-md-preview th,
2230
+ .editor-md-preview td {
2231
+ border: 1px solid #3e4451;
2232
+ padding: 5px 10px;
2233
+ }
2234
+ .editor-md-preview th {
2235
+ background: #21252b;
2236
+ }
2237
+ .editor-md-preview hr {
2238
+ border: none;
2239
+ border-top: 1px solid #3e4451;
2240
+ margin: 1.5em 0;
2241
+ }
2242
+ .editor-md-preview ul,
2243
+ .editor-md-preview ol {
2244
+ padding-left: 1.6em;
2245
+ }
2246
+ .editor-md-preview img {
2247
+ max-width: 100%;
2248
+ }
2249
+
2250
+ @media (max-width: 800px) {
2251
+ .editor-shell {
2252
+ height: calc(100vh - 100px);
2253
+ }
2254
+ .editor-body {
2255
+ flex-direction: column;
2256
+ }
2257
+ .editor-side {
2258
+ width: 100%;
2259
+ max-height: 200px;
2260
+ border-right: none;
2261
+ border-bottom: 1px solid var(--border);
2262
+ }
2263
+ .editor-side.collapsed {
2264
+ width: 100%;
2265
+ max-height: 32px;
2266
+ }
2267
+ }
2268
+
2269
+ /* ---------- Bars / charts ---------- */
2270
+
2271
+ .bar {
2272
+ background: var(--bg-3);
2273
+ border-radius: var(--radius-sm);
2274
+ overflow: hidden;
2275
+ height: 8px;
2276
+ position: relative;
2277
+ }
2278
+
2279
+ .bar > .fill {
2280
+ height: 100%;
2281
+ background: var(--gradient-rule);
2282
+ }
2283
+
2284
+ .spinner {
2285
+ display: inline-block;
2286
+ width: 12px;
2287
+ height: 12px;
2288
+ border: 2px solid var(--border);
2289
+ border-top-color: var(--primary);
2290
+ border-radius: 50%;
2291
+ animation: spin 0.8s linear infinite;
2292
+ vertical-align: middle;
2293
+ }
2294
+
2295
+ @keyframes spin {
2296
+ to {
2297
+ transform: rotate(360deg);
2298
+ }
2299
+ }
2300
+
2301
+ /* ---------- Notice / banners ---------- */
2302
+
2303
+ .notice {
2304
+ padding: 10px 14px;
2305
+ border-radius: var(--radius-md);
2306
+ border-left: 3px solid var(--accent);
2307
+ background: rgba(196, 181, 253, 0.06);
2308
+ margin-bottom: 16px;
2309
+ font-size: 13px;
2310
+ color: var(--fg-1);
2311
+ }
2312
+
2313
+ .notice.warn {
2314
+ border-left-color: var(--warn);
2315
+ background: rgba(251, 191, 36, 0.05);
2316
+ }
2317
+
2318
+ .notice.err {
2319
+ border-left-color: var(--err);
2320
+ background: rgba(248, 113, 113, 0.05);
2321
+ color: var(--err);
2322
+ }
2323
+
2324
+ /* ---------- Code-ish inline ---------- */
2325
+
2326
+ code,
2327
+ .mono {
2328
+ font-family: var(--mono);
2329
+ background: var(--bg-2);
2330
+ padding: 1px 6px;
2331
+ border-radius: var(--radius-sm);
2332
+ font-size: 12px;
2333
+ color: var(--primary);
2334
+ }
2335
+
2336
+ /* ---------- Empty state ---------- */
2337
+
2338
+ .empty {
2339
+ padding: 28px;
2340
+ text-align: center;
2341
+ color: var(--fg-3);
2342
+ font-family: var(--mono);
2343
+ font-size: 13px;
2344
+ border: 1px dashed var(--border);
2345
+ border-radius: var(--radius-md);
2346
+ }