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}
19
20:root.dark {
21 color-scheme: dark;
22 --bg: #0f1115;
23 --panel: #171a20;
24 --text: #e5e7eb;
25 --muted: #9ca3af;
26 --accent: #60a5fa;
27 --accent-hover: #3b82f6;
28 --accent-border: #79b5fc;
29 --danger: #f87171;
30 --danger-border: #fa8b8b;
31 --border: #2a2f3a;
32}
33
34@media (prefers-color-scheme: dark) {
35 :root:not(.light) {
36 color-scheme: dark;
37 --bg: #0f1115;
38 --panel: #171a20;
39 --text: #e5e7eb;
40 --muted: #9ca3af;
41 --accent: #60a5fa;
42 --accent-hover: #3b82f6;
43 --accent-border: #79b5fc;
44 --danger: #f87171;
45 --danger-border: #fa8b8b;
46 --border: #2a2f3a;
47 }
48}
49
50* {
51 box-sizing: border-box;
52 /* The design language is sharp: everything stays square. */
53 border-radius: 0;
54}
55
56body {
57 margin: 0;
58 font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
59 background: var(--bg);
60 color: var(--text);
61 font-size: 15px;
62}
63
64.muted {
65 color: var(--muted);
66}
67
68.card {
69 background: var(--panel);
70 border: 1px solid var(--border);
71 padding: 24px;
72}
73
74.center-screen {
75 min-height: 100vh;
76 display: flex;
77 flex-direction: column;
78 align-items: center;
79 justify-content: center;
80 padding: 16px;
81 text-align: center;
82}
83
84.auth-card {
85 width: 100%;
86 max-width: 380px;
87}
88
89.auth-card h1 {
90 margin: 0 0 8px;
91 font-size: 22px;
92}
93
94.auth-logo {
95 width: 44px;
96 height: 44px;
97 margin-bottom: 12px;
98}
99
100.auth-card p {
101 margin: 0 0 20px;
102 font-size: 13px;
103}
104
105.field {
106 display: block;
107 margin-bottom: 14px;
108}
109
110.field span {
111 display: block;
112 font-size: 13px;
113 color: var(--muted);
114 margin-bottom: 4px;
115}
116
117input {
118 width: 100%;
119 padding: 10px 12px;
120 border: 1px solid var(--border);
121 background: var(--bg);
122 color: var(--text);
123 font-size: 14px;
124}
125
126input:focus {
127 outline: 2px solid var(--accent);
128 outline-offset: -1px;
129}
130
131button {
132 font: inherit;
133 cursor: pointer;
134 display: inline-flex;
135 align-items: center;
136 justify-content: center;
137 gap: 6px;
138 border: 1px solid var(--border);
139 background: var(--panel);
140 color: var(--text);
141 padding: 9px 14px;
142}
143
144button:hover {
145 border-color: var(--muted);
146}
147
148button:disabled {
149 opacity: 0.6;
150 cursor: default;
151}
152
153.btn-primary {
154 width: 100%;
155 background: var(--accent);
156 /* One step away from the fill, per theme (see palette above), so the
157 button's edge reads the same as on neutral buttons. */
158 border-color: var(--accent-border);
159 color: #fff;
160 font-weight: 600;
161}
162
163.btn-primary:hover {
164 background: var(--accent-hover);
165 border-color: var(--accent-border);
166}
167
168.error {
169 color: var(--danger);
170 font-size: 13px;
171 min-height: 18px;
172 margin: 0 0 10px;
173}
174
175/* layout (signed-in): full-width topbar, then sidebar + content below */
176
177.layout {
178 min-height: 100vh;
179 display: flex;
180 flex-direction: column;
181}
182
183.topbar {
184 flex: none;
185 position: sticky;
186 top: 0;
187 z-index: 130;
188 height: var(--topbar-h);
189 display: flex;
190 align-items: center;
191 justify-content: space-between;
192 gap: 12px;
193 padding: 0 16px;
194 background: var(--panel);
195 border-bottom: 1px solid var(--border);
196}
197
198.topbar-left {
199 display: flex;
200 align-items: center;
201 gap: 10px;
202 min-width: 0;
203}
204
205.icon-btn.nav-toggle {
206 display: none;
207}
208
209.body-row {
210 flex: 1;
211 display: flex;
212 align-items: stretch;
213}
214
215/* ---- sidebar ---- */
216
217.sidebar {
218 flex: none;
219 width: 224px;
220 display: flex;
221 flex-direction: column;
222 background: var(--panel);
223 border-right: 1px solid var(--border);
224 position: sticky;
225 top: var(--topbar-h);
226 height: calc(100vh - var(--topbar-h));
227}
228
229.brand {
230 display: flex;
231 align-items: center;
232 gap: 10px;
233 font-weight: 700;
234 white-space: nowrap;
235}
236
237.brand-name {
238 overflow: hidden;
239 text-overflow: ellipsis;
240}
241
242.logo {
243 width: 26px;
244 height: 26px;
245 flex: none;
246 display: block;
247}
248
249.nav {
250 flex: 1;
251 overflow-y: auto;
252 padding: 14px 8px 16px;
253 display: flex;
254 flex-direction: column;
255 gap: 20px;
256}
257
258.sidebar-user {
259 padding: 0 10px 2px;
260 font-size: 14px;
261 font-weight: 600;
262 overflow: hidden;
263 text-overflow: ellipsis;
264 white-space: nowrap;
265}
266
267.nav-section-label {
268 font-size: 11px;
269 font-weight: 700;
270 text-transform: uppercase;
271 letter-spacing: 0.08em;
272 color: var(--muted);
273 padding: 0 10px 6px;
274}
275
276/* Section header with a right-aligned action (the Files refresh). */
277.nav-section-head {
278 display: flex;
279 align-items: center;
280 justify-content: space-between;
281 gap: 6px;
282}
283
284.nav-section-head .nav-section-label {
285 flex: 1;
286 padding-bottom: 2px;
287}
288
289.nav-section-refresh {
290 color: var(--muted);
291 background: none;
292 border-color: transparent;
293 padding: 3px 5px;
294}
295
296.nav-section-refresh:hover {
297 color: var(--text);
298 border-color: var(--border);
299}
300
301.nav-tab {
302 display: flex;
303 align-items: center;
304 justify-content: flex-start;
305 gap: 10px;
306 width: 100%;
307 margin-bottom: 2px;
308 padding: 8px 10px;
309 text-align: left;
310 background: none;
311 border: none;
312 color: var(--muted);
313 font-size: 14px;
314}
315
316.nav-tab:hover {
317 background: var(--bg);
318 color: var(--text);
319}
320
321.nav-tab.active {
322 background: var(--accent);
323 border-color: var(--accent);
324 color: #fff;
325}
326
327.ic-tab {
328 width: 18px;
329 height: 18px;
330 flex: none;
331}
332
333.nav-tab.active .icon {
334 color: #fff;
335}
336
337.nav-tab-name {
338 flex: 1;
339 min-width: 0;
340 overflow: hidden;
341 text-overflow: ellipsis;
342 white-space: nowrap;
343}
344
345.nav-tab-note {
346 flex: none;
347 font-size: 10px;
348 font-weight: 700;
349 padding: 1px 5px;
350 background: var(--bg);
351 border: 1px solid var(--border);
352 color: var(--muted);
353}
354
355.nav-tab.active .nav-tab-note {
356 background: rgb(255 255 255 / 18%);
357 border-color: rgb(255 255 255 / 30%);
358 color: #fff;
359}
360
361.nav-backdrop {
362 display: none;
363}
364
365/* Sidebar footer: theme toggle, log out, and the project version.
366 Sits at the bottom of the sidebar, below the manage section. */
367.sidebar-footer {
368 flex: none;
369 border-top: 1px solid var(--border);
370 padding: 8px;
371}
372
373.sidebar-footer .nav-tab {
374 margin-bottom: 0;
375}
376
377.sidebar-action.logout {
378 color: var(--danger);
379}
380
381.sidebar-action.logout:hover {
382 color: var(--danger);
383}
384
385.sidebar-version {
386 margin-top: 8px;
387 padding: 0 10px;
388 font-size: 11.5px;
389 color: var(--muted);
390 white-space: nowrap;
391 overflow: hidden;
392 text-overflow: ellipsis;
393}
394
395.badge {
396 font-size: 11px;
397 padding: 2px 8px;
398 background: var(--bg);
399 border: 1px solid var(--border);
400 color: var(--muted);
401}
402
403.content {
404 flex: 1;
405 min-width: 0;
406 min-height: 0;
407 display: flex;
408 flex-direction: column;
409 padding: 20px;
410}
411
412/* While a file is open the app is a fixed-height frame: the file view
413 * (editor, image, …) scrolls inside, the page itself never grows. */
414.layout.file-mode {
415 height: 100vh;
416 overflow: hidden;
417}
418
419.layout.file-mode .body-row {
420 min-height: 0;
421}
422
423/* Narrow screens: the sidebar becomes an off-canvas drawer that only
424 covers the content, below the (always visible) topbar. */
425@media (max-width: 860px) {
426 .sidebar {
427 position: fixed;
428 top: var(--topbar-h);
429 bottom: 0;
430 left: 0;
431 right: auto;
432 height: auto;
433 z-index: 120;
434 transform: translateX(-100%);
435 transition: transform 0.15s ease;
436 }
437
438 .sidebar.open {
439 transform: translateX(0);
440 box-shadow: 0 0 48px rgb(0 0 0 / 35%);
441 }
442
443 .nav-backdrop {
444 display: block;
445 position: fixed;
446 top: var(--topbar-h);
447 bottom: 0;
448 left: 0;
449 right: 0;
450 z-index: 110;
451 background: rgb(0 0 0 / 40%);
452 }
453
454 .icon-btn.nav-toggle {
455 display: inline-flex;
456 }
457
458 .content {
459 padding: 14px;
460 }
461}
462
463/* ---- file browser ---- */
464
465.browser {
466 width: 100%;
467 max-width: 1200px;
468 margin: 0 auto;
469 flex: 1;
470 display: flex;
471 flex-direction: column;
472 min-height: 0;
473}
474
475.icon {
476 width: 20px;
477 height: 20px;
478 display: inline-block;
479 vertical-align: middle;
480}
481
482.ic-folder {
483 color: var(--accent);
484}
485
486.ic-muted {
487 color: var(--muted);
488}
489
490.crumbs {
491 display: flex;
492 align-items: center;
493 gap: 2px;
494 padding: 6px 0 12px;
495 font-size: 15px;
496 flex-wrap: wrap;
497}
498
499.crumb {
500 cursor: pointer;
501 color: var(--muted);
502 padding: 3px 6px;
503}
504
505.crumb:hover {
506 color: var(--text);
507 background: var(--panel);
508}
509
510.crumb.current {
511 color: var(--text);
512 font-weight: 600;
513 cursor: default;
514 background: none;
515}
516
517.crumb-sep {
518 color: var(--muted);
519 padding: 0 1px;
520}
521
522.toolbar {
523 display: flex;
524 align-items: center;
525 justify-content: space-between;
526 gap: 6px;
527 padding-bottom: 12px;
528}
529
530.toolbar-right {
531 display: flex;
532 gap: 6px;
533}
534
535.icon-btn {
536 padding: 7px 9px;
537 border: 1px solid var(--border);
538 background: var(--panel);
539 color: var(--muted);
540 display: inline-flex;
541 align-items: center;
542}
543
544.icon-btn:hover {
545 border-color: var(--muted);
546}
547
548.icon-btn.active {
549 background: var(--accent);
550 border-color: var(--accent);
551 color: #fff;
552}
553
554.ic-btn {
555 width: 18px;
556 height: 18px;
557 color: inherit;
558}
559
560.entries-area {
561 flex: 1;
562 min-height: 240px;
563}
564
565.center-note {
566 text-align: center;
567 padding: 48px 0;
568}
569
570.error-card {
571 display: flex;
572 align-items: center;
573 justify-content: space-between;
574 gap: 16px;
575 color: var(--danger);
576 font-size: 14px;
577}
578
579/* root tiles were replaced by the sidebar's folder tabs */
580
581/* grid view */
582
583.entries-grid {
584 display: grid;
585 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
586 gap: 10px;
587}
588
589.tile {
590 background: var(--panel);
591 border: 1px solid var(--border);
592 padding: 16px 10px 12px;
593 text-align: center;
594 cursor: pointer;
595}
596
597.tile:hover {
598 border-color: var(--muted);
599}
600
601.tile-icon {
602 width: 42px;
603 height: 42px;
604 margin: 0 auto 10px;
605 display: block;
606}
607
608.tile-name {
609 font-size: 13px;
610 line-height: 1.3;
611 word-break: break-word;
612}
613
614/* list view */
615
616.entries-list {
617 background: var(--panel);
618 border: 1px solid var(--border);
619 overflow: hidden;
620}
621
622.row {
623 display: grid;
624 grid-template-columns: 28px minmax(0, 1fr) 90px 150px;
625 gap: 12px;
626 align-items: center;
627 padding: 9px 14px;
628 border-bottom: 1px solid var(--border);
629 cursor: pointer;
630 font-size: 14px;
631}
632
633.row:last-child {
634 border-bottom: none;
635}
636
637.row:hover {
638 background: var(--bg);
639}
640
641.row-icon {
642 width: 20px;
643 height: 20px;
644}
645
646.row-name {
647 overflow: hidden;
648 text-overflow: ellipsis;
649 white-space: nowrap;
650}
651
652.row-size,
653.row-date {
654 font-size: 13px;
655 text-align: right;
656}
657
658@media (max-width: 640px) {
659 .row {
660 grid-template-columns: 28px minmax(0, 1fr) 90px;
661 }
662
663 .row-date {
664 display: none;
665 }
666}
667
668/* context menu */
669
670.ctx-menu {
671 position: fixed;
672 z-index: 100;
673 min-width: 190px;
674 background: var(--panel);
675 border: 1px solid var(--border);
676 padding: 5px;
677 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
678}
679
680.ctx-item {
681 display: flex;
682 align-items: center;
683 gap: 10px;
684 padding: 8px 12px;
685 font-size: 14px;
686 cursor: pointer;
687}
688
689.ic-ctx {
690 width: 18px;
691 height: 18px;
692 flex: none;
693}
694
695.ctx-item:hover {
696 background: var(--bg);
697}
698
699.ctx-item.disabled {
700 opacity: 0.45;
701 cursor: default;
702}
703
704.ctx-item.disabled:hover {
705 background: none;
706}
707
708/* toolbar selection actions (top right) */
709
710.sel-actions {
711 display: flex;
712 align-items: center;
713 gap: 6px;
714 position: relative;
715}
716
717.sel-actions .icon-btn:disabled {
718 opacity: 0.45;
719 cursor: default;
720}
721
722.sel-actions .icon-btn:disabled:hover {
723 border-color: var(--border);
724 color: var(--muted);
725}
726
727.sel-more-wrap {
728 position: relative;
729}
730
731.sel-more-menu {
732 position: absolute;
733 right: 0;
734 top: calc(100% + 6px);
735 z-index: 100;
736 min-width: 190px;
737 background: var(--panel);
738 border: 1px solid var(--border);
739 padding: 5px;
740 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
741}
742
743.sel-more-menu.hidden {
744 display: none;
745}
746
747/* selection actions in the top bar */
748
749.topbar .sel-actions {
750 min-height: 0;
751}
752
753.topbar .sel-actions .icon-btn {
754 padding: 5px 7px;
755}
756
757/* selection highlight in the grid and list */
758
759.tile.selected {
760 border-color: var(--accent);
761 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
762}
763
764.row.selected {
765 background: color-mix(in srgb, var(--accent) 12%, var(--panel));
766 box-shadow: inset 2px 0 0 var(--accent);
767}
768
769/* settings tabs (profile / server) */
770
771.settings-tabs {
772 display: flex;
773 gap: 8px;
774}
775
776.settings-tab-btn {
777 padding: 7px 14px;
778 border: 1px solid var(--border);
779 background: var(--panel);
780 color: var(--muted);
781 font-size: 13px;
782 font-weight: 600;
783}
784
785.settings-tab-btn:hover {
786 border-color: var(--muted);
787 color: var(--text);
788}
789
790.settings-tab-btn.active {
791 border-color: var(--accent);
792 color: var(--accent);
793 background: color-mix(in srgb, var(--accent) 10%, var(--panel));
794}
795
796/* toast */
797
798.toast {
799 position: fixed;
800 bottom: 20px;
801 right: 20px;
802 z-index: 200;
803 background: var(--panel);
804 color: var(--text);
805 border: 1px solid var(--border);
806 padding: 11px 16px;
807 font-size: 14px;
808 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
809 max-width: 320px;
810}
811
812
813/* ---- modals ---- */
814
815.modal-overlay {
816 position: fixed;
817 inset: 0;
818 background: rgb(0 0 0 / 45%);
819 display: flex;
820 align-items: center;
821 justify-content: center;
822 z-index: 100;
823}
824
825.modal {
826 width: 440px;
827 max-width: calc(100vw - 32px);
828 padding: 20px;
829 background: var(--panel);
830 border: 1px solid var(--border);
831 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
832}
833
834.modal.picker {
835 width: 520px;
836}
837
838.modal-title {
839 margin: 0 0 12px;
840 font-size: 16px;
841}
842
843.modal-label {
844 display: block;
845 font-size: 13px;
846 color: var(--muted);
847 margin-bottom: 6px;
848}
849
850.modal .input {
851 width: 100%;
852 box-sizing: border-box;
853 margin-bottom: 16px;
854}
855
856.modal-message {
857 white-space: pre-line;
858 font-size: 14px;
859 margin: 0 0 8px;
860}
861
862.modal-actions {
863 display: flex;
864 justify-content: flex-end;
865 gap: 8px;
866 margin-top: 16px;
867}
868
869.btn-danger {
870 background: var(--danger);
871 /* A visible border (one step away from the fill, per theme) so the
872 button's edge reads the same as on neutral buttons. */
873 border-color: var(--danger-border);
874 color: #fff;
875}
876
877.btn-danger:hover {
878 background: color-mix(in srgb, var(--danger) 85%, black);
879}
880
881.btn:disabled {
882 opacity: 0.5;
883 cursor: not-allowed;
884}
885
886.conflict-list {
887 max-height: 200px;
888 overflow-y: auto;
889 margin: 8px 0;
890 padding-left: 20px;
891 font-size: 13px;
892}
893
894.picker-roots {
895 display: flex;
896 gap: 6px;
897 flex-wrap: wrap;
898 margin-bottom: 12px;
899}
900
901.root-opt {
902 font-size: 13px;
903}
904
905.root-opt.active {
906 background: var(--accent);
907 border-color: var(--accent);
908 color: #fff;
909}
910
911.picker-current {
912 font-size: 13px;
913 margin: 0 0 8px;
914}
915
916.picker-crumbs {
917 margin-bottom: 8px;
918}
919
920.picker-entries {
921 max-height: 240px;
922 overflow-y: auto;
923 border: 1px solid var(--border);
924}
925
926.picker-row {
927 display: flex;
928 align-items: center;
929 gap: 10px;
930 padding: 8px 12px;
931 cursor: pointer;
932}
933
934.picker-row:hover {
935 background: var(--bg);
936}
937
938/* ---------------------------------------------------------------------------
939 * Full-page file view (preview / editor / "no preview"). The top bar carries
940 * the title + actions; the content area below is edge to edge.
941 * ------------------------------------------------------------------------- */
942.content.file-open {
943 padding: 0;
944 overflow: hidden;
945}
946
947/* The browser stays mounted (state, fetch callback) but hidden. */
948.content.file-open .browser {
949 display: none;
950}
951
952.file-view {
953 flex: 1;
954 min-height: 0;
955 display: flex;
956 flex-direction: column;
957}
958
959.file-title {
960 display: flex;
961 align-items: center;
962 gap: 8px;
963 min-width: 0;
964}
965
966.file-title-icon {
967 width: 18px;
968 height: 18px;
969 flex: none;
970 color: var(--muted);
971}
972
973.file-title-name {
974 font-weight: 600;
975 font-size: 14px;
976 white-space: nowrap;
977 overflow: hidden;
978 text-overflow: ellipsis;
979}
980
981.file-actions {
982 display: flex;
983 align-items: center;
984 gap: 10px;
985 flex: none;
986}
987
988.file-close {
989 border: none;
990 background: transparent;
991 color: var(--muted);
992 padding: 6px 8px;
993}
994
995.file-close:hover {
996 color: var(--text);
997 background: var(--bg);
998}
999.preview-body {
1000 flex: 1;
1001 min-height: 0;
1002 overflow: auto;
1003 display: flex;
1004 background: var(--bg);
1005}
1006.preview-img {
1007 max-width: 100%;
1008 max-height: 100%;
1009 display: block;
1010 margin: auto;
1011}
1012.preview-pdf {
1013 width: 100%;
1014 height: 100%;
1015 border: none;
1016 background: #fff;
1017}
1018.preview-video {
1019 width: 100%;
1020 max-height: 100%;
1021 background: #000;
1022}
1023.preview-audio {
1024 display: flex;
1025 align-items: center;
1026 justify-content: center;
1027 width: 100%;
1028 padding: 24px;
1029}
1030.preview-audio audio {
1031 width: 100%;
1032 max-width: 480px;
1033}
1034
1035/* CodeMirror (text editor) */
1036.cm-container {
1037 height: 100%;
1038}
1039.cm-container .cm-editor {
1040 height: 100%;
1041}
1042/* Load/save failure: dims the editor and shows the message in a card
1043 * (the top-bar Save button stays reachable to retry). */
1044.cm-error {
1045 position: absolute;
1046 inset: 0;
1047 z-index: 5;
1048 display: flex;
1049 align-items: center;
1050 justify-content: center;
1051 padding: 24px;
1052 background: rgb(0 0 0 / 45%);
1053}
1054
1055.cm-error-card {
1056 position: relative;
1057 max-width: 440px;
1058 min-width: 200px;
1059 background: var(--panel);
1060 border: 1px solid var(--border);
1061 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
1062}
1063
1064.cm-error-close {
1065 position: absolute;
1066 top: 7px;
1067 right: 7px;
1068 display: inline-flex;
1069 align-items: center;
1070 justify-content: center;
1071 border: none;
1072 background: transparent;
1073 color: var(--muted);
1074 padding: 3px;
1075}
1076
1077.cm-error-close:hover {
1078 color: var(--text);
1079 background: var(--bg);
1080}
1081
1082.cm-error-close .ic-btn {
1083 width: 16px;
1084 height: 16px;
1085}
1086
1087.cm-error-text {
1088 padding: 16px 40px 16px 20px;
1089 font-size: 14px;
1090 text-align: center;
1091 overflow-wrap: anywhere;
1092}
1093
1094/* ---------------------------------------------------------------------------
1095 * Text editor (full page; title/save/close live in the top bar)
1096 * ------------------------------------------------------------------------- */
1097.file-editor {
1098 flex: 1;
1099 min-height: 0;
1100 display: flex;
1101 position: relative;
1102 background: var(--bg);
1103}
1104.file-editor .cm-container {
1105 width: 100%;
1106 height: 100%;
1107}
1108/* "No preview" fallback (binaries, archives). */
1109.file-nopreview {
1110 flex: 1;
1111 display: flex;
1112 align-items: center;
1113 justify-content: center;
1114}
1115.file-nopreview .btn-primary {
1116 width: auto;
1117 margin-top: 14px;
1118}
1119/* Conflict / discard dialogs render above the file view. */
1120.editor-sub-overlay {
1121 z-index: 101;
1122 background: rgb(0 0 0 / 25%);
1123}
1124
1125/* ---------------------------------------------------------------------------
1126 * Download format dialog
1127 * ------------------------------------------------------------------------- */
1128.dl-formats {
1129 display: flex;
1130 flex-direction: column;
1131 gap: 8px;
1132 margin-bottom: 8px;
1133}
1134.dl-fmt {
1135 justify-content: flex-start;
1136}
1137
1138/* ---------------------------------------------------------------------------
1139 * Item info dialog
1140 * ------------------------------------------------------------------------- */
1141.info-list {
1142 margin: 8px 0 16px;
1143 display: grid;
1144 grid-template-columns: 90px 1fr;
1145 row-gap: 8px;
1146 column-gap: 12px;
1147}
1148.info-list dt {
1149 color: var(--muted);
1150}
1151.info-list dd {
1152 margin: 0;
1153 word-break: break-word;
1154}
1155
1156/* ---------------------------------------------------------------------------
1157 Shares (milestone 6)
1158 --------------------------------------------------------------------------- */
1159
1160.share-modal {
1161 width: 480px;
1162}
1163
1164.share-link-row {
1165 display: flex;
1166 gap: 8px;
1167 margin: 12px 0;
1168}
1169
1170.share-link-input {
1171 flex: 1;
1172 font-family: ui-monospace, monospace;
1173 font-size: 12.5px;
1174 padding: 8px 10px;
1175 border: 1px solid var(--border);
1176 background: var(--bg);
1177 color: var(--text);
1178 min-width: 0;
1179}
1180
1181.share-check {
1182 display: flex;
1183 align-items: center;
1184 gap: 8px;
1185 margin: 4px 0 14px;
1186 font-size: 14px;
1187}
1188
1189.share-check input {
1190 width: 16px;
1191 height: 16px;
1192}
1193
1194.share-expiry-row {
1195 display: flex;
1196 align-items: center;
1197 gap: 10px;
1198 margin: 0 0 10px;
1199}
1200
1201.share-expiry-row label {
1202 font-size: 13px;
1203 color: var(--muted);
1204 min-width: 52px;
1205}
1206
1207.share-expiry-row select,
1208.share-expiry-row input {
1209 flex: 1;
1210 padding: 8px 10px;
1211 border: 1px solid var(--border);
1212 background: var(--panel);
1213 color: var(--text);
1214 font: inherit;
1215}
1216
1217.share-expiry-note {
1218 margin: 4px 0 0;
1219 font-size: 12.5px;
1220}
1221
1222.btn-sm {
1223 padding: 5px 10px;
1224 font-size: 12.5px;
1225}
1226
1227.icon-btn-sm {
1228 padding: 4px 6px;
1229}
1230
1231/* "Your shares" manage view */
1232
1233.shares-view {
1234 width: 100%;
1235 max-width: 960px;
1236 margin: 0 auto;
1237}
1238
1239.view-header {
1240 margin-bottom: 16px;
1241}
1242
1243.view-header .admin-section-title {
1244 margin-bottom: 0;
1245}
1246
1247.view-hint {
1248 margin: 4px 0 0;
1249 font-size: 13px;
1250 max-width: 64ch;
1251}
1252
1253.share-list {
1254 display: flex;
1255 flex-direction: column;
1256 gap: 10px;
1257}
1258
1259.share-item {
1260 display: flex;
1261 align-items: center;
1262 justify-content: space-between;
1263 gap: 12px;
1264 padding: 10px 12px;
1265 border: 1px solid var(--border);
1266 background: var(--panel);
1267}
1268
1269.share-item-main {
1270 min-width: 0;
1271}
1272
1273.share-item-name {
1274 display: flex;
1275 align-items: center;
1276 gap: 8px;
1277 font-weight: 600;
1278 font-size: 14px;
1279 overflow: hidden;
1280 text-overflow: ellipsis;
1281 white-space: nowrap;
1282}
1283
1284.ic-row {
1285 width: 18px;
1286 height: 18px;
1287 flex: none;
1288}
1289
1290.share-item-meta {
1291 font-size: 12px;
1292 margin-top: 2px;
1293 overflow: hidden;
1294 text-overflow: ellipsis;
1295 white-space: nowrap;
1296}
1297
1298.share-item-actions {
1299 display: flex;
1300 gap: 6px;
1301 flex-shrink: 0;
1302}
1303
1304/* ------------------------------------------------------------------ */
1305/* Admin (milestone 7) */
1306/* ------------------------------------------------------------------ */
1307
1308.admin-view {
1309 display: flex;
1310 flex-direction: column;
1311 gap: 16px;
1312 width: 100%;
1313 max-width: 960px;
1314 margin: 0 auto;
1315}
1316
1317.admin-section-title {
1318 margin: 0 0 14px;
1319 font-size: 15px;
1320}
1321
1322.users-header {
1323 display: flex;
1324 align-items: center;
1325 justify-content: space-between;
1326 margin-bottom: 4px;
1327}
1328
1329.users-header .admin-section-title {
1330 margin-bottom: 0;
1331}
1332
1333.users-header .btn-primary {
1334 width: auto;
1335}
1336
1337.user-list {
1338 display: flex;
1339 flex-direction: column;
1340 gap: 10px;
1341}
1342
1343.user-row {
1344 display: flex;
1345 align-items: center;
1346 justify-content: space-between;
1347 gap: 12px;
1348 padding: 12px 14px;
1349 border: 1px solid var(--border);
1350}
1351
1352.user-row-main {
1353 min-width: 0;
1354}
1355
1356.user-row-name {
1357 display: flex;
1358 align-items: center;
1359 gap: 6px;
1360 font-weight: 600;
1361 font-size: 14px;
1362 flex-wrap: wrap;
1363}
1364
1365.ic-admin {
1366 width: 16px;
1367 height: 16px;
1368 flex: none;
1369}
1370
1371.user-row-actions {
1372 display: flex;
1373 gap: 6px;
1374 flex-shrink: 0;
1375}
1376
1377.badge-off {
1378 background: color-mix(in srgb, var(--danger) 15%, var(--panel));
1379 border-color: var(--danger);
1380 color: var(--danger);
1381}
1382
1383.setting-row {
1384 display: flex;
1385 align-items: flex-start;
1386 gap: 10px;
1387 padding: 14px;
1388 border: 1px solid var(--border);
1389 cursor: pointer;
1390}
1391
1392.setting-row input {
1393 width: auto;
1394 margin-top: 2px;
1395}
1396
1397.setting-label {
1398 display: block;
1399 font-weight: 600;
1400 font-size: 14px;
1401}
1402
1403.setting-desc {
1404 display: block;
1405 font-size: 12px;
1406 color: var(--muted);
1407 margin-top: 2px;
1408}
1409
1410/* User create/edit form */
1411
1412.user-form {
1413 width: 520px;
1414}
1415
1416.field-input {
1417 width: 100%;
1418 box-sizing: border-box;
1419}
1420
1421.field-hint {
1422 font-size: 12px;
1423 margin: -2px 0 8px;
1424}
1425
1426.check-row {
1427 display: flex;
1428 align-items: center;
1429 gap: 8px;
1430 font-size: 14px;
1431 margin-bottom: 12px;
1432 cursor: pointer;
1433}
1434
1435.check-row input {
1436 width: auto;
1437}
1438
1439.form-error {
1440 color: var(--danger);
1441 font-size: 13px;
1442 margin: 4px 0 8px;
1443}
1444
1445.roots-editor {
1446 display: flex;
1447 flex-direction: column;
1448 gap: 6px;
1449}
1450
1451.root-draft {
1452 display: flex;
1453 align-items: center;
1454 gap: 8px;
1455}
1456
1457.root-draft-path {
1458 flex: 1;
1459 font-size: 13px;
1460 overflow: hidden;
1461 text-overflow: ellipsis;
1462 white-space: nowrap;
1463}
1464
1465.root-draft-mode {
1466 width: auto;
1467 padding: 6px 8px;
1468}
1469
1470.root-add {
1471 display: flex;
1472 gap: 8px;
1473 margin-top: 4px;
1474}
1475
1476/* ------------------------------------------------------------------ */
1477/* Empty state + keyboard focus (milestone 8) */
1478/* ------------------------------------------------------------------ */
1479
1480.empty-state {
1481 display: flex;
1482 flex-direction: column;
1483 align-items: center;
1484 justify-content: center;
1485 gap: 8px;
1486 padding: 64px 20px;
1487 text-align: center;
1488}
1489
1490.empty-glyph {
1491 width: 52px;
1492 height: 52px;
1493}
1494
1495.empty-state h3 {
1496 margin: 0;
1497 font-size: 16px;
1498}
1499
1500/* Visible keyboard focus on selectable file/folder entries. */
1501.tile:focus-visible,
1502.row:focus-visible {
1503 outline: 2px solid var(--accent);
1504 outline-offset: 2px;
1505}
1506