app.css
⎇
Raw
1/* Theme palettes. The base is light; dark is applied either by the OS
2 preference (theme = auto, the default) or forced by the theme toggle,
3 which puts `light`/`dark` on <html> (see web/src/theme.rs). Keep the two
4 dark blocks in sync. */
5:root {
6 color-scheme: light;
7 --bg: #f6f7f9;
8 --panel: #ffffff;
9 --text: #1a1d21;
10 --muted: #6b7280;
11 --accent: #3b82f6;
12 --accent-hover: #2563eb;
13 --accent-border: #1d4ed8;
14 --danger: #ef4444;
15 --danger-border: #dc2626;
16 --border: #e5e7eb;
17 --topbar-h: 48px;
18 --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.5' stroke-linecap='square'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
19}
20
21:root.dark {
22 color-scheme: dark;
23 --bg: #0f1115;
24 --panel: #171a20;
25 --text: #e5e7eb;
26 --muted: #9ca3af;
27 --accent: #60a5fa;
28 --accent-hover: #3b82f6;
29 --accent-border: #79b5fc;
30 --danger: #f87171;
31 --danger-border: #fa8b8b;
32 --border: #2a2f3a;
33 --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2.5' stroke-linecap='square'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
34}
35
36@media (prefers-color-scheme: dark) {
37 :root:not(.light) {
38 color-scheme: dark;
39 --bg: #0f1115;
40 --panel: #171a20;
41 --text: #e5e7eb;
42 --muted: #9ca3af;
43 --accent: #60a5fa;
44 --accent-hover: #3b82f6;
45 --accent-border: #79b5fc;
46 --danger: #f87171;
47 --danger-border: #fa8b8b;
48 --border: #2a2f3a;
49 --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2.5' stroke-linecap='square'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
50 }
51}
52
53* {
54 box-sizing: border-box;
55 /* The design language is sharp: everything stays square. */
56 border-radius: 0;
57}
58
59body {
60 margin: 0;
61 font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
62 background: var(--bg);
63 color: var(--text);
64 font-size: 15px;
65}
66
67.muted {
68 color: var(--muted);
69}
70
71.card {
72 background: var(--panel);
73 border: 1px solid var(--border);
74 padding: 24px;
75}
76
77.center-screen {
78 min-height: 100vh;
79 display: flex;
80 flex-direction: column;
81 align-items: center;
82 justify-content: center;
83 padding: 16px;
84 text-align: center;
85}
86
87.auth-card {
88 width: 100%;
89 max-width: 380px;
90}
91
92.auth-card h1 {
93 margin: 0 0 8px;
94 font-size: 22px;
95}
96
97.auth-logo {
98 width: 44px;
99 height: 44px;
100 margin-bottom: 12px;
101}
102
103.auth-card p {
104 margin: 0 0 20px;
105 font-size: 13px;
106}
107
108.field {
109 display: block;
110 margin-bottom: 14px;
111}
112
113.field span {
114 display: block;
115 font-size: 13px;
116 color: var(--muted);
117 margin-bottom: 4px;
118}
119
120input {
121 width: 100%;
122 padding: 10px 12px;
123 border: 1px solid var(--border);
124 background: var(--bg);
125 color: var(--text);
126 font-size: 14px;
127}
128
129input:focus {
130 outline: 2px solid var(--accent);
131 outline-offset: -1px;
132}
133
134/* Square checkboxes — native controls are rounded, the theme is sharp. */
135input[type="checkbox"] {
136 appearance: none;
137 -webkit-appearance: none;
138 width: 16px;
139 height: 16px;
140 margin: 0;
141 padding: 0;
142 flex: none;
143 border: 1px solid var(--border);
144 background: var(--panel);
145 cursor: pointer;
146 position: relative;
147 vertical-align: -3px;
148}
149
150input[type="checkbox"]:checked {
151 background: var(--accent);
152 border-color: var(--accent-border);
153}
154
155input[type="checkbox"]:checked::after {
156 content: "";
157 position: absolute;
158 left: 4px;
159 top: 1px;
160 width: 4px;
161 height: 8px;
162 border: solid #fff;
163 border-width: 0 2px 2px 0;
164 transform: rotate(45deg);
165}
166
167button {
168 font: inherit;
169 cursor: pointer;
170 display: inline-flex;
171 align-items: center;
172 justify-content: center;
173 gap: 6px;
174 border: 1px solid var(--border);
175 background: var(--panel);
176 color: var(--text);
177 padding: 9px 14px;
178}
179
180button:hover {
181 border-color: var(--muted);
182}
183
184button:disabled {
185 opacity: 0.6;
186 cursor: default;
187}
188
189.btn-primary {
190 width: 100%;
191 background: var(--accent);
192 /* One step away from the fill, per theme (see palette above), so the
193 button's edge reads the same as on neutral buttons. */
194 border-color: var(--accent-border);
195 color: #fff;
196 font-weight: 600;
197}
198
199.btn-primary:hover {
200 background: var(--accent-hover);
201 border-color: var(--accent-border);
202}
203
204.error {
205 color: var(--danger);
206 font-size: 13px;
207 min-height: 18px;
208 margin: 0 0 10px;
209}
210
211/* layout (signed-in): full-width topbar, then sidebar + content below */
212
213.layout {
214 min-height: 100vh;
215 display: flex;
216 flex-direction: column;
217}
218
219.topbar {
220 flex: none;
221 position: sticky;
222 top: 0;
223 z-index: 130;
224 height: var(--topbar-h);
225 display: flex;
226 align-items: center;
227 justify-content: space-between;
228 gap: 12px;
229 padding: 0 16px;
230 background: var(--panel);
231 border-bottom: 1px solid var(--border);
232}
233
234.topbar-left {
235 display: flex;
236 align-items: center;
237 gap: 10px;
238 min-width: 0;
239}
240
241.icon-btn.nav-toggle {
242 display: none;
243}
244
245.body-row {
246 flex: 1;
247 display: flex;
248 align-items: stretch;
249}
250
251/* ---- sidebar ---- */
252
253.sidebar {
254 flex: none;
255 width: 224px;
256 display: flex;
257 flex-direction: column;
258 background: var(--panel);
259 border-right: 1px solid var(--border);
260 position: sticky;
261 top: var(--topbar-h);
262 height: calc(100vh - var(--topbar-h));
263}
264
265.brand {
266 display: flex;
267 align-items: center;
268 gap: 10px;
269 font-weight: 700;
270 white-space: nowrap;
271 color: inherit;
272 text-decoration: none;
273 cursor: pointer;
274}
275
276.brand:hover {
277 opacity: 0.8;
278}
279
280.brand-name {
281 overflow: hidden;
282 text-overflow: ellipsis;
283}
284
285.logo {
286 width: 26px;
287 height: 26px;
288 flex: none;
289 display: block;
290}
291
292.nav {
293 flex: 1;
294 overflow-y: auto;
295 padding: 14px 8px 16px;
296 display: flex;
297 flex-direction: column;
298 gap: 20px;
299}
300
301.sidebar-user {
302 padding: 0 10px 2px;
303 font-size: 14px;
304 font-weight: 600;
305 overflow: hidden;
306 text-overflow: ellipsis;
307 white-space: nowrap;
308}
309
310.nav-section-label {
311 font-size: 11px;
312 font-weight: 700;
313 text-transform: uppercase;
314 letter-spacing: 0.08em;
315 color: var(--muted);
316 padding: 0 10px 6px;
317}
318
319/* Section header with a right-aligned action (the Files refresh). */
320.nav-section-head {
321 display: flex;
322 align-items: center;
323 justify-content: space-between;
324 gap: 6px;
325 margin-bottom: 4px;
326}
327
328.nav-section-head .nav-section-label {
329 flex: 1;
330 padding-bottom: 2px;
331}
332
333.nav-section-refresh {
334 color: var(--muted);
335 background: none;
336 border-color: transparent;
337 padding: 3px 5px;
338}
339
340.nav-section-refresh:hover {
341 color: var(--text);
342 border-color: var(--border);
343}
344
345.nav-tab {
346 display: flex;
347 align-items: center;
348 justify-content: flex-start;
349 gap: 10px;
350 width: 100%;
351 margin-bottom: 2px;
352 padding: 8px 10px;
353 text-align: left;
354 background: none;
355 border: none;
356 color: var(--muted);
357 font-size: 14px;
358}
359
360.nav-tab:hover {
361 background: var(--bg);
362 color: var(--text);
363}
364
365.nav-tab.active {
366 background: var(--accent);
367 border-color: var(--accent);
368 color: #fff;
369}
370
371.ic-tab {
372 width: 18px;
373 height: 18px;
374 flex: none;
375}
376
377.nav-tab.active .icon {
378 color: #fff;
379}
380
381.nav-tab-name {
382 flex: 1;
383 min-width: 0;
384 overflow: hidden;
385 text-overflow: ellipsis;
386 white-space: nowrap;
387}
388
389.nav-tab-note {
390 flex: none;
391 font-size: 10px;
392 font-weight: 700;
393 padding: 1px 5px;
394 background: var(--bg);
395 border: 1px solid var(--border);
396 color: var(--muted);
397}
398
399.nav-tab.active .nav-tab-note {
400 background: rgb(255 255 255 / 18%);
401 border-color: rgb(255 255 255 / 30%);
402 color: #fff;
403}
404
405.nav-backdrop {
406 display: none;
407}
408
409/* Sidebar footer: theme toggle, log out, and the project version.
410 Sits at the bottom of the sidebar, below the manage section. */
411.sidebar-footer {
412 flex: none;
413 border-top: 1px solid var(--border);
414 padding: 8px;
415}
416
417.sidebar-footer .nav-tab {
418 margin-bottom: 0;
419}
420
421.sidebar-action.logout {
422 color: var(--danger);
423}
424
425.sidebar-action.logout:hover {
426 color: var(--danger);
427}
428
429.sidebar-version {
430 margin-top: 8px;
431 padding: 0 10px;
432 font-size: 11.5px;
433 color: var(--muted);
434 white-space: nowrap;
435 overflow: hidden;
436 text-overflow: ellipsis;
437}
438
439.badge {
440 font-size: 11px;
441 padding: 2px 8px;
442 background: var(--bg);
443 border: 1px solid var(--border);
444 color: var(--muted);
445}
446
447.content {
448 flex: 1;
449 min-width: 0;
450 min-height: 0;
451 display: flex;
452 flex-direction: column;
453 padding: 20px;
454}
455
456/* While a file is open the app is a fixed-height frame: the file view
457 * (editor, image, …) scrolls inside, the page itself never grows. */
458.layout.file-mode {
459 height: 100vh;
460 overflow: hidden;
461}
462
463.layout.file-mode .body-row {
464 min-height: 0;
465}
466
467/* Narrow screens: the sidebar becomes an off-canvas drawer that only
468 covers the content, below the (always visible) topbar. */
469@media (max-width: 860px) {
470 .sidebar {
471 position: fixed;
472 top: var(--topbar-h);
473 bottom: 0;
474 left: 0;
475 right: auto;
476 height: auto;
477 z-index: 120;
478 transform: translateX(-100%);
479 transition: transform 0.15s ease;
480 }
481
482 .sidebar.open {
483 transform: translateX(0);
484 box-shadow: 0 0 48px rgb(0 0 0 / 35%);
485 }
486
487 .nav-backdrop {
488 display: block;
489 position: fixed;
490 top: var(--topbar-h);
491 bottom: 0;
492 left: 0;
493 right: 0;
494 z-index: 110;
495 background: rgb(0 0 0 / 40%);
496 }
497
498 .icon-btn.nav-toggle {
499 display: inline-flex;
500 }
501
502 .content {
503 padding: 14px;
504 }
505}
506
507/* ---- file browser ---- */
508
509.browser {
510 width: 100%;
511 max-width: 1200px;
512 margin: 0 auto;
513 flex: 1;
514 display: flex;
515 flex-direction: column;
516 min-height: 0;
517}
518
519.icon {
520 width: 20px;
521 height: 20px;
522 display: inline-block;
523 vertical-align: middle;
524}
525
526.ic-folder {
527 color: var(--accent);
528}
529
530.ic-muted {
531 color: var(--muted);
532}
533
534.crumbs {
535 display: flex;
536 align-items: center;
537 gap: 2px;
538 padding: 6px 0 12px;
539 font-size: 15px;
540 flex-wrap: wrap;
541}
542
543.crumb {
544 cursor: pointer;
545 color: var(--muted);
546 padding: 3px 6px;
547}
548
549.crumb:hover {
550 color: var(--text);
551 background: var(--panel);
552}
553
554.crumb.current {
555 color: var(--text);
556 font-weight: 600;
557 cursor: default;
558 background: none;
559}
560
561.crumb-sep {
562 color: var(--muted);
563 padding: 0 1px;
564}
565
566.toolbar {
567 display: flex;
568 align-items: center;
569 justify-content: space-between;
570 gap: 6px;
571 padding-bottom: 12px;
572}
573
574.toolbar-right {
575 display: flex;
576 gap: 6px;
577}
578
579.icon-btn {
580 padding: 7px 9px;
581 border: 1px solid var(--border);
582 background: var(--panel);
583 color: var(--muted);
584 display: inline-flex;
585 align-items: center;
586}
587
588.icon-btn:hover {
589 border-color: var(--muted);
590}
591
592.icon-btn.active {
593 background: var(--accent);
594 border-color: var(--accent);
595 color: #fff;
596}
597
598.ic-btn {
599 width: 18px;
600 height: 18px;
601 color: inherit;
602}
603
604.entries-area {
605 flex: 1;
606 min-height: 240px;
607}
608
609.center-note {
610 text-align: center;
611 padding: 48px 0;
612}
613
614.error-card {
615 display: flex;
616 align-items: center;
617 justify-content: space-between;
618 gap: 16px;
619 color: var(--danger);
620 font-size: 14px;
621}
622
623/* root tiles were replaced by the sidebar's folder tabs */
624
625/* grid view */
626
627.entries-grid {
628 display: grid;
629 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
630 gap: 10px;
631}
632
633.tile {
634 background: var(--panel);
635 border: 1px solid var(--border);
636 padding: 16px 10px 12px;
637 text-align: center;
638 cursor: pointer;
639 user-select: none;
640}
641
642.tile:hover {
643 border-color: var(--muted);
644}
645
646.tile-icon {
647 width: 42px;
648 height: 42px;
649 margin: 0 auto 10px;
650 display: block;
651}
652
653.tile-name {
654 font-size: 13px;
655 line-height: 1.3;
656 word-break: break-word;
657}
658
659/* list view */
660
661.entries-list {
662 background: var(--panel);
663 border: 1px solid var(--border);
664 overflow: hidden;
665}
666
667.row {
668 display: grid;
669 grid-template-columns: 28px minmax(0, 1fr) 90px 150px;
670 gap: 12px;
671 align-items: center;
672 padding: 9px 14px;
673 border-bottom: 1px solid var(--border);
674 cursor: pointer;
675 font-size: 14px;
676 user-select: none;
677}
678
679.row:last-child {
680 border-bottom: none;
681}
682
683.row:hover {
684 background: var(--bg);
685}
686
687.row-icon {
688 width: 20px;
689 height: 20px;
690}
691
692.row-name {
693 overflow: hidden;
694 text-overflow: ellipsis;
695 white-space: nowrap;
696}
697
698.row-size,
699.row-date {
700 font-size: 13px;
701 text-align: right;
702}
703
704@media (max-width: 640px) {
705 .row {
706 grid-template-columns: 28px minmax(0, 1fr) 90px;
707 }
708
709 .row-date {
710 display: none;
711 }
712}
713
714/* context menu */
715
716.ctx-menu {
717 position: fixed;
718 z-index: 100;
719 min-width: 190px;
720 background: var(--panel);
721 border: 1px solid var(--border);
722 padding: 5px;
723 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
724}
725
726.ctx-item {
727 display: flex;
728 align-items: center;
729 gap: 10px;
730 padding: 8px 12px;
731 font-size: 14px;
732 cursor: pointer;
733}
734
735.ic-ctx {
736 width: 18px;
737 height: 18px;
738 flex: none;
739}
740
741.ctx-item:hover {
742 background: var(--bg);
743}
744
745.ctx-item.disabled {
746 opacity: 0.45;
747 cursor: default;
748}
749
750.ctx-item.disabled:hover {
751 background: none;
752}
753
754/* toolbar selection actions (top right) */
755
756.sel-actions {
757 display: flex;
758 align-items: center;
759 gap: 6px;
760 position: relative;
761}
762
763.sel-actions .icon-btn:disabled {
764 opacity: 0.45;
765 cursor: default;
766}
767
768.sel-actions .icon-btn:disabled:hover {
769 border-color: var(--border);
770 color: var(--muted);
771}
772
773.sel-more-wrap {
774 position: relative;
775}
776
777.sel-more-menu {
778 position: absolute;
779 right: 0;
780 top: calc(100% + 6px);
781 z-index: 100;
782 min-width: 190px;
783 background: var(--panel);
784 border: 1px solid var(--border);
785 padding: 5px;
786 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
787}
788
789.sel-more-menu.hidden {
790 display: none;
791}
792
793/* selection actions in the top bar */
794
795.topbar .sel-actions {
796 min-height: 0;
797}
798
799.topbar .sel-actions .icon-btn {
800 padding: 5px 7px;
801}
802
803/* selection highlight in the grid and list */
804
805.tile.selected {
806 border-color: var(--accent);
807 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
808}
809
810.row.selected {
811 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
812 box-shadow: inset 2px 0 0 var(--accent);
813}
814
815/* settings tabs (profile / server) */
816
817.settings-tabs {
818 display: flex;
819 gap: 8px;
820}
821
822.settings-tab-btn {
823 padding: 7px 14px;
824 border: 1px solid var(--border);
825 background: var(--panel);
826 color: var(--muted);
827 font-size: 13px;
828 font-weight: 600;
829}
830
831.settings-tab-btn:hover {
832 border-color: var(--muted);
833 color: var(--text);
834}
835
836.settings-tab-btn.active {
837 border-color: var(--accent);
838 color: var(--accent);
839 background: color-mix(in srgb, var(--accent) 10%, var(--panel));
840}
841
842/* toast */
843
844.toast {
845 position: fixed;
846 bottom: 20px;
847 right: 20px;
848 z-index: 200;
849 background: var(--panel);
850 color: var(--text);
851 border: 1px solid var(--border);
852 padding: 11px 16px;
853 font-size: 14px;
854 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
855 max-width: 320px;
856}
857
858.toast-error {
859 background: color-mix(in srgb, var(--danger) 12%, var(--panel));
860 border-color: var(--danger-border);
861 color: var(--danger);
862}
863
864
865/* ---- modals ---- */
866
867.modal-overlay {
868 position: fixed;
869 inset: 0;
870 background: rgb(0 0 0 / 45%);
871 display: flex;
872 align-items: center;
873 justify-content: center;
874 z-index: 100;
875}
876
877.modal {
878 width: 440px;
879 max-width: calc(100vw - 32px);
880 padding: 20px;
881 background: var(--panel);
882 border: 1px solid var(--border);
883 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
884}
885
886.modal.picker {
887 width: 520px;
888}
889
890.modal-title {
891 margin: 0 0 12px;
892 font-size: 16px;
893}
894
895.modal-label {
896 display: block;
897 font-size: 13px;
898 color: var(--muted);
899 margin-bottom: 6px;
900}
901
902.modal .input {
903 width: 100%;
904 box-sizing: border-box;
905 margin-bottom: 16px;
906}
907
908.modal-label.error,
909.dialog-error {
910 color: var(--danger);
911 font-size: 13px;
912}
913
914.dialog-error {
915 margin-top: 8px;
916}
917
918.modal-message {
919 white-space: pre-line;
920 font-size: 14px;
921 margin: 0 0 8px;
922}
923
924.modal-actions {
925 display: flex;
926 justify-content: flex-end;
927 gap: 8px;
928 margin-top: 16px;
929}
930
931.btn-danger {
932 background: var(--danger);
933 /* A visible border (one step away from the fill, per theme) so the
934 button's edge reads the same as on neutral buttons. */
935 border-color: var(--danger-border);
936 color: #fff;
937}
938
939.btn-danger:hover {
940 background: color-mix(in srgb, var(--danger) 85%, black);
941}
942
943.btn:disabled {
944 opacity: 0.5;
945 cursor: not-allowed;
946}
947
948.conflict-list {
949 max-height: 200px;
950 overflow-y: auto;
951 margin: 8px 0;
952 padding-left: 20px;
953 font-size: 13px;
954}
955
956.picker-roots {
957 display: flex;
958 gap: 6px;
959 flex-wrap: wrap;
960 margin-bottom: 12px;
961}
962
963.root-opt {
964 font-size: 13px;
965}
966
967.root-opt.active {
968 background: var(--accent);
969 border-color: var(--accent);
970 color: #fff;
971}
972
973.picker-current {
974 font-size: 13px;
975 margin: 0 0 8px;
976}
977
978.picker-crumbs {
979 margin-bottom: 8px;
980}
981
982.picker-entries {
983 max-height: 240px;
984 overflow-y: auto;
985 border: 1px solid var(--border);
986}
987
988.picker-row {
989 display: flex;
990 align-items: center;
991 gap: 10px;
992 padding: 8px 12px;
993 cursor: pointer;
994}
995
996.picker-row:hover {
997 background: var(--bg);
998}
999
1000/* ---------------------------------------------------------------------------
1001 * Full-page file view (preview / editor / "no preview"). The top bar carries
1002 * the title + actions; the content area below is edge to edge.
1003 * ------------------------------------------------------------------------- */
1004.content.file-open {
1005 padding: 0;
1006 overflow: hidden;
1007}
1008
1009/* The browser stays mounted (state, fetch callback) but hidden. */
1010.content.file-open .browser {
1011 display: none;
1012}
1013
1014.file-view {
1015 flex: 1;
1016 min-height: 0;
1017 display: flex;
1018 flex-direction: column;
1019}
1020
1021.file-title {
1022 display: flex;
1023 align-items: center;
1024 gap: 8px;
1025 min-width: 0;
1026}
1027
1028.file-title-icon {
1029 width: 18px;
1030 height: 18px;
1031 flex: none;
1032 color: var(--muted);
1033}
1034
1035.file-title-name {
1036 font-weight: 600;
1037 font-size: 14px;
1038 white-space: nowrap;
1039 overflow: hidden;
1040 text-overflow: ellipsis;
1041}
1042
1043.file-actions {
1044 display: flex;
1045 align-items: center;
1046 gap: 10px;
1047 flex: none;
1048}
1049
1050.file-close,
1051.file-download {
1052 border: none;
1053 background: transparent;
1054 color: var(--muted);
1055 padding: 6px 8px;
1056}
1057
1058.file-close:hover,
1059.file-download:hover {
1060 color: var(--text);
1061 background: var(--bg);
1062}
1063.preview-body {
1064 flex: 1;
1065 min-height: 0;
1066 overflow: auto;
1067 display: flex;
1068 background: var(--bg);
1069}
1070.preview-img {
1071 max-width: 100%;
1072 max-height: 100%;
1073 display: block;
1074 margin: auto;
1075}
1076.preview-pdf {
1077 width: 100%;
1078 height: 100%;
1079 border: none;
1080 background: #fff;
1081}
1082.preview-video {
1083 width: 100%;
1084 max-height: 100%;
1085 background: #000;
1086}
1087.preview-audio {
1088 display: flex;
1089 align-items: center;
1090 justify-content: center;
1091 width: 100%;
1092 padding: 24px;
1093}
1094.preview-audio audio {
1095 width: 100%;
1096 max-width: 480px;
1097}
1098
1099/* CodeMirror (text editor) */
1100.cm-container {
1101 height: 100%;
1102}
1103.cm-container .cm-editor {
1104 height: 100%;
1105}
1106/* Load/save failure: dims the editor and shows the message in a card
1107 * (the top-bar Save button stays reachable to retry). */
1108.cm-error {
1109 position: absolute;
1110 inset: 0;
1111 z-index: 5;
1112 display: flex;
1113 align-items: center;
1114 justify-content: center;
1115 padding: 24px;
1116 background: rgb(0 0 0 / 45%);
1117}
1118
1119.cm-error-card {
1120 position: relative;
1121 max-width: 440px;
1122 min-width: 200px;
1123 background: var(--panel);
1124 border: 1px solid var(--border);
1125 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
1126}
1127
1128.cm-error-close {
1129 position: absolute;
1130 top: 7px;
1131 right: 7px;
1132 display: inline-flex;
1133 align-items: center;
1134 justify-content: center;
1135 border: none;
1136 background: transparent;
1137 color: var(--muted);
1138 padding: 3px;
1139}
1140
1141.cm-error-close:hover {
1142 color: var(--text);
1143 background: var(--bg);
1144}
1145
1146.cm-error-close .ic-btn {
1147 width: 16px;
1148 height: 16px;
1149}
1150
1151.cm-error-text {
1152 padding: 16px 40px 16px 20px;
1153 font-size: 14px;
1154 text-align: center;
1155 overflow-wrap: anywhere;
1156}
1157
1158/* ---------------------------------------------------------------------------
1159 * Text editor (full page; title/save/close live in the top bar)
1160 * ------------------------------------------------------------------------- */
1161.file-editor {
1162 flex: 1;
1163 min-height: 0;
1164 display: flex;
1165 position: relative;
1166 background: var(--bg);
1167}
1168.file-editor .cm-container {
1169 width: 100%;
1170 height: 100%;
1171}
1172/* "No preview" fallback (binaries, archives). */
1173.file-nopreview {
1174 flex: 1;
1175 display: flex;
1176 align-items: center;
1177 justify-content: center;
1178}
1179.file-nopreview .btn-primary {
1180 width: auto;
1181 margin-top: 14px;
1182}
1183/* Conflict / discard dialogs render above the file view. */
1184.editor-sub-overlay {
1185 z-index: 101;
1186 background: rgb(0 0 0 / 25%);
1187}
1188
1189/* ---------------------------------------------------------------------------
1190 * Download format dialog
1191 * ------------------------------------------------------------------------- */
1192.dl-formats {
1193 display: flex;
1194 flex-direction: column;
1195 gap: 8px;
1196 margin-bottom: 8px;
1197}
1198.dl-fmt {
1199 justify-content: flex-start;
1200}
1201
1202/* ---------------------------------------------------------------------------
1203 * Item info dialog
1204 * ------------------------------------------------------------------------- */
1205.info-list {
1206 margin: 8px 0 16px;
1207 display: grid;
1208 grid-template-columns: 90px 1fr;
1209 row-gap: 8px;
1210 column-gap: 12px;
1211}
1212.info-list dt {
1213 color: var(--muted);
1214}
1215.info-list dd {
1216 margin: 0;
1217 word-break: break-word;
1218}
1219
1220/* ---------------------------------------------------------------------------
1221 Shares (milestone 6)
1222 --------------------------------------------------------------------------- */
1223
1224.share-modal {
1225 width: 480px;
1226}
1227
1228.share-link-row {
1229 display: flex;
1230 gap: 8px;
1231 margin: 12px 0;
1232}
1233
1234.share-link-input {
1235 flex: 1;
1236 font-family: ui-monospace, monospace;
1237 font-size: 12.5px;
1238 padding: 8px 10px;
1239 border: 1px solid var(--border);
1240 background: var(--bg);
1241 color: var(--text);
1242 min-width: 0;
1243}
1244
1245.share-check {
1246 display: flex;
1247 align-items: center;
1248 gap: 8px;
1249 margin: 4px 0 14px;
1250 font-size: 14px;
1251}
1252
1253.share-check input {
1254 width: 16px;
1255 height: 16px;
1256}
1257
1258.share-expiry-row {
1259 display: flex;
1260 align-items: center;
1261 gap: 10px;
1262 margin: 0 0 10px;
1263}
1264
1265.share-expiry-row label {
1266 font-size: 13px;
1267 color: var(--muted);
1268 min-width: 52px;
1269}
1270
1271.share-expiry-row select,
1272.share-expiry-row input {
1273 flex: 1;
1274 padding: 8px 10px;
1275 border: 1px solid var(--border);
1276 background: var(--panel);
1277 color: var(--text);
1278 font: inherit;
1279}
1280
1281.share-expiry-note {
1282 margin: 4px 0 0;
1283 font-size: 12.5px;
1284}
1285
1286.btn-sm {
1287 padding: 5px 10px;
1288 font-size: 12.5px;
1289}
1290
1291.icon-btn-sm {
1292 padding: 4px 6px;
1293}
1294
1295/* "Your shares" manage view */
1296
1297.shares-view {
1298 width: 100%;
1299 max-width: 960px;
1300 margin: 0 auto;
1301}
1302
1303.view-header {
1304 margin-bottom: 16px;
1305}
1306
1307.view-header .admin-section-title {
1308 margin-bottom: 0;
1309}
1310
1311.view-hint {
1312 margin: 4px 0 0;
1313 font-size: 13px;
1314 max-width: 64ch;
1315}
1316
1317.share-list {
1318 display: flex;
1319 flex-direction: column;
1320 gap: 10px;
1321}
1322
1323.share-item {
1324 display: flex;
1325 align-items: center;
1326 justify-content: space-between;
1327 gap: 12px;
1328 padding: 10px 12px;
1329 border: 1px solid var(--border);
1330 background: var(--panel);
1331}
1332
1333.share-item-main {
1334 min-width: 0;
1335}
1336
1337.share-item-name {
1338 display: flex;
1339 align-items: center;
1340 gap: 8px;
1341 font-weight: 600;
1342 font-size: 14px;
1343 overflow: hidden;
1344 text-overflow: ellipsis;
1345 white-space: nowrap;
1346}
1347
1348.ic-row {
1349 width: 18px;
1350 height: 18px;
1351 flex: none;
1352}
1353
1354.share-item-meta {
1355 font-size: 12px;
1356 margin-top: 2px;
1357 overflow: hidden;
1358 text-overflow: ellipsis;
1359 white-space: nowrap;
1360}
1361
1362.share-item-actions {
1363 display: flex;
1364 gap: 6px;
1365 flex-shrink: 0;
1366}
1367
1368/* ------------------------------------------------------------------ */
1369/* Admin (milestone 7) */
1370/* ------------------------------------------------------------------ */
1371
1372.admin-view {
1373 display: flex;
1374 flex-direction: column;
1375 gap: 16px;
1376 width: 100%;
1377 max-width: 960px;
1378 margin: 0 auto;
1379}
1380
1381.admin-section-title {
1382 margin: 0 0 14px;
1383 font-size: 15px;
1384}
1385
1386.users-header {
1387 display: flex;
1388 align-items: center;
1389 justify-content: space-between;
1390 margin-bottom: 4px;
1391}
1392
1393.users-header .admin-section-title {
1394 margin-bottom: 0;
1395}
1396
1397.users-header .btn-primary {
1398 width: auto;
1399}
1400
1401.user-list {
1402 display: flex;
1403 flex-direction: column;
1404 gap: 10px;
1405}
1406
1407.user-row {
1408 display: flex;
1409 align-items: center;
1410 justify-content: space-between;
1411 gap: 12px;
1412 padding: 12px 14px;
1413 border: 1px solid var(--border);
1414}
1415
1416.user-row-main {
1417 min-width: 0;
1418}
1419
1420.user-row-name {
1421 display: flex;
1422 align-items: center;
1423 gap: 6px;
1424 font-weight: 600;
1425 font-size: 14px;
1426 flex-wrap: wrap;
1427}
1428
1429.ic-admin {
1430 width: 16px;
1431 height: 16px;
1432 flex: none;
1433}
1434
1435.user-row-actions {
1436 display: flex;
1437 gap: 6px;
1438 flex-shrink: 0;
1439}
1440
1441.badge-off {
1442 background: color-mix(in srgb, var(--danger) 15%, var(--panel));
1443 border-color: var(--danger);
1444 color: var(--danger);
1445}
1446
1447.setting-row {
1448 display: flex;
1449 align-items: center;
1450 gap: 10px;
1451 padding: 14px;
1452 border: 1px solid var(--border);
1453 cursor: pointer;
1454}
1455
1456.setting-row input {
1457 margin-left: auto;
1458}
1459
1460.setting-label {
1461 display: block;
1462 font-weight: 600;
1463 font-size: 14px;
1464}
1465
1466.setting-desc {
1467 display: block;
1468 font-size: 12px;
1469 color: var(--muted);
1470 margin-top: 2px;
1471}
1472
1473/* Setting row whose control is a select, pushed to the right. */
1474.setting-row-select {
1475 cursor: default;
1476}
1477
1478.setting-row-select > span {
1479 flex: 1;
1480}
1481
1482.setting-row-select select {
1483 appearance: none;
1484 margin-left: auto;
1485 padding: 10px 42px 10px 12px;
1486 border: 1px solid var(--border);
1487 background-color: var(--panel);
1488 background-image: var(--select-arrow);
1489 background-repeat: no-repeat;
1490 background-position: right 12px center;
1491 background-size: 14px 14px;
1492 color: var(--text);
1493 font: inherit;
1494 max-width: 190px;
1495}
1496
1497/* User create/edit form */
1498
1499.user-form {
1500 width: 520px;
1501}
1502
1503.field-input {
1504 width: 100%;
1505 box-sizing: border-box;
1506}
1507
1508.field-hint {
1509 font-size: 12px;
1510 margin: -2px 0 8px;
1511}
1512
1513.check-row {
1514 display: flex;
1515 align-items: center;
1516 gap: 8px;
1517 font-size: 14px;
1518 margin-bottom: 12px;
1519 cursor: pointer;
1520}
1521
1522.check-row input {
1523 width: auto;
1524}
1525
1526.form-error {
1527 color: var(--danger);
1528 font-size: 13px;
1529 margin: 4px 0 8px;
1530}
1531
1532.roots-editor {
1533 display: flex;
1534 flex-direction: column;
1535 gap: 6px;
1536}
1537
1538.root-draft {
1539 display: flex;
1540 align-items: center;
1541 gap: 8px;
1542}
1543
1544.root-draft-path {
1545 flex: 1;
1546 font-size: 13px;
1547 overflow: hidden;
1548 text-overflow: ellipsis;
1549 white-space: nowrap;
1550}
1551
1552.root-draft-mode {
1553 width: auto;
1554 padding: 6px 8px;
1555}
1556
1557.root-add {
1558 display: flex;
1559 gap: 8px;
1560 margin-top: 4px;
1561}
1562
1563/* ------------------------------------------------------------------ */
1564/* Empty state + keyboard focus (milestone 8) */
1565/* ------------------------------------------------------------------ */
1566
1567.empty-state {
1568 display: flex;
1569 flex-direction: column;
1570 align-items: center;
1571 justify-content: center;
1572 gap: 8px;
1573 padding: 64px 20px;
1574 text-align: center;
1575}
1576
1577.empty-glyph {
1578 width: 52px;
1579 height: 52px;
1580}
1581
1582.empty-state h3 {
1583 margin: 0;
1584 font-size: 16px;
1585}
1586
1587/* Visible keyboard focus on selectable file/folder entries. The ring is
1588 inset (negative offset) so the scroll container never clips it. */
1589.tile:focus-visible,
1590.row:focus-visible {
1591 outline: 2px solid var(--accent);
1592 outline-offset: -2px;
1593}
1594
1595/* ------------------------------------------------------------------ */
1596/* Search view (#/search) */
1597/* ------------------------------------------------------------------ */
1598
1599.search-view {
1600 display: flex;
1601 flex-direction: column;
1602 gap: 14px;
1603}
1604
1605/* Query bar ------------------------------------------------------ */
1606
1607.query-bar {
1608 display: flex;
1609 align-items: stretch;
1610 gap: 8px;
1611}
1612
1613.query-input {
1614 flex: 1;
1615 display: flex;
1616 align-items: center;
1617 gap: 8px;
1618 background: var(--panel);
1619 border: 1px solid var(--border);
1620 padding: 0 10px;
1621 min-width: 0;
1622}
1623
1624.query-input .qi-icon {
1625 width: 18px;
1626 height: 18px;
1627 color: var(--muted);
1628 flex: none;
1629}
1630
1631.query-input input {
1632 flex: 1;
1633 min-width: 0;
1634 border: none;
1635 outline: none;
1636 background: transparent;
1637 color: var(--text);
1638 font: inherit;
1639 font-size: 14px;
1640 height: 38px;
1641 padding: 0;
1642}
1643
1644.query-input input::placeholder {
1645 color: var(--muted);
1646}
1647
1648/* Segmented Name / Content / Both control */
1649
1650.seg {
1651 display: flex;
1652 border: 1px solid var(--border);
1653 background: var(--panel);
1654}
1655
1656.seg button {
1657 appearance: none;
1658 border: none;
1659 border-right: 1px solid var(--border);
1660 background: transparent;
1661 color: var(--muted);
1662 font: inherit;
1663 font-size: 13px;
1664 padding: 0 14px;
1665 cursor: pointer;
1666}
1667
1668.seg button:last-child {
1669 border-right: none;
1670}
1671
1672.seg button:hover {
1673 background: var(--bg);
1674}
1675
1676.seg button.on {
1677 background: var(--accent);
1678 color: #fff;
1679}
1680
1681/* Roots multi-select --------------------------------------------- */
1682
1683/* The root a search covers. A native select, styled like the query bar. */
1684.root-select {
1685 flex: none;
1686 max-width: 220px;
1687 border: 1px solid var(--border);
1688 background: var(--panel);
1689 color: var(--text);
1690 font: inherit;
1691 font-size: 13px;
1692 padding: 0 10px;
1693}
1694
1695.ms {
1696 position: relative;
1697 display: flex;
1698}
1699
1700.ms-btn {
1701 display: flex;
1702 align-items: center;
1703 gap: 6px;
1704 border: 1px solid var(--border);
1705 background: var(--panel);
1706 color: var(--text);
1707 font: inherit;
1708 font-size: 13px;
1709 padding: 0 10px;
1710 cursor: pointer;
1711 max-width: 180px;
1712}
1713
1714.ms-btn:hover {
1715 background: var(--bg);
1716}
1717
1718.ms-btn > span {
1719 overflow: hidden;
1720 text-overflow: ellipsis;
1721 white-space: nowrap;
1722}
1723
1724/* Square caret drawn with borders (the icon set has no chevron). */
1725.ms-caret {
1726 flex: none;
1727 width: 8px;
1728 height: 8px;
1729 border-right: 2px solid var(--muted);
1730 border-bottom: 2px solid var(--muted);
1731 transform: rotate(45deg) translate(-1px, -1px);
1732}
1733
1734.ms-backdrop {
1735 position: fixed;
1736 inset: 0;
1737 z-index: 40;
1738}
1739
1740.ms-drop {
1741 position: absolute;
1742 right: 0;
1743 top: calc(100% + 4px);
1744 z-index: 41;
1745 min-width: 200px;
1746 max-height: 280px;
1747 overflow: auto;
1748 background: var(--panel);
1749 border: 1px solid var(--border);
1750 padding: 4px 0;
1751}
1752
1753.ms-opt {
1754 display: flex;
1755 align-items: center;
1756 gap: 8px;
1757 padding: 7px 12px;
1758 font-size: 14px;
1759 cursor: pointer;
1760 user-select: none;
1761}
1762
1763.ms-opt:hover {
1764 background: var(--bg);
1765}
1766
1767.ms-opt span {
1768 overflow: hidden;
1769 text-overflow: ellipsis;
1770 white-space: nowrap;
1771}
1772
1773/* Run / stop ------------------------------------------------------- */
1774
1775.btn-run {
1776 border: 1px solid var(--accent-border);
1777 background: var(--accent);
1778 color: #fff;
1779 font: inherit;
1780 font-size: 13px;
1781 font-weight: 600;
1782 padding: 0 18px;
1783 cursor: pointer;
1784}
1785
1786.btn-run:hover {
1787 background: var(--accent-hover);
1788}
1789
1790.btn-stop {
1791 display: flex;
1792 align-items: center;
1793 gap: 6px;
1794 border: 1px solid var(--danger-border);
1795 background: var(--danger);
1796 color: #fff;
1797 font: inherit;
1798 font-size: 13px;
1799 font-weight: 600;
1800 padding: 0 14px;
1801 cursor: pointer;
1802}
1803
1804.btn-stop:hover {
1805 opacity: 0.9;
1806}
1807
1808.btn-stop .ic-stop {
1809 width: 14px;
1810 height: 14px;
1811}
1812
1813/* Status line ------------------------------------------------------ */
1814
1815.status-line {
1816 display: flex;
1817 align-items: center;
1818 gap: 8px;
1819 font-size: 13px;
1820 color: var(--muted);
1821}
1822
1823.status-line .dot {
1824 width: 8px;
1825 height: 8px;
1826 background: var(--accent);
1827 animation: search-pulse 1s ease-in-out infinite;
1828}
1829
1830@keyframes search-pulse {
1831 0%,
1832 100% {
1833 opacity: 1;
1834 }
1835 50% {
1836 opacity: 0.3;
1837 }
1838}
1839
1840.status-line .skip {
1841 opacity: 0.75;
1842}
1843
1844/* Group labels ----------------------------------------------------- */
1845
1846.group-label {
1847 display: flex;
1848 align-items: center;
1849 gap: 8px;
1850 font-size: 12px;
1851 font-weight: 600;
1852 letter-spacing: 0.04em;
1853 text-transform: uppercase;
1854 color: var(--muted);
1855}
1856
1857/* Result group: a `display:flex` (or `none`, from the inline style) flex
1858 item of `.search-view` that re-establishes the column layout for its
1859 label/list/more-row children. */
1860.result-group {
1861 flex-direction: column;
1862 gap: 14px;
1863}
1864
1865.group-label .gl-icon {
1866 width: 15px;
1867 height: 15px;
1868}
1869
1870.group-label .n {
1871 font-weight: 400;
1872 text-transform: none;
1873 letter-spacing: 0;
1874}
1875
1876.group-label .grow {
1877 flex: 1;
1878}
1879
1880.collapse-all {
1881 appearance: none;
1882 border: 1px solid var(--border);
1883 background: transparent;
1884 color: var(--muted);
1885 font: inherit;
1886 font-size: 12px;
1887 text-transform: none;
1888 letter-spacing: 0;
1889 padding: 3px 10px;
1890 cursor: pointer;
1891}
1892
1893.collapse-all:hover {
1894 background: var(--bg);
1895 color: var(--text);
1896}
1897
1898/* Name-result rows --------------------------------------------------- */
1899
1900.srow {
1901 display: grid;
1902 /* icon | name+dir | size | goto */
1903 grid-template-columns: 28px minmax(0, 1fr) 90px 30px;
1904 gap: 12px;
1905 align-items: center;
1906 padding: 9px 14px;
1907 border-bottom: 1px solid var(--border);
1908 cursor: pointer;
1909 font-size: 14px;
1910 user-select: none;
1911}
1912
1913.srow:last-child {
1914 border-bottom: none;
1915}
1916
1917.srow:hover {
1918 background: var(--bg);
1919}
1920
1921.srow-icon {
1922 width: 20px;
1923 height: 20px;
1924}
1925
1926.srow-main {
1927 min-width: 0;
1928 display: flex;
1929 flex-direction: column;
1930 line-height: 1.3;
1931}
1932
1933.srow-name {
1934 overflow: hidden;
1935 text-overflow: ellipsis;
1936 white-space: nowrap;
1937}
1938
1939/* Highlighted query hits (plain fragments render as bare spans). */
1940mark.hl-hit {
1941 background: color-mix(in srgb, var(--accent) 25%, transparent);
1942 color: inherit;
1943}
1944
1945/* The directory-path line (the name line lives inside .srow-name). */
1946.srow-dir {
1947 font-size: 12px;
1948 color: var(--muted);
1949 overflow: hidden;
1950 text-overflow: ellipsis;
1951 white-space: nowrap;
1952}
1953
1954.srow-dir mark.hl-hit {
1955 color: inherit;
1956}
1957
1958.ssize {
1959 font-size: 13px;
1960 color: var(--muted);
1961 text-align: right;
1962}
1963
1964/* Paging footer: position in the results on the left, the action on the
1965 right. Separated from the list by its own border so the button never reads
1966 as another result row. */
1967.page-foot {
1968 display: flex;
1969 align-items: center;
1970 justify-content: space-between;
1971 gap: 12px;
1972 padding: 10px 14px;
1973 border-top: 1px solid var(--border);
1974 font-size: 12px;
1975 color: var(--muted);
1976}
1977
1978.page-foot .pf-count {
1979 font-variant-numeric: tabular-nums;
1980}
1981
1982.page-foot .pf-more {
1983 appearance: none;
1984 padding: 5px 12px;
1985 border: 1px solid var(--border);
1986 background: var(--panel);
1987 font: inherit;
1988 font-weight: 500;
1989 color: var(--text);
1990 cursor: pointer;
1991}
1992
1993.page-foot .pf-more:hover {
1994 border-color: var(--accent);
1995 color: var(--accent);
1996}
1997
1998/* Content matches ----------------------------------------------------- */
1999
2000.match-card {
2001 background: var(--panel);
2002 border: 1px solid var(--border);
2003 border-top: none;
2004}
2005
2006/* The first card is the one right after the group label; `:first-of-type`
2007 cannot be used because the label is an earlier `div` sibling. */
2008.group-label + .match-card {
2009 border-top: 1px solid var(--border);
2010}
2011
2012/* The header opens the file; the matched lines below are text to read. */
2013.match-head {
2014 display: flex;
2015 align-items: center;
2016 gap: 10px;
2017 padding: 9px 14px;
2018 font-size: 14px;
2019 cursor: pointer;
2020}
2021
2022.match-head:hover {
2023 background: var(--bg);
2024}
2025
2026.match-head .mi {
2027 width: 18px;
2028 height: 18px;
2029 color: var(--muted);
2030 flex: none;
2031}
2032
2033/* Takes the slack, so the count and the two buttons sit at the right edge. */
2034.mpath {
2035 flex: 1;
2036 min-width: 0;
2037 overflow: hidden;
2038 text-overflow: ellipsis;
2039 white-space: nowrap;
2040}
2041
2042.mpath b {
2043 font-weight: 600;
2044}
2045
2046.mcount {
2047 flex: none;
2048 font-size: 12px;
2049 color: var(--muted);
2050}
2051
2052/* "Show in folder", in both the name rows and the match-card headers. */
2053.goto-btn {
2054 appearance: none;
2055 flex: none;
2056 justify-self: end;
2057 display: flex;
2058 align-items: center;
2059 justify-content: center;
2060 width: 26px;
2061 height: 26px;
2062 padding: 0;
2063 border: 1px solid transparent;
2064 background: transparent;
2065 cursor: pointer;
2066}
2067
2068.goto-btn:hover {
2069 border-color: var(--border);
2070}
2071
2072.goto-btn .goto-ic {
2073 width: 16px;
2074 height: 16px;
2075 color: var(--muted);
2076}
2077
2078.goto-btn:hover .goto-ic {
2079 color: var(--accent);
2080}
2081
2082.chev {
2083 appearance: none;
2084 border: 1px solid var(--border);
2085 background: transparent;
2086 width: 26px;
2087 height: 26px;
2088 display: flex;
2089 align-items: center;
2090 justify-content: center;
2091 cursor: pointer;
2092 flex: none;
2093}
2094
2095.chev:hover {
2096 background: var(--bg);
2097}
2098
2099.chev .chev-down,
2100.chev .chev-up {
2101 display: block;
2102 width: 10px;
2103 height: 10px;
2104 border-right: 2px solid var(--muted);
2105 border-bottom: 2px solid var(--muted);
2106}
2107
2108.chev .chev-down {
2109 transform: rotate(45deg) translate(-1px, -1px);
2110}
2111
2112.chev .chev-up {
2113 transform: rotate(-135deg) translate(-1px, -1px);
2114}
2115
2116.match-lines {
2117 border-top: 1px solid var(--border);
2118 background: var(--bg);
2119 font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
2120 font-size: 12.5px;
2121}
2122
2123/* Matched lines are text to read, not a control: the card header is what
2124 opens the file, so no pointer cursor and no hover here. */
2125.mline {
2126 display: grid;
2127 grid-template-columns: 52px minmax(0, 1fr);
2128 gap: 12px;
2129 padding: 5px 14px;
2130 border-bottom: 1px solid var(--border);
2131 white-space: pre;
2132 user-select: text;
2133}
2134
2135.mline:last-child {
2136 border-bottom: none;
2137}
2138
2139.mline .ln {
2140 color: var(--muted);
2141 text-align: right;
2142 user-select: none;
2143}
2144
2145.mline .tx {
2146 overflow: hidden;
2147 text-overflow: ellipsis;
2148}
2149
2150.search-empty {
2151 padding: 48px 20px;
2152 text-align: center;
2153 color: var(--muted);
2154 font-size: 14px;
2155}
2156