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}
496
497.modal.picker {
498 width: 520px;
499}
500
501.modal-title {
502 margin: 0 0 12px;
503 font-size: 16px;
504}
505
506.modal-label {
507 display: block;
508 font-size: 13px;
509 color: var(--muted);
510 margin-bottom: 6px;
511}
512
513.modal .input {
514 width: 100%;
515 box-sizing: border-box;
516 margin-bottom: 16px;
517}
518
519.modal-message {
520 white-space: pre-line;
521 font-size: 14px;
522 margin: 0 0 8px;
523}
524
525.modal-actions {
526 display: flex;
527 justify-content: flex-end;
528 gap: 8px;
529 margin-top: 16px;
530}
531
532.btn-danger {
533 background: var(--danger);
534 border-color: var(--danger);
535 color: #fff;
536}
537
538.btn-danger:hover {
539 background: color-mix(in srgb, var(--danger) 85%, black);
540}
541
542.btn:disabled {
543 opacity: 0.5;
544 cursor: not-allowed;
545}
546
547.conflict-list {
548 max-height: 200px;
549 overflow-y: auto;
550 margin: 8px 0;
551 padding-left: 20px;
552 font-size: 13px;
553}
554
555.picker-roots {
556 display: flex;
557 gap: 6px;
558 flex-wrap: wrap;
559 margin-bottom: 12px;
560}
561
562.root-opt {
563 font-size: 13px;
564}
565
566.root-opt.active {
567 background: var(--accent);
568 border-color: var(--accent);
569 color: #fff;
570}
571
572.picker-current {
573 font-size: 13px;
574 margin: 0 0 8px;
575}
576
577.picker-crumbs {
578 margin-bottom: 8px;
579}
580
581.picker-entries {
582 max-height: 240px;
583 overflow-y: auto;
584 border: 1px solid var(--border);
585 border-radius: 8px;
586}
587
588.picker-row {
589 display: flex;
590 align-items: center;
591 gap: 10px;
592 padding: 8px 12px;
593 cursor: pointer;
594}
595
596.picker-row:hover {
597 background: var(--bg);
598}
599
600/* ---------------------------------------------------------------------------
601 * Preview modal (image / PDF / video / audio / text)
602 * ------------------------------------------------------------------------- */
603.preview-modal {
604 width: min(960px, calc(100vw - 48px));
605 height: min(720px, calc(100vh - 48px));
606 display: flex;
607 flex-direction: column;
608 padding: 0;
609 overflow: hidden;
610}
611.preview-head {
612 display: flex;
613 align-items: center;
614 justify-content: space-between;
615 gap: 12px;
616 padding: 10px 14px;
617 border-bottom: 1px solid var(--border);
618}
619.preview-title {
620 font-weight: 600;
621 font-size: 14px;
622 white-space: nowrap;
623 overflow: hidden;
624 text-overflow: ellipsis;
625}
626.preview-close {
627 flex: none;
628 border: none;
629 background: transparent;
630 color: var(--muted);
631 font-size: 24px;
632 line-height: 1;
633 cursor: pointer;
634 padding: 0 8px;
635 border-radius: 8px;
636}
637.preview-close:hover {
638 background: var(--bg);
639 color: var(--text);
640}
641.preview-body {
642 flex: 1;
643 min-height: 0;
644 overflow: auto;
645 display: flex;
646 background: var(--bg);
647}
648.preview-img {
649 max-width: 100%;
650 max-height: 100%;
651 display: block;
652 margin: auto;
653}
654.preview-pdf {
655 width: 100%;
656 height: 100%;
657 border: none;
658 background: #fff;
659}
660.preview-video {
661 width: 100%;
662 max-height: 100%;
663 background: #000;
664}
665.preview-audio {
666 display: flex;
667 align-items: center;
668 justify-content: center;
669 width: 100%;
670 padding: 24px;
671}
672.preview-audio audio {
673 width: 100%;
674 max-width: 480px;
675}
676
677/* CodeMirror text preview */
678.cm-wrap {
679 position: relative;
680 width: 100%;
681 height: 100%;
682}
683.cm-container {
684 height: 100%;
685}
686.cm-container .cm-editor {
687 height: 100%;
688}
689.cm-error {
690 position: absolute;
691 inset: 0;
692 display: flex;
693 align-items: center;
694 justify-content: center;
695 padding: 24px;
696 text-align: center;
697}
698
699/* ---------------------------------------------------------------------------
700 * Download format dialog
701 * ------------------------------------------------------------------------- */
702.dl-formats {
703 display: flex;
704 flex-direction: column;
705 gap: 8px;
706 margin-bottom: 8px;
707}
708.dl-fmt {
709 text-align: left;
710}
711
712/* ---------------------------------------------------------------------------
713 * Item info dialog
714 * ------------------------------------------------------------------------- */
715.info-list {
716 margin: 8px 0 16px;
717 display: grid;
718 grid-template-columns: 90px 1fr;
719 row-gap: 8px;
720 column-gap: 12px;
721}
722.info-list dt {
723 color: var(--muted);
724}
725.info-list dd {
726 margin: 0;
727 word-break: break-word;
728}
729