@opentrace/components 0.1.1-rc.30 → 0.1.1-rc.44

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.
@@ -1,3 +1,1144 @@
1
+ /*
2
+ * Copyright 2026 OpenTrace Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ /* ── Backdrop ─────────────────────────────────── */
18
+ .modal-backdrop {
19
+ position: fixed;
20
+ inset: 0;
21
+ z-index: 100;
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ background: rgba(0, 0, 0, 0.6);
26
+ backdrop-filter: blur(4px);
27
+ }
28
+
29
+ /* ── Card ─────────────────────────────────────── */
30
+ .modal-card {
31
+ background: var(--card);
32
+ border: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
33
+ border-radius: calc(var(--radius) + 8px);
34
+ padding: 36px 32px 28px;
35
+ width: 460px;
36
+ max-width: 90vw;
37
+ box-shadow: var(--shadow-xl);
38
+ animation: modalEnter 0.25s ease-out;
39
+ }
40
+
41
+ .modal-card-wide {
42
+ width: 520px;
43
+ min-height: 340px;
44
+ overflow: hidden;
45
+ }
46
+
47
+ @keyframes modalEnter {
48
+ from {
49
+ opacity: 0;
50
+ transform: translateY(10px) scale(0.97);
51
+ }
52
+ to {
53
+ opacity: 1;
54
+ transform: translateY(0) scale(1);
55
+ }
56
+ }
57
+
58
+ .modal-card h2 {
59
+ margin: 0;
60
+ font-size: 1.15rem;
61
+ font-weight: 600;
62
+ color: var(--foreground);
63
+ }
64
+
65
+ /* ── CTA Button ──────────────────────────────── */
66
+ .btn-cta {
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ gap: 8px;
71
+ width: 100%;
72
+ padding: 14px 24px;
73
+ margin-top: 16px;
74
+ font-size: 0.95rem;
75
+ font-weight: 600;
76
+ color: var(--primary-foreground);
77
+ background: var(--primary);
78
+ border: none;
79
+ border-radius: 14px;
80
+ cursor: pointer;
81
+ transition:
82
+ background 0.15s,
83
+ transform 0.1s;
84
+ }
85
+
86
+ .btn-cta:hover:not(:disabled) {
87
+ background: color-mix(in oklch, var(--primary) 85%, black);
88
+ }
89
+
90
+ .btn-cta:active:not(:disabled) {
91
+ transform: scale(0.985);
92
+ }
93
+
94
+ .btn-cta:disabled {
95
+ opacity: 0.6;
96
+ cursor: not-allowed;
97
+ }
98
+
99
+ .btn-cta--secondary {
100
+ background: color-mix(in oklch, var(--foreground) 10%, transparent);
101
+ color: var(--foreground);
102
+ }
103
+
104
+ .btn-cta--secondary:hover:not(:disabled) {
105
+ background: color-mix(in oklch, var(--foreground) 15%, transparent);
106
+ }
107
+
108
+ .btn-spinner {
109
+ width: 14px;
110
+ height: 14px;
111
+ border: 2px solid
112
+ color-mix(in oklch, var(--primary-foreground) 30%, transparent);
113
+ border-top-color: var(--primary-foreground);
114
+ border-radius: 50%;
115
+ animation: btnSpin 0.6s linear infinite;
116
+ }
117
+
118
+ @keyframes btnSpin {
119
+ to {
120
+ transform: rotate(360deg);
121
+ }
122
+ }
123
+
124
+ /* ── Mobile (≤ 640px): tighter modal layout ── */
125
+ @media (max-width: 640px) {
126
+ .modal-card {
127
+ padding: 24px 20px 20px;
128
+ }
129
+
130
+ .btn-cta {
131
+ min-height: 48px;
132
+ }
133
+ }
134
+ /*
135
+ * Copyright 2026 OpenTrace Contributors
136
+ *
137
+ * Licensed under the Apache License, Version 2.0 (the "License");
138
+ * you may not use this file except in compliance with the License.
139
+ * You may obtain a copy of the License at
140
+ *
141
+ * http://www.apache.org/licenses/LICENSE-2.0
142
+ *
143
+ * Unless required by applicable law or agreed to in writing, software
144
+ * distributed under the License is distributed on an "AS IS" BASIS,
145
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
146
+ * See the License for the specific language governing permissions and
147
+ * limitations under the License.
148
+ */
149
+
150
+ /* ── Chip Toggle (URL / Directory) ─────────────── */
151
+ .chip-toggle {
152
+ display: inline-flex;
153
+ border: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
154
+ border-radius: 20px;
155
+ overflow: hidden;
156
+ }
157
+
158
+ .chip-toggle-btn {
159
+ padding: 6px 12px;
160
+ font-size: 0.75rem;
161
+ font-weight: 500;
162
+ color: var(--muted-foreground);
163
+ background: transparent;
164
+ border: none;
165
+ cursor: pointer;
166
+ transition: all 0.15s;
167
+ }
168
+
169
+ .chip-toggle-btn + .chip-toggle-btn {
170
+ border-left: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
171
+ }
172
+
173
+ .chip-toggle-btn:hover:not(.active) {
174
+ color: var(--foreground);
175
+ }
176
+
177
+ .chip-toggle-btn.active {
178
+ color: var(--primary);
179
+ background: color-mix(in oklch, var(--primary) 10%, transparent);
180
+ font-weight: 600;
181
+ }
182
+
183
+ /* ── Source Toggle ───────────────────────────── */
184
+ .source-toggle {
185
+ display: flex;
186
+ justify-content: center;
187
+ margin-bottom: 20px;
188
+ }
189
+
190
+ /* ── Form Hero (centered icon + title) ───────── */
191
+ .form-hero {
192
+ display: flex;
193
+ flex-direction: column;
194
+ align-items: center;
195
+ text-align: center;
196
+ margin-bottom: 28px;
197
+ }
198
+
199
+ .hero-icon {
200
+ width: 64px;
201
+ height: 64px;
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ border-radius: 16px;
206
+ background: color-mix(in oklch, var(--foreground) 10%, transparent);
207
+ color: var(--foreground);
208
+ margin-bottom: 16px;
209
+ position: relative;
210
+ overflow: hidden;
211
+ transition:
212
+ background 0.5s cubic-bezier(0.4, 0, 0.2, 1),
213
+ color 0.5s cubic-bezier(0.4, 0, 0.2, 1);
214
+ }
215
+
216
+ .hero-icon--provider {
217
+ background: color-mix(in oklch, var(--primary) 15%, transparent);
218
+ color: var(--primary);
219
+ }
220
+
221
+ /* --- Quad-split provider icon --- */
222
+
223
+ /* Each icon layer fills the hero-icon, clipped to its quadrant */
224
+ .quad-layer {
225
+ position: absolute;
226
+ inset: 12px;
227
+ display: flex;
228
+ align-items: center;
229
+ justify-content: center;
230
+ transition: clip-path 0.6s cubic-bezier(0.4, 0, 0.2, 1);
231
+ }
232
+
233
+ /* X-shaped divider lines overlay */
234
+ .quad-dividers {
235
+ position: absolute;
236
+ inset: 0;
237
+ z-index: 1;
238
+ pointer-events: none;
239
+ transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
240
+ }
241
+
242
+ .quad-dividers--hidden {
243
+ opacity: 0;
244
+ }
245
+
246
+ .form-hero h2 {
247
+ margin: 0 0 6px;
248
+ font-size: 1.2rem;
249
+ }
250
+
251
+ .hero-subtitle {
252
+ margin: 0;
253
+ font-size: 0.82rem;
254
+ color: var(--muted-foreground);
255
+ line-height: 1.45;
256
+ }
257
+
258
+ /* ── Pill Inputs ─────────────────────────────── */
259
+ .form-fields {
260
+ display: flex;
261
+ flex-direction: column;
262
+ gap: 10px;
263
+ }
264
+
265
+ .input-pill {
266
+ display: block;
267
+ width: 100%;
268
+ padding: 14px 18px;
269
+ font-size: 0.88rem;
270
+ color: var(--foreground);
271
+ background: color-mix(in oklch, var(--foreground) 5%, transparent);
272
+ border: 1px solid color-mix(in oklch, var(--border) 25%, transparent);
273
+ border-radius: 14px;
274
+ outline: none;
275
+ transition:
276
+ border-color 0.15s,
277
+ box-shadow 0.15s;
278
+ box-sizing: border-box;
279
+ }
280
+
281
+ .input-pill:focus {
282
+ border-color: var(--primary);
283
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--primary) 10%, transparent);
284
+ }
285
+
286
+ .input-pill::placeholder {
287
+ color: var(--muted-foreground);
288
+ opacity: 0.55;
289
+ }
290
+
291
+ /* Pill row with inline icons */
292
+ .input-pill-row {
293
+ position: relative;
294
+ display: flex;
295
+ align-items: center;
296
+ }
297
+
298
+ .input-pill-row .input-icon {
299
+ position: absolute;
300
+ left: 14px;
301
+ color: var(--muted-foreground);
302
+ opacity: 0.5;
303
+ pointer-events: none;
304
+ z-index: 1;
305
+ }
306
+
307
+ .input-pill--icon {
308
+ padding-left: 42px;
309
+ padding-right: 42px;
310
+ }
311
+
312
+ .input-toggle {
313
+ position: absolute;
314
+ right: 8px;
315
+ width: 32px;
316
+ height: 32px;
317
+ display: flex;
318
+ align-items: center;
319
+ justify-content: center;
320
+ background: transparent;
321
+ border: none;
322
+ border-radius: 8px;
323
+ color: var(--muted-foreground);
324
+ opacity: 0.5;
325
+ cursor: pointer;
326
+ transition:
327
+ opacity 0.15s,
328
+ background 0.15s;
329
+ }
330
+
331
+ .input-toggle:hover {
332
+ opacity: 0.8;
333
+ background: color-mix(in oklch, var(--foreground) 6%, transparent);
334
+ }
335
+
336
+ /* ── Autocomplete Dropdown ─────────────────── */
337
+ .autocomplete-wrapper {
338
+ position: relative;
339
+ }
340
+
341
+ .autocomplete-dropdown {
342
+ position: absolute;
343
+ top: calc(100% + 4px);
344
+ left: 0;
345
+ right: 0;
346
+ z-index: 10;
347
+ background: var(--card);
348
+ border: 1px solid color-mix(in oklch, var(--border) 40%, transparent);
349
+ border-radius: 12px;
350
+ padding: 4px;
351
+ box-shadow: var(--shadow-xl);
352
+ animation: dropdownEnter 0.15s ease-out;
353
+ }
354
+
355
+ @keyframes dropdownEnter {
356
+ from {
357
+ opacity: 0;
358
+ transform: translateY(-4px);
359
+ }
360
+ to {
361
+ opacity: 1;
362
+ transform: translateY(0);
363
+ }
364
+ }
365
+
366
+ .autocomplete-label {
367
+ padding: 6px 10px 4px;
368
+ font-size: 0.65rem;
369
+ font-weight: 600;
370
+ text-transform: uppercase;
371
+ letter-spacing: 0.05em;
372
+ color: var(--muted-foreground);
373
+ opacity: 0.6;
374
+ }
375
+
376
+ .autocomplete-item {
377
+ display: flex;
378
+ align-items: center;
379
+ gap: 8px;
380
+ width: 100%;
381
+ padding: 8px 10px;
382
+ font-size: 0.82rem;
383
+ color: var(--foreground);
384
+ background: transparent;
385
+ border: none;
386
+ border-radius: 8px;
387
+ cursor: pointer;
388
+ text-align: left;
389
+ transition: background 0.1s;
390
+ }
391
+
392
+ .autocomplete-item:hover {
393
+ background: color-mix(in oklch, var(--foreground) 6%, transparent);
394
+ }
395
+
396
+ .autocomplete-item svg {
397
+ flex-shrink: 0;
398
+ color: var(--muted-foreground);
399
+ opacity: 0.5;
400
+ }
401
+
402
+ .autocomplete-item-text {
403
+ overflow: hidden;
404
+ text-overflow: ellipsis;
405
+ white-space: nowrap;
406
+ flex: 1;
407
+ min-width: 0;
408
+ }
409
+
410
+ .autocomplete-item-remove {
411
+ display: flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ width: 22px;
415
+ height: 22px;
416
+ flex-shrink: 0;
417
+ background: transparent;
418
+ border: none;
419
+ border-radius: 6px;
420
+ color: var(--muted-foreground);
421
+ opacity: 0;
422
+ cursor: pointer;
423
+ transition:
424
+ opacity 0.15s,
425
+ background 0.15s,
426
+ color 0.15s;
427
+ }
428
+
429
+ .autocomplete-item:hover .autocomplete-item-remove {
430
+ opacity: 0.5;
431
+ }
432
+
433
+ .autocomplete-item-remove:hover {
434
+ opacity: 1 !important;
435
+ background: color-mix(in oklch, var(--destructive) 12%, transparent);
436
+ color: var(--destructive);
437
+ }
438
+
439
+ /* ── Example Repos ──────────────────────────── */
440
+ .example-repos {
441
+ display: flex;
442
+ align-items: center;
443
+ gap: 6px;
444
+ flex-wrap: wrap;
445
+ }
446
+
447
+ .example-repos-label {
448
+ font-size: 0.72rem;
449
+ font-weight: 500;
450
+ color: var(--muted-foreground);
451
+ opacity: 0.7;
452
+ }
453
+
454
+ .example-repo-chip {
455
+ display: inline-flex;
456
+ align-items: center;
457
+ padding: 4px 10px;
458
+ font-size: 0.72rem;
459
+ font-weight: 500;
460
+ color: var(--muted-foreground);
461
+ background: color-mix(in oklch, var(--foreground) 5%, transparent);
462
+ border: 1px solid color-mix(in oklch, var(--border) 25%, transparent);
463
+ border-radius: 12px;
464
+ cursor: pointer;
465
+ transition: all 0.15s;
466
+ }
467
+
468
+ .example-repo-chip:hover {
469
+ color: var(--primary);
470
+ border-color: color-mix(in oklch, var(--primary) 40%, transparent);
471
+ background: color-mix(in oklch, var(--primary) 8%, transparent);
472
+ }
473
+
474
+ .example-repo-size {
475
+ margin-left: 6px;
476
+ padding: 1px 5px;
477
+ font-size: 0.6rem;
478
+ font-weight: 600;
479
+ letter-spacing: 0.02em;
480
+ border-radius: 4px;
481
+ line-height: 1.3;
482
+ }
483
+
484
+ .example-repo-size--s {
485
+ color: #4ade80;
486
+ background: color-mix(in oklch, #4ade80 12%, transparent);
487
+ }
488
+
489
+ .example-repo-size--m {
490
+ color: #fbbf24;
491
+ background: color-mix(in oklch, #fbbf24 12%, transparent);
492
+ }
493
+
494
+ .example-repo-size--l {
495
+ color: #f87171;
496
+ background: color-mix(in oklch, #f87171 12%, transparent);
497
+ }
498
+
499
+ /* ── Directory Picker ───────────────────────── */
500
+ .directory-picker {
501
+ position: relative;
502
+ }
503
+
504
+ .directory-input {
505
+ /* Hidden native file input */
506
+ position: absolute;
507
+ width: 1px;
508
+ height: 1px;
509
+ opacity: 0;
510
+ overflow: hidden;
511
+ }
512
+
513
+ .directory-browse-btn {
514
+ display: flex;
515
+ align-items: center;
516
+ gap: 10px;
517
+ cursor: pointer;
518
+ text-align: left;
519
+ color: var(--muted-foreground);
520
+ transition:
521
+ border-color 0.15s,
522
+ color 0.15s;
523
+ }
524
+
525
+ .directory-browse-btn:hover {
526
+ border-color: var(--primary);
527
+ color: var(--foreground);
528
+ }
529
+
530
+ .directory-browse-btn svg {
531
+ flex-shrink: 0;
532
+ opacity: 0.6;
533
+ }
534
+
535
+ .directory-name {
536
+ color: var(--foreground);
537
+ font-weight: 500;
538
+ }
539
+
540
+ .directory-count {
541
+ color: var(--muted-foreground);
542
+ font-weight: 400;
543
+ }
544
+
545
+ /* ── Form Error ──────────────────────────────── */
546
+ .form-error {
547
+ display: flex;
548
+ align-items: center;
549
+ gap: 8px;
550
+ padding: 10px 14px;
551
+ margin-top: 10px;
552
+ font-size: 0.8rem;
553
+ color: var(--destructive);
554
+ background: color-mix(in oklch, var(--destructive) 8%, transparent);
555
+ border: 1px solid color-mix(in oklch, var(--destructive) 20%, transparent);
556
+ border-radius: 10px;
557
+ }
558
+
559
+ .form-error svg {
560
+ flex-shrink: 0;
561
+ }
562
+
563
+ /* ── Already Indexed Notice ──────────────────── */
564
+ .form-indexed {
565
+ display: flex;
566
+ align-items: center;
567
+ gap: 8px;
568
+ padding: 10px 14px;
569
+ margin-top: 10px;
570
+ font-size: 0.8rem;
571
+ color: oklch(0.7 0.18 155);
572
+ background: color-mix(in oklch, oklch(0.7 0.18 155) 8%, transparent);
573
+ border: 1px solid color-mix(in oklch, oklch(0.7 0.18 155) 20%, transparent);
574
+ border-radius: 10px;
575
+ }
576
+
577
+ .form-indexed svg {
578
+ flex-shrink: 0;
579
+ }
580
+
581
+ .form-indexed strong {
582
+ font-weight: 600;
583
+ }
584
+
585
+ /* ── Form Info (warnings / informational notices) ── */
586
+ .form-info {
587
+ display: flex;
588
+ align-items: flex-start;
589
+ gap: 8px;
590
+ padding: 10px 14px;
591
+ margin-top: 6px;
592
+ font-size: 0.75rem;
593
+ line-height: 1.45;
594
+ color: color-mix(in oklch, var(--foreground) 70%, transparent);
595
+ background: color-mix(in oklch, var(--foreground) 4%, transparent);
596
+ border: 1px solid color-mix(in oklch, var(--foreground) 10%, transparent);
597
+ border-radius: 10px;
598
+ }
599
+
600
+ .form-info svg {
601
+ flex-shrink: 0;
602
+ margin-top: 1px;
603
+ opacity: 0.6;
604
+ }
605
+
606
+ /* ── Bottom Chips ────────────────────────────── */
607
+ .form-chips {
608
+ display: flex;
609
+ justify-content: center;
610
+ gap: 8px;
611
+ margin-top: 16px;
612
+ }
613
+
614
+ .chip {
615
+ display: inline-flex;
616
+ align-items: center;
617
+ gap: 5px;
618
+ padding: 6px 14px;
619
+ font-size: 0.75rem;
620
+ font-weight: 500;
621
+ color: var(--muted-foreground);
622
+ background: transparent;
623
+ border: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
624
+ border-radius: 20px;
625
+ cursor: pointer;
626
+ transition: all 0.15s;
627
+ }
628
+
629
+ .chip:hover {
630
+ border-color: color-mix(in oklch, var(--border) 60%, transparent);
631
+ color: var(--foreground);
632
+ }
633
+
634
+ .chip svg {
635
+ opacity: 0.6;
636
+ }
637
+
638
+ .chip-input {
639
+ background: transparent;
640
+ border: none;
641
+ outline: none;
642
+ font-size: 0.75rem;
643
+ font-weight: 500;
644
+ color: var(--foreground);
645
+ width: 90px;
646
+ padding: 0;
647
+ margin: 0;
648
+ }
649
+
650
+ .chip-input::placeholder {
651
+ color: var(--muted-foreground);
652
+ opacity: 0.7;
653
+ }
654
+
655
+ /* ── Mobile (≤ 640px) ────────────────────────── */
656
+ @media (max-width: 640px) {
657
+ .autocomplete-dropdown {
658
+ max-height: 200px;
659
+ overflow-y: auto;
660
+ }
661
+
662
+ .chip-toggle-btn {
663
+ min-height: 44px;
664
+ }
665
+ }
666
+ /*
667
+ * Copyright 2026 OpenTrace Contributors
668
+ *
669
+ * Licensed under the Apache License, Version 2.0 (the "License");
670
+ * you may not use this file except in compliance with the License.
671
+ * You may obtain a copy of the License at
672
+ *
673
+ * http://www.apache.org/licenses/LICENSE-2.0
674
+ *
675
+ * Unless required by applicable law or agreed to in writing, software
676
+ * distributed under the License is distributed on an "AS IS" BASIS,
677
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
678
+ * See the License for the specific language governing permissions and
679
+ * limitations under the License.
680
+ */
681
+
682
+ /* ── Indexing Header (icon + title) ──────────── */
683
+ .indexing-header {
684
+ display: flex;
685
+ align-items: center;
686
+ gap: 10px;
687
+ margin-bottom: 4px;
688
+ }
689
+
690
+ .indexing-header h2 {
691
+ margin: 0;
692
+ }
693
+
694
+ .indexing-header-icon {
695
+ display: flex;
696
+ align-items: center;
697
+ justify-content: center;
698
+ width: 32px;
699
+ height: 32px;
700
+ border-radius: 8px;
701
+ background: color-mix(in oklch, var(--foreground) 8%, transparent);
702
+ color: var(--foreground);
703
+ flex-shrink: 0;
704
+ }
705
+
706
+ /* ── Indexing Progress ───────────────────────── */
707
+ .indexing-progress {
708
+ text-align: center;
709
+ padding: 12px 0;
710
+ }
711
+
712
+ .indexing-progress h2 {
713
+ margin-bottom: 20px;
714
+ }
715
+
716
+ .indexing-message {
717
+ font-size: 0.8rem;
718
+ color: var(--muted-foreground);
719
+ margin: 16px 0;
720
+ }
721
+
722
+ .indexing-message--truncate {
723
+ overflow: hidden;
724
+ text-overflow: ellipsis;
725
+ white-space: nowrap;
726
+ max-width: 100%;
727
+ }
728
+
729
+ .indexing-message--detail {
730
+ font-size: 0.75rem;
731
+ opacity: 0.7;
732
+ margin-top: -8px;
733
+ }
734
+
735
+ /* ── Multi-Stage Progress ────────────────────── */
736
+ .multi-stage-progress {
737
+ display: flex;
738
+ flex-direction: column;
739
+ margin-bottom: 16px;
740
+ text-align: left;
741
+ }
742
+
743
+ .stage-row {
744
+ display: flex;
745
+ flex-direction: column;
746
+ gap: 5px;
747
+ padding: 0 4px;
748
+ margin-bottom: 10px;
749
+ max-height: 70px;
750
+ opacity: 1;
751
+ overflow: hidden;
752
+ transition:
753
+ opacity 0.5s ease,
754
+ max-height 0.4s ease 0.15s,
755
+ gap 0.4s ease 0.15s,
756
+ margin 0.4s ease 0.15s;
757
+ }
758
+
759
+ .stage-row:last-child {
760
+ margin-bottom: 0;
761
+ }
762
+
763
+ .stage-row--completed {
764
+ opacity: 0.35;
765
+ }
766
+
767
+ .stage-row--removing {
768
+ opacity: 0;
769
+ max-height: 0;
770
+ gap: 0;
771
+ padding: 0;
772
+ margin-bottom: 0;
773
+ overflow: hidden;
774
+ pointer-events: none;
775
+ }
776
+
777
+ .stage-row--active .stage-label {
778
+ color: var(--foreground);
779
+ }
780
+
781
+ .stage-header {
782
+ display: flex;
783
+ align-items: baseline;
784
+ justify-content: space-between;
785
+ }
786
+
787
+ .stage-label {
788
+ font-size: 0.75rem;
789
+ font-weight: 600;
790
+ color: var(--muted-foreground);
791
+ white-space: nowrap;
792
+ }
793
+
794
+ .stage-count {
795
+ font-size: 0.68rem;
796
+ font-weight: 500;
797
+ color: var(--muted-foreground);
798
+ font-variant-numeric: tabular-nums;
799
+ white-space: nowrap;
800
+ }
801
+
802
+ .stage-detail {
803
+ font-size: 0.65rem;
804
+ color: var(--muted-foreground);
805
+ white-space: nowrap;
806
+ overflow: hidden;
807
+ text-overflow: ellipsis;
808
+ line-height: 1;
809
+ }
810
+
811
+ .stage-row--active .stage-detail {
812
+ color: color-mix(in oklch, var(--foreground) 65%, transparent);
813
+ }
814
+
815
+ .stage-row--completed .stage-detail {
816
+ font-size: 0.62rem;
817
+ }
818
+
819
+ .stage-bar {
820
+ height: 5px;
821
+ background: color-mix(in oklch, var(--foreground) 8%, transparent);
822
+ border-radius: 3px;
823
+ overflow: hidden;
824
+ }
825
+
826
+ .stage-bar-fill {
827
+ display: block;
828
+ height: 100%;
829
+ background: var(--primary);
830
+ border-radius: 3px;
831
+ transition: width 0.3s ease;
832
+ }
833
+
834
+ .stage-row--completed .stage-bar-fill {
835
+ background: oklch(0.7 0.18 155);
836
+ }
837
+
838
+ .stage-bar--indeterminate .stage-bar-fill {
839
+ width: 40%;
840
+ animation: indeterminate-slide 1.4s ease-in-out infinite;
841
+ }
842
+
843
+ @keyframes indeterminate-slide {
844
+ 0% {
845
+ transform: translateX(-100%);
846
+ }
847
+ 100% {
848
+ transform: translateX(250%);
849
+ }
850
+ }
851
+
852
+ /* ── Stats Grid ──────────────────────────────── */
853
+ .indexing-stats-grid {
854
+ display: grid;
855
+ grid-template-columns: 1fr 1fr;
856
+ gap: 12px;
857
+ margin: 16px 0;
858
+ }
859
+
860
+ .stat-card {
861
+ display: flex;
862
+ flex-direction: column;
863
+ align-items: center;
864
+ padding: 14px 12px;
865
+ background: color-mix(in oklch, var(--primary) 6%, transparent);
866
+ border: 1px solid color-mix(in oklch, var(--primary) 15%, transparent);
867
+ border-radius: var(--radius);
868
+ }
869
+
870
+ .stat-value {
871
+ font-size: 1.5rem;
872
+ font-weight: 700;
873
+ color: var(--foreground);
874
+ font-variant-numeric: tabular-nums;
875
+ line-height: 1.2;
876
+ }
877
+
878
+ .stat-label {
879
+ font-size: 0.7rem;
880
+ font-weight: 500;
881
+ color: var(--muted-foreground);
882
+ margin-top: 2px;
883
+ text-transform: uppercase;
884
+ letter-spacing: 0.05em;
885
+ }
886
+
887
+ /* ── Failed Stage ─────────────────────────────── */
888
+ .failed-content {
889
+ display: flex;
890
+ flex-direction: column;
891
+ align-items: center;
892
+ gap: 8px;
893
+ margin-bottom: 12px;
894
+ }
895
+
896
+ .failed-icon {
897
+ color: var(--destructive);
898
+ animation: doneAppear 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
899
+ }
900
+
901
+ .failed-content h2 {
902
+ margin: 0;
903
+ font-size: 1.1rem;
904
+ font-weight: 600;
905
+ color: var(--destructive);
906
+ }
907
+
908
+ .failed-message {
909
+ margin: 0;
910
+ font-size: 0.82rem;
911
+ color: var(--muted-foreground);
912
+ line-height: 1.45;
913
+ max-width: 360px;
914
+ }
915
+
916
+ /* ── Done Stage ──────────────────────────────── */
917
+ .done-content {
918
+ display: flex;
919
+ flex-direction: column;
920
+ align-items: center;
921
+ gap: 12px;
922
+ margin-bottom: 8px;
923
+ }
924
+
925
+ .done-content h2 {
926
+ margin: 0;
927
+ font-size: 1.1rem;
928
+ font-weight: 600;
929
+ color: oklch(0.7 0.18 155);
930
+ }
931
+
932
+ .done-checkmark {
933
+ color: oklch(0.7 0.18 155);
934
+ animation: doneAppear 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
935
+ }
936
+
937
+ .done-check-path {
938
+ animation: checkDraw 0.3s ease-out 0.3s both;
939
+ }
940
+
941
+ @keyframes doneAppear {
942
+ 0% {
943
+ transform: scale(0);
944
+ opacity: 0;
945
+ }
946
+ 70% {
947
+ transform: scale(1.15);
948
+ }
949
+ 100% {
950
+ transform: scale(1);
951
+ opacity: 1;
952
+ }
953
+ }
954
+
955
+ @keyframes checkDraw {
956
+ 0% {
957
+ opacity: 0;
958
+ stroke-dasharray: 20;
959
+ stroke-dashoffset: 20;
960
+ }
961
+ 100% {
962
+ opacity: 1;
963
+ stroke-dasharray: 20;
964
+ stroke-dashoffset: 0;
965
+ }
966
+ }
967
+
968
+ /* ── Step Indicator (legacy) ──────────────────── */
969
+ .step-indicator {
970
+ display: flex;
971
+ align-items: flex-start;
972
+ justify-content: center;
973
+ gap: 0;
974
+ margin-bottom: 20px;
975
+ }
976
+
977
+ .step {
978
+ display: flex;
979
+ flex-direction: column;
980
+ align-items: center;
981
+ position: relative;
982
+ flex: 1;
983
+ min-width: 0;
984
+ }
985
+
986
+ .step-circle {
987
+ width: 28px;
988
+ height: 28px;
989
+ border-radius: 50%;
990
+ display: flex;
991
+ align-items: center;
992
+ justify-content: center;
993
+ font-size: 0.7rem;
994
+ font-weight: 600;
995
+ position: relative;
996
+ z-index: 1;
997
+ transition: all 0.3s ease;
998
+ }
999
+
1000
+ .step-circle.completed {
1001
+ background: var(--primary);
1002
+ color: var(--primary-foreground);
1003
+ border: 2px solid var(--primary);
1004
+ }
1005
+
1006
+ .step-circle.current {
1007
+ background: transparent;
1008
+ color: var(--primary);
1009
+ border: 2px solid var(--primary);
1010
+ animation: stepPulse 2s ease-in-out infinite;
1011
+ }
1012
+
1013
+ .step-circle.future {
1014
+ background: transparent;
1015
+ color: var(--muted-foreground);
1016
+ border: 2px solid color-mix(in oklch, var(--border) 50%, transparent);
1017
+ }
1018
+
1019
+ .step-circle.failed {
1020
+ background: var(--destructive);
1021
+ color: white;
1022
+ border: 2px solid var(--destructive);
1023
+ }
1024
+
1025
+ .step-number {
1026
+ line-height: 1;
1027
+ }
1028
+
1029
+ .step-label {
1030
+ font-size: 0.65rem;
1031
+ font-weight: 500;
1032
+ color: var(--muted-foreground);
1033
+ margin-top: 6px;
1034
+ white-space: nowrap;
1035
+ }
1036
+
1037
+ .step-circle.completed + .step-label,
1038
+ .step-circle.current + .step-label {
1039
+ color: var(--foreground);
1040
+ }
1041
+
1042
+ .step-connector {
1043
+ position: absolute;
1044
+ top: 14px;
1045
+ right: calc(50% + 14px);
1046
+ width: calc(100% - 28px);
1047
+ height: 2px;
1048
+ background: color-mix(in oklch, var(--border) 50%, transparent);
1049
+ z-index: 0;
1050
+ transition: background 0.3s ease;
1051
+ }
1052
+
1053
+ .step-connector.completed {
1054
+ background: var(--primary);
1055
+ }
1056
+
1057
+ @keyframes stepPulse {
1058
+ 0%,
1059
+ 100% {
1060
+ box-shadow: 0 0 0 0 color-mix(in oklch, var(--primary) 40%, transparent);
1061
+ }
1062
+ 50% {
1063
+ box-shadow: 0 0 0 6px color-mix(in oklch, var(--primary) 0%, transparent);
1064
+ }
1065
+ }
1066
+
1067
+ /* ── Error Card ──────────────────────────────── */
1068
+ .indexing-error {
1069
+ margin-top: 16px;
1070
+ padding: 16px;
1071
+ background: color-mix(in oklch, var(--destructive) 8%, transparent);
1072
+ border: 1px solid color-mix(in oklch, var(--destructive) 25%, transparent);
1073
+ border-radius: var(--radius);
1074
+ text-align: left;
1075
+ }
1076
+
1077
+ .error-header {
1078
+ display: flex;
1079
+ align-items: center;
1080
+ gap: 8px;
1081
+ font-size: 0.85rem;
1082
+ font-weight: 600;
1083
+ color: var(--destructive);
1084
+ margin-bottom: 8px;
1085
+ }
1086
+
1087
+ .error-message {
1088
+ font-size: 0.8rem;
1089
+ color: var(--muted-foreground);
1090
+ margin: 0 0 8px;
1091
+ }
1092
+
1093
+ .error-list {
1094
+ font-size: 0.75rem;
1095
+ color: var(--muted-foreground);
1096
+ margin: 0 0 12px;
1097
+ padding-left: 18px;
1098
+ }
1099
+
1100
+ .error-list li {
1101
+ margin-bottom: 4px;
1102
+ }
1103
+
1104
+ /* ── Legacy support ──────────────────────────── */
1105
+ .modal-error {
1106
+ color: var(--destructive);
1107
+ font-size: 0.8rem;
1108
+ margin: 8px 0;
1109
+ }
1110
+
1111
+ .btn-cancel {
1112
+ padding: 8px 18px;
1113
+ font-size: 0.8rem;
1114
+ font-weight: 500;
1115
+ border-radius: var(--radius);
1116
+ border: 1px solid color-mix(in oklch, var(--border) 40%, transparent);
1117
+ color: var(--muted-foreground);
1118
+ background: transparent;
1119
+ cursor: pointer;
1120
+ transition: background 0.15s;
1121
+ }
1122
+
1123
+ .btn-cancel:hover {
1124
+ background: color-mix(in oklch, var(--border) 20%, transparent);
1125
+ }
1126
+
1127
+ .btn-cancel:disabled {
1128
+ opacity: 0.5;
1129
+ cursor: not-allowed;
1130
+ }
1131
+
1132
+ .indexing-error .btn-cancel {
1133
+ margin-top: 4px;
1134
+ }
1135
+
1136
+ /* ── Mobile (≤ 640px) ────────────────────────── */
1137
+ @media (max-width: 640px) {
1138
+ .indexing-stats-grid {
1139
+ grid-template-columns: 1fr;
1140
+ }
1141
+ }
1
1142
  :root{--sigma-background-color:#fff;--sigma-controls-background-color:#fff;--sigma-controls-background-color-hover:rgba(0,0,0,0.2);--sigma-controls-border-color:rgba(0,0,0,0.2);--sigma-controls-color:#000;--sigma-controls-zindex:100;--sigma-controls-margin:5px;--sigma-controls-size:30px;}div.react-sigma{height:100%;width:100%;position:relative;background:var(--sigma-background-color);}div.sigma-container{height:100%;width:100%;}.react-sigma-controls{position:absolute;z-index:var(--sigma-controls-zindex);border:2px solid var(--sigma-controls-border-color);border-radius:4px;color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color);}.react-sigma-controls.bottom-right{bottom:var(--sigma-controls-margin);right:var(--sigma-controls-margin);}.react-sigma-controls.bottom-left{bottom:var(--sigma-controls-margin);left:var(--sigma-controls-margin);}.react-sigma-controls.top-right{top:var(--sigma-controls-margin);right:var(--sigma-controls-margin);}.react-sigma-controls.top-left{top:var(--sigma-controls-margin);left:var(--sigma-controls-margin);}.react-sigma-controls:first-child{border-top-left-radius:2px;border-top-right-radius:2px;}.react-sigma-controls:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px;}.react-sigma-control{width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-color:var(--sigma-controls-background-color);border-bottom:1px solid var(--sigma-controls-border-color);}.react-sigma-control:last-child{border-bottom:none;}.react-sigma-control>*{box-sizing:border-box;}.react-sigma-control>button{display:block;border:none;margin:0;padding:0;width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-position:center;background-size:50%;background-repeat:no-repeat;background-color:var(--sigma-controls-background-color);clip:rect(0,0,0,0);}.react-sigma-control>button:hover{background-color:var(--sigma-controls-background-color-hover);}.react-sigma-search{background-color:var(--sigma-controls-background-color);}.react-sigma-search label{visibility:hidden;}.react-sigma-search input{color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color);font-size:1em;width:100%;margin:0;border:none;padding:var(--sigma-controls-margin);box-sizing:border-box;}/*
2
1143
  * Copyright 2026 OpenTrace Contributors
3
1144
  *
@@ -244,6 +1385,28 @@
244
1385
  .graph-badge-sep {
245
1386
  margin: 0 3px;
246
1387
  }
1388
+
1389
+ /* ── Compact badge (1100px–1300px) ──────────── */
1390
+ @media (max-width: 1300px) and (min-width: 1100px) {
1391
+ .graph-badge-total,
1392
+ .graph-badge-label {
1393
+ display: none;
1394
+ }
1395
+
1396
+ .graph-badge {
1397
+ gap: 4px;
1398
+ padding: 0 10px;
1399
+ }
1400
+ }
1401
+
1402
+ /* ── Hidden badge (1025px–1099px) ───────────── */
1403
+ /* Below 1024px the toolbar collapses to burger dropdown where the
1404
+ badge reappears as a full-width menu row, so we stop hiding at 1025px. */
1405
+ @media (max-width: 1099px) and (min-width: 1025px) {
1406
+ .graph-badge {
1407
+ display: none;
1408
+ }
1409
+ }
247
1410
  /*
248
1411
  * Copyright 2026 OpenTrace Contributors
249
1412
  *
@@ -363,6 +1526,427 @@
363
1526
  * limitations under the License.
364
1527
  */
365
1528
 
1529
+ /* ── Toolbar layout ─────────────────────────── */
1530
+
1531
+ .ot-toolbar {
1532
+ position: absolute;
1533
+ top: 0;
1534
+ left: 0;
1535
+ right: 0;
1536
+ z-index: 10;
1537
+ display: flex;
1538
+ align-items: center;
1539
+ gap: 12px;
1540
+ padding: 16px 24px;
1541
+ pointer-events: none;
1542
+ }
1543
+
1544
+ .ot-toolbar h1 {
1545
+ margin: 0;
1546
+ font-size: 1.25rem;
1547
+ font-weight: 600;
1548
+ color: var(--foreground);
1549
+ letter-spacing: -0.02em;
1550
+ pointer-events: auto;
1551
+ }
1552
+
1553
+ /* ── Nav (inline on desktop, dropdown on mobile) */
1554
+
1555
+ .ot-toolbar-nav {
1556
+ display: flex;
1557
+ align-items: center;
1558
+ gap: 12px;
1559
+ flex: 1;
1560
+ pointer-events: auto;
1561
+ }
1562
+
1563
+ /* Hidden on desktop */
1564
+ .ot-toolbar .ot-menu-label {
1565
+ display: none;
1566
+ }
1567
+
1568
+ .ot-toolbar .ot-mobile-panel-btn,
1569
+ .ot-toolbar .ot-menu-divider {
1570
+ display: none;
1571
+ }
1572
+
1573
+ /* ── Search placement ──────────────────────── */
1574
+ /* Desktop: search inside nav is visible, tablet search is hidden */
1575
+ .ot-toolbar .ot-search-tablet {
1576
+ display: none;
1577
+ }
1578
+
1579
+ .ot-toolbar .ot-search-nav {
1580
+ display: contents;
1581
+ }
1582
+
1583
+ /* ── Persistent actions ─────────────────────── */
1584
+ /* On desktop: hidden here, shown inside nav via .ot-persistent-desktop */
1585
+ .ot-toolbar .ot-persistent-mobile {
1586
+ display: none;
1587
+ pointer-events: auto;
1588
+ }
1589
+
1590
+ .ot-toolbar .ot-persistent-desktop {
1591
+ display: contents;
1592
+ }
1593
+
1594
+ /* ── Burger button ──────────────────────────── */
1595
+
1596
+ .ot-toolbar .ot-burger-btn {
1597
+ display: none;
1598
+ background: var(--card);
1599
+ border: 1px solid var(--border);
1600
+ border-radius: 8px;
1601
+ padding: 6px;
1602
+ cursor: pointer;
1603
+ color: var(--foreground);
1604
+ pointer-events: auto;
1605
+ flex-shrink: 0;
1606
+ margin-left: auto;
1607
+ }
1608
+
1609
+ .ot-toolbar .ot-burger-btn:hover {
1610
+ background: var(--accent);
1611
+ }
1612
+
1613
+ /* ── Search ─────────────────────────────────── */
1614
+
1615
+ .ot-toolbar .ot-search-container {
1616
+ position: relative;
1617
+ flex: 1;
1618
+ max-width: 460px;
1619
+ margin: 0 0.5rem;
1620
+ pointer-events: auto;
1621
+ display: flex;
1622
+ align-items: center;
1623
+ }
1624
+
1625
+ .ot-toolbar .ot-search-input {
1626
+ width: 100%;
1627
+ height: 36px;
1628
+ padding: 0 12px;
1629
+ padding-right: 155px;
1630
+ background: color-mix(in oklch, var(--card) 80%, transparent);
1631
+ border: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
1632
+ border-radius: calc(var(--radius) + 2px);
1633
+ color: var(--foreground);
1634
+ font-size: 0.8rem;
1635
+ transition: all 0.2s;
1636
+ }
1637
+
1638
+ .ot-toolbar .ot-search-input:focus {
1639
+ outline: none;
1640
+ border-color: color-mix(in oklch, var(--primary) 50%, transparent);
1641
+ box-shadow: 0 0 0 2px color-mix(in oklch, var(--primary) 12%, transparent);
1642
+ }
1643
+
1644
+ .ot-toolbar .ot-search-input::placeholder {
1645
+ color: var(--muted-foreground);
1646
+ }
1647
+
1648
+ .ot-toolbar .ot-search-params {
1649
+ position: absolute;
1650
+ right: 56px;
1651
+ display: flex;
1652
+ align-items: center;
1653
+ gap: 6px;
1654
+ font-size: 0.7rem;
1655
+ color: var(--muted-foreground);
1656
+ border-left: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
1657
+ padding-left: 8px;
1658
+ }
1659
+
1660
+ .ot-toolbar .ot-hops-input {
1661
+ width: 32px;
1662
+ height: 22px;
1663
+ background: color-mix(in oklch, var(--background) 60%, transparent);
1664
+ border: 1px solid color-mix(in oklch, var(--border) 25%, transparent);
1665
+ border-radius: calc(var(--radius) - 2px);
1666
+ color: var(--foreground);
1667
+ font-size: 0.7rem;
1668
+ padding: 0 4px;
1669
+ text-align: center;
1670
+ }
1671
+
1672
+ .ot-toolbar .ot-hops-input:focus {
1673
+ outline: none;
1674
+ border-color: var(--primary);
1675
+ }
1676
+
1677
+ .ot-toolbar .ot-hops-input::-webkit-inner-spin-button,
1678
+ .ot-toolbar .ot-hops-input::-webkit-outer-spin-button {
1679
+ -webkit-appearance: none;
1680
+ margin: 0;
1681
+ }
1682
+
1683
+ .ot-toolbar .ot-search-actions {
1684
+ position: absolute;
1685
+ right: 6px;
1686
+ top: 50%;
1687
+ transform: translateY(-50%);
1688
+ display: flex;
1689
+ align-items: center;
1690
+ gap: 2px;
1691
+ }
1692
+
1693
+ .ot-toolbar .ot-clear-search {
1694
+ background: none;
1695
+ border: none;
1696
+ color: var(--muted-foreground);
1697
+ font-size: 1rem;
1698
+ cursor: pointer;
1699
+ padding: 2px;
1700
+ line-height: 1;
1701
+ display: flex;
1702
+ align-items: center;
1703
+ justify-content: center;
1704
+ }
1705
+
1706
+ .ot-toolbar .ot-clear-search:hover {
1707
+ color: var(--foreground);
1708
+ }
1709
+
1710
+ .ot-toolbar .ot-search-btn {
1711
+ background: var(--primary);
1712
+ border: none;
1713
+ border-radius: calc(var(--radius) - 2px);
1714
+ color: var(--primary-foreground);
1715
+ width: 24px;
1716
+ height: 24px;
1717
+ cursor: pointer;
1718
+ display: flex;
1719
+ align-items: center;
1720
+ justify-content: center;
1721
+ transition: background 0.15s;
1722
+ }
1723
+
1724
+ .ot-toolbar .ot-search-btn:hover:not(:disabled) {
1725
+ background: color-mix(in oklch, var(--primary) 85%, black);
1726
+ }
1727
+
1728
+ .ot-toolbar .ot-search-btn:disabled {
1729
+ background: color-mix(in oklch, var(--secondary) 60%, transparent);
1730
+ color: var(--muted-foreground);
1731
+ cursor: not-allowed;
1732
+ }
1733
+
1734
+ /* ── Reset / Show All button ────────────────── */
1735
+
1736
+ .ot-toolbar .ot-reset-btn {
1737
+ pointer-events: auto;
1738
+ background: color-mix(in oklch, var(--card) 80%, transparent);
1739
+ border: 1px solid color-mix(in oklch, var(--border) 30%, transparent);
1740
+ color: var(--muted-foreground);
1741
+ height: 36px;
1742
+ padding: 0 12px;
1743
+ border-radius: calc(var(--radius) + 2px);
1744
+ font-size: 0.75rem;
1745
+ cursor: pointer;
1746
+ transition: all 0.2s;
1747
+ }
1748
+
1749
+ .ot-toolbar .ot-reset-btn:hover {
1750
+ background: color-mix(in oklch, var(--primary) 10%, transparent);
1751
+ color: var(--primary);
1752
+ border-color: color-mix(in oklch, var(--primary) 30%, transparent);
1753
+ }
1754
+
1755
+ /* ── Tablet + Mobile (≤ 1024px): burger dropdown ── */
1756
+
1757
+ @media (max-width: 1024px) {
1758
+ .ot-toolbar {
1759
+ flex-wrap: wrap;
1760
+ padding: max(12px, env(safe-area-inset-top))
1761
+ max(16px, env(safe-area-inset-right)) 12px
1762
+ max(16px, env(safe-area-inset-left));
1763
+ gap: 0;
1764
+ }
1765
+
1766
+ /* Tablet search: visible outside the nav at 600–1024px */
1767
+ .ot-toolbar .ot-search-tablet {
1768
+ display: flex;
1769
+ flex: 1;
1770
+ min-width: 0;
1771
+ pointer-events: auto;
1772
+ }
1773
+
1774
+ .ot-toolbar .ot-search-tablet .ot-search-container {
1775
+ flex: 1;
1776
+ max-width: none;
1777
+ margin: 0 8px;
1778
+ }
1779
+
1780
+ /* Hide the in-nav copy of search */
1781
+ .ot-toolbar .ot-search-nav {
1782
+ display: none;
1783
+ }
1784
+
1785
+ .ot-toolbar .ot-persistent-mobile {
1786
+ display: flex;
1787
+ align-items: center;
1788
+ gap: 8px;
1789
+ margin-left: 0;
1790
+ flex-shrink: 0;
1791
+ }
1792
+
1793
+ .ot-toolbar .ot-persistent-desktop {
1794
+ display: none;
1795
+ }
1796
+
1797
+ .ot-toolbar .ot-burger-btn {
1798
+ display: flex;
1799
+ align-items: center;
1800
+ justify-content: center;
1801
+ margin-left: 8px;
1802
+ }
1803
+
1804
+ .ot-toolbar-nav {
1805
+ display: none;
1806
+ flex-basis: 100%;
1807
+ flex-direction: column;
1808
+ align-items: stretch;
1809
+ gap: 0;
1810
+ background: var(--card);
1811
+ border: 1px solid var(--border);
1812
+ border-radius: calc(var(--radius) + 2px);
1813
+ padding: 6px 0;
1814
+ margin-top: 8px;
1815
+ pointer-events: auto;
1816
+ }
1817
+
1818
+ .ot-toolbar-nav.open {
1819
+ display: flex;
1820
+ }
1821
+
1822
+ /* Show panel shortcuts and dividers */
1823
+ .ot-toolbar .ot-mobile-panel-btn {
1824
+ display: flex;
1825
+ align-items: center;
1826
+ gap: 10px;
1827
+ padding: 10px 16px;
1828
+ background: transparent;
1829
+ border: none;
1830
+ color: var(--foreground);
1831
+ cursor: pointer;
1832
+ font-size: 14px;
1833
+ font-weight: 500;
1834
+ pointer-events: auto;
1835
+ }
1836
+
1837
+ .ot-toolbar .ot-mobile-panel-btn:hover {
1838
+ background: var(--accent);
1839
+ }
1840
+
1841
+ .ot-toolbar .ot-menu-divider {
1842
+ display: block;
1843
+ height: 1px;
1844
+ background: var(--border);
1845
+ margin: 4px 0;
1846
+ }
1847
+
1848
+ .ot-toolbar .ot-menu-label {
1849
+ display: inline;
1850
+ font-size: 14px;
1851
+ font-weight: 500;
1852
+ }
1853
+
1854
+ /* Search full width in dropdown */
1855
+ .ot-toolbar-nav .ot-search-container {
1856
+ width: auto;
1857
+ max-width: none;
1858
+ min-width: 0;
1859
+ margin: 4px 10px;
1860
+ }
1861
+
1862
+ /* Reset button as menu row */
1863
+ .ot-toolbar-nav .ot-reset-btn {
1864
+ border: none;
1865
+ border-radius: 0;
1866
+ background: transparent;
1867
+ height: auto;
1868
+ padding: 10px 16px;
1869
+ font-size: 14px;
1870
+ font-weight: 500;
1871
+ color: var(--foreground);
1872
+ }
1873
+
1874
+ .ot-toolbar-nav .ot-reset-btn:hover {
1875
+ background: var(--accent);
1876
+ border-color: transparent;
1877
+ }
1878
+
1879
+ /* Badge as menu row */
1880
+ .ot-toolbar-nav .graph-badge {
1881
+ border: none;
1882
+ border-radius: 0;
1883
+ background: transparent;
1884
+ backdrop-filter: none;
1885
+ height: auto;
1886
+ padding: 10px 16px;
1887
+ font-size: 13px;
1888
+ }
1889
+ }
1890
+
1891
+ /* ── Small mobile (≤ 600px): search goes back into burger ── */
1892
+
1893
+ @media (max-width: 600px) {
1894
+ .ot-toolbar .ot-search-tablet {
1895
+ display: none;
1896
+ }
1897
+
1898
+ .ot-toolbar .ot-search-nav {
1899
+ display: contents;
1900
+ }
1901
+
1902
+ .ot-toolbar .ot-persistent-mobile {
1903
+ margin-left: auto;
1904
+ }
1905
+ }
1906
+
1907
+ /* ── Extra small (≤ 640px) ──────────────────── */
1908
+
1909
+ @media (max-width: 640px) {
1910
+ .ot-toolbar {
1911
+ padding: max(10px, env(safe-area-inset-top))
1912
+ max(12px, env(safe-area-inset-right)) 10px
1913
+ max(12px, env(safe-area-inset-left));
1914
+ }
1915
+
1916
+ .ot-toolbar h1 {
1917
+ display: none;
1918
+ }
1919
+
1920
+ .ot-toolbar-nav .ot-search-container {
1921
+ margin: 4px 8px;
1922
+ }
1923
+
1924
+ .ot-toolbar .ot-search-btn {
1925
+ width: 32px;
1926
+ height: 32px;
1927
+ }
1928
+
1929
+ .ot-toolbar .ot-hops-input {
1930
+ width: 40px;
1931
+ height: 28px;
1932
+ }
1933
+ }
1934
+ /*
1935
+ * Copyright 2026 OpenTrace Contributors
1936
+ *
1937
+ * Licensed under the Apache License, Version 2.0 (the "License");
1938
+ * you may not use this file except in compliance with the License.
1939
+ * You may obtain a copy of the License at
1940
+ *
1941
+ * http://www.apache.org/licenses/LICENSE-2.0
1942
+ *
1943
+ * Unless required by applicable law or agreed to in writing, software
1944
+ * distributed under the License is distributed on an "AS IS" BASIS,
1945
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1946
+ * See the License for the specific language governing permissions and
1947
+ * limitations under the License.
1948
+ */
1949
+
366
1950
  /* Discover Panel — directory tree view */
367
1951
 
368
1952
  .discover-panel {