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