@oxy-hq/sdk 2.3.0 → 2.5.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.
package/dist/shell.css ADDED
@@ -0,0 +1,1263 @@
1
+ /* ============================================================================
2
+ @oxy-hq/sdk/shell — workspace chrome styles (icon rail + universal top bar)
3
+
4
+ Namespaced (`oxy-shell-*`) and self-contained: no Tailwind required in the
5
+ consuming app. Every color resolves through a two-level token scheme:
6
+
7
+ --oxy-shell-<name>: var(--<host token>, <pinned fallback>);
8
+
9
+ Inside the Oxygen web-app the host tokens (--sidebar-background, --border,
10
+ …) exist, so the shell tracks the product theme exactly. In an external
11
+ customer app the pinned fallbacks apply — their values are copied verbatim
12
+ from web-app/src/styles/shadcn/{light,dark}.css and must be kept in sync
13
+ with that file, not restyled here.
14
+
15
+ Dark mode: a `.dark` class on the scope element or any ancestor — the same
16
+ contract as the web-app (`data-theme` is decorative there; no CSS keys on
17
+ it). `color-scheme` is intentionally not set: the host app owns it.
18
+ ============================================================================ */
19
+
20
+ .oxy-shell-scope {
21
+ --oxy-shell-sidebar-bg: var(--sidebar-background, #fafafa);
22
+ --oxy-shell-sidebar-accent: var(--sidebar-accent, rgba(228, 228, 231, 0.5));
23
+ --oxy-shell-sidebar-accent-fg: var(--sidebar-accent-foreground, #18181b);
24
+ --oxy-shell-sidebar-border: var(--sidebar-border, #e5e7eb);
25
+ --oxy-shell-background: var(--background, #ffffff);
26
+ --oxy-shell-foreground: var(--foreground, #0a0a0a);
27
+ --oxy-shell-muted: var(--muted, #e4e4e7);
28
+ --oxy-shell-muted-fg: var(--muted-foreground, #52525b);
29
+ --oxy-shell-primary: var(--primary, #18181b);
30
+ --oxy-shell-primary-fg: var(--primary-foreground, #fafafa);
31
+ --oxy-shell-accent: var(--accent, #f5f5f5);
32
+ --oxy-shell-border: var(--border, #d4d4d8);
33
+ --oxy-shell-ring: var(--ring, #a1a1a1);
34
+ --oxy-shell-success: var(--success, #22c55e);
35
+ --oxy-shell-destructive: var(--destructive, #e7000b);
36
+ --oxy-shell-tooltip-bg: var(--zinc-200, #e4e4e7);
37
+ --oxy-shell-link: var(--info, #2563eb);
38
+ --oxy-shell-radius: var(--radius, 0.625rem);
39
+ --oxy-shell-font: var(--font-inter, "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif);
40
+ --oxy-shell-font-mono: ui-monospace, "SF Mono", Menlo, monospace;
41
+
42
+ font-family: var(--oxy-shell-font);
43
+ }
44
+
45
+ .dark .oxy-shell-scope,
46
+ .oxy-shell-scope.dark {
47
+ --oxy-shell-sidebar-bg: var(--sidebar-background, #000000);
48
+ --oxy-shell-sidebar-accent: var(--sidebar-accent, rgba(255, 255, 255, 0.145));
49
+ --oxy-shell-sidebar-accent-fg: var(--sidebar-accent-foreground, #ededed);
50
+ --oxy-shell-sidebar-border: var(--sidebar-border, #27272a);
51
+ --oxy-shell-background: var(--background, #0a0a0a);
52
+ --oxy-shell-foreground: var(--foreground, #ededed);
53
+ --oxy-shell-muted: var(--muted, #27272a);
54
+ --oxy-shell-muted-fg: var(--muted-foreground, #a1a1aa);
55
+ --oxy-shell-primary: var(--primary, #ededed);
56
+ --oxy-shell-primary-fg: var(--primary-foreground, #0a0a0a);
57
+ --oxy-shell-accent: var(--accent, #262626);
58
+ --oxy-shell-border: var(--border, rgba(255, 255, 255, 0.145));
59
+ --oxy-shell-ring: var(--ring, #525252);
60
+ --oxy-shell-success: var(--success, #22c55e);
61
+ --oxy-shell-destructive: var(--destructive, #ff6467);
62
+ --oxy-shell-tooltip-bg: var(--muted, #27272a);
63
+ --oxy-shell-link: var(--info, #60a5fa);
64
+ }
65
+
66
+ /* ─── Frame (OxyShell / ShellLayout) ────────────────────────────────────── */
67
+
68
+ .oxy-shell {
69
+ position: relative; /* portal anchor for tooltips */
70
+ display: flex;
71
+ height: 100%;
72
+ width: 100%;
73
+ background: var(--oxy-shell-background);
74
+ color: var(--oxy-shell-foreground);
75
+ }
76
+
77
+ /* Degraded (bootstrap unavailable): the wrappers stay mounted so the app
78
+ tree never reparents, but they impose nothing — no chrome, no colors,
79
+ no font, no scroll trap. */
80
+ .oxy-shell--degraded,
81
+ .oxy-shell--degraded .oxy-shell__main {
82
+ background: transparent;
83
+ color: inherit;
84
+ font-family: inherit;
85
+ }
86
+
87
+ .oxy-shell--degraded .oxy-shell__main {
88
+ overflow: visible;
89
+ }
90
+
91
+ .oxy-shell__content-col {
92
+ display: flex;
93
+ height: 100%;
94
+ min-width: 0;
95
+ flex: 1;
96
+ flex-direction: column;
97
+ }
98
+
99
+ .oxy-shell__main {
100
+ position: relative;
101
+ display: flex;
102
+ height: 100%;
103
+ min-height: 0;
104
+ min-width: 0;
105
+ flex: 1;
106
+ flex-direction: column;
107
+ background: var(--oxy-shell-background);
108
+ /* `auto`, not `hidden`: bundle content flows naturally and scrolls
109
+ inside the frame; apps that manage their own scroll regions are
110
+ unaffected. */
111
+ overflow: auto;
112
+ }
113
+
114
+ /* ─── Icon rail ─────────────────────────────────────────────────────────── */
115
+
116
+ .oxy-rail {
117
+ display: flex;
118
+ height: 100%;
119
+ width: 3rem; /* 48px — matches the web-app rail */
120
+ flex-shrink: 0;
121
+ flex-direction: column;
122
+ /* border color: the web-app frame borders resolve to --border (the global
123
+ base rule), NOT --sidebar-border — only the group divider uses that. */
124
+ border-right: 1px solid var(--oxy-shell-border);
125
+ background: var(--oxy-shell-sidebar-bg);
126
+ }
127
+
128
+ /* Fixed 3rem so the logo cell matches the top bar height exactly — the two
129
+ bottom borders line up into one continuous divider. */
130
+ .oxy-rail__top {
131
+ display: flex;
132
+ height: 3rem;
133
+ flex-shrink: 0;
134
+ flex-direction: column;
135
+ align-items: center;
136
+ justify-content: center;
137
+ border-bottom: 1px solid var(--oxy-shell-border);
138
+ padding: 0 0.25rem;
139
+ }
140
+
141
+ .oxy-rail__nav {
142
+ display: flex;
143
+ min-height: 0;
144
+ flex: 1;
145
+ flex-direction: column;
146
+ align-items: center;
147
+ gap: 0.25rem;
148
+ overflow-y: auto;
149
+ padding: 0.5rem 0.25rem;
150
+ }
151
+
152
+ .oxy-rail__divider {
153
+ margin: 0.25rem 0;
154
+ height: 1px;
155
+ width: 1.25rem;
156
+ flex-shrink: 0;
157
+ background: var(--oxy-shell-sidebar-border);
158
+ }
159
+
160
+ .oxy-rail__footer {
161
+ margin-top: auto;
162
+ display: flex;
163
+ flex-direction: column;
164
+ align-items: center;
165
+ gap: 0.25rem;
166
+ padding-top: 0.5rem;
167
+ }
168
+
169
+ .oxy-rail__bottom {
170
+ display: flex;
171
+ flex-shrink: 0;
172
+ flex-direction: column;
173
+ align-items: center;
174
+ gap: 0.25rem;
175
+ border-top: 1px solid var(--oxy-shell-border);
176
+ padding: 0.5rem 0.25rem;
177
+ }
178
+
179
+ /* Rail entry — replicates the web-app ghost icon Button + itemClasses. */
180
+ .oxy-rail__item {
181
+ display: inline-flex;
182
+ height: 2rem;
183
+ width: 2rem;
184
+ flex-shrink: 0;
185
+ align-items: center;
186
+ justify-content: center;
187
+ border: none;
188
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
189
+ background: transparent;
190
+ color: var(--oxy-shell-foreground);
191
+ padding: 0;
192
+ margin: 0;
193
+ cursor: pointer;
194
+ text-decoration: none;
195
+ opacity: 0.6;
196
+ outline: none;
197
+ transition:
198
+ color 0.15s,
199
+ opacity 0.15s,
200
+ box-shadow 0.15s;
201
+ }
202
+
203
+ .oxy-rail__item:hover {
204
+ opacity: 1;
205
+ background: var(--oxy-shell-accent);
206
+ }
207
+
208
+ .oxy-rail__item:focus-visible {
209
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
210
+ }
211
+
212
+ .oxy-rail__item--active {
213
+ opacity: 1;
214
+ background: var(--oxy-shell-sidebar-accent);
215
+ color: var(--oxy-shell-sidebar-accent-fg);
216
+ }
217
+
218
+ .oxy-rail__item--active:hover {
219
+ /* Matches the original ghost Button: hover:bg-accent applies even on the
220
+ active item. */
221
+ background: var(--oxy-shell-accent);
222
+ }
223
+
224
+ .oxy-rail__item svg {
225
+ pointer-events: none;
226
+ flex-shrink: 0;
227
+ }
228
+
229
+ /* Replicates the shadcn Button rule [&_svg:not([class*='size-'])]:size-4 —
230
+ unsized icons clamp to 16px. */
231
+ .oxy-rail__item svg:not([class*="size-"]) {
232
+ height: 1rem;
233
+ width: 1rem;
234
+ }
235
+
236
+ .oxy-rail__item-img {
237
+ height: 1.25rem;
238
+ width: 1.25rem;
239
+ border-radius: calc(var(--oxy-shell-radius) - 4px);
240
+ object-fit: contain;
241
+ }
242
+
243
+ .oxy-rail__item-letter {
244
+ font-size: 12px;
245
+ line-height: 1;
246
+ font-weight: 600;
247
+ color: var(--oxy-shell-primary);
248
+ }
249
+
250
+ /* ─── Workspace tile ────────────────────────────────────────────────────── */
251
+
252
+ .oxy-workspace-tile {
253
+ display: flex;
254
+ height: 2rem;
255
+ width: 2rem;
256
+ align-items: center;
257
+ justify-content: center;
258
+ overflow: hidden;
259
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
260
+ background: color-mix(in srgb, var(--oxy-shell-primary) 10%, transparent);
261
+ }
262
+
263
+ .oxy-workspace-tile__img {
264
+ height: 100%;
265
+ width: 100%;
266
+ object-fit: contain;
267
+ }
268
+
269
+ .oxy-workspace-tile__letter {
270
+ font-size: 12px;
271
+ line-height: 1;
272
+ font-weight: 700;
273
+ color: var(--oxy-shell-primary);
274
+ }
275
+
276
+ /* ─── Top bar ───────────────────────────────────────────────────────────── */
277
+
278
+ .oxy-topbar {
279
+ display: flex;
280
+ height: 3rem;
281
+ flex-shrink: 0;
282
+ align-items: center;
283
+ gap: 0.75rem;
284
+ border-bottom: 1px solid var(--oxy-shell-border);
285
+ background: var(--oxy-shell-sidebar-bg);
286
+ padding: 0 0.75rem;
287
+ }
288
+
289
+ .oxy-topbar__right {
290
+ margin-left: auto;
291
+ display: flex;
292
+ align-items: center;
293
+ gap: 0.75rem;
294
+ }
295
+
296
+ /* ─── Breadcrumb ────────────────────────────────────────────────────────── */
297
+
298
+ .oxy-breadcrumb {
299
+ display: flex;
300
+ min-width: 0;
301
+ align-items: center;
302
+ gap: 0.5rem;
303
+ font-size: 14px;
304
+ line-height: 1.4;
305
+ }
306
+
307
+ .oxy-breadcrumb__workspace {
308
+ flex-shrink: 0;
309
+ font-weight: 500;
310
+ color: var(--oxy-shell-foreground);
311
+ text-decoration: none;
312
+ transition: opacity 0.15s;
313
+ }
314
+
315
+ .oxy-breadcrumb__workspace:hover {
316
+ opacity: 0.7;
317
+ }
318
+
319
+ .oxy-breadcrumb__sep {
320
+ color: color-mix(in srgb, var(--oxy-shell-muted-fg) 40%, transparent);
321
+ }
322
+
323
+ .oxy-breadcrumb__page {
324
+ overflow: hidden;
325
+ text-overflow: ellipsis;
326
+ white-space: nowrap;
327
+ color: var(--oxy-shell-muted-fg);
328
+ }
329
+
330
+ /* ─── System indicator ──────────────────────────────────────────────────── */
331
+
332
+ .oxy-sysind {
333
+ display: none;
334
+ align-items: center;
335
+ gap: 0.375rem;
336
+ font-family: var(--oxy-shell-font-mono);
337
+ font-size: 12px;
338
+ color: var(--oxy-shell-muted-fg);
339
+ }
340
+
341
+ .oxy-sysind__state {
342
+ display: inline-flex;
343
+ align-items: center;
344
+ gap: 0.25rem;
345
+ }
346
+
347
+ .oxy-sysind__state--online {
348
+ color: var(--oxy-shell-success);
349
+ }
350
+
351
+ .oxy-sysind__state--offline {
352
+ color: var(--oxy-shell-destructive);
353
+ }
354
+
355
+ .oxy-sysind__dot-wrap {
356
+ position: relative;
357
+ display: inline-flex;
358
+ height: 0.375rem;
359
+ width: 0.375rem;
360
+ }
361
+
362
+ .oxy-sysind__dot {
363
+ position: relative;
364
+ display: inline-flex;
365
+ height: 0.375rem;
366
+ width: 0.375rem;
367
+ border-radius: 9999px;
368
+ }
369
+
370
+ .oxy-sysind__dot--online {
371
+ background: var(--oxy-shell-success);
372
+ }
373
+
374
+ .oxy-sysind__dot--offline {
375
+ background: var(--oxy-shell-destructive);
376
+ }
377
+
378
+ .oxy-sysind__ping {
379
+ position: absolute;
380
+ display: inline-flex;
381
+ height: 0.375rem;
382
+ width: 0.375rem;
383
+ border-radius: 9999px;
384
+ background: var(--oxy-shell-success);
385
+ opacity: 0.75;
386
+ animation: oxy-shell-ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
387
+ }
388
+
389
+ @keyframes oxy-shell-ping {
390
+ 75%,
391
+ 100% {
392
+ transform: scale(2);
393
+ opacity: 0;
394
+ }
395
+ }
396
+
397
+ /* ─── Clock ─────────────────────────────────────────────────────────────── */
398
+
399
+ .oxy-clock {
400
+ display: none;
401
+ font-family: var(--oxy-shell-font-mono);
402
+ font-size: 12px;
403
+ font-variant-numeric: tabular-nums;
404
+ color: var(--oxy-shell-muted-fg);
405
+ }
406
+
407
+ @media (min-width: 640px) {
408
+ .oxy-sysind {
409
+ display: inline-flex;
410
+ }
411
+
412
+ .oxy-clock {
413
+ display: inline;
414
+ }
415
+ }
416
+
417
+ /* ─── Tooltip (Radix content, portaled into the shell scope) ────────────── */
418
+
419
+ .oxy-shell-tooltip {
420
+ z-index: 50;
421
+ width: fit-content;
422
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
423
+ background: var(--oxy-shell-tooltip-bg);
424
+ color: var(--oxy-shell-foreground);
425
+ padding: 0.375rem 0.75rem;
426
+ font-family: var(--oxy-shell-font);
427
+ font-size: 12px;
428
+ font-weight: 400;
429
+ line-height: 1.5;
430
+ text-wrap: balance;
431
+ box-shadow:
432
+ 0 4px 6px -1px rgb(0 0 0 / 0.1),
433
+ 0 2px 4px -2px rgb(0 0 0 / 0.1);
434
+ animation: oxy-shell-tooltip-in 0.15s ease-out;
435
+ }
436
+
437
+ /* Side-aware entry slide (0.5rem, mirroring the web-app's
438
+ data-[side=*]:slide-in-from-*-2) and an exit animation — Radix keeps the
439
+ content mounted until the closed-state animation finishes. */
440
+ .oxy-shell-tooltip[data-side="right"] {
441
+ --oxy-shell-tip-slide: translateX(-0.5rem);
442
+ }
443
+
444
+ .oxy-shell-tooltip[data-side="left"] {
445
+ --oxy-shell-tip-slide: translateX(0.5rem);
446
+ }
447
+
448
+ .oxy-shell-tooltip[data-side="top"] {
449
+ --oxy-shell-tip-slide: translateY(0.5rem);
450
+ }
451
+
452
+ .oxy-shell-tooltip[data-side="bottom"] {
453
+ --oxy-shell-tip-slide: translateY(-0.5rem);
454
+ }
455
+
456
+ .oxy-shell-tooltip[data-state="closed"] {
457
+ animation: oxy-shell-tooltip-out 0.15s ease-in forwards;
458
+ }
459
+
460
+ @keyframes oxy-shell-tooltip-out {
461
+ from {
462
+ opacity: 1;
463
+ transform: none;
464
+ }
465
+
466
+ to {
467
+ opacity: 0;
468
+ transform: scale(0.95);
469
+ }
470
+ }
471
+
472
+ .oxy-shell-tooltip__arrow {
473
+ z-index: 50;
474
+ height: 0.625rem;
475
+ width: 0.625rem;
476
+ translate: 0 calc(-50% - 2px);
477
+ rotate: 45deg;
478
+ border-radius: 2px;
479
+ background: var(--oxy-shell-tooltip-bg);
480
+ fill: var(--oxy-shell-tooltip-bg);
481
+ }
482
+
483
+ @keyframes oxy-shell-tooltip-in {
484
+ from {
485
+ opacity: 0;
486
+ transform: var(--oxy-shell-tip-slide, none) scale(0.95);
487
+ }
488
+
489
+ to {
490
+ opacity: 1;
491
+ transform: none;
492
+ }
493
+ }
494
+
495
+ /* ─── Ask Oxygen button (top bar) ───────────────────────────────────────── */
496
+
497
+ .oxy-askbtn {
498
+ display: flex;
499
+ align-items: center;
500
+ gap: 0.375rem;
501
+ border: 1px solid var(--oxy-shell-border);
502
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
503
+ background: transparent;
504
+ padding: 0.25rem 0.5rem;
505
+ font-family: var(--oxy-shell-font);
506
+ font-size: 12px;
507
+ color: var(--oxy-shell-muted-fg);
508
+ cursor: pointer;
509
+ transition:
510
+ color 0.15s,
511
+ border-color 0.15s,
512
+ background 0.15s;
513
+ }
514
+
515
+ .oxy-askbtn:hover {
516
+ border-color: color-mix(in srgb, var(--oxy-shell-primary) 40%, transparent);
517
+ color: var(--oxy-shell-foreground);
518
+ }
519
+
520
+ .oxy-askbtn--open {
521
+ border-color: color-mix(in srgb, var(--oxy-shell-primary) 40%, transparent);
522
+ background: color-mix(in srgb, var(--oxy-shell-primary) 10%, transparent);
523
+ color: var(--oxy-shell-foreground);
524
+ }
525
+
526
+ .oxy-askbtn:focus-visible {
527
+ outline: none;
528
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
529
+ }
530
+
531
+ .oxy-askbtn__mark {
532
+ width: 0.875rem;
533
+ height: 0.875rem;
534
+ color: var(--oxy-shell-primary);
535
+ }
536
+
537
+ .oxy-askbtn__label,
538
+ .oxy-askbtn__kbd {
539
+ display: none;
540
+ }
541
+
542
+ .oxy-askbtn__kbd {
543
+ border-radius: 4px;
544
+ background: var(--oxy-shell-muted);
545
+ padding: 0.125rem 0.375rem;
546
+ font-family: var(--oxy-shell-font-mono);
547
+ font-size: 10px;
548
+ line-height: 1.2;
549
+ }
550
+
551
+ @media (min-width: 640px) {
552
+ .oxy-askbtn__label {
553
+ display: inline;
554
+ }
555
+
556
+ .oxy-askbtn__kbd {
557
+ display: inline-block;
558
+ }
559
+ }
560
+
561
+ /* ─── Ask Oxygen dock ───────────────────────────────────────────────────── */
562
+
563
+ .oxy-askdock {
564
+ display: flex;
565
+ height: 100%;
566
+ width: min(23rem, 85vw);
567
+ flex-shrink: 0;
568
+ flex-direction: column;
569
+ min-width: 0;
570
+ border-left: 1px solid var(--oxy-shell-border);
571
+ background: var(--oxy-shell-background);
572
+ color: var(--oxy-shell-foreground);
573
+ overflow: hidden;
574
+ transition: width 0.2s ease;
575
+ }
576
+
577
+ .oxy-askdock--closed {
578
+ width: 0;
579
+ border-left-width: 0;
580
+ visibility: hidden;
581
+ }
582
+
583
+ .oxy-askdock__head {
584
+ display: flex;
585
+ height: 3rem;
586
+ flex-shrink: 0;
587
+ align-items: center;
588
+ gap: 0.5rem;
589
+ border-bottom: 1px solid var(--oxy-shell-border);
590
+ padding: 0 0.75rem;
591
+ }
592
+
593
+ .oxy-askdock__mark {
594
+ width: 1rem;
595
+ height: 1rem;
596
+ flex-shrink: 0;
597
+ color: var(--oxy-shell-primary);
598
+ }
599
+
600
+ .oxy-askdock__title {
601
+ font-size: 14px;
602
+ font-weight: 600;
603
+ white-space: nowrap;
604
+ }
605
+
606
+ .oxy-askdock__actions {
607
+ margin-left: auto;
608
+ display: flex;
609
+ align-items: center;
610
+ gap: 0.25rem;
611
+ }
612
+
613
+ .oxy-askdock__iconbtn {
614
+ display: inline-flex;
615
+ height: 1.75rem;
616
+ width: 1.75rem;
617
+ align-items: center;
618
+ justify-content: center;
619
+ border: none;
620
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
621
+ background: transparent;
622
+ color: var(--oxy-shell-muted-fg);
623
+ cursor: pointer;
624
+ transition:
625
+ color 0.15s,
626
+ background 0.15s;
627
+ }
628
+
629
+ .oxy-askdock__iconbtn:hover {
630
+ background: var(--oxy-shell-accent);
631
+ color: var(--oxy-shell-foreground);
632
+ }
633
+
634
+ .oxy-askdock__iconbtn:focus-visible {
635
+ outline: none;
636
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
637
+ }
638
+
639
+ .oxy-askdock__iconbtn:disabled {
640
+ cursor: default;
641
+ opacity: 0.35;
642
+ }
643
+
644
+ .oxy-askdock__iconbtn:disabled:hover {
645
+ background: transparent;
646
+ color: var(--oxy-shell-muted-fg);
647
+ }
648
+
649
+ .oxy-askdock__iconbtn--active {
650
+ background: var(--oxy-shell-accent);
651
+ color: var(--oxy-shell-foreground);
652
+ }
653
+
654
+ /* ─── Chat history (session-scoped) ─────────────────────────────────────── */
655
+
656
+ .oxy-askdock__history {
657
+ display: flex;
658
+ min-height: 0;
659
+ flex: 1;
660
+ flex-direction: column;
661
+ overflow-y: auto;
662
+ padding: 0.5rem;
663
+ gap: 0.25rem;
664
+ }
665
+
666
+ .oxy-askdock__history-empty {
667
+ margin: 0.75rem 0.5rem;
668
+ font-size: 12.5px;
669
+ color: var(--oxy-shell-muted-fg);
670
+ }
671
+
672
+ .oxy-askdock__history-search {
673
+ display: flex;
674
+ align-items: center;
675
+ gap: 0.5rem;
676
+ margin-bottom: 0.25rem;
677
+ padding: 0.5rem 0.625rem;
678
+ border: 1px solid var(--oxy-shell-border);
679
+ border-radius: var(--oxy-shell-radius);
680
+ color: var(--oxy-shell-muted-fg);
681
+ }
682
+
683
+ .oxy-askdock__history-search:focus-within {
684
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--oxy-shell-ring) 45%, transparent);
685
+ }
686
+
687
+ .oxy-askdock__history-search svg {
688
+ flex: none;
689
+ }
690
+
691
+ .oxy-askdock__history-searchinput {
692
+ flex: 1;
693
+ min-width: 0;
694
+ border: none;
695
+ background: transparent;
696
+ outline: none;
697
+ color: var(--oxy-shell-foreground);
698
+ font-family: var(--oxy-shell-font);
699
+ font-size: 13px;
700
+ }
701
+
702
+ .oxy-askdock__history-searchinput::placeholder {
703
+ color: var(--oxy-shell-muted-fg);
704
+ }
705
+
706
+ .oxy-askdock__history-more {
707
+ align-self: center;
708
+ margin-top: 0.25rem;
709
+ padding: 0.5rem 0.75rem;
710
+ border: none;
711
+ background: transparent;
712
+ color: var(--oxy-shell-muted-fg);
713
+ font-family: var(--oxy-shell-font);
714
+ font-size: 11px;
715
+ font-weight: 600;
716
+ letter-spacing: 0.05em;
717
+ text-transform: uppercase;
718
+ cursor: pointer;
719
+ transition: color 0.15s;
720
+ }
721
+
722
+ .oxy-askdock__history-more:hover {
723
+ color: var(--oxy-shell-foreground);
724
+ }
725
+
726
+ .oxy-askdock__history-item {
727
+ display: flex;
728
+ flex-direction: row;
729
+ align-items: center;
730
+ gap: 0.5rem;
731
+ width: 100%;
732
+ border: none;
733
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
734
+ background: transparent;
735
+ padding: 0.5rem 0.625rem;
736
+ font-family: var(--oxy-shell-font);
737
+ text-align: left;
738
+ cursor: pointer;
739
+ transition: background 0.15s;
740
+ }
741
+
742
+ .oxy-askdock__history-icon {
743
+ display: inline-flex;
744
+ flex: none;
745
+ color: var(--oxy-shell-muted-fg);
746
+ }
747
+
748
+ .oxy-askdock__history-item:hover {
749
+ background: var(--oxy-shell-accent);
750
+ }
751
+
752
+ .oxy-askdock__history-item:focus-visible {
753
+ outline: none;
754
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
755
+ }
756
+
757
+ /* The conversation currently open in the dock — kept in the list (not hidden)
758
+ and highlighted with the same background as :hover, plus a bolder title so
759
+ the current chat stays distinguishable from a merely-hovered one. */
760
+ .oxy-askdock__history-item--active {
761
+ background: var(--oxy-shell-accent);
762
+ }
763
+
764
+ .oxy-askdock__history-item--active .oxy-askdock__history-title {
765
+ font-weight: 600;
766
+ }
767
+
768
+ .oxy-askdock__history-title {
769
+ flex: 1;
770
+ min-width: 0;
771
+ overflow: hidden;
772
+ text-overflow: ellipsis;
773
+ white-space: nowrap;
774
+ font-size: 13px;
775
+ color: var(--oxy-shell-foreground);
776
+ }
777
+
778
+ .oxy-askdock__history-time {
779
+ flex: none;
780
+ font-size: 12px;
781
+ color: var(--oxy-shell-muted-fg);
782
+ white-space: nowrap;
783
+ }
784
+
785
+ .oxy-askdock__scroll {
786
+ display: flex;
787
+ min-height: 0;
788
+ flex: 1;
789
+ flex-direction: column;
790
+ overflow-y: auto;
791
+ padding: 0.75rem;
792
+ }
793
+
794
+ .oxy-askdock__chips {
795
+ display: flex;
796
+ flex-direction: column;
797
+ align-items: flex-start;
798
+ gap: 0.5rem;
799
+ }
800
+
801
+ .oxy-askdock__chip {
802
+ border: 1px solid var(--oxy-shell-border);
803
+ border-radius: 999px;
804
+ background: transparent;
805
+ padding: 0.375rem 0.75rem;
806
+ font-family: var(--oxy-shell-font);
807
+ font-size: 12.5px;
808
+ text-align: left;
809
+ color: var(--oxy-shell-foreground);
810
+ cursor: pointer;
811
+ transition: background 0.15s;
812
+ }
813
+
814
+ .oxy-askdock__chip:hover {
815
+ background: var(--oxy-shell-accent);
816
+ }
817
+
818
+ .oxy-askdock__chip:focus-visible {
819
+ outline: none;
820
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
821
+ }
822
+
823
+ .oxy-askdock__turn {
824
+ display: flex;
825
+ flex-direction: column;
826
+ font-size: 13.5px;
827
+ }
828
+
829
+ .oxy-askdock__q {
830
+ align-self: flex-end;
831
+ max-width: 85%;
832
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
833
+ background: var(--oxy-shell-muted);
834
+ padding: 0.375rem 0.625rem;
835
+ margin: 0.5rem 0 0.375rem;
836
+ white-space: pre-wrap;
837
+ overflow-wrap: anywhere;
838
+ }
839
+
840
+ .oxy-askdock__composer {
841
+ margin: 0.75rem;
842
+ flex-shrink: 0;
843
+ border: 1px solid var(--oxy-shell-border);
844
+ border-radius: var(--oxy-shell-radius);
845
+ padding: 0.625rem;
846
+ transition: border-color 0.15s;
847
+ }
848
+
849
+ .oxy-askdock__composer:focus-within {
850
+ border-color: var(--oxy-shell-ring);
851
+ }
852
+
853
+ .oxy-askdock__input {
854
+ display: block;
855
+ width: 100%;
856
+ border: none;
857
+ outline: none;
858
+ resize: none;
859
+ background: transparent;
860
+ color: var(--oxy-shell-foreground);
861
+ font-family: var(--oxy-shell-font);
862
+ font-size: 13.5px;
863
+ line-height: 1.5;
864
+ }
865
+
866
+ .oxy-askdock__input::placeholder {
867
+ color: var(--oxy-shell-muted-fg);
868
+ }
869
+
870
+ .oxy-askdock__composer-row {
871
+ display: flex;
872
+ justify-content: flex-end;
873
+ }
874
+
875
+ .oxy-askdock__send {
876
+ display: inline-flex;
877
+ height: 1.75rem;
878
+ width: 1.75rem;
879
+ align-items: center;
880
+ justify-content: center;
881
+ border: none;
882
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
883
+ background: var(--oxy-shell-primary);
884
+ color: var(--oxy-shell-primary-fg);
885
+ cursor: pointer;
886
+ transition: opacity 0.15s;
887
+ }
888
+
889
+ .oxy-askdock__send:disabled {
890
+ cursor: default;
891
+ opacity: 0.35;
892
+ }
893
+
894
+ .oxy-askdock__send:focus-visible {
895
+ outline: none;
896
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
897
+ }
898
+
899
+ /* ─── Reasoning trace (Ask dock) ────────────────────────────────────────── */
900
+
901
+ .oxy-trace {
902
+ margin: 0.375rem 0;
903
+ border: 1px solid var(--oxy-shell-border);
904
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
905
+ font-size: 12px;
906
+ color: var(--oxy-shell-muted-fg);
907
+ overflow: hidden;
908
+ }
909
+
910
+ .oxy-trace__head {
911
+ display: flex;
912
+ width: 100%;
913
+ align-items: center;
914
+ gap: 0.375rem;
915
+ border: none;
916
+ background: transparent;
917
+ padding: 0.375rem 0.625rem;
918
+ font-family: var(--oxy-shell-font);
919
+ font-size: 12px;
920
+ color: var(--oxy-shell-muted-fg);
921
+ cursor: pointer;
922
+ text-align: left;
923
+ }
924
+
925
+ .oxy-trace__head:hover {
926
+ color: var(--oxy-shell-foreground);
927
+ }
928
+
929
+ .oxy-trace__head:focus-visible {
930
+ outline: none;
931
+ box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
932
+ }
933
+
934
+ .oxy-trace__title {
935
+ font-weight: 600;
936
+ color: var(--oxy-shell-foreground);
937
+ }
938
+
939
+ .oxy-trace__meta {
940
+ color: var(--oxy-shell-muted-fg);
941
+ }
942
+
943
+ .oxy-trace__body {
944
+ display: flex;
945
+ flex-direction: column;
946
+ gap: 0.375rem;
947
+ border-top: 1px solid var(--oxy-shell-border);
948
+ padding: 0.5rem 0.625rem;
949
+ }
950
+
951
+ .oxy-trace__step {
952
+ display: flex;
953
+ flex-direction: column;
954
+ gap: 0.25rem;
955
+ }
956
+
957
+ .oxy-trace__step-row {
958
+ display: flex;
959
+ align-items: baseline;
960
+ gap: 0.375rem;
961
+ min-width: 0;
962
+ }
963
+
964
+ .oxy-trace__label {
965
+ flex-shrink: 0;
966
+ font-weight: 500;
967
+ color: var(--oxy-shell-foreground);
968
+ }
969
+
970
+ .oxy-trace__summary {
971
+ min-width: 0;
972
+ overflow: hidden;
973
+ text-overflow: ellipsis;
974
+ white-space: nowrap;
975
+ color: var(--oxy-shell-muted-fg);
976
+ }
977
+
978
+ .oxy-trace__icon {
979
+ flex-shrink: 0;
980
+ width: 0.875rem;
981
+ text-align: center;
982
+ font-size: 10px;
983
+ }
984
+
985
+ .oxy-trace__icon--ok {
986
+ color: var(--oxy-shell-success);
987
+ }
988
+
989
+ .oxy-trace__icon--fail {
990
+ color: var(--oxy-shell-destructive);
991
+ }
992
+
993
+ .oxy-trace__icon--wait {
994
+ color: var(--oxy-shell-muted-fg);
995
+ }
996
+
997
+ .oxy-trace__items {
998
+ display: flex;
999
+ flex-direction: column;
1000
+ gap: 0.25rem;
1001
+ margin-left: 0.375rem;
1002
+ border-left: 2px solid var(--oxy-shell-border);
1003
+ padding-left: 0.75rem;
1004
+ }
1005
+
1006
+ .oxy-trace__row {
1007
+ display: flex;
1008
+ align-items: baseline;
1009
+ gap: 0.375rem;
1010
+ min-width: 0;
1011
+ font-size: 11.5px;
1012
+ }
1013
+
1014
+ .oxy-trace__row--error .oxy-trace__row-label,
1015
+ .oxy-trace__row--error .oxy-trace__row-detail {
1016
+ color: var(--oxy-shell-destructive);
1017
+ }
1018
+
1019
+ .oxy-trace__row-label {
1020
+ flex-shrink: 0;
1021
+ font-weight: 500;
1022
+ color: var(--oxy-shell-foreground);
1023
+ }
1024
+
1025
+ .oxy-trace__row-preview {
1026
+ min-width: 0;
1027
+ flex: 1;
1028
+ overflow: hidden;
1029
+ text-overflow: ellipsis;
1030
+ white-space: nowrap;
1031
+ color: var(--oxy-shell-muted-fg);
1032
+ }
1033
+
1034
+ .oxy-trace__row-detail {
1035
+ margin-left: auto;
1036
+ flex-shrink: 0;
1037
+ font-family: var(--oxy-shell-font-mono);
1038
+ font-size: 10.5px;
1039
+ color: var(--oxy-shell-muted-fg);
1040
+ }
1041
+
1042
+ .oxy-trace__think {
1043
+ margin: 0.125rem 0;
1044
+ font-size: 11.5px;
1045
+ line-height: 1.5;
1046
+ color: var(--oxy-shell-muted-fg);
1047
+ white-space: pre-wrap;
1048
+ overflow-wrap: anywhere;
1049
+ }
1050
+
1051
+ .oxy-trace__spin {
1052
+ display: inline-block;
1053
+ width: 0.625rem;
1054
+ height: 0.625rem;
1055
+ flex-shrink: 0;
1056
+ border-radius: 50%;
1057
+ border: 2px solid var(--oxy-shell-border);
1058
+ border-top-color: var(--oxy-shell-muted-fg);
1059
+ animation: oxy-shell-spin 0.8s linear infinite;
1060
+ }
1061
+
1062
+ .oxy-trace__spin--sm {
1063
+ width: 0.5rem;
1064
+ height: 0.5rem;
1065
+ border-width: 1.5px;
1066
+ }
1067
+
1068
+ @keyframes oxy-shell-spin {
1069
+ to {
1070
+ transform: rotate(360deg);
1071
+ }
1072
+ }
1073
+
1074
+ @media (prefers-reduced-motion: reduce) {
1075
+ .oxy-trace__spin {
1076
+ animation: none;
1077
+ }
1078
+ }
1079
+
1080
+ /* ─── Answer charts (chart_rendered blocks) ─────────────────────────────── */
1081
+
1082
+ .oxy-chart {
1083
+ margin: 0.5rem 0;
1084
+ border: 1px solid var(--oxy-shell-border);
1085
+ border-radius: calc(var(--oxy-shell-radius) - 2px);
1086
+ padding: 0.625rem 0.625rem 0.375rem;
1087
+ }
1088
+
1089
+ .oxy-chart__title {
1090
+ margin-bottom: 0.375rem;
1091
+ font-size: 12.5px;
1092
+ font-weight: 600;
1093
+ color: var(--oxy-shell-foreground);
1094
+ }
1095
+
1096
+ .oxy-chart__svg {
1097
+ display: block;
1098
+ width: 100%;
1099
+ height: auto;
1100
+ }
1101
+
1102
+ .oxy-chart__grid line {
1103
+ stroke: var(--oxy-shell-border);
1104
+ stroke-width: 0.5;
1105
+ }
1106
+
1107
+ /* Zero baseline for signed (negative-valued) bar/line charts — a touch
1108
+ stronger than the grid so it reads as the axis origin. */
1109
+ .oxy-chart__grid-zero {
1110
+ stroke: var(--oxy-shell-muted-fg);
1111
+ stroke-width: 1;
1112
+ }
1113
+
1114
+ .oxy-chart__tick {
1115
+ fill: var(--oxy-shell-muted-fg);
1116
+ font-family: var(--oxy-shell-font);
1117
+ font-size: 8px;
1118
+ }
1119
+
1120
+ .oxy-chart__legend {
1121
+ display: flex;
1122
+ flex-wrap: wrap;
1123
+ gap: 0.375rem 0.75rem;
1124
+ padding: 0.25rem 0 0.125rem;
1125
+ }
1126
+
1127
+ .oxy-chart__legend-item {
1128
+ display: inline-flex;
1129
+ align-items: center;
1130
+ gap: 0.25rem;
1131
+ font-size: 10.5px;
1132
+ color: var(--oxy-shell-muted-fg);
1133
+ }
1134
+
1135
+ .oxy-chart__legend-dot {
1136
+ width: 0.5rem;
1137
+ height: 0.5rem;
1138
+ border-radius: 2px;
1139
+ }
1140
+
1141
+ .oxy-chart__table-wrap {
1142
+ overflow-x: auto;
1143
+ }
1144
+
1145
+ .oxy-chart__table {
1146
+ width: 100%;
1147
+ border-collapse: collapse;
1148
+ font-size: 11.5px;
1149
+ }
1150
+
1151
+ .oxy-chart__table th {
1152
+ text-align: left;
1153
+ padding: 0.25rem 0.5rem;
1154
+ border-bottom: 1px solid var(--oxy-shell-border);
1155
+ font-weight: 600;
1156
+ color: var(--oxy-shell-foreground);
1157
+ }
1158
+
1159
+ .oxy-chart__table td {
1160
+ padding: 0.25rem 0.5rem;
1161
+ border-bottom: 1px solid var(--oxy-shell-border);
1162
+ color: var(--oxy-shell-muted-fg);
1163
+ }
1164
+
1165
+ .oxy-chart__note {
1166
+ padding: 0.25rem 0.5rem;
1167
+ font-size: 10.5px;
1168
+ color: var(--oxy-shell-muted-fg);
1169
+ }
1170
+
1171
+ /* Per-step detail toggle: running steps show their rows, finished steps
1172
+ collapse to the header line; the whole row is the toggle. */
1173
+ .oxy-trace__step-row--btn {
1174
+ width: 100%;
1175
+ border: none;
1176
+ background: transparent;
1177
+ padding: 0;
1178
+ font-family: var(--oxy-shell-font);
1179
+ font-size: 12px;
1180
+ cursor: pointer;
1181
+ text-align: left;
1182
+ }
1183
+
1184
+ .oxy-trace__step-row--btn:hover .oxy-trace__label {
1185
+ color: var(--oxy-shell-foreground);
1186
+ }
1187
+
1188
+ .oxy-trace__step-row--btn:focus-visible {
1189
+ outline: none;
1190
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
1191
+ border-radius: 4px;
1192
+ }
1193
+
1194
+ .oxy-trace__count {
1195
+ flex-shrink: 0;
1196
+ margin-left: auto;
1197
+ font-size: 10.5px;
1198
+ color: var(--oxy-shell-muted-fg);
1199
+ }
1200
+
1201
+ .oxy-trace__step-chevron {
1202
+ flex-shrink: 0;
1203
+ display: inline-flex;
1204
+ align-self: center;
1205
+ color: var(--oxy-shell-muted-fg);
1206
+ }
1207
+
1208
+ .oxy-trace__step-row--btn .oxy-trace__step-chevron:only-of-type,
1209
+ .oxy-trace__step-row--btn .oxy-trace__step-chevron {
1210
+ margin-left: 0.25rem;
1211
+ }
1212
+
1213
+ .oxy-trace__step-row--btn:not(:hover) .oxy-trace__step-chevron {
1214
+ opacity: 0.6;
1215
+ }
1216
+
1217
+ /* Expandable action detail: full tool input/output under the row. */
1218
+ .oxy-trace__item {
1219
+ display: flex;
1220
+ flex-direction: column;
1221
+ gap: 0.25rem;
1222
+ }
1223
+
1224
+ .oxy-trace__row--btn {
1225
+ width: 100%;
1226
+ border: none;
1227
+ background: transparent;
1228
+ padding: 0;
1229
+ font-family: var(--oxy-shell-font);
1230
+ cursor: pointer;
1231
+ text-align: left;
1232
+ }
1233
+
1234
+ .oxy-trace__row--btn:focus-visible {
1235
+ outline: none;
1236
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--oxy-shell-ring) 50%, transparent);
1237
+ border-radius: 4px;
1238
+ }
1239
+
1240
+ .oxy-trace__row--btn:not(:hover) .oxy-trace__step-chevron {
1241
+ opacity: 0.6;
1242
+ }
1243
+
1244
+ .oxy-trace__payloads {
1245
+ display: flex;
1246
+ flex-direction: column;
1247
+ gap: 0.25rem;
1248
+ }
1249
+
1250
+ /* Plain colored text, no card — matches the inline preview style. */
1251
+ .oxy-trace__payload {
1252
+ margin: 0 0 0 0.25rem;
1253
+ font-family: var(--oxy-shell-font-mono);
1254
+ font-size: 10.5px;
1255
+ line-height: 1.5;
1256
+ color: var(--oxy-shell-muted-fg);
1257
+ white-space: pre-wrap;
1258
+ overflow-wrap: anywhere;
1259
+ }
1260
+
1261
+ .oxy-trace__payload--out {
1262
+ color: var(--oxy-shell-success);
1263
+ }