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