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 /* Uniform tile height: the name area always takes two lines and
658 never overflows (the full name is in the title tooltip). */
659 min-height: calc(2 * 1.3em);
660 display: -webkit-box;
661 -webkit-line-clamp: 2;
662 -webkit-box-orient: vertical;
663 overflow: hidden;
664}
665
666/* list view */
667
668.entries-list {
669 background: var(--panel);
670 border: 1px solid var(--border);
671 overflow: hidden;
672}
673
674.row {
675 display: grid;
676 grid-template-columns: 28px minmax(0, 1fr) 90px 150px;
677 gap: 12px;
678 align-items: center;
679 padding: 9px 14px;
680 border-bottom: 1px solid var(--border);
681 cursor: pointer;
682 font-size: 14px;
683 user-select: none;
684}
685
686.row:last-child {
687 border-bottom: none;
688}
689
690.row:hover {
691 background: var(--bg);
692}
693
694.row-icon {
695 width: 20px;
696 height: 20px;
697}
698
699.row-name {
700 overflow: hidden;
701 text-overflow: ellipsis;
702 white-space: nowrap;
703}
704
705.row-size,
706.row-date {
707 font-size: 13px;
708 text-align: right;
709}
710
711@media (max-width: 640px) {
712 .row {
713 grid-template-columns: 28px minmax(0, 1fr) 90px;
714 }
715
716 .row-date {
717 display: none;
718 }
719}
720
721/* context menu */
722
723.ctx-menu {
724 position: fixed;
725 z-index: 100;
726 min-width: 190px;
727 background: var(--panel);
728 border: 1px solid var(--border);
729 padding: 5px;
730 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
731}
732
733.ctx-item {
734 display: flex;
735 align-items: center;
736 gap: 10px;
737 padding: 8px 12px;
738 font-size: 14px;
739 cursor: pointer;
740}
741
742.ic-ctx {
743 width: 18px;
744 height: 18px;
745 flex: none;
746}
747
748.ctx-item:hover {
749 background: var(--bg);
750}
751
752.ctx-item.disabled {
753 opacity: 0.45;
754 cursor: default;
755}
756
757.ctx-item.disabled:hover {
758 background: none;
759}
760
761/* toolbar selection actions (top right) */
762
763.sel-actions {
764 display: flex;
765 align-items: center;
766 gap: 6px;
767 position: relative;
768}
769
770.sel-actions .icon-btn:disabled {
771 opacity: 0.45;
772 cursor: default;
773}
774
775.sel-actions .icon-btn:disabled:hover {
776 border-color: var(--border);
777 color: var(--muted);
778}
779
780.sel-more-wrap {
781 position: relative;
782}
783
784.sel-more-menu {
785 position: absolute;
786 right: 0;
787 top: calc(100% + 6px);
788 z-index: 100;
789 min-width: 190px;
790 background: var(--panel);
791 border: 1px solid var(--border);
792 padding: 5px;
793 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
794}
795
796.sel-more-menu.hidden {
797 display: none;
798}
799
800/* selection actions in the top bar */
801
802.topbar .sel-actions {
803 min-height: 0;
804}
805
806.topbar .sel-actions .icon-btn {
807 padding: 5px 7px;
808}
809
810/* selection highlight in the grid and list */
811
812.tile.selected {
813 border-color: var(--accent);
814 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
815}
816
817.row.selected {
818 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
819 box-shadow: inset 2px 0 0 var(--accent);
820}
821
822/* settings tabs (profile / server) */
823
824.settings-tabs {
825 display: flex;
826 gap: 8px;
827}
828
829.settings-tab-btn {
830 padding: 7px 14px;
831 border: 1px solid var(--border);
832 background: var(--panel);
833 color: var(--muted);
834 font-size: 13px;
835 font-weight: 600;
836}
837
838.settings-tab-btn:hover {
839 border-color: var(--muted);
840 color: var(--text);
841}
842
843.settings-tab-btn.active {
844 border-color: var(--accent);
845 color: var(--accent);
846 background: color-mix(in srgb, var(--accent) 10%, var(--panel));
847}
848
849/* toast */
850
851.toast {
852 position: fixed;
853 bottom: 20px;
854 right: 20px;
855 z-index: 200;
856 background: var(--panel);
857 color: var(--text);
858 border: 1px solid var(--border);
859 padding: 11px 16px;
860 font-size: 14px;
861 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
862 max-width: 320px;
863}
864
865.toast-error {
866 background: color-mix(in srgb, var(--danger) 12%, var(--panel));
867 border-color: var(--danger-border);
868 color: var(--danger);
869}
870
871
872/* ---- modals ---- */
873
874.modal-overlay {
875 position: fixed;
876 inset: 0;
877 background: rgb(0 0 0 / 45%);
878 display: flex;
879 align-items: center;
880 justify-content: center;
881 z-index: 100;
882}
883
884.modal {
885 width: 440px;
886 max-width: calc(100vw - 32px);
887 padding: 20px;
888 background: var(--panel);
889 border: 1px solid var(--border);
890 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
891}
892
893.modal.picker {
894 width: 520px;
895}
896
897.modal-title {
898 margin: 0 0 12px;
899 font-size: 16px;
900}
901
902.modal-label {
903 display: block;
904 font-size: 13px;
905 color: var(--muted);
906 margin-bottom: 6px;
907}
908
909.modal .input {
910 width: 100%;
911 box-sizing: border-box;
912 margin-bottom: 16px;
913}
914
915.modal-label.error,
916.dialog-error {
917 color: var(--danger);
918 font-size: 13px;
919}
920
921.dialog-error {
922 margin-top: 8px;
923}
924
925.modal-message {
926 white-space: pre-line;
927 font-size: 14px;
928 margin: 0 0 8px;
929}
930
931.modal-actions {
932 display: flex;
933 justify-content: flex-end;
934 gap: 8px;
935 margin-top: 16px;
936}
937
938.btn-danger {
939 background: var(--danger);
940 /* A visible border (one step away from the fill, per theme) so the
941 button's edge reads the same as on neutral buttons. */
942 border-color: var(--danger-border);
943 color: #fff;
944}
945
946.btn-danger:hover {
947 background: color-mix(in srgb, var(--danger) 85%, black);
948}
949
950.btn:disabled {
951 opacity: 0.5;
952 cursor: not-allowed;
953}
954
955.conflict-list {
956 max-height: 200px;
957 overflow-y: auto;
958 margin: 8px 0;
959 padding-left: 20px;
960 font-size: 13px;
961}
962
963.picker-roots {
964 display: flex;
965 gap: 6px;
966 flex-wrap: wrap;
967 margin-bottom: 12px;
968}
969
970.root-opt {
971 font-size: 13px;
972}
973
974.root-opt.active {
975 background: var(--accent);
976 border-color: var(--accent);
977 color: #fff;
978}
979
980.picker-current {
981 font-size: 13px;
982 margin: 0 0 8px;
983}
984
985.picker-crumbs {
986 margin-bottom: 8px;
987}
988
989.picker-entries {
990 max-height: 240px;
991 overflow-y: auto;
992 border: 1px solid var(--border);
993}
994
995.picker-row {
996 display: flex;
997 align-items: center;
998 gap: 10px;
999 padding: 8px 12px;
1000 cursor: pointer;
1001}
1002
1003.picker-row:hover {
1004 background: var(--bg);
1005}
1006
1007/* ---------------------------------------------------------------------------
1008 * Full-page file view (preview / editor / "no preview"). The top bar carries
1009 * the title + actions; the content area below is edge to edge.
1010 * ------------------------------------------------------------------------- */
1011.content.file-open {
1012 padding: 0;
1013 overflow: hidden;
1014}
1015
1016/* The browser stays mounted (state, fetch callback) but hidden. */
1017.content.file-open .browser {
1018 display: none;
1019}
1020
1021.file-view {
1022 flex: 1;
1023 min-height: 0;
1024 display: flex;
1025 flex-direction: column;
1026}
1027
1028.file-title {
1029 display: flex;
1030 align-items: center;
1031 gap: 8px;
1032 min-width: 0;
1033}
1034
1035.file-title-icon {
1036 width: 18px;
1037 height: 18px;
1038 flex: none;
1039 color: var(--muted);
1040}
1041
1042.file-title-name {
1043 font-weight: 600;
1044 font-size: 14px;
1045 white-space: nowrap;
1046 overflow: hidden;
1047 text-overflow: ellipsis;
1048}
1049
1050.file-actions {
1051 display: flex;
1052 align-items: center;
1053 gap: 10px;
1054 flex: none;
1055}
1056
1057.file-close,
1058.file-download {
1059 border: none;
1060 background: transparent;
1061 color: var(--muted);
1062 padding: 6px 8px;
1063}
1064
1065.file-close:hover,
1066.file-download:hover {
1067 color: var(--text);
1068 background: var(--bg);
1069}
1070.preview-body {
1071 flex: 1;
1072 min-height: 0;
1073 overflow: auto;
1074 display: flex;
1075 background: var(--bg);
1076}
1077.preview-img {
1078 max-width: 100%;
1079 max-height: 100%;
1080 display: block;
1081 margin: auto;
1082}
1083.preview-pdf {
1084 width: 100%;
1085 height: 100%;
1086 border: none;
1087 background: #fff;
1088}
1089.preview-video {
1090 width: 100%;
1091 max-height: 100%;
1092 background: #000;
1093}
1094.preview-audio {
1095 display: flex;
1096 align-items: center;
1097 justify-content: center;
1098 width: 100%;
1099 padding: 24px;
1100}
1101.preview-audio audio {
1102 width: 100%;
1103 max-width: 480px;
1104}
1105
1106/* CodeMirror (text editor) */
1107.cm-container {
1108 height: 100%;
1109}
1110.cm-container .cm-editor {
1111 height: 100%;
1112}
1113/* Load/save failure: dims the editor and shows the message in a card
1114 * (the top-bar Save button stays reachable to retry). */
1115.cm-error {
1116 position: absolute;
1117 inset: 0;
1118 z-index: 5;
1119 display: flex;
1120 align-items: center;
1121 justify-content: center;
1122 padding: 24px;
1123 background: rgb(0 0 0 / 45%);
1124}
1125
1126.cm-error-card {
1127 position: relative;
1128 max-width: 440px;
1129 min-width: 200px;
1130 background: var(--panel);
1131 border: 1px solid var(--border);
1132 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
1133}
1134
1135.cm-error-close {
1136 position: absolute;
1137 top: 7px;
1138 right: 7px;
1139 display: inline-flex;
1140 align-items: center;
1141 justify-content: center;
1142 border: none;
1143 background: transparent;
1144 color: var(--muted);
1145 padding: 3px;
1146}
1147
1148.cm-error-close:hover {
1149 color: var(--text);
1150 background: var(--bg);
1151}
1152
1153.cm-error-close .ic-btn {
1154 width: 16px;
1155 height: 16px;
1156}
1157
1158.cm-error-text {
1159 padding: 16px 40px 16px 20px;
1160 font-size: 14px;
1161 text-align: center;
1162 overflow-wrap: anywhere;
1163}
1164
1165/* ---------------------------------------------------------------------------
1166 * Text editor (full page; title/save/close live in the top bar)
1167 * ------------------------------------------------------------------------- */
1168.file-editor {
1169 flex: 1;
1170 min-height: 0;
1171 display: flex;
1172 position: relative;
1173 background: var(--bg);
1174}
1175.file-editor .cm-container {
1176 width: 100%;
1177 height: 100%;
1178}
1179/* "No preview" fallback (binaries, archives). */
1180.file-nopreview {
1181 flex: 1;
1182 display: flex;
1183 align-items: center;
1184 justify-content: center;
1185}
1186.file-nopreview .btn-primary {
1187 width: auto;
1188 margin-top: 14px;
1189}
1190/* Conflict / discard dialogs render above the file view. */
1191.editor-sub-overlay {
1192 z-index: 101;
1193 background: rgb(0 0 0 / 25%);
1194}
1195
1196/* ---------------------------------------------------------------------------
1197 * Download format dialog
1198 * ------------------------------------------------------------------------- */
1199.dl-formats {
1200 display: flex;
1201 flex-direction: column;
1202 gap: 8px;
1203 margin-bottom: 8px;
1204}
1205.dl-fmt {
1206 justify-content: flex-start;
1207}
1208
1209/* ---------------------------------------------------------------------------
1210 * Item info dialog
1211 * ------------------------------------------------------------------------- */
1212.info-list {
1213 margin: 8px 0 16px;
1214 display: grid;
1215 grid-template-columns: 90px 1fr;
1216 row-gap: 8px;
1217 column-gap: 12px;
1218}
1219.info-list dt {
1220 color: var(--muted);
1221}
1222.info-list dd {
1223 margin: 0;
1224 word-break: break-word;
1225}
1226
1227/* ---------------------------------------------------------------------------
1228 Shares (milestone 6)
1229 --------------------------------------------------------------------------- */
1230
1231.share-modal {
1232 width: 480px;
1233}
1234
1235.share-link-row {
1236 display: flex;
1237 gap: 8px;
1238 margin: 12px 0;
1239}
1240
1241.share-link-input {
1242 flex: 1;
1243 font-family: ui-monospace, monospace;
1244 font-size: 12.5px;
1245 padding: 8px 10px;
1246 border: 1px solid var(--border);
1247 background: var(--bg);
1248 color: var(--text);
1249 min-width: 0;
1250}
1251
1252.share-check {
1253 display: flex;
1254 align-items: center;
1255 gap: 8px;
1256 margin: 4px 0 14px;
1257 font-size: 14px;
1258}
1259
1260.share-check input {
1261 width: 16px;
1262 height: 16px;
1263}
1264
1265.share-expiry-row {
1266 display: flex;
1267 align-items: center;
1268 gap: 10px;
1269 margin: 0 0 10px;
1270}
1271
1272.share-expiry-row label {
1273 font-size: 13px;
1274 color: var(--muted);
1275 min-width: 52px;
1276}
1277
1278.share-expiry-row select,
1279.share-expiry-row input {
1280 flex: 1;
1281 padding: 8px 10px;
1282 border: 1px solid var(--border);
1283 background: var(--panel);
1284 color: var(--text);
1285 font: inherit;
1286}
1287
1288.share-expiry-note {
1289 margin: 4px 0 0;
1290 font-size: 12.5px;
1291}
1292
1293.btn-sm {
1294 padding: 5px 10px;
1295 font-size: 12.5px;
1296}
1297
1298.icon-btn-sm {
1299 padding: 4px 6px;
1300}
1301
1302/* "Your shares" manage view */
1303
1304.shares-view {
1305 width: 100%;
1306 max-width: 960px;
1307 margin: 0 auto;
1308}
1309
1310.view-header {
1311 margin-bottom: 16px;
1312}
1313
1314.view-header .admin-section-title {
1315 margin-bottom: 0;
1316}
1317
1318.view-hint {
1319 margin: 4px 0 0;
1320 font-size: 13px;
1321 max-width: 64ch;
1322}
1323
1324.share-list {
1325 display: flex;
1326 flex-direction: column;
1327 gap: 10px;
1328}
1329
1330.share-item {
1331 display: flex;
1332 align-items: center;
1333 justify-content: space-between;
1334 gap: 12px;
1335 padding: 10px 12px;
1336 border: 1px solid var(--border);
1337 background: var(--panel);
1338}
1339
1340.share-item-main {
1341 min-width: 0;
1342}
1343
1344.share-item-name {
1345 display: flex;
1346 align-items: center;
1347 gap: 8px;
1348 font-weight: 600;
1349 font-size: 14px;
1350 overflow: hidden;
1351 text-overflow: ellipsis;
1352 white-space: nowrap;
1353}
1354
1355.ic-row {
1356 width: 18px;
1357 height: 18px;
1358 flex: none;
1359}
1360
1361.share-item-meta {
1362 font-size: 12px;
1363 margin-top: 2px;
1364 overflow: hidden;
1365 text-overflow: ellipsis;
1366 white-space: nowrap;
1367}
1368
1369.share-item-actions {
1370 display: flex;
1371 gap: 6px;
1372 flex-shrink: 0;
1373}
1374
1375/* ------------------------------------------------------------------ */
1376/* Admin (milestone 7) */
1377/* ------------------------------------------------------------------ */
1378
1379.admin-view {
1380 display: flex;
1381 flex-direction: column;
1382 gap: 16px;
1383 width: 100%;
1384 max-width: 960px;
1385 margin: 0 auto;
1386}
1387
1388.admin-section-title {
1389 margin: 0 0 14px;
1390 font-size: 15px;
1391}
1392
1393.users-header {
1394 display: flex;
1395 align-items: center;
1396 justify-content: space-between;
1397 margin-bottom: 4px;
1398}
1399
1400.users-header .admin-section-title {
1401 margin-bottom: 0;
1402}
1403
1404.users-header .btn-primary {
1405 width: auto;
1406}
1407
1408.user-list {
1409 display: flex;
1410 flex-direction: column;
1411 gap: 10px;
1412}
1413
1414.user-row {
1415 display: flex;
1416 align-items: center;
1417 justify-content: space-between;
1418 gap: 12px;
1419 padding: 12px 14px;
1420 border: 1px solid var(--border);
1421}
1422
1423.user-row-main {
1424 min-width: 0;
1425}
1426
1427.user-row-name {
1428 display: flex;
1429 align-items: center;
1430 gap: 6px;
1431 font-weight: 600;
1432 font-size: 14px;
1433 flex-wrap: wrap;
1434}
1435
1436.ic-admin {
1437 width: 16px;
1438 height: 16px;
1439 flex: none;
1440}
1441
1442.user-row-actions {
1443 display: flex;
1444 gap: 6px;
1445 flex-shrink: 0;
1446}
1447
1448.badge-off {
1449 background: color-mix(in srgb, var(--danger) 15%, var(--panel));
1450 border-color: var(--danger);
1451 color: var(--danger);
1452}
1453
1454.setting-row {
1455 display: flex;
1456 align-items: center;
1457 gap: 10px;
1458 padding: 14px;
1459 border: 1px solid var(--border);
1460 cursor: pointer;
1461}
1462
1463.setting-row input {
1464 margin-left: auto;
1465}
1466
1467.setting-label {
1468 display: block;
1469 font-weight: 600;
1470 font-size: 14px;
1471}
1472
1473.setting-desc {
1474 display: block;
1475 font-size: 12px;
1476 color: var(--muted);
1477 margin-top: 2px;
1478}
1479
1480/* Setting row whose control is a select, pushed to the right. */
1481.setting-row-select {
1482 cursor: default;
1483}
1484
1485.setting-row-select > span {
1486 flex: 1;
1487}
1488
1489.setting-row-select select {
1490 appearance: none;
1491 margin-left: auto;
1492 padding: 10px 42px 10px 12px;
1493 border: 1px solid var(--border);
1494 background-color: var(--panel);
1495 background-image: var(--select-arrow);
1496 background-repeat: no-repeat;
1497 background-position: right 12px center;
1498 background-size: 14px 14px;
1499 color: var(--text);
1500 font: inherit;
1501 max-width: 190px;
1502}
1503
1504/* User create/edit form */
1505
1506.user-form {
1507 width: 520px;
1508}
1509
1510.field-input {
1511 width: 100%;
1512 box-sizing: border-box;
1513}
1514
1515.field-hint {
1516 font-size: 12px;
1517 margin: -2px 0 8px;
1518}
1519
1520.check-row {
1521 display: flex;
1522 align-items: center;
1523 gap: 8px;
1524 font-size: 14px;
1525 margin-bottom: 12px;
1526 cursor: pointer;
1527}
1528
1529.check-row input {
1530 width: auto;
1531}
1532
1533.form-error {
1534 color: var(--danger);
1535 font-size: 13px;
1536 margin: 4px 0 8px;
1537}
1538
1539.roots-editor {
1540 display: flex;
1541 flex-direction: column;
1542 gap: 6px;
1543}
1544
1545.root-draft {
1546 display: flex;
1547 align-items: center;
1548 gap: 8px;
1549}
1550
1551.root-draft-path {
1552 flex: 1;
1553 font-size: 13px;
1554 overflow: hidden;
1555 text-overflow: ellipsis;
1556 white-space: nowrap;
1557}
1558
1559.root-draft-mode {
1560 width: auto;
1561 padding: 6px 8px;
1562}
1563
1564.root-add {
1565 display: flex;
1566 gap: 8px;
1567 margin-top: 4px;
1568}
1569
1570/* ------------------------------------------------------------------ */
1571/* Empty state + keyboard focus (milestone 8) */
1572/* ------------------------------------------------------------------ */
1573
1574.empty-state {
1575 display: flex;
1576 flex-direction: column;
1577 align-items: center;
1578 justify-content: center;
1579 gap: 8px;
1580 padding: 64px 20px;
1581 text-align: center;
1582}
1583
1584.empty-glyph {
1585 width: 52px;
1586 height: 52px;
1587}
1588
1589.empty-state h3 {
1590 margin: 0;
1591 font-size: 16px;
1592}
1593
1594/* Visible keyboard focus on selectable file/folder entries. The ring is
1595 inset (negative offset) so the scroll container never clips it. */
1596.tile:focus-visible,
1597.row:focus-visible {
1598 outline: 2px solid var(--accent);
1599 outline-offset: -2px;
1600}
1601
1602/* ------------------------------------------------------------------ */
1603/* Search view (#/search) */
1604/* ------------------------------------------------------------------ */
1605
1606.search-view {
1607 display: flex;
1608 flex-direction: column;
1609 gap: 14px;
1610}
1611
1612/* Query bar ------------------------------------------------------ */
1613
1614.query-bar {
1615 display: flex;
1616 align-items: stretch;
1617 gap: 8px;
1618}
1619
1620.query-input {
1621 flex: 1;
1622 display: flex;
1623 align-items: center;
1624 gap: 8px;
1625 background: var(--panel);
1626 border: 1px solid var(--border);
1627 padding: 0 10px;
1628 min-width: 0;
1629}
1630
1631.query-input .qi-icon {
1632 width: 18px;
1633 height: 18px;
1634 color: var(--muted);
1635 flex: none;
1636}
1637
1638.query-input input {
1639 flex: 1;
1640 min-width: 0;
1641 border: none;
1642 outline: none;
1643 background: transparent;
1644 color: var(--text);
1645 font: inherit;
1646 font-size: 14px;
1647 height: 38px;
1648 padding: 0;
1649}
1650
1651.query-input input::placeholder {
1652 color: var(--muted);
1653}
1654
1655/* Segmented Name / Content / Both control */
1656
1657.seg {
1658 display: flex;
1659 border: 1px solid var(--border);
1660 background: var(--panel);
1661}
1662
1663.seg button {
1664 appearance: none;
1665 border: none;
1666 border-right: 1px solid var(--border);
1667 background: transparent;
1668 color: var(--muted);
1669 font: inherit;
1670 font-size: 13px;
1671 padding: 0 14px;
1672 cursor: pointer;
1673}
1674
1675.seg button:last-child {
1676 border-right: none;
1677}
1678
1679.seg button:hover {
1680 background: var(--bg);
1681}
1682
1683.seg button.on {
1684 background: var(--accent);
1685 color: #fff;
1686}
1687
1688/* Roots multi-select --------------------------------------------- */
1689
1690/* The root a search covers. A native select, styled like the query bar. */
1691.root-select {
1692 flex: none;
1693 max-width: 220px;
1694 border: 1px solid var(--border);
1695 background: var(--panel);
1696 color: var(--text);
1697 font: inherit;
1698 font-size: 13px;
1699 padding: 0 10px;
1700}
1701
1702.ms {
1703 position: relative;
1704 display: flex;
1705}
1706
1707.ms-btn {
1708 display: flex;
1709 align-items: center;
1710 gap: 6px;
1711 border: 1px solid var(--border);
1712 background: var(--panel);
1713 color: var(--text);
1714 font: inherit;
1715 font-size: 13px;
1716 padding: 0 10px;
1717 cursor: pointer;
1718 max-width: 180px;
1719}
1720
1721.ms-btn:hover {
1722 background: var(--bg);
1723}
1724
1725.ms-btn > span {
1726 overflow: hidden;
1727 text-overflow: ellipsis;
1728 white-space: nowrap;
1729}
1730
1731/* Square caret drawn with borders (the icon set has no chevron). */
1732.ms-caret {
1733 flex: none;
1734 width: 8px;
1735 height: 8px;
1736 border-right: 2px solid var(--muted);
1737 border-bottom: 2px solid var(--muted);
1738 transform: rotate(45deg) translate(-1px, -1px);
1739}
1740
1741.ms-backdrop {
1742 position: fixed;
1743 inset: 0;
1744 z-index: 40;
1745}
1746
1747.ms-drop {
1748 position: absolute;
1749 right: 0;
1750 top: calc(100% + 4px);
1751 z-index: 41;
1752 min-width: 200px;
1753 max-height: 280px;
1754 overflow: auto;
1755 background: var(--panel);
1756 border: 1px solid var(--border);
1757 padding: 4px 0;
1758}
1759
1760.ms-opt {
1761 display: flex;
1762 align-items: center;
1763 gap: 8px;
1764 padding: 7px 12px;
1765 font-size: 14px;
1766 cursor: pointer;
1767 user-select: none;
1768}
1769
1770.ms-opt:hover {
1771 background: var(--bg);
1772}
1773
1774.ms-opt span {
1775 overflow: hidden;
1776 text-overflow: ellipsis;
1777 white-space: nowrap;
1778}
1779
1780/* Run / stop ------------------------------------------------------- */
1781
1782.btn-run {
1783 border: 1px solid var(--accent-border);
1784 background: var(--accent);
1785 color: #fff;
1786 font: inherit;
1787 font-size: 13px;
1788 font-weight: 600;
1789 padding: 0 18px;
1790 cursor: pointer;
1791}
1792
1793.btn-run:hover {
1794 background: var(--accent-hover);
1795}
1796
1797.btn-stop {
1798 display: flex;
1799 align-items: center;
1800 gap: 6px;
1801 border: 1px solid var(--danger-border);
1802 background: var(--danger);
1803 color: #fff;
1804 font: inherit;
1805 font-size: 13px;
1806 font-weight: 600;
1807 padding: 0 14px;
1808 cursor: pointer;
1809}
1810
1811.btn-stop:hover {
1812 opacity: 0.9;
1813}
1814
1815.btn-stop .ic-stop {
1816 width: 14px;
1817 height: 14px;
1818}
1819
1820/* Status line ------------------------------------------------------ */
1821
1822.status-line {
1823 display: flex;
1824 align-items: center;
1825 gap: 8px;
1826 font-size: 13px;
1827 color: var(--muted);
1828}
1829
1830.status-line .dot {
1831 width: 8px;
1832 height: 8px;
1833 background: var(--accent);
1834 animation: search-pulse 1s ease-in-out infinite;
1835}
1836
1837@keyframes search-pulse {
1838 0%,
1839 100% {
1840 opacity: 1;
1841 }
1842 50% {
1843 opacity: 0.3;
1844 }
1845}
1846
1847.status-line .skip {
1848 opacity: 0.75;
1849}
1850
1851/* Group labels ----------------------------------------------------- */
1852
1853.group-label {
1854 display: flex;
1855 align-items: center;
1856 gap: 8px;
1857 font-size: 12px;
1858 font-weight: 600;
1859 letter-spacing: 0.04em;
1860 text-transform: uppercase;
1861 color: var(--muted);
1862}
1863
1864/* Result group: a `display:flex` (or `none`, from the inline style) flex
1865 item of `.search-view` that re-establishes the column layout for its
1866 label/list/more-row children. */
1867.result-group {
1868 flex-direction: column;
1869 gap: 14px;
1870}
1871
1872.group-label .gl-icon {
1873 width: 15px;
1874 height: 15px;
1875}
1876
1877.group-label .n {
1878 font-weight: 400;
1879 text-transform: none;
1880 letter-spacing: 0;
1881}
1882
1883.group-label .grow {
1884 flex: 1;
1885}
1886
1887.collapse-all {
1888 appearance: none;
1889 border: 1px solid var(--border);
1890 background: transparent;
1891 color: var(--muted);
1892 font: inherit;
1893 font-size: 12px;
1894 text-transform: none;
1895 letter-spacing: 0;
1896 padding: 3px 10px;
1897 cursor: pointer;
1898}
1899
1900.collapse-all:hover {
1901 background: var(--bg);
1902 color: var(--text);
1903}
1904
1905/* Name-result rows --------------------------------------------------- */
1906
1907.srow {
1908 display: grid;
1909 /* icon | name+dir | size | goto */
1910 grid-template-columns: 28px minmax(0, 1fr) 90px 30px;
1911 gap: 12px;
1912 align-items: center;
1913 padding: 9px 14px;
1914 border-bottom: 1px solid var(--border);
1915 cursor: pointer;
1916 font-size: 14px;
1917 user-select: none;
1918}
1919
1920.srow:last-child {
1921 border-bottom: none;
1922}
1923
1924.srow:hover {
1925 background: var(--bg);
1926}
1927
1928.srow-icon {
1929 width: 20px;
1930 height: 20px;
1931}
1932
1933.srow-main {
1934 min-width: 0;
1935 display: flex;
1936 flex-direction: column;
1937 line-height: 1.3;
1938}
1939
1940.srow-name {
1941 overflow: hidden;
1942 text-overflow: ellipsis;
1943 white-space: nowrap;
1944}
1945
1946/* Highlighted query hits (plain fragments render as bare spans). */
1947mark.hl-hit {
1948 background: color-mix(in srgb, var(--accent) 25%, transparent);
1949 color: inherit;
1950}
1951
1952/* The directory-path line (the name line lives inside .srow-name). */
1953.srow-dir {
1954 font-size: 12px;
1955 color: var(--muted);
1956 overflow: hidden;
1957 text-overflow: ellipsis;
1958 white-space: nowrap;
1959}
1960
1961.srow-dir mark.hl-hit {
1962 color: inherit;
1963}
1964
1965.ssize {
1966 font-size: 13px;
1967 color: var(--muted);
1968 text-align: right;
1969}
1970
1971/* Paging footer: position in the results on the left, the action on the
1972 right. Separated from the list by its own border so the button never reads
1973 as another result row. */
1974.page-foot {
1975 display: flex;
1976 align-items: center;
1977 justify-content: space-between;
1978 gap: 12px;
1979 padding: 10px 14px;
1980 border-top: 1px solid var(--border);
1981 font-size: 12px;
1982 color: var(--muted);
1983}
1984
1985.page-foot .pf-count {
1986 font-variant-numeric: tabular-nums;
1987}
1988
1989.page-foot .pf-more {
1990 appearance: none;
1991 padding: 5px 12px;
1992 border: 1px solid var(--border);
1993 background: var(--panel);
1994 font: inherit;
1995 font-weight: 500;
1996 color: var(--text);
1997 cursor: pointer;
1998}
1999
2000.page-foot .pf-more:hover {
2001 border-color: var(--accent);
2002 color: var(--accent);
2003}
2004
2005/* Content matches ----------------------------------------------------- */
2006
2007.match-card {
2008 background: var(--panel);
2009 border: 1px solid var(--border);
2010 border-top: none;
2011}
2012
2013/* The first card is the one right after the group label; `:first-of-type`
2014 cannot be used because the label is an earlier `div` sibling. */
2015.group-label + .match-card {
2016 border-top: 1px solid var(--border);
2017}
2018
2019/* The header opens the file; the matched lines below are text to read. */
2020.match-head {
2021 display: flex;
2022 align-items: center;
2023 gap: 10px;
2024 padding: 9px 14px;
2025 font-size: 14px;
2026 cursor: pointer;
2027}
2028
2029.match-head:hover {
2030 background: var(--bg);
2031}
2032
2033.match-head .mi {
2034 width: 18px;
2035 height: 18px;
2036 color: var(--muted);
2037 flex: none;
2038}
2039
2040/* Takes the slack, so the count and the two buttons sit at the right edge. */
2041.mpath {
2042 flex: 1;
2043 min-width: 0;
2044 overflow: hidden;
2045 text-overflow: ellipsis;
2046 white-space: nowrap;
2047}
2048
2049.mpath b {
2050 font-weight: 600;
2051}
2052
2053.mcount {
2054 flex: none;
2055 font-size: 12px;
2056 color: var(--muted);
2057}
2058
2059/* "Show in folder", in both the name rows and the match-card headers. */
2060.goto-btn {
2061 appearance: none;
2062 flex: none;
2063 justify-self: end;
2064 display: flex;
2065 align-items: center;
2066 justify-content: center;
2067 width: 26px;
2068 height: 26px;
2069 padding: 0;
2070 border: 1px solid transparent;
2071 background: transparent;
2072 cursor: pointer;
2073}
2074
2075.goto-btn:hover {
2076 border-color: var(--border);
2077}
2078
2079.goto-btn .goto-ic {
2080 width: 16px;
2081 height: 16px;
2082 color: var(--muted);
2083}
2084
2085.goto-btn:hover .goto-ic {
2086 color: var(--accent);
2087}
2088
2089.chev {
2090 appearance: none;
2091 border: 1px solid var(--border);
2092 background: transparent;
2093 width: 26px;
2094 height: 26px;
2095 display: flex;
2096 align-items: center;
2097 justify-content: center;
2098 cursor: pointer;
2099 flex: none;
2100}
2101
2102.chev:hover {
2103 background: var(--bg);
2104}
2105
2106.chev .chev-down,
2107.chev .chev-up {
2108 display: block;
2109 width: 10px;
2110 height: 10px;
2111 border-right: 2px solid var(--muted);
2112 border-bottom: 2px solid var(--muted);
2113}
2114
2115.chev .chev-down {
2116 transform: rotate(45deg) translate(-1px, -1px);
2117}
2118
2119.chev .chev-up {
2120 transform: rotate(-135deg) translate(-1px, -1px);
2121}
2122
2123.match-lines {
2124 border-top: 1px solid var(--border);
2125 background: var(--bg);
2126 font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
2127 font-size: 12.5px;
2128}
2129
2130/* Matched lines are text to read, not a control: the card header is what
2131 opens the file, so no pointer cursor and no hover here. */
2132.mline {
2133 display: grid;
2134 grid-template-columns: 52px minmax(0, 1fr);
2135 gap: 12px;
2136 padding: 5px 14px;
2137 border-bottom: 1px solid var(--border);
2138 white-space: pre;
2139 user-select: text;
2140}
2141
2142.mline:last-child {
2143 border-bottom: none;
2144}
2145
2146.mline .ln {
2147 color: var(--muted);
2148 text-align: right;
2149 user-select: none;
2150}
2151
2152.mline .tx {
2153 overflow: hidden;
2154 text-overflow: ellipsis;
2155}
2156
2157.search-empty {
2158 padding: 48px 20px;
2159 text-align: center;
2160 color: var(--muted);
2161 font-size: 14px;
2162}
2163