style.css
⎇
Raw
1/* Custom layout and components on top of Pico.css */
2
3/* Scale down Pico's default sizing */
4html {
5 font-size: 16px;
6}
7
8/* Remove Pico's default bottom margin on button types */
9[type="button"],
10[type="reset"],
11[type="submit"] {
12 margin-bottom: 0;
13}
14
15/* Layout */
16body {
17 min-height: 100vh;
18 display: flex;
19 flex-direction: column;
20}
21
22header {
23 padding: 1rem 2rem;
24 position: sticky;
25 top: 0;
26 z-index: 100;
27 background-color: var(--pico-card-background-color);
28 border-bottom: 1px solid var(--pico-muted-border-color);
29 display: flex;
30 align-items: center;
31 gap: 2rem;
32}
33
34header h1 {
35 margin: 0;
36 flex-shrink: 0;
37 font-size: 1.5rem;
38}
39
40nav {
41 display: flex;
42 gap: 1rem;
43}
44
45nav a {
46 color: var(--pico-muted-color);
47 text-decoration: none;
48 padding: 0.5rem 1rem;
49 border-radius: var(--pico-border-radius);
50 transition: all 0.2s;
51}
52
53nav a:hover {
54 color: var(--pico-primary);
55 background-color: var(--pico-card-sectioning-background-color);
56}
57
58nav a.active {
59 background-color: var(--pico-primary);
60 color: var(--pico-primary-inverse);
61 font-weight: 600;
62}
63
64main {
65 flex: 1;
66 padding: 2rem 1rem;
67}
68
69main > * {
70 max-width: 1400px;
71 margin-left: auto;
72 margin-right: auto;
73}
74
75footer {
76 padding: 1rem 2rem;
77 text-align: center;
78 color: var(--pico-muted-color);
79 font-size: 0.9rem;
80 background-color: var(--pico-card-background-color);
81 border-top: 1px solid var(--pico-muted-border-color);
82}
83
84/* Page headers */
85.page-header {
86 display: flex;
87 justify-content: space-between;
88 align-items: center;
89 margin-bottom: 1.5rem;
90 flex-wrap: wrap;
91 gap: 1rem;
92}
93
94.page-header h2 {
95 font-size: 1.5rem;
96 margin: 0;
97}
98
99.actions {
100 display: flex;
101 gap: 1rem;
102 align-items: center;
103 flex-wrap: wrap;
104}
105
106/* Forms */
107.form-group {
108 margin-bottom: 1rem;
109}
110
111.form-row {
112 display: grid;
113 grid-template-columns: 1fr 1fr;
114 gap: 1rem;
115}
116
117.radio-group {
118 display: flex;
119 flex-wrap: wrap;
120 gap: 1rem;
121}
122
123.radio-group label {
124 display: flex;
125 align-items: center;
126 gap: 0.3rem;
127 cursor: pointer;
128 font-weight: normal;
129 margin-bottom: 0;
130}
131
132.form-actions {
133 display: flex;
134 gap: 1rem;
135 margin-top: 1.5rem;
136}
137
138/* Buttons */
139button.small,
140[role="button"].small {
141 padding: 0.3rem 0.6rem;
142 font-size: 0.85rem;
143}
144
145button.danger,
146button.danger:hover,
147button.danger:focus,
148[role="button"].danger,
149[role="button"].danger:hover,
150[role="button"].danger:focus {
151 --pico-background-color: #c62828;
152 --pico-border-color: #c62828;
153 --pico-color: white;
154}
155
156button.danger:hover,
157button.danger:focus,
158[role="button"].danger:hover,
159[role="button"].danger:focus {
160 --pico-background-color: #b71c1c;
161 --pico-border-color: #b71c1c;
162}
163
164button:disabled {
165 opacity: 0.5;
166 cursor: not-allowed;
167}
168
169/* Library */
170.breadcrumbs {
171 margin-bottom: 1rem;
172}
173
174.library-grid {
175 display: grid;
176 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
177 gap: 1rem;
178}
179
180.folder-item,
181.media-item {
182 background: var(--pico-card-background-color);
183 border: 1px solid var(--pico-card-border-color);
184 border-radius: var(--pico-border-radius);
185 overflow: hidden;
186 text-decoration: none;
187 color: var(--pico-color);
188 transition: transform 0.2s, box-shadow 0.2s;
189 box-shadow: var(--pico-card-box-shadow);
190}
191
192.folder-item:hover,
193.media-item:hover {
194 transform: translateY(-2px);
195 box-shadow: var(--pico-card-box-shadow), 0 4px 12px rgba(0, 0, 0, 0.15);
196}
197
198.folder-icon,
199.media-thumbnail {
200 aspect-ratio: 16/9;
201 background: var(--pico-card-sectioning-background-color);
202 display: flex;
203 align-items: center;
204 justify-content: center;
205 font-size: 3rem;
206}
207
208.media-thumbnail img {
209 width: 100%;
210 height: 100%;
211 object-fit: cover;
212}
213
214.media-thumbnail img[src$=".svg"] {
215 width: 48px;
216 height: 48px;
217 opacity: 0.5;
218 object-fit: contain;
219}
220
221.folder-name,
222.media-info {
223 padding: 0.75rem;
224}
225
226.media-title {
227 font-weight: 500;
228 margin-bottom: 0.3rem;
229 overflow: hidden;
230 text-overflow: ellipsis;
231 white-space: nowrap;
232}
233
234.media-duration,
235.media-path {
236 font-size: 0.85rem;
237}
238
239/* Detail view */
240.detail-view {
241 max-width: 900px;
242}
243
244.detail-header {
245 display: flex;
246 justify-content: space-between;
247 align-items: center;
248 margin-bottom: 1.5rem;
249 flex-wrap: wrap;
250 gap: 1rem;
251}
252
253.player-container {
254 background: #000;
255 border-radius: var(--pico-border-radius);
256 overflow: hidden;
257 margin-bottom: 1.5rem;
258 max-height: 80vh;
259 display: flex;
260 align-items: center;
261 justify-content: center;
262}
263
264.player-container video,
265.player-container audio {
266 max-width: 100%;
267 max-height: 80vh;
268 width: auto;
269 height: auto;
270 display: block;
271}
272
273.detail-meta dl {
274 display: grid;
275 grid-template-columns: 150px 1fr;
276 gap: 0.5rem 1rem;
277}
278
279.detail-meta dd {
280 word-break: break-all;
281 margin: 0;
282}
283
284/* Queue */
285.queue-list {
286 display: flex;
287 flex-direction: column;
288 gap: 1rem;
289}
290
291.queue-item {
292 padding: 1rem;
293 margin-bottom: 0;
294}
295
296.queue-header {
297 display: flex;
298 justify-content: space-between;
299 align-items: flex-start;
300 gap: 1rem;
301 flex-wrap: wrap;
302 margin-bottom: 0.5rem;
303}
304
305.queue-url {
306 flex: 1;
307 min-width: 0;
308}
309
310.queue-url a {
311 word-break: break-all;
312}
313
314.queue-status {
315 display: flex;
316 gap: 0.5rem;
317 align-items: center;
318 flex-wrap: wrap;
319}
320
321.status-badge {
322 padding: 0.2rem 0.6rem;
323 border-radius: 12px;
324 font-size: 0.85rem;
325 font-weight: 500;
326}
327
328.status-badge.queued {
329 background: var(--pico-card-sectioning-background-color);
330 color: var(--pico-muted-color);
331}
332
333.status-badge.downloading {
334 background: var(--pico-primary);
335 color: var(--pico-primary-inverse);
336}
337
338.status-badge.completed {
339 background: var(--pico-ins-color);
340 color: white;
341}
342
343.status-badge.error {
344 background: var(--pico-del-color);
345 color: white;
346}
347
348.error-message {
349 color: var(--pico-del-color);
350 font-size: 0.9rem;
351 margin-top: 0.5rem;
352}
353
354.error-text {
355 color: var(--pico-del-color);
356}
357
358.queue-meta {
359 margin-top: 0.5rem;
360 font-size: 0.85rem;
361 display: flex;
362 gap: 1rem;
363}
364
365/* Logs */
366.logs {
367 max-height: 500px;
368 overflow-y: auto;
369 white-space: pre-wrap;
370 word-break: break-all;
371}
372
373pre {
374 padding: 1.5rem;
375}
376
377/* Settings */
378.settings-layout {
379 display: flex;
380 flex-direction: column;
381 gap: 2rem;
382}
383
384.presets-list {
385 display: flex;
386 flex-direction: column;
387 gap: 1rem;
388 margin-bottom: 1.5rem;
389}
390
391.preset-header {
392 display: flex;
393 justify-content: space-between;
394 align-items: center;
395 margin-bottom: 0.5rem;
396}
397
398.preset-header h4 {
399 display: flex;
400 align-items: center;
401 gap: 0.5rem;
402 margin: 0;
403}
404
405.badge {
406 background: var(--pico-primary);
407 color: var(--pico-primary-inverse);
408 padding: 0.1rem 0.4rem;
409 border-radius: 10px;
410 font-size: 0.75rem;
411}
412
413.preset-actions {
414 display: flex;
415 gap: 0.5rem;
416 flex-wrap: wrap;
417 margin-top: 1rem;
418}
419
420.preset-description {
421 margin-bottom: 0.5rem;
422}
423
424.preset-flags {
425 margin-top: 0.5rem;
426}
427
428.preset-flags pre {
429 overflow-x: auto;
430 margin-top: 0.3rem;
431 margin-bottom: 0;
432}
433
434/* Nested articles need visible borders */
435.presets-list article {
436 border: 1px solid var(--pico-muted-border-color);
437}
438
439/* Suppress Pico details marker for button-like summaries */
440details:has(summary[role="button"]) summary::after {
441 display: none !important;
442}
443
444details summary[role="button"] {
445 display: inline-flex;
446 width: auto;
447}
448
449/* Toggle text: Edit vs Cancel */
450details .cancel-text {
451 display: none;
452}
453
454details[open] .edit-text {
455 display: none;
456}
457
458details[open] .cancel-text {
459 display: inline;
460}
461
462/* Delete overlay popover */
463.delete-overlay {
464 position: relative;
465}
466
467.delete-overlay summary {
468 list-style: none;
469 cursor: pointer;
470}
471
472.delete-overlay summary::-webkit-details-marker {
473 display: none;
474}
475
476.delete-overlay summary::after {
477 display: none !important;
478}
479
480.delete-overlay .overlay-panel {
481 position: absolute;
482 top: calc(100% + 0.5rem);
483 right: 0;
484 z-index: 1000;
485 width: 260px;
486 background: var(--pico-background-color);
487 border: 1px solid var(--pico-muted-border-color);
488 border-radius: var(--pico-border-radius);
489 padding: 1rem;
490 box-shadow: var(--pico-dropdown-box-shadow);
491}
492
493/* Popover arrow */
494.delete-overlay .overlay-panel::before {
495 content: '';
496 position: absolute;
497 top: -6px;
498 right: 1rem;
499 width: 10px;
500 height: 10px;
501 background: var(--pico-background-color);
502 border-left: 1px solid var(--pico-muted-border-color);
503 border-top: 1px solid var(--pico-muted-border-color);
504 transform: rotate(45deg);
505}
506
507.delete-overlay .overlay-panel p {
508 margin-bottom: 1rem;
509 font-size: 0.9rem;
510}
511
512.delete-overlay .overlay-panel .form-actions {
513 margin-top: 0;
514 justify-content: flex-end;
515}
516
517/* Inline edit form */
518.edit-form {
519 padding: 1rem;
520}
521
522/* Conditional sections (no-JS show/hide) */
523.conditional-section {
524 margin-bottom: 1rem;
525}
526
527.conditional-section .conditional-content {
528 display: none;
529 margin-top: 1rem;
530}
531
532/* Checkbox triggers */
533.conditional-section:has(input[type="checkbox"].conditional-trigger:checked) .conditional-content {
534 display: block;
535}
536
537/* Radio triggers for format mode */
538.conditional-section:has(.radio-group input[value="preset"]:checked) .conditional-content.format-preset,
539.conditional-section:has(.radio-group input[value="custom"]:checked) .conditional-content.format-custom {
540 display: block;
541}
542
543/* Format mode selector - hidden radio inputs with button-like labels */
544.radio-group.format-mode {
545 display: flex;
546 gap: 0.5rem;
547 margin-top: 0.5rem;
548 flex-wrap: wrap;
549}
550
551.radio-group.format-mode input[type="radio"] {
552 position: absolute;
553 opacity: 0;
554 width: 0;
555 height: 0;
556}
557
558.radio-group.format-mode label {
559 padding: 0.4rem 0.8rem;
560 border: 1px solid var(--pico-muted-border-color);
561 border-radius: var(--pico-border-radius);
562 cursor: pointer;
563 background: var(--pico-background-color);
564 transition: all 0.2s;
565 font-weight: normal;
566}
567
568.radio-group.format-mode label:hover {
569 background: var(--pico-card-sectioning-background-color);
570}
571
572.radio-group.format-mode label:has(input:checked) {
573 background: var(--pico-primary);
574 color: var(--pico-primary-inverse);
575 border-color: var(--pico-primary);
576}
577
578/* Theme selector */
579.theme-selector {
580 display: flex;
581 gap: 0.5rem;
582}
583
584.theme-selector button {
585 min-width: 80px;
586}
587
588.theme-selector button.active {
589 background: var(--pico-primary);
590 color: var(--pico-primary-inverse);
591 border-color: var(--pico-primary);
592}
593
594/* Download form */
595.download-form {
596 max-width: 900px;
597}
598
599.download-form form {
600 max-width: 800px;
601}
602
603/* Filter form inline */
604.filter-form {
605 display: flex;
606 gap: 0.5rem;
607 align-items: center;
608}
609
610.filter-form input,
611.filter-form select,
612.filter-form button {
613 margin-bottom: 0;
614 width: auto;
615 display: inline-block;
616 flex-shrink: 0;
617}
618
619.filter-form input[type="text"] {
620 min-width: 200px;
621}
622
623/* Empty state */
624.empty-state {
625 text-align: center;
626 padding: 3rem;
627}
628
629/* Utility */
630.inline {
631 display: inline;
632}
633
634/* Responsive */
635@media (max-width: 768px) {
636 main {
637 padding: 1rem;
638 }
639
640 .page-header {
641 flex-direction: column;
642 align-items: flex-start;
643 }
644
645 .library-grid {
646 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
647 }
648
649 .form-row {
650 grid-template-columns: 1fr;
651 }
652
653 .detail-meta dl {
654 grid-template-columns: 1fr;
655 }
656
657 .queue-header {
658 flex-direction: column;
659 }
660
661 header {
662 flex-direction: column;
663 gap: 1rem;
664 padding: 1rem;
665 }
666
667 nav {
668 width: 100%;
669 justify-content: center;
670 }
671}
672