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
22body > header {
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
34body > header h1 {
35 margin: 0;
36 flex-shrink: 0;
37 font-size: 1.5rem;
38}
39
40/* Brand: logo + wordmark, no longer a link */
41.brand {
42 display: flex;
43 align-items: center;
44 gap: 0.55rem;
45}
46
47.brand-logo {
48 display: block;
49 flex-shrink: 0;
50}
51
52nav {
53 display: flex;
54 gap: 1rem;
55}
56
57nav a {
58 color: var(--pico-muted-color);
59 text-decoration: none;
60 padding: 0.5rem 1rem;
61 border-radius: var(--pico-border-radius);
62 transition: all 0.2s;
63}
64
65nav a:hover {
66 color: var(--pico-primary);
67 background-color: var(--pico-card-sectioning-background-color);
68}
69
70nav a.active {
71 background-color: var(--pico-primary);
72 color: var(--pico-primary-inverse);
73 font-weight: 600;
74}
75
76main {
77 flex: 1;
78 padding: 2rem 1rem;
79}
80
81main > * {
82 max-width: 1400px;
83 margin-left: auto;
84 margin-right: auto;
85}
86
87footer {
88 padding: 1rem 2rem;
89 text-align: center;
90 color: var(--pico-muted-color);
91 font-size: 0.9rem;
92 background-color: var(--pico-card-background-color);
93 border-top: 1px solid var(--pico-muted-border-color);
94}
95
96/* Page headers */
97.page-header {
98 display: flex;
99 justify-content: space-between;
100 align-items: center;
101 margin-bottom: 1.5rem;
102 flex-wrap: wrap;
103 gap: 1rem;
104}
105
106.page-header h2 {
107 font-size: 1.5rem;
108 margin: 0;
109}
110
111.actions {
112 display: flex;
113 gap: 1rem;
114 align-items: center;
115 flex-wrap: wrap;
116}
117
118/* Forms */
119.form-group {
120 margin-bottom: 1rem;
121}
122
123.form-row {
124 display: grid;
125 grid-template-columns: 1fr 1fr;
126 gap: 1rem;
127}
128
129.radio-group {
130 display: flex;
131 flex-wrap: wrap;
132 gap: 1rem;
133}
134
135.radio-group label {
136 display: flex;
137 align-items: center;
138 gap: 0.3rem;
139 cursor: pointer;
140 font-weight: normal;
141 margin-bottom: 0;
142}
143
144.form-actions {
145 display: flex;
146 gap: 1rem;
147 margin-top: 1.5rem;
148}
149
150.file-selector {
151 display: flex;
152 align-items: center;
153 gap: 0.75rem;
154 flex-wrap: wrap;
155 margin-bottom: 1rem;
156}
157
158.file-selector label {
159 margin: 0;
160}
161
162.file-selector select {
163 flex: 1;
164 min-width: 0;
165 margin: 0;
166}
167
168.file-selector button {
169 margin: 0;
170 width: auto;
171 flex: none;
172}
173
174/* Buttons */
175button.small,
176[role="button"].small {
177 padding: 0.3rem 0.6rem;
178 font-size: 0.85rem;
179}
180
181button.danger,
182button.danger:hover,
183button.danger:focus,
184[role="button"].danger,
185[role="button"].danger:hover,
186[role="button"].danger:focus {
187 --pico-background-color: #c62828;
188 --pico-border-color: #c62828;
189 --pico-color: white;
190}
191
192button.danger:hover,
193button.danger:focus,
194[role="button"].danger:hover,
195[role="button"].danger:focus {
196 --pico-background-color: #b71c1c;
197 --pico-border-color: #b71c1c;
198}
199
200/* One-shot feedback banner shown after a form action (see PageData.Flash). */
201.flash {
202 padding: 0.75rem 1rem;
203 margin-bottom: 1.5rem;
204 border-radius: var(--pico-border-radius);
205 border: 1px solid transparent;
206 border-left-width: 4px;
207}
208
209.flash-success {
210 background-color: rgba(46, 125, 50, 0.12);
211 border-color: #2e7d32;
212 color: var(--pico-color);
213}
214
215.flash-error {
216 background-color: rgba(198, 40, 40, 0.12);
217 border-color: #c62828;
218 color: var(--pico-color);
219}
220
221button:disabled {
222 opacity: 0.5;
223 cursor: not-allowed;
224}
225
226/* Library */
227.breadcrumbs {
228 margin-bottom: 1rem;
229 display: flex;
230 align-items: center;
231 justify-content: flex-start;
232 gap: 0.35rem;
233 flex-wrap: wrap;
234 text-align: left;
235 width: 100%;
236}
237
238.breadcrumbs a,
239.breadcrumbs span {
240 flex-shrink: 0;
241}
242
243.breadcrumbs .current {
244 cursor: default;
245 pointer-events: none;
246}
247
248.library-grid {
249 display: grid;
250 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
251 gap: 1rem;
252}
253
254.folder-item,
255.media-item {
256 background: var(--pico-card-background-color);
257 border: 1px solid var(--pico-card-border-color);
258 border-radius: var(--pico-border-radius);
259 overflow: hidden;
260 text-decoration: none;
261 color: var(--pico-color);
262 box-shadow: var(--pico-card-box-shadow);
263}
264
265.folder-item:hover,
266.media-item:hover {
267 background-color: var(--pico-primary-background);
268 border-color: var(--pico-primary-border);
269 box-shadow: var(--pico-card-box-shadow), 0 4px 12px rgba(0, 0, 0, 0.15);
270}
271
272.folder-item:hover .folder-name,
273.media-item:hover .media-info,
274.media-item:hover .media-title {
275 color: var(--pico-primary-inverse);
276}
277
278.media-info {
279 transition: color 0.2s;
280}
281
282.media-thumbnail {
283 aspect-ratio: 16/9;
284 background: var(--pico-card-sectioning-background-color);
285 display: flex;
286 align-items: center;
287 justify-content: center;
288 font-size: 3rem;
289 position: relative;
290}
291
292/* Each thumbnail sits in a tile so it can carry its own per-file duration
293 badge; the tile fills the container (single file) or a grid cell (multi). */
294.thumb-tile {
295 position: relative;
296 display: flex;
297 align-items: center;
298 justify-content: center;
299 overflow: hidden;
300 width: 100%;
301 height: 100%;
302 min-width: 0;
303 min-height: 0;
304}
305
306.thumb-tile .media-duration {
307 position: absolute;
308 bottom: 0.4rem;
309 right: 0.4rem;
310 background: rgba(0, 0, 0, 0.75);
311 color: #fff;
312 padding: 0.15rem 0.4rem;
313 border-radius: var(--pico-border-radius);
314 font-size: 0.7rem;
315 font-weight: 500;
316 line-height: 1;
317}
318
319.folder-icon {
320 aspect-ratio: 16/9;
321 background: var(--pico-card-sectioning-background-color);
322 display: flex;
323 align-items: center;
324 justify-content: center;
325 font-size: 3rem;
326}
327
328.thumb-tile img {
329 width: 100%;
330 height: 100%;
331 /* contain: show the whole thumbnail (letterboxed) and never overflow the
332 16/9 box, including portrait/vertical sources. */
333 object-fit: contain;
334}
335
336.thumb-tile img[src$=".svg"] {
337 width: 48px;
338 height: 48px;
339 opacity: 0.5;
340 object-fit: contain;
341}
342
343/* Multi-file items: tile each media file's thumbnail in a grid. */
344.media-thumbnail.count-2,
345.media-thumbnail.count-3,
346.media-thumbnail.count-many {
347 display: grid;
348 gap: 2px;
349}
350
351.media-thumbnail.count-2 {
352 grid-template-columns: 1fr 1fr;
353}
354
355.media-thumbnail.count-3,
356.media-thumbnail.count-many {
357 grid-template-columns: 1fr 1fr;
358 grid-template-rows: 1fr 1fr;
359}
360
361/* For 3 files, let the first thumbnail span the full top row. */
362.media-thumbnail.count-3 .thumb-tile:first-of-type {
363 grid-column: 1 / -1;
364}
365
366/* "+N" overlay on the last tile when there are more than 4 files. */
367.media-thumbnail .thumb-more {
368 position: absolute;
369 right: 0;
370 bottom: 0;
371 width: 50%;
372 height: 50%;
373 display: flex;
374 align-items: center;
375 justify-content: center;
376 background: rgba(0, 0, 0, 0.6);
377 color: #fff;
378 font-size: 1.1rem;
379 font-weight: 600;
380 pointer-events: none;
381}
382
383/* File-count badge in the top-left for multi-file items. */
384.media-thumbnail .thumb-count {
385 position: absolute;
386 top: 0.4rem;
387 left: 0.4rem;
388 background: rgba(0, 0, 0, 0.75);
389 color: #fff;
390 padding: 0.15rem 0.4rem;
391 border-radius: var(--pico-border-radius);
392 font-size: 0.7rem;
393 font-weight: 500;
394 line-height: 1;
395}
396
397.folder-name,
398.media-info {
399 padding: 0.75rem;
400}
401
402.media-title {
403 font-weight: 500;
404 margin-bottom: 0.3rem;
405 overflow: hidden;
406 text-overflow: ellipsis;
407 white-space: nowrap;
408}
409
410.media-info .media-duration {
411 display: none;
412}
413
414/* Detail view */
415.detail-view {
416 max-width: 900px;
417}
418
419.detail-header {
420 display: flex;
421 justify-content: space-between;
422 align-items: center;
423 margin-bottom: 1.5rem;
424 flex-wrap: wrap;
425 gap: 1rem;
426}
427
428.player-container {
429 background: #000;
430 border-radius: var(--pico-border-radius);
431 overflow: hidden;
432 margin-bottom: 1.5rem;
433 max-height: 80vh;
434 display: flex;
435 align-items: center;
436 justify-content: center;
437}
438
439.player-container video,
440.player-container audio {
441 max-width: 100%;
442 max-height: 80vh;
443 width: auto;
444 height: auto;
445 display: block;
446}
447
448.detail-meta dl {
449 display: grid;
450 grid-template-columns: 150px 1fr;
451 gap: 0.5rem 1rem;
452 align-items: baseline;
453}
454
455/* Render keys as understated labels so they read as keys — not just another
456 line of value text — in both the two-column and the stacked (narrow) layout. */
457.detail-meta dt {
458 font-size: 0.75rem;
459 font-weight: 600;
460 text-transform: uppercase;
461 letter-spacing: 0.04em;
462 color: var(--pico-muted-color);
463}
464
465.detail-meta dd {
466 word-break: break-all;
467 margin: 0;
468}
469
470/* Description: preserve the source line breaks; collapse long ones to ~2 lines
471 with a pure-CSS (no-JS, CSP-safe) Show more/less toggle. */
472.detail-meta dd.description {
473 margin: 0;
474}
475
476.description .desc-text {
477 white-space: pre-wrap;
478 word-break: normal;
479 overflow-wrap: anywhere;
480 line-height: 1.5;
481}
482
483/* The checkbox is the toggle state; it's driven by the label, never shown. */
484.description.collapsible .desc-toggle {
485 display: none;
486}
487
488/* Collapsed: clamp to ~2 lines (max-height works with pre-wrap; line-clamp
489 does not), with a fade so the cut reads as intentional. */
490.description.collapsible .desc-text {
491 position: relative;
492 max-height: 3em;
493 overflow: hidden;
494}
495
496.description.collapsible .desc-text::after {
497 content: "";
498 position: absolute;
499 left: 0;
500 right: 0;
501 bottom: 0;
502 height: 1.5em;
503 background: linear-gradient(to bottom, transparent, var(--pico-background-color));
504 pointer-events: none;
505}
506
507.description.collapsible .desc-toggle:checked ~ .desc-text {
508 max-height: none;
509}
510
511.description.collapsible .desc-toggle:checked ~ .desc-text::after {
512 display: none;
513}
514
515.description.collapsible .desc-toggle-label {
516 display: inline-block;
517 margin-top: 0.4rem;
518 color: var(--pico-primary);
519 font-size: 0.85rem;
520 font-weight: 600;
521 cursor: pointer;
522 user-select: none;
523}
524
525.description.collapsible .desc-toggle-label::after {
526 content: "Show more \25be";
527}
528
529.description.collapsible .desc-toggle:checked ~ .desc-toggle-label::after {
530 content: "Show less \25b4";
531}
532
533/* Engagement metadata */
534.engagement-section {
535 margin-top: 2rem;
536}
537
538.engagement-section > summary .badge {
539 margin-left: 0.35rem;
540}
541
542.comments-actions {
543 margin: 0.75rem 0;
544 text-align: right;
545}
546
547.comment-settings-group:has(input[name="write_info_json"]:not(:checked)) .comment-options {
548 display: none;
549}
550
551.comment-options:has(input[name="write_comments"]:not(:checked)) .comment-settings-fields {
552 display: none;
553}
554
555.comment-options {
556 margin-top: 1rem;
557 padding: 0.75rem 1rem 1rem;
558}
559
560.comment-options legend {
561 padding: 0 0.35rem;
562 font-weight: 600;
563}
564
565.comment-settings-fields {
566 margin: 0.75rem 0 0 1.5rem;
567 padding-left: 1rem;
568 border-left: 2px solid var(--pico-muted-border-color);
569}
570
571.comment-settings-fields small {
572 display: block;
573 margin: -0.5rem 0 0.75rem;
574 color: var(--pico-muted-color);
575}
576
577.heatmap-figure {
578 margin: 0;
579}
580
581.heatmap {
582 height: 7rem;
583 display: flex;
584 align-items: flex-end;
585 gap: 0;
586 padding: 0.5rem 0;
587 border-bottom: 1px solid var(--pico-muted-border-color);
588}
589
590.heatmap-bar {
591 flex: 0 0 auto;
592 min-width: 0;
593 background: var(--pico-primary);
594 opacity: 0.8;
595 border-radius: 2px 2px 0 0;
596}
597
598.heatmap-figure figcaption {
599 display: flex;
600 justify-content: space-between;
601 color: var(--pico-muted-color);
602 font-size: 0.8rem;
603}
604
605.comment-list {
606 display: flex;
607 flex-direction: column;
608 gap: 0.75rem;
609}
610
611.comment {
612 margin: 0;
613 padding: 0.85rem 1rem;
614 border: 1px solid var(--pico-card-border-color);
615 border-radius: var(--pico-border-radius);
616 background: var(--pico-card-background-color);
617}
618
619.comment-depth-1 {
620 margin-left: 1.25rem;
621}
622
623.comment-depth-2 {
624 margin-left: 2.5rem;
625}
626
627.comment-depth-3 {
628 margin-left: 3.75rem;
629}
630
631.comment-depth-4 {
632 margin-left: 5rem;
633}
634
635.comment header {
636 display: flex;
637 align-items: center;
638 gap: 0.5rem;
639 flex-wrap: wrap;
640}
641
642.comment time {
643 color: var(--pico-muted-color);
644 font-size: 0.85rem;
645 margin-left: auto;
646}
647
648.comment-reply-to {
649 display: block;
650 margin-top: 0.35rem;
651 color: var(--pico-muted-color);
652}
653
654.comment p {
655 white-space: pre-wrap;
656 overflow-wrap: anywhere;
657 margin: 0.5rem 0 0.25rem;
658}
659
660.comment small,
661.muted {
662 color: var(--pico-muted-color);
663}
664
665/* Queue */
666.queue-list {
667 display: flex;
668 flex-direction: column;
669 gap: 1rem;
670}
671
672.queue-item {
673 padding: 1rem;
674 margin-bottom: 0;
675 position: relative;
676 transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
677}
678
679/* Stretched link: the whole row navigates to the detail page, matching the
680 library card hover. Interactive children (Remove) sit above it via z-index. */
681.queue-link {
682 position: absolute;
683 inset: 0;
684 z-index: 1;
685}
686
687.queue-item:hover {
688 background-color: var(--pico-primary-background);
689 border-color: var(--pico-primary-border);
690 box-shadow: var(--pico-card-box-shadow), 0 4px 12px rgba(0, 0, 0, 0.15);
691 cursor: pointer;
692}
693
694/* Keep text legible on the solid primary hover background (status badges and
695 the error message keep their own colors). */
696.queue-item:hover .queue-url,
697.queue-item:hover .queue-meta {
698 color: var(--pico-primary-inverse);
699}
700
701.queue-header {
702 display: flex;
703 justify-content: space-between;
704 align-items: flex-start;
705 gap: 1rem;
706 flex-wrap: wrap;
707 margin-bottom: 0.5rem;
708}
709
710.queue-url {
711 flex: 1;
712 min-width: 0;
713 word-break: break-all;
714}
715
716.queue-status {
717 display: flex;
718 gap: 0.5rem;
719 align-items: center;
720 flex-wrap: wrap;
721}
722
723/* Keep the Remove action clickable above the stretched link overlay. */
724.queue-action {
725 position: relative;
726 z-index: 2;
727}
728
729.status-badge {
730 padding: 0.2rem 0.6rem;
731 border-radius: 12px;
732 font-size: 0.85rem;
733 font-weight: 500;
734}
735
736.status-badge.queued {
737 background: var(--pico-card-sectioning-background-color);
738 color: var(--pico-muted-color);
739}
740
741.status-badge.downloading {
742 background: var(--pico-primary);
743 color: var(--pico-primary-inverse);
744}
745
746.status-badge.completed {
747 background: var(--pico-ins-color);
748 color: white;
749}
750
751.status-badge.error {
752 background: var(--pico-del-color);
753 color: white;
754}
755
756.status-badge.cancelled {
757 background: var(--pico-muted-color);
758 color: var(--pico-background-color);
759}
760
761.error-message {
762 color: var(--pico-del-color);
763 font-size: 0.9rem;
764 margin-top: 0.5rem;
765}
766
767.error-text {
768 color: var(--pico-del-color);
769}
770
771.queue-meta {
772 margin-top: 0.5rem;
773 font-size: 0.85rem;
774 display: flex;
775 gap: 1rem;
776}
777
778/* Logs */
779.logs {
780 max-height: 500px;
781 overflow-y: auto;
782 white-space: pre-wrap;
783 word-break: break-all;
784}
785
786pre {
787 padding: 1.5rem;
788}
789
790/* Settings */
791.settings-layout {
792 display: flex;
793 flex-direction: column;
794 gap: 2rem;
795}
796
797.presets-list {
798 display: flex;
799 flex-direction: column;
800 gap: 1rem;
801 margin-bottom: 1.5rem;
802}
803
804.preset-header {
805 display: flex;
806 justify-content: space-between;
807 align-items: center;
808 margin-bottom: 0.5rem;
809}
810
811.preset-header h4 {
812 display: flex;
813 align-items: center;
814 gap: 0.5rem;
815 margin: 0;
816}
817
818.badge {
819 background: var(--pico-primary);
820 color: var(--pico-primary-inverse);
821 padding: 0.1rem 0.4rem;
822 border-radius: 10px;
823 font-size: 0.75rem;
824}
825
826.preset-actions {
827 display: flex;
828 gap: 0.5rem;
829 flex-wrap: wrap;
830 margin-top: 1rem;
831}
832
833.preset-actions > details {
834 flex: 1 1 100%;
835 min-width: 0;
836}
837
838.preset-description {
839 margin-bottom: 0.5rem;
840}
841
842.preset-flags {
843 margin-top: 0.5rem;
844}
845
846.preset-flags pre {
847 overflow-x: auto;
848 margin-top: 0.3rem;
849 margin-bottom: 0;
850}
851
852/* Nested articles need visible borders */
853.presets-list article {
854 border: 1px solid var(--pico-muted-border-color);
855}
856
857/* Suppress Pico details marker for button-like summaries */
858details:has(summary[role="button"]) summary::after {
859 display: none !important;
860}
861
862details summary[role="button"] {
863 display: inline-flex;
864 width: auto;
865}
866
867/* Toggle text: Edit vs Cancel */
868details .cancel-text {
869 display: none;
870}
871
872details[open] .edit-text {
873 display: none;
874}
875
876details[open] .cancel-text {
877 display: inline;
878}
879
880/* Delete overlay popover */
881.delete-overlay {
882 position: relative;
883}
884
885.delete-overlay summary {
886 list-style: none;
887 cursor: pointer;
888}
889
890.delete-overlay summary::-webkit-details-marker {
891 display: none;
892}
893
894.delete-overlay summary::after {
895 display: none !important;
896}
897
898.delete-overlay .overlay-panel {
899 position: absolute;
900 top: calc(100% + 0.5rem);
901 right: 0;
902 z-index: 1000;
903 width: 260px;
904 background: var(--pico-background-color);
905 border: 1px solid var(--pico-muted-border-color);
906 border-radius: var(--pico-border-radius);
907 padding: 1rem;
908 box-shadow: var(--pico-dropdown-box-shadow);
909}
910
911/* Popover arrow */
912.delete-overlay .overlay-panel::before {
913 content: '';
914 position: absolute;
915 top: -6px;
916 right: 1rem;
917 width: 10px;
918 height: 10px;
919 background: var(--pico-background-color);
920 border-left: 1px solid var(--pico-muted-border-color);
921 border-top: 1px solid var(--pico-muted-border-color);
922 transform: rotate(45deg);
923}
924
925.delete-overlay .overlay-panel p {
926 margin-bottom: 1rem;
927 font-size: 0.9rem;
928}
929
930.delete-overlay .overlay-panel .form-actions {
931 margin-top: 0;
932 justify-content: flex-end;
933}
934
935/* Inline edit form */
936.edit-form {
937 width: 100%;
938 box-sizing: border-box;
939 padding: 1rem;
940}
941
942/* Conditional sections (no-JS show/hide) */
943.conditional-section {
944 margin-bottom: 1rem;
945}
946
947.conditional-section .conditional-content {
948 display: none;
949 margin-top: 1rem;
950}
951
952/* Checkbox triggers */
953.conditional-section:has(input[type="checkbox"].conditional-trigger:checked) .conditional-content {
954 display: block;
955}
956
957/* Radio triggers for format mode */
958.conditional-section:has(.radio-group input[value="preset"]:checked) .conditional-content.format-preset,
959.conditional-section:has(.radio-group input[value="custom"]:checked) .conditional-content.format-custom {
960 display: block;
961}
962
963/* Subscriptions: lock the cron field unless the schedule is "Custom (cron)".
964 Pure CSS — the :has() reacts live as the <select> changes, no JS needed. */
965input[name="cron_expr"] {
966 opacity: 0.5;
967 pointer-events: none;
968}
969.form-row:has(select[name="schedule_kind"] option[value="cron"]:checked) input[name="cron_expr"] {
970 opacity: 1;
971 pointer-events: auto;
972}
973
974/* Format mode selector - hidden radio inputs with button-like labels */
975.radio-group.format-mode {
976 display: flex;
977 gap: 0.5rem;
978 margin-top: 0.5rem;
979 flex-wrap: wrap;
980}
981
982.radio-group.format-mode input[type="radio"] {
983 position: absolute;
984 opacity: 0;
985 width: 0;
986 height: 0;
987}
988
989.radio-group.format-mode label {
990 padding: 0.4rem 0.8rem;
991 border: 1px solid var(--pico-muted-border-color);
992 border-radius: var(--pico-border-radius);
993 cursor: pointer;
994 background: var(--pico-background-color);
995 transition: all 0.2s;
996 font-weight: normal;
997}
998
999.radio-group.format-mode label:hover {
1000 background: var(--pico-card-sectioning-background-color);
1001}
1002
1003.radio-group.format-mode label:has(input:checked) {
1004 background: var(--pico-primary);
1005 color: var(--pico-primary-inverse);
1006 border-color: var(--pico-primary);
1007}
1008
1009/* Inline informational note paragraph */
1010.note {
1011 font-size: 0.85rem;
1012 color: var(--pico-muted-color);
1013}
1014
1015/* Collapsible "managed yt-dlp options" notes component */
1016.ytdlp-notes {
1017 margin: 0 0 1rem;
1018 border: 1px solid var(--pico-muted-border-color);
1019 border-radius: var(--pico-border-radius);
1020 background: var(--pico-card-sectioning-background-color);
1021 overflow: hidden;
1022}
1023
1024.ytdlp-notes > summary {
1025 cursor: pointer;
1026 padding: 0.6rem 0.9rem;
1027 font-size: 0.9rem;
1028 font-weight: 600;
1029 color: var(--pico-color);
1030 user-select: none;
1031 transition: background 0.15s ease-in-out;
1032}
1033
1034.ytdlp-notes > summary:hover {
1035 background: var(--pico-card-background-color);
1036}
1037
1038.ytdlp-notes-icon {
1039 color: var(--pico-primary);
1040 font-style: normal;
1041 font-size: 1rem;
1042 margin-right: 0.4rem;
1043}
1044
1045.ytdlp-notes-body {
1046 padding: 0 0.9rem 0.6rem;
1047 border-top: 1px solid var(--pico-muted-border-color);
1048}
1049
1050.ytdlp-notes-body > p {
1051 font-size: 0.85rem;
1052 color: var(--pico-muted-color);
1053 margin: 0.7rem 0;
1054}
1055
1056.ytdlp-notes-table-wrap {
1057 overflow-x: auto;
1058}
1059
1060.ytdlp-notes-body table {
1061 margin: 0;
1062 font-size: 0.85rem;
1063}
1064
1065.ytdlp-notes-body th,
1066.ytdlp-notes-body td {
1067 padding: 0.4rem 0.6rem;
1068 vertical-align: top;
1069}
1070
1071.ytdlp-notes-body td:first-child {
1072 white-space: nowrap;
1073}
1074
1075.ytdlp-notes-body code {
1076 font-size: 0.8rem;
1077}
1078
1079/* Theme selector */
1080.theme-selector {
1081 display: flex;
1082 gap: 0.5rem;
1083}
1084
1085.theme-selector button {
1086 min-width: 80px;
1087}
1088
1089.theme-selector button.active {
1090 background: var(--pico-primary);
1091 color: var(--pico-primary-inverse);
1092 border-color: var(--pico-primary);
1093}
1094
1095/* Download form */
1096.download-form {
1097 max-width: 900px;
1098}
1099
1100.download-form form {
1101 max-width: 800px;
1102}
1103
1104/* Filter form inline */
1105.filter-form {
1106 display: flex;
1107 gap: 0.5rem;
1108 align-items: center;
1109}
1110
1111.filter-form input,
1112.filter-form select,
1113.filter-form button {
1114 margin-bottom: 0;
1115 width: auto;
1116 display: inline-block;
1117 flex-shrink: 0;
1118}
1119
1120.filter-form input[type="text"] {
1121 min-width: 200px;
1122}
1123
1124/* Empty state */
1125.empty-state {
1126 text-align: center;
1127 padding: 3rem;
1128}
1129
1130/* Utility */
1131.inline {
1132 display: inline;
1133}
1134
1135/* Responsive */
1136@media (max-width: 768px) {
1137 main {
1138 padding: 1rem;
1139 }
1140
1141 .page-header {
1142 flex-direction: column;
1143 align-items: flex-start;
1144 }
1145
1146 .library-grid {
1147 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
1148 }
1149
1150 .form-row {
1151 grid-template-columns: 1fr;
1152 }
1153
1154 .detail-meta dl {
1155 grid-template-columns: 1fr;
1156 gap: 0;
1157 }
1158
1159 /* Stacked layout: tighten key→value and space out each pair so the grouping
1160 is obvious without the column alignment to lean on. */
1161 .detail-meta dt {
1162 margin-top: 0.85rem;
1163 }
1164
1165 .detail-meta dt:first-child {
1166 margin-top: 0;
1167 }
1168
1169 .detail-meta dd {
1170 margin-top: 0.15rem;
1171 }
1172
1173 .queue-header {
1174 flex-direction: column;
1175 }
1176
1177 body > header {
1178 flex-direction: column;
1179 gap: 1rem;
1180 padding: 1rem;
1181 }
1182
1183 nav {
1184 width: 100%;
1185 justify-content: center;
1186 }
1187}
1188