app.css
⎇
Raw
1:root {
2 --bg: #f6f7f9;
3 --panel: #ffffff;
4 --text: #1a1d21;
5 --muted: #6b7280;
6 --accent: #3b82f6;
7 --accent-hover: #2563eb;
8 --danger: #ef4444;
9 --border: #e5e7eb;
10 --radius: 12px;
11}
12
13@media (prefers-color-scheme: dark) {
14 :root {
15 --bg: #0f1115;
16 --panel: #171a20;
17 --text: #e5e7eb;
18 --muted: #9ca3af;
19 --accent: #60a5fa;
20 --accent-hover: #3b82f6;
21 --danger: #f87171;
22 --border: #2a2f3a;
23 }
24}
25
26* {
27 box-sizing: border-box;
28}
29
30body {
31 margin: 0;
32 font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
33 background: var(--bg);
34 color: var(--text);
35 font-size: 15px;
36}
37
38.muted {
39 color: var(--muted);
40}
41
42.card {
43 background: var(--panel);
44 border: 1px solid var(--border);
45 border-radius: var(--radius);
46 padding: 24px;
47}
48
49.center-screen {
50 min-height: 100vh;
51 display: flex;
52 align-items: center;
53 justify-content: center;
54 padding: 16px;
55}
56
57.auth-card {
58 width: 100%;
59 max-width: 380px;
60}
61
62.auth-card h1 {
63 margin: 0 0 8px;
64 font-size: 22px;
65}
66
67.auth-card p {
68 margin: 0 0 20px;
69 font-size: 13px;
70}
71
72.field {
73 display: block;
74 margin-bottom: 14px;
75}
76
77.field span {
78 display: block;
79 font-size: 13px;
80 color: var(--muted);
81 margin-bottom: 4px;
82}
83
84input {
85 width: 100%;
86 padding: 10px 12px;
87 border-radius: 8px;
88 border: 1px solid var(--border);
89 background: var(--bg);
90 color: var(--text);
91 font-size: 14px;
92}
93
94input:focus {
95 outline: 2px solid var(--accent);
96 outline-offset: -1px;
97}
98
99button {
100 font: inherit;
101 cursor: pointer;
102 border-radius: 8px;
103 border: 1px solid var(--border);
104 background: var(--panel);
105 color: var(--text);
106 padding: 9px 14px;
107}
108
109button:hover {
110 border-color: var(--muted);
111}
112
113button:disabled {
114 opacity: 0.6;
115 cursor: default;
116}
117
118.btn-primary {
119 width: 100%;
120 background: var(--accent);
121 border-color: var(--accent);
122 color: #fff;
123 font-weight: 600;
124}
125
126.btn-primary:hover {
127 background: var(--accent-hover);
128 border-color: var(--accent-hover);
129}
130
131.error {
132 color: var(--danger);
133 font-size: 13px;
134 min-height: 18px;
135 margin: 0 0 10px;
136}
137
138/* layout (signed-in) */
139
140.layout {
141 min-height: 100vh;
142 display: flex;
143 flex-direction: column;
144}
145
146.topbar {
147 display: flex;
148 align-items: center;
149 justify-content: space-between;
150 padding: 10px 20px;
151 background: var(--panel);
152 border-bottom: 1px solid var(--border);
153}
154
155.brand {
156 font-weight: 700;
157}
158
159.topbar-right {
160 display: flex;
161 align-items: center;
162 gap: 12px;
163}
164
165.user-badge {
166 font-size: 14px;
167 display: flex;
168 align-items: center;
169 gap: 8px;
170}
171
172.badge {
173 font-size: 11px;
174 padding: 2px 8px;
175 border-radius: 999px;
176 background: var(--bg);
177 border: 1px solid var(--border);
178 color: var(--muted);
179}
180
181.content {
182 flex: 1;
183 display: flex;
184 flex-direction: column;
185 padding: 20px;
186}
187
188/* ---- file browser ---- */
189
190.browser {
191 width: 100%;
192 max-width: 1200px;
193 margin: 0 auto;
194 flex: 1;
195 display: flex;
196 flex-direction: column;
197 min-height: 0;
198}
199
200.icon {
201 width: 20px;
202 height: 20px;
203 display: inline-block;
204 vertical-align: middle;
205}
206
207.ic-folder {
208 color: var(--accent);
209}
210
211.ic-muted {
212 color: var(--muted);
213}
214
215.crumbs {
216 display: flex;
217 align-items: center;
218 gap: 2px;
219 padding: 6px 0 12px;
220 font-size: 15px;
221 flex-wrap: wrap;
222}
223
224.crumb {
225 cursor: pointer;
226 color: var(--muted);
227 padding: 3px 6px;
228 border-radius: 6px;
229}
230
231.crumb:hover {
232 color: var(--text);
233 background: var(--panel);
234}
235
236.crumb.current {
237 color: var(--text);
238 font-weight: 600;
239 cursor: default;
240 background: none;
241}
242
243.crumb-sep {
244 color: var(--muted);
245 padding: 0 1px;
246}
247
248.toolbar {
249 display: flex;
250 justify-content: flex-end;
251 gap: 6px;
252 padding-bottom: 12px;
253}
254
255.icon-btn {
256 padding: 7px 9px;
257 border-radius: 8px;
258 border: 1px solid var(--border);
259 background: var(--panel);
260 color: var(--muted);
261 display: inline-flex;
262 align-items: center;
263}
264
265.icon-btn:hover {
266 border-color: var(--muted);
267}
268
269.icon-btn.active {
270 background: var(--accent);
271 border-color: var(--accent);
272 color: #fff;
273}
274
275.ic-btn {
276 width: 18px;
277 height: 18px;
278 color: inherit;
279}
280
281.entries-area {
282 flex: 1;
283 min-height: 240px;
284}
285
286.center-note {
287 text-align: center;
288 padding: 48px 0;
289}
290
291.error-card {
292 display: flex;
293 align-items: center;
294 justify-content: space-between;
295 gap: 16px;
296 color: var(--danger);
297 font-size: 14px;
298}
299
300/* root picker */
301
302.root-picker {
303 display: grid;
304 grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
305 gap: 14px;
306}
307
308.root-tile {
309 background: var(--panel);
310 border: 1px solid var(--border);
311 border-radius: var(--radius);
312 padding: 20px;
313 cursor: pointer;
314 display: flex;
315 flex-direction: column;
316 align-items: flex-start;
317 gap: 6px;
318}
319
320.root-tile:hover {
321 border-color: var(--muted);
322}
323
324.icon-big {
325 width: 44px;
326 height: 44px;
327}
328
329.root-tile-name {
330 font-weight: 600;
331 font-size: 15px;
332}
333
334.root-tile-path {
335 font-size: 13px;
336 flex: 1;
337}
338
339/* grid view */
340
341.entries-grid {
342 display: grid;
343 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
344 gap: 10px;
345}
346
347.tile {
348 background: var(--panel);
349 border: 1px solid var(--border);
350 border-radius: 10px;
351 padding: 16px 10px 12px;
352 text-align: center;
353 cursor: pointer;
354}
355
356.tile:hover {
357 border-color: var(--muted);
358}
359
360.tile-icon {
361 width: 42px;
362 height: 42px;
363 margin: 0 auto 10px;
364 display: block;
365}
366
367.tile-name {
368 font-size: 13px;
369 line-height: 1.3;
370 word-break: break-word;
371}
372
373/* list view */
374
375.entries-list {
376 background: var(--panel);
377 border: 1px solid var(--border);
378 border-radius: 10px;
379 overflow: hidden;
380}
381
382.row {
383 display: grid;
384 grid-template-columns: 28px minmax(0, 1fr) 90px 150px;
385 gap: 12px;
386 align-items: center;
387 padding: 9px 14px;
388 border-bottom: 1px solid var(--border);
389 cursor: pointer;
390 font-size: 14px;
391}
392
393.row:last-child {
394 border-bottom: none;
395}
396
397.row:hover {
398 background: var(--bg);
399}
400
401.row-icon {
402 width: 20px;
403 height: 20px;
404}
405
406.row-name {
407 overflow: hidden;
408 text-overflow: ellipsis;
409 white-space: nowrap;
410}
411
412.row-size,
413.row-date {
414 font-size: 13px;
415 text-align: right;
416}
417
418@media (max-width: 640px) {
419 .row {
420 grid-template-columns: 28px minmax(0, 1fr) 90px;
421 }
422
423 .row-date {
424 display: none;
425 }
426}
427
428/* context menu */
429
430.ctx-menu {
431 position: fixed;
432 z-index: 100;
433 min-width: 190px;
434 background: var(--panel);
435 border: 1px solid var(--border);
436 border-radius: 10px;
437 padding: 5px;
438 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
439}
440
441.ctx-item {
442 padding: 8px 12px;
443 border-radius: 7px;
444 font-size: 14px;
445 cursor: pointer;
446}
447
448.ctx-item:hover {
449 background: var(--bg);
450}
451
452.ctx-item.disabled {
453 opacity: 0.45;
454 cursor: default;
455}
456
457.ctx-item.disabled:hover {
458 background: none;
459}
460
461/* toast */
462
463.toast {
464 position: fixed;
465 bottom: 20px;
466 right: 20px;
467 z-index: 200;
468 background: var(--panel);
469 color: var(--text);
470 border: 1px solid var(--border);
471 border-radius: 10px;
472 padding: 11px 16px;
473 font-size: 14px;
474 box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
475 max-width: 320px;
476}
477
478
479/* ---- modals ---- */
480
481.modal-overlay {
482 position: fixed;
483 inset: 0;
484 background: rgb(0 0 0 / 45%);
485 display: flex;
486 align-items: center;
487 justify-content: center;
488 z-index: 100;
489}
490
491.modal {
492 width: 440px;
493 max-width: calc(100vw - 32px);
494 padding: 20px;
495 background: var(--panel);
496 border: 1px solid var(--border);
497 border-radius: var(--radius);
498 box-shadow: 0 12px 44px rgb(0 0 0 / 35%);
499}
500
501.modal.picker {
502 width: 520px;
503}
504
505.modal-title {
506 margin: 0 0 12px;
507 font-size: 16px;
508}
509
510.modal-label {
511 display: block;
512 font-size: 13px;
513 color: var(--muted);
514 margin-bottom: 6px;
515}
516
517.modal .input {
518 width: 100%;
519 box-sizing: border-box;
520 margin-bottom: 16px;
521}
522
523.modal-message {
524 white-space: pre-line;
525 font-size: 14px;
526 margin: 0 0 8px;
527}
528
529.modal-actions {
530 display: flex;
531 justify-content: flex-end;
532 gap: 8px;
533 margin-top: 16px;
534}
535
536.btn-danger {
537 background: var(--danger);
538 border-color: var(--danger);
539 color: #fff;
540}
541
542.btn-danger:hover {
543 background: color-mix(in srgb, var(--danger) 85%, black);
544}
545
546.btn:disabled {
547 opacity: 0.5;
548 cursor: not-allowed;
549}
550
551.conflict-list {
552 max-height: 200px;
553 overflow-y: auto;
554 margin: 8px 0;
555 padding-left: 20px;
556 font-size: 13px;
557}
558
559.picker-roots {
560 display: flex;
561 gap: 6px;
562 flex-wrap: wrap;
563 margin-bottom: 12px;
564}
565
566.root-opt {
567 font-size: 13px;
568}
569
570.root-opt.active {
571 background: var(--accent);
572 border-color: var(--accent);
573 color: #fff;
574}
575
576.picker-current {
577 font-size: 13px;
578 margin: 0 0 8px;
579}
580
581.picker-crumbs {
582 margin-bottom: 8px;
583}
584
585.picker-entries {
586 max-height: 240px;
587 overflow-y: auto;
588 border: 1px solid var(--border);
589 border-radius: 8px;
590}
591
592.picker-row {
593 display: flex;
594 align-items: center;
595 gap: 10px;
596 padding: 8px 12px;
597 cursor: pointer;
598}
599
600.picker-row:hover {
601 background: var(--bg);
602}
603
604/* ---------------------------------------------------------------------------
605 * Preview modal (image / PDF / video / audio / text)
606 * ------------------------------------------------------------------------- */
607.preview-modal {
608 width: min(960px, calc(100vw - 48px));
609 height: min(720px, calc(100vh - 48px));
610 display: flex;
611 flex-direction: column;
612 padding: 0;
613 overflow: hidden;
614}
615.preview-head {
616 display: flex;
617 align-items: center;
618 justify-content: space-between;
619 gap: 12px;
620 padding: 10px 14px;
621 border-bottom: 1px solid var(--border);
622}
623.preview-title {
624 font-weight: 600;
625 font-size: 14px;
626 white-space: nowrap;
627 overflow: hidden;
628 text-overflow: ellipsis;
629}
630.preview-close {
631 flex: none;
632 border: none;
633 background: transparent;
634 color: var(--muted);
635 font-size: 24px;
636 line-height: 1;
637 cursor: pointer;
638 padding: 0 8px;
639 border-radius: 8px;
640}
641.preview-close:hover {
642 background: var(--bg);
643 color: var(--text);
644}
645.preview-body {
646 flex: 1;
647 min-height: 0;
648 overflow: auto;
649 display: flex;
650 background: var(--bg);
651}
652.preview-img {
653 max-width: 100%;
654 max-height: 100%;
655 display: block;
656 margin: auto;
657}
658.preview-pdf {
659 width: 100%;
660 height: 100%;
661 border: none;
662 background: #fff;
663}
664.preview-video {
665 width: 100%;
666 max-height: 100%;
667 background: #000;
668}
669.preview-audio {
670 display: flex;
671 align-items: center;
672 justify-content: center;
673 width: 100%;
674 padding: 24px;
675}
676.preview-audio audio {
677 width: 100%;
678 max-width: 480px;
679}
680
681/* CodeMirror text preview */
682.cm-wrap {
683 position: relative;
684 width: 100%;
685 height: 100%;
686}
687.cm-container {
688 height: 100%;
689}
690.cm-container .cm-editor {
691 height: 100%;
692}
693.cm-error {
694 position: absolute;
695 inset: 0;
696 display: flex;
697 align-items: center;
698 justify-content: center;
699 padding: 24px;
700 text-align: center;
701}
702
703/* ---------------------------------------------------------------------------
704 * Text editor (milestone 5)
705 * ------------------------------------------------------------------------- */
706.editor-modal {
707 width: min(960px, calc(100vw - 48px));
708 height: min(720px, calc(100vh - 48px));
709 display: flex;
710 flex-direction: column;
711 padding: 0;
712 overflow: hidden;
713}
714.editor-head {
715 display: flex;
716 align-items: center;
717 justify-content: space-between;
718 gap: 12px;
719 padding: 10px 14px;
720 border-bottom: 1px solid var(--border);
721}
722.editor-title {
723 font-weight: 600;
724 font-size: 14px;
725 white-space: nowrap;
726 overflow: hidden;
727 text-overflow: ellipsis;
728}
729.editor-actions {
730 display: flex;
731 align-items: center;
732 gap: 10px;
733 flex: none;
734}
735.editor-body {
736 flex: 1;
737 min-height: 0;
738 display: flex;
739 position: relative;
740 background: var(--bg);
741}
742.editor-body .cm-container {
743 width: 100%;
744 height: 100%;
745}
746/* Conflict / discard dialogs render above the editor overlay. */
747.editor-sub-overlay {
748 z-index: 101;
749 background: rgb(0 0 0 / 25%);
750}
751
752/* ---------------------------------------------------------------------------
753 * Download format dialog
754 * ------------------------------------------------------------------------- */
755.dl-formats {
756 display: flex;
757 flex-direction: column;
758 gap: 8px;
759 margin-bottom: 8px;
760}
761.dl-fmt {
762 text-align: left;
763}
764
765/* ---------------------------------------------------------------------------
766 * Item info dialog
767 * ------------------------------------------------------------------------- */
768.info-list {
769 margin: 8px 0 16px;
770 display: grid;
771 grid-template-columns: 90px 1fr;
772 row-gap: 8px;
773 column-gap: 12px;
774}
775.info-list dt {
776 color: var(--muted);
777}
778.info-list dd {
779 margin: 0;
780 word-break: break-word;
781}
782
783/* ---------------------------------------------------------------------------
784 Shares (milestone 6)
785 --------------------------------------------------------------------------- */
786
787.share-modal {
788 width: 480px;
789}
790
791.share-link-row {
792 display: flex;
793 gap: 8px;
794 margin: 12px 0;
795}
796
797.share-link-input {
798 flex: 1;
799 font-family: ui-monospace, monospace;
800 font-size: 12.5px;
801 padding: 8px 10px;
802 border: 1px solid var(--border);
803 border-radius: 8px;
804 background: var(--bg);
805 color: var(--text);
806 min-width: 0;
807}
808
809.share-check {
810 display: flex;
811 align-items: center;
812 gap: 8px;
813 margin: 4px 0 14px;
814 font-size: 14px;
815}
816
817.share-check input {
818 width: 16px;
819 height: 16px;
820}
821
822.share-expiry-row {
823 display: flex;
824 align-items: center;
825 gap: 10px;
826 margin: 0 0 10px;
827}
828
829.share-expiry-row label {
830 font-size: 13px;
831 color: var(--muted);
832 min-width: 52px;
833}
834
835.share-expiry-row select,
836.share-expiry-row input {
837 flex: 1;
838 padding: 8px 10px;
839 border: 1px solid var(--border);
840 border-radius: 8px;
841 background: var(--panel);
842 color: var(--text);
843 font: inherit;
844}
845
846.share-expiry-note {
847 margin: 4px 0 0;
848 font-size: 12.5px;
849}
850
851.btn-sm {
852 padding: 5px 10px;
853 font-size: 12.5px;
854}
855
856/* "Your shares" panel */
857
858.shares-panel {
859 width: 560px;
860}
861
862.share-list {
863 display: flex;
864 flex-direction: column;
865 gap: 10px;
866 max-height: 60vh;
867 overflow-y: auto;
868 margin-bottom: 4px;
869}
870
871.share-item {
872 display: flex;
873 align-items: center;
874 justify-content: space-between;
875 gap: 12px;
876 padding: 10px 12px;
877 border: 1px solid var(--border);
878 border-radius: 10px;
879}
880
881.share-item-main {
882 min-width: 0;
883}
884
885.share-item-name {
886 font-weight: 600;
887 font-size: 14px;
888 overflow: hidden;
889 text-overflow: ellipsis;
890 white-space: nowrap;
891}
892
893.share-item-meta {
894 font-size: 12px;
895 margin-top: 2px;
896 overflow: hidden;
897 text-overflow: ellipsis;
898 white-space: nowrap;
899}
900
901.share-item-actions {
902 display: flex;
903 gap: 6px;
904 flex-shrink: 0;
905}
906
907/* Public share page */
908
909.share-badge {
910 font-size: 13px;
911 color: var(--muted);
912 background: var(--panel);
913 border: 1px solid var(--border);
914 padding: 4px 10px;
915 border-radius: 999px;
916}
917
918.share-footer {
919 padding: 16px;
920 text-align: center;
921 font-size: 12px;
922 border-top: 1px solid var(--border);
923 margin-top: auto;
924}
925
926.share-file-page {
927 display: flex;
928 flex-direction: column;
929 align-items: center;
930 gap: 12px;
931 padding: 80px 20px;
932 text-align: center;
933}
934
935.share-file-icon {
936 font-size: 64px;
937}
938
939.share-file-page h2 {
940 margin: 0;
941 word-break: break-word;
942}
943
944.share-file-actions .btn-primary {
945 width: auto;
946 min-width: 140px;
947}
948