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