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: 640px;
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/* Folder picker: roots on the left, the selected root's tree on the right. */
964
965.picker-body {
966 display: grid;
967 grid-template-columns: 180px minmax(0, 1fr);
968 border: 1px solid var(--border);
969 height: 320px;
970}
971
972.picker-roots {
973 display: flex;
974 flex-direction: column;
975 gap: 2px;
976 padding: 6px;
977 border-right: 1px solid var(--border);
978 background: var(--bg);
979 min-height: 0;
980 overflow-y: auto;
981}
982
983.picker-root {
984 display: flex;
985 align-items: center;
986 justify-content: flex-start;
987 gap: 8px;
988 padding: 7px 8px;
989 border: none;
990 background: transparent;
991 color: var(--text);
992 font: inherit;
993 font-size: 13px;
994 text-align: left;
995 cursor: pointer;
996 min-width: 0;
997}
998
999.picker-root:hover {
1000 background: var(--panel);
1001}
1002
1003.picker-root.active {
1004 background: var(--accent);
1005 color: #fff;
1006}
1007
1008.picker-root.ro .picker-root-name {
1009 opacity: 0.6;
1010 text-decoration: line-through dotted;
1011}
1012
1013.picker-root-ic {
1014 width: 16px;
1015 height: 16px;
1016 flex: none;
1017}
1018
1019.picker-root-name {
1020 overflow: hidden;
1021 text-overflow: ellipsis;
1022 white-space: nowrap;
1023}
1024
1025.picker-main {
1026 display: flex;
1027 flex-direction: column;
1028 min-width: 0;
1029 /* Grid items default to min-height:auto, which would let a long
1030 folder list stretch the dialog instead of scrolling. */
1031 min-height: 0;
1032}
1033
1034.picker-crumbs {
1035 padding: 8px 10px;
1036 font-size: 13px;
1037 border-bottom: 1px solid var(--border);
1038 flex: none;
1039}
1040
1041.picker-entries {
1042 flex: 1;
1043 min-height: 0;
1044 overflow-y: auto;
1045}
1046
1047.picker-row {
1048 display: flex;
1049 align-items: center;
1050 gap: 10px;
1051 padding: 8px 12px;
1052 cursor: pointer;
1053 font-size: 14px;
1054 user-select: none;
1055}
1056
1057.picker-row:hover {
1058 background: var(--bg);
1059}
1060
1061.picker-row .row-name {
1062 flex: 1;
1063}
1064
1065/* A right-pointing chevron drawn with borders (no icon needed). */
1066.picker-chev {
1067 width: 7px;
1068 height: 7px;
1069 border-right: 1.5px solid var(--muted);
1070 border-bottom: 1.5px solid var(--muted);
1071 transform: rotate(-45deg);
1072 flex: none;
1073}
1074
1075.picker-empty {
1076 height: 100%;
1077 display: flex;
1078 flex-direction: column;
1079 align-items: center;
1080 justify-content: center;
1081 gap: 8px;
1082 font-size: 13px;
1083}
1084
1085.picker-empty-ic {
1086 width: 32px;
1087 height: 32px;
1088 opacity: 0.5;
1089}
1090
1091.picker-root.active .picker-root-ic {
1092 color: #fff;
1093}
1094
1095@media (max-width: 640px) {
1096 .picker-body {
1097 grid-template-columns: 1fr;
1098 grid-template-rows: auto minmax(0, 1fr);
1099 height: 380px;
1100 }
1101
1102 .picker-roots {
1103 flex-direction: row;
1104 flex-wrap: wrap;
1105 border-right: none;
1106 border-bottom: 1px solid var(--border);
1107 }
1108}
1109
1110/* ---------------------------------------------------------------------------
1111 * Full-page file view (preview / editor / "no preview"). The top bar carries
1112 * the title + actions; the content area below is edge to edge.
1113 * ------------------------------------------------------------------------- */
1114.content.file-open {
1115 padding: 0;
1116 overflow: hidden;
1117}
1118
1119/* The browser stays mounted (state, fetch callback) but hidden. */
1120.content.file-open .browser {
1121 display: none;
1122}
1123
1124.file-view {
1125 flex: 1;
1126 min-height: 0;
1127 display: flex;
1128 flex-direction: column;
1129}
1130
1131.file-title {
1132 display: flex;
1133 align-items: center;
1134 gap: 8px;
1135 min-width: 0;
1136}
1137
1138.file-title-icon {
1139 width: 18px;
1140 height: 18px;
1141 flex: none;
1142 color: var(--muted);
1143}
1144
1145.file-title-name {
1146 font-weight: 600;
1147 font-size: 14px;
1148 white-space: nowrap;
1149 overflow: hidden;
1150 text-overflow: ellipsis;
1151}
1152
1153.file-actions {
1154 display: flex;
1155 align-items: center;
1156 gap: 10px;
1157 flex: none;
1158}
1159
1160.file-close,
1161.file-download {
1162 border: none;
1163 background: transparent;
1164 color: var(--muted);
1165 padding: 6px 8px;
1166}
1167
1168.file-close:hover,
1169.file-download:hover {
1170 color: var(--text);
1171 background: var(--bg);
1172}
1173.preview-body {
1174 flex: 1;
1175 min-height: 0;
1176 overflow: auto;
1177 display: flex;
1178 background: var(--bg);
1179}
1180.preview-img {
1181 max-width: 100%;
1182 max-height: 100%;
1183 display: block;
1184 margin: auto;
1185}
1186.preview-pdf {
1187 width: 100%;
1188 height: 100%;
1189 border: none;
1190 background: #fff;
1191}
1192.preview-video {
1193 width: 100%;
1194 max-height: 100%;
1195 background: #000;
1196}
1197.preview-audio {
1198 display: flex;
1199 align-items: center;
1200 justify-content: center;
1201 width: 100%;
1202 padding: 24px;
1203}
1204.preview-audio audio {
1205 width: 100%;
1206 max-width: 480px;
1207}
1208
1209/* CodeMirror (text editor) */
1210.cm-container {
1211 height: 100%;
1212}
1213.cm-container .cm-editor {
1214 height: 100%;
1215}
1216/* Load/save failure: dims the editor and shows the message in a card
1217 * (the top-bar Save button stays reachable to retry). */
1218.cm-error {
1219 position: absolute;
1220 inset: 0;
1221 z-index: 5;
1222 display: flex;
1223 align-items: center;
1224 justify-content: center;
1225 padding: 24px;
1226 background: rgb(0 0 0 / 45%);
1227}
1228
1229.cm-error-card {
1230 position: relative;
1231 max-width: 440px;
1232 min-width: 200px;
1233 background: var(--panel);
1234 border: 1px solid var(--border);
1235 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
1236}
1237
1238.cm-error-close {
1239 position: absolute;
1240 top: 7px;
1241 right: 7px;
1242 display: inline-flex;
1243 align-items: center;
1244 justify-content: center;
1245 border: none;
1246 background: transparent;
1247 color: var(--muted);
1248 padding: 3px;
1249}
1250
1251.cm-error-close:hover {
1252 color: var(--text);
1253 background: var(--bg);
1254}
1255
1256.cm-error-close .ic-btn {
1257 width: 16px;
1258 height: 16px;
1259}
1260
1261.cm-error-text {
1262 padding: 16px 40px 16px 20px;
1263 font-size: 14px;
1264 text-align: center;
1265 overflow-wrap: anywhere;
1266}
1267
1268/* ---------------------------------------------------------------------------
1269 * Text editor (full page; title/save/close live in the top bar)
1270 * ------------------------------------------------------------------------- */
1271.file-editor {
1272 flex: 1;
1273 min-height: 0;
1274 display: flex;
1275 position: relative;
1276 background: var(--bg);
1277}
1278.file-editor .cm-container {
1279 width: 100%;
1280 height: 100%;
1281}
1282/* "No preview" fallback (binaries, archives). */
1283.file-nopreview {
1284 flex: 1;
1285 display: flex;
1286 align-items: center;
1287 justify-content: center;
1288}
1289.file-nopreview .btn-primary {
1290 width: auto;
1291 margin-top: 14px;
1292}
1293/* Conflict / discard dialogs render above the file view. */
1294.editor-sub-overlay {
1295 z-index: 101;
1296 background: rgb(0 0 0 / 25%);
1297}
1298
1299/* ---------------------------------------------------------------------------
1300 * Download format dialog
1301 * ------------------------------------------------------------------------- */
1302.dl-formats {
1303 display: flex;
1304 flex-direction: column;
1305 gap: 8px;
1306 margin-bottom: 8px;
1307}
1308.dl-fmt {
1309 justify-content: flex-start;
1310}
1311
1312/* ---------------------------------------------------------------------------
1313 * Item info dialog
1314 * ------------------------------------------------------------------------- */
1315.info-list {
1316 margin: 8px 0 16px;
1317 display: grid;
1318 grid-template-columns: 90px 1fr;
1319 row-gap: 8px;
1320 column-gap: 12px;
1321}
1322.info-list dt {
1323 color: var(--muted);
1324}
1325.info-list dd {
1326 margin: 0;
1327 word-break: break-word;
1328}
1329
1330/* ---------------------------------------------------------------------------
1331 Shares (milestone 6)
1332 --------------------------------------------------------------------------- */
1333
1334.share-modal {
1335 width: 480px;
1336}
1337
1338.share-link-row {
1339 display: flex;
1340 gap: 8px;
1341 margin: 12px 0;
1342}
1343
1344.share-link-input {
1345 flex: 1;
1346 font-family: ui-monospace, monospace;
1347 font-size: 12.5px;
1348 padding: 8px 10px;
1349 border: 1px solid var(--border);
1350 background: var(--bg);
1351 color: var(--text);
1352 min-width: 0;
1353}
1354
1355.share-check {
1356 display: flex;
1357 align-items: center;
1358 gap: 8px;
1359 margin: 4px 0 14px;
1360 font-size: 14px;
1361}
1362
1363.share-check input {
1364 width: 16px;
1365 height: 16px;
1366}
1367
1368.share-expiry-row {
1369 display: flex;
1370 align-items: center;
1371 gap: 10px;
1372 margin: 0 0 10px;
1373}
1374
1375.share-expiry-row label {
1376 font-size: 13px;
1377 color: var(--muted);
1378 min-width: 52px;
1379}
1380
1381.share-expiry-row select,
1382.share-expiry-row input {
1383 flex: 1;
1384 padding: 8px 10px;
1385 border: 1px solid var(--border);
1386 background: var(--panel);
1387 color: var(--text);
1388 font: inherit;
1389}
1390
1391.share-expiry-note {
1392 margin: 4px 0 0;
1393 font-size: 12.5px;
1394}
1395
1396.btn-sm {
1397 padding: 5px 10px;
1398 font-size: 12.5px;
1399}
1400
1401.icon-btn-sm {
1402 padding: 4px 6px;
1403}
1404
1405/* "Your shares" manage view */
1406
1407.shares-view {
1408 width: 100%;
1409 max-width: 960px;
1410 margin: 0 auto;
1411}
1412
1413.view-header {
1414 margin-bottom: 16px;
1415}
1416
1417.view-header .admin-section-title {
1418 margin-bottom: 0;
1419}
1420
1421.view-hint {
1422 margin: 4px 0 0;
1423 font-size: 13px;
1424 max-width: 64ch;
1425}
1426
1427.share-list {
1428 display: flex;
1429 flex-direction: column;
1430 gap: 10px;
1431}
1432
1433.share-item {
1434 display: flex;
1435 align-items: center;
1436 justify-content: space-between;
1437 gap: 12px;
1438 padding: 10px 12px;
1439 border: 1px solid var(--border);
1440 background: var(--panel);
1441}
1442
1443.share-item-main {
1444 min-width: 0;
1445}
1446
1447.share-item-name {
1448 display: flex;
1449 align-items: center;
1450 gap: 8px;
1451 font-weight: 600;
1452 font-size: 14px;
1453 overflow: hidden;
1454 text-overflow: ellipsis;
1455 white-space: nowrap;
1456}
1457
1458.ic-row {
1459 width: 18px;
1460 height: 18px;
1461 flex: none;
1462}
1463
1464.share-item-meta {
1465 font-size: 12px;
1466 margin-top: 2px;
1467 overflow: hidden;
1468 text-overflow: ellipsis;
1469 white-space: nowrap;
1470}
1471
1472.share-item-actions {
1473 display: flex;
1474 gap: 6px;
1475 flex-shrink: 0;
1476}
1477
1478/* ------------------------------------------------------------------ */
1479/* Admin (milestone 7) */
1480/* ------------------------------------------------------------------ */
1481
1482.admin-view {
1483 display: flex;
1484 flex-direction: column;
1485 gap: 16px;
1486 width: 100%;
1487 max-width: 960px;
1488 margin: 0 auto;
1489}
1490
1491.admin-section-title {
1492 margin: 0 0 14px;
1493 font-size: 15px;
1494}
1495
1496.users-header {
1497 display: flex;
1498 align-items: center;
1499 justify-content: space-between;
1500 margin-bottom: 4px;
1501}
1502
1503.users-header .admin-section-title {
1504 margin-bottom: 0;
1505}
1506
1507.users-header .btn-primary {
1508 width: auto;
1509}
1510
1511.user-list {
1512 display: flex;
1513 flex-direction: column;
1514 gap: 10px;
1515}
1516
1517.user-row {
1518 display: flex;
1519 align-items: center;
1520 justify-content: space-between;
1521 gap: 12px;
1522 padding: 12px 14px;
1523 border: 1px solid var(--border);
1524}
1525
1526.user-row-main {
1527 min-width: 0;
1528}
1529
1530.user-row-name {
1531 display: flex;
1532 align-items: center;
1533 gap: 6px;
1534 font-weight: 600;
1535 font-size: 14px;
1536 flex-wrap: wrap;
1537}
1538
1539.ic-admin {
1540 width: 16px;
1541 height: 16px;
1542 flex: none;
1543}
1544
1545.user-row-actions {
1546 display: flex;
1547 gap: 6px;
1548 flex-shrink: 0;
1549}
1550
1551.badge-off {
1552 background: color-mix(in srgb, var(--danger) 15%, var(--panel));
1553 border-color: var(--danger);
1554 color: var(--danger);
1555}
1556
1557.setting-row {
1558 display: flex;
1559 align-items: center;
1560 gap: 10px;
1561 padding: 14px;
1562 border: 1px solid var(--border);
1563 cursor: pointer;
1564}
1565
1566.setting-row input {
1567 margin-left: auto;
1568}
1569
1570.setting-label {
1571 display: block;
1572 font-weight: 600;
1573 font-size: 14px;
1574}
1575
1576.setting-desc {
1577 display: block;
1578 font-size: 12px;
1579 color: var(--muted);
1580 margin-top: 2px;
1581}
1582
1583/* Setting row whose control is a select, pushed to the right. */
1584.setting-row-select {
1585 cursor: default;
1586}
1587
1588.setting-row-select > span {
1589 flex: 1;
1590}
1591
1592.setting-row-select select {
1593 appearance: none;
1594 margin-left: auto;
1595 padding: 10px 42px 10px 12px;
1596 border: 1px solid var(--border);
1597 background-color: var(--panel);
1598 background-image: var(--select-arrow);
1599 background-repeat: no-repeat;
1600 background-position: right 12px center;
1601 background-size: 14px 14px;
1602 color: var(--text);
1603 font: inherit;
1604 max-width: 190px;
1605}
1606
1607/* User create/edit form */
1608
1609.user-form {
1610 width: 520px;
1611}
1612
1613.field-input {
1614 width: 100%;
1615 box-sizing: border-box;
1616}
1617
1618.field-hint {
1619 font-size: 12px;
1620 margin: -2px 0 8px;
1621}
1622
1623.check-row {
1624 display: flex;
1625 align-items: center;
1626 gap: 8px;
1627 font-size: 14px;
1628 margin-bottom: 12px;
1629 cursor: pointer;
1630}
1631
1632.form-error {
1633 color: var(--danger);
1634 font-size: 13px;
1635 margin: 4px 0 8px;
1636}
1637
1638.roots-editor {
1639 display: flex;
1640 flex-direction: column;
1641 gap: 6px;
1642}
1643
1644.root-draft {
1645 display: flex;
1646 align-items: center;
1647 gap: 8px;
1648}
1649
1650.root-draft-path {
1651 flex: 1;
1652 font-size: 13px;
1653 overflow: hidden;
1654 text-overflow: ellipsis;
1655 white-space: nowrap;
1656}
1657
1658.root-draft-mode {
1659 width: auto;
1660 padding: 6px 8px;
1661}
1662
1663.root-add {
1664 align-self: flex-start;
1665 margin-top: 4px;
1666}
1667
1668/* ------------------------------------------------------------------ */
1669/* Empty state + keyboard focus (milestone 8) */
1670/* ------------------------------------------------------------------ */
1671
1672.empty-state {
1673 display: flex;
1674 flex-direction: column;
1675 align-items: center;
1676 justify-content: center;
1677 gap: 8px;
1678 padding: 64px 20px;
1679 text-align: center;
1680}
1681
1682.empty-glyph {
1683 width: 52px;
1684 height: 52px;
1685}
1686
1687.empty-state h3 {
1688 margin: 0;
1689 font-size: 16px;
1690}
1691
1692/* Visible keyboard focus on selectable file/folder entries. The ring is
1693 inset (negative offset) so the scroll container never clips it. */
1694.tile:focus-visible,
1695.row:focus-visible {
1696 outline: 2px solid var(--accent);
1697 outline-offset: -2px;
1698}
1699
1700/* ------------------------------------------------------------------ */
1701/* Search view (#/search) */
1702/* ------------------------------------------------------------------ */
1703
1704.search-view {
1705 display: flex;
1706 flex-direction: column;
1707 gap: 14px;
1708}
1709
1710/* Query bar ------------------------------------------------------ */
1711
1712.query-bar {
1713 display: flex;
1714 align-items: stretch;
1715 gap: 8px;
1716}
1717
1718.query-input {
1719 flex: 1;
1720 display: flex;
1721 align-items: center;
1722 gap: 8px;
1723 background: var(--panel);
1724 border: 1px solid var(--border);
1725 padding: 0 10px;
1726 min-width: 0;
1727}
1728
1729.query-input .qi-icon {
1730 width: 18px;
1731 height: 18px;
1732 color: var(--muted);
1733 flex: none;
1734}
1735
1736.query-input input {
1737 flex: 1;
1738 min-width: 0;
1739 border: none;
1740 outline: none;
1741 background: transparent;
1742 color: var(--text);
1743 font: inherit;
1744 font-size: 14px;
1745 height: 38px;
1746 padding: 0;
1747}
1748
1749.query-input input::placeholder {
1750 color: var(--muted);
1751}
1752
1753/* Segmented Name / Content / Both control */
1754
1755.seg {
1756 display: flex;
1757 border: 1px solid var(--border);
1758 background: var(--panel);
1759}
1760
1761.seg button {
1762 appearance: none;
1763 border: none;
1764 border-right: 1px solid var(--border);
1765 background: transparent;
1766 color: var(--muted);
1767 font: inherit;
1768 font-size: 13px;
1769 padding: 0 14px;
1770 cursor: pointer;
1771}
1772
1773.seg button:last-child {
1774 border-right: none;
1775}
1776
1777.seg button:hover {
1778 background: var(--bg);
1779}
1780
1781.seg button.on {
1782 background: var(--accent);
1783 color: #fff;
1784}
1785
1786/* Start folder --------------------------------------------------- */
1787
1788/* The folder a search starts in; opens the folder picker. */
1789.folder-pick {
1790 flex: none;
1791 display: flex;
1792 align-items: center;
1793 gap: 8px;
1794 max-width: 260px;
1795 border: 1px solid var(--border);
1796 background: var(--panel);
1797 color: var(--text);
1798 font: inherit;
1799 font-size: 13px;
1800 padding: 0 10px;
1801 cursor: pointer;
1802}
1803
1804.folder-pick:hover {
1805 border-color: var(--muted);
1806}
1807
1808.folder-pick .fp-icon {
1809 width: 16px;
1810 height: 16px;
1811 color: var(--muted);
1812 flex: none;
1813}
1814
1815.folder-pick .fp-path {
1816 overflow: hidden;
1817 text-overflow: ellipsis;
1818 white-space: nowrap;
1819}
1820
1821.ms {
1822 position: relative;
1823 display: flex;
1824}
1825
1826.ms-btn {
1827 display: flex;
1828 align-items: center;
1829 gap: 6px;
1830 border: 1px solid var(--border);
1831 background: var(--panel);
1832 color: var(--text);
1833 font: inherit;
1834 font-size: 13px;
1835 padding: 0 10px;
1836 cursor: pointer;
1837 max-width: 180px;
1838}
1839
1840.ms-btn:hover {
1841 background: var(--bg);
1842}
1843
1844.ms-btn > span {
1845 overflow: hidden;
1846 text-overflow: ellipsis;
1847 white-space: nowrap;
1848}
1849
1850/* Square caret drawn with borders (the icon set has no chevron). */
1851.ms-caret {
1852 flex: none;
1853 width: 8px;
1854 height: 8px;
1855 border-right: 2px solid var(--muted);
1856 border-bottom: 2px solid var(--muted);
1857 transform: rotate(45deg) translate(-1px, -1px);
1858}
1859
1860.ms-backdrop {
1861 position: fixed;
1862 inset: 0;
1863 z-index: 40;
1864}
1865
1866.ms-drop {
1867 position: absolute;
1868 right: 0;
1869 top: calc(100% + 4px);
1870 z-index: 41;
1871 min-width: 200px;
1872 max-height: 280px;
1873 overflow: auto;
1874 background: var(--panel);
1875 border: 1px solid var(--border);
1876 padding: 4px 0;
1877}
1878
1879.ms-opt {
1880 display: flex;
1881 align-items: center;
1882 gap: 8px;
1883 padding: 7px 12px;
1884 font-size: 14px;
1885 cursor: pointer;
1886 user-select: none;
1887}
1888
1889.ms-opt:hover {
1890 background: var(--bg);
1891}
1892
1893.ms-opt span {
1894 overflow: hidden;
1895 text-overflow: ellipsis;
1896 white-space: nowrap;
1897}
1898
1899/* Run / stop ------------------------------------------------------- */
1900
1901.btn-run {
1902 border: 1px solid var(--accent-border);
1903 background: var(--accent);
1904 color: #fff;
1905 font: inherit;
1906 font-size: 13px;
1907 font-weight: 600;
1908 padding: 0 18px;
1909 cursor: pointer;
1910}
1911
1912.btn-run:hover {
1913 background: var(--accent-hover);
1914}
1915
1916.btn-stop {
1917 display: flex;
1918 align-items: center;
1919 gap: 6px;
1920 border: 1px solid var(--danger-border);
1921 background: var(--danger);
1922 color: #fff;
1923 font: inherit;
1924 font-size: 13px;
1925 font-weight: 600;
1926 padding: 0 14px;
1927 cursor: pointer;
1928}
1929
1930.btn-stop:hover {
1931 opacity: 0.9;
1932}
1933
1934.btn-stop .ic-stop {
1935 width: 14px;
1936 height: 14px;
1937}
1938
1939/* Status line ------------------------------------------------------ */
1940
1941.status-line {
1942 display: flex;
1943 align-items: center;
1944 gap: 8px;
1945 font-size: 13px;
1946 color: var(--muted);
1947}
1948
1949.status-line .dot {
1950 width: 8px;
1951 height: 8px;
1952 background: var(--accent);
1953 animation: search-pulse 1s ease-in-out infinite;
1954}
1955
1956@keyframes search-pulse {
1957 0%,
1958 100% {
1959 opacity: 1;
1960 }
1961 50% {
1962 opacity: 0.3;
1963 }
1964}
1965
1966.status-line .skip {
1967 opacity: 0.75;
1968}
1969
1970/* Group labels ----------------------------------------------------- */
1971
1972.group-label {
1973 display: flex;
1974 align-items: center;
1975 gap: 8px;
1976 font-size: 12px;
1977 font-weight: 600;
1978 letter-spacing: 0.04em;
1979 text-transform: uppercase;
1980 color: var(--muted);
1981}
1982
1983/* Result group: a `display:flex` (or `none`, from the inline style) flex
1984 item of `.search-view` that re-establishes the column layout for its
1985 label/list/more-row children. */
1986.result-group {
1987 flex-direction: column;
1988 gap: 14px;
1989}
1990
1991.group-label .gl-icon {
1992 width: 15px;
1993 height: 15px;
1994}
1995
1996.group-label .n {
1997 font-weight: 400;
1998 text-transform: none;
1999 letter-spacing: 0;
2000}
2001
2002.group-label .grow {
2003 flex: 1;
2004}
2005
2006.collapse-all {
2007 appearance: none;
2008 border: 1px solid var(--border);
2009 background: transparent;
2010 color: var(--muted);
2011 font: inherit;
2012 font-size: 12px;
2013 text-transform: none;
2014 letter-spacing: 0;
2015 padding: 3px 10px;
2016 cursor: pointer;
2017}
2018
2019.collapse-all:hover {
2020 background: var(--bg);
2021 color: var(--text);
2022}
2023
2024/* Name-result rows --------------------------------------------------- */
2025
2026.srow {
2027 display: grid;
2028 /* icon | name+dir | size | goto */
2029 grid-template-columns: 28px minmax(0, 1fr) 90px 30px;
2030 gap: 12px;
2031 align-items: center;
2032 padding: 9px 14px;
2033 border-bottom: 1px solid var(--border);
2034 cursor: pointer;
2035 font-size: 14px;
2036 user-select: none;
2037}
2038
2039.srow:last-child {
2040 border-bottom: none;
2041}
2042
2043.srow:hover {
2044 background: var(--bg);
2045}
2046
2047.srow-icon {
2048 width: 20px;
2049 height: 20px;
2050}
2051
2052.srow-main {
2053 min-width: 0;
2054 display: flex;
2055 flex-direction: column;
2056 line-height: 1.3;
2057}
2058
2059.srow-name {
2060 overflow: hidden;
2061 text-overflow: ellipsis;
2062 white-space: nowrap;
2063}
2064
2065/* Highlighted query hits (plain fragments render as bare spans). */
2066mark.hl-hit {
2067 background: color-mix(in srgb, var(--accent) 25%, transparent);
2068 color: inherit;
2069}
2070
2071/* The directory-path line (the name line lives inside .srow-name). */
2072.srow-dir {
2073 font-size: 12px;
2074 color: var(--muted);
2075 overflow: hidden;
2076 text-overflow: ellipsis;
2077 white-space: nowrap;
2078}
2079
2080.srow-dir mark.hl-hit {
2081 color: inherit;
2082}
2083
2084.ssize {
2085 font-size: 13px;
2086 color: var(--muted);
2087 text-align: right;
2088}
2089
2090/* Paging footer: position in the results on the left, the action on the
2091 right. Separated from the list by its own border so the button never reads
2092 as another result row. */
2093.page-foot {
2094 display: flex;
2095 align-items: center;
2096 justify-content: space-between;
2097 gap: 12px;
2098 padding: 10px 14px;
2099 border-top: 1px solid var(--border);
2100 font-size: 12px;
2101 color: var(--muted);
2102}
2103
2104.page-foot .pf-count {
2105 font-variant-numeric: tabular-nums;
2106}
2107
2108.page-foot .pf-more {
2109 appearance: none;
2110 padding: 5px 12px;
2111 border: 1px solid var(--border);
2112 background: var(--panel);
2113 font: inherit;
2114 font-weight: 500;
2115 color: var(--text);
2116 cursor: pointer;
2117}
2118
2119.page-foot .pf-more:hover {
2120 border-color: var(--accent);
2121 color: var(--accent);
2122}
2123
2124/* Content matches ----------------------------------------------------- */
2125
2126.match-card {
2127 background: var(--panel);
2128 border: 1px solid var(--border);
2129 border-top: none;
2130}
2131
2132/* The first card is the one right after the group label; `:first-of-type`
2133 cannot be used because the label is an earlier `div` sibling. */
2134.group-label + .match-card {
2135 border-top: 1px solid var(--border);
2136}
2137
2138/* The header opens the file; the matched lines below are text to read. */
2139.match-head {
2140 display: flex;
2141 align-items: center;
2142 gap: 10px;
2143 padding: 9px 14px;
2144 font-size: 14px;
2145 cursor: pointer;
2146}
2147
2148.match-head:hover {
2149 background: var(--bg);
2150}
2151
2152.match-head .mi {
2153 width: 18px;
2154 height: 18px;
2155 color: var(--muted);
2156 flex: none;
2157}
2158
2159/* Takes the slack, so the count and the two buttons sit at the right edge. */
2160.mpath {
2161 flex: 1;
2162 min-width: 0;
2163 overflow: hidden;
2164 text-overflow: ellipsis;
2165 white-space: nowrap;
2166}
2167
2168.mpath b {
2169 font-weight: 600;
2170}
2171
2172.mcount {
2173 flex: none;
2174 font-size: 12px;
2175 color: var(--muted);
2176}
2177
2178/* "Show in folder", in both the name rows and the match-card headers. */
2179.goto-btn {
2180 appearance: none;
2181 flex: none;
2182 justify-self: end;
2183 display: flex;
2184 align-items: center;
2185 justify-content: center;
2186 width: 26px;
2187 height: 26px;
2188 padding: 0;
2189 border: 1px solid transparent;
2190 background: transparent;
2191 cursor: pointer;
2192}
2193
2194.goto-btn:hover {
2195 border-color: var(--border);
2196}
2197
2198.goto-btn .goto-ic {
2199 width: 16px;
2200 height: 16px;
2201 color: var(--muted);
2202}
2203
2204.goto-btn:hover .goto-ic {
2205 color: var(--accent);
2206}
2207
2208.chev {
2209 appearance: none;
2210 border: 1px solid var(--border);
2211 background: transparent;
2212 width: 26px;
2213 height: 26px;
2214 display: flex;
2215 align-items: center;
2216 justify-content: center;
2217 cursor: pointer;
2218 flex: none;
2219}
2220
2221.chev:hover {
2222 background: var(--bg);
2223}
2224
2225.chev .chev-down,
2226.chev .chev-up {
2227 display: block;
2228 width: 10px;
2229 height: 10px;
2230 border-right: 2px solid var(--muted);
2231 border-bottom: 2px solid var(--muted);
2232}
2233
2234.chev .chev-down {
2235 transform: rotate(45deg) translate(-1px, -1px);
2236}
2237
2238.chev .chev-up {
2239 transform: rotate(-135deg) translate(-1px, -1px);
2240}
2241
2242.match-lines {
2243 border-top: 1px solid var(--border);
2244 background: var(--bg);
2245 font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
2246 font-size: 12.5px;
2247}
2248
2249/* Matched lines are text to read, not a control: the card header is what
2250 opens the file, so no pointer cursor and no hover here. */
2251.mline {
2252 display: grid;
2253 grid-template-columns: 52px minmax(0, 1fr);
2254 gap: 12px;
2255 padding: 5px 14px;
2256 border-bottom: 1px solid var(--border);
2257 white-space: pre;
2258 user-select: text;
2259}
2260
2261.mline:last-child {
2262 border-bottom: none;
2263}
2264
2265.mline .ln {
2266 color: var(--muted);
2267 text-align: right;
2268 user-select: none;
2269}
2270
2271.mline .tx {
2272 overflow: hidden;
2273 text-overflow: ellipsis;
2274}
2275
2276.search-empty {
2277 padding: 48px 20px;
2278 text-align: center;
2279 color: var(--muted);
2280 font-size: 14px;
2281}
2282