Skip to main content

max / makenotwork

31.3 KB · 1762 lines History Blame Raw
1 /* ===========================================
2 Multithreaded — Forum Stylesheet
3 Adapted from Makenot.work design language
4 =========================================== */
5
6 /* ===========================================
7 FONTS
8 =========================================== */
9
10 @font-face {
11 font-family: "Young Serif";
12 src: url("/static/fonts/ysrf.ttf");
13 font-display: swap;
14 }
15
16 @font-face {
17 font-family: "IBM Plex Mono";
18 src: url("/static/fonts/IBMPlexMono-Regular.ttf");
19 font-weight: normal;
20 font-display: swap;
21 }
22
23 @font-face {
24 font-family: "IBM Plex Mono";
25 src: url("/static/fonts/IBMPlexMono-Bold.ttf");
26 font-weight: bold;
27 font-display: swap;
28 }
29
30 @font-face {
31 font-family: "Lato";
32 src: url("/static/fonts/Lato-Regular.ttf");
33 font-weight: normal;
34 font-display: swap;
35 }
36
37 @font-face {
38 font-family: "Lato";
39 src: url("/static/fonts/Lato-Bold.ttf");
40 font-weight: bold;
41 font-display: swap;
42 }
43
44 /* ===========================================
45 VARIABLES
46 =========================================== */
47
48 :root {
49 --background: #ede8e1;
50 --detail: #3d3530;
51 --highlight: #6c5ce7;
52 --light-background: #f4f0eb;
53
54 --surface-muted: #ddd7c5;
55 --surface-alt: #ebe7db;
56 --surface-border: #d0cbb8;
57 --border: #d0cbb8;
58 --text-muted: #8a8480;
59 --input-background: #e2dad2;
60
61 --primary-dark: #000000;
62 --primary-light: #ffffff;
63 --success: #2d5016;
64 --warning: #8b7355;
65 --danger: #d62828;
66 --error: #d62828;
67
68 --focus-ring: #6c5ce7;
69 }
70
71 /* ===========================================
72 RESET
73 =========================================== */
74
75 * {
76 margin: 0;
77 padding: 0;
78 box-sizing: border-box;
79 }
80
81 /* ===========================================
82 BASE
83 =========================================== */
84
85 body {
86 margin: 0;
87 background-color: var(--background);
88 color: var(--detail);
89 font-family: "Lato", sans-serif;
90 line-height: 1.5;
91 }
92
93 h1 {
94 font-family: "Young Serif", serif;
95 font-weight: normal;
96 color: var(--detail);
97 text-align: left;
98 font-size: 1.5rem;
99 }
100
101 h2,
102 h3 {
103 font-family: "IBM Plex Mono", monospace;
104 font-weight: normal;
105 color: var(--detail);
106 }
107
108 p {
109 font-family: "Lato", sans-serif;
110 color: var(--detail);
111 }
112
113 a {
114 color: var(--detail);
115 text-decoration: none;
116 }
117
118 a:hover {
119 text-decoration: underline;
120 }
121
122 /* The signature dot */
123 .dot {
124 color: var(--highlight);
125 }
126
127 /* ===========================================
128 LAYOUT
129 =========================================== */
130
131 .container {
132 max-width: 1200px;
133 margin: 0 auto;
134 padding: 1rem;
135 }
136
137 .padded-page {
138 padding: 1.25rem;
139 }
140
141 /* ===========================================
142 SITE HEADER & NAV
143 =========================================== */
144
145 .site-header {
146 display: flex;
147 justify-content: space-between;
148 align-items: center;
149 padding: 0.75rem 1.25rem;
150 margin-bottom: 0.5rem;
151 }
152
153 .site-header nav {
154 margin: 0;
155 }
156
157 .site-header .nav-links {
158 display: flex;
159 gap: 1.5rem;
160 align-items: center;
161 }
162
163 .nav-links a {
164 color: var(--detail);
165 text-decoration: none;
166 font-family: "IBM Plex Mono", monospace;
167 transition: opacity 0.2s ease;
168 }
169
170 .nav-links a:hover {
171 opacity: 0.6;
172 text-decoration: none;
173 }
174
175 .site-logo {
176 font-family: "Young Serif", serif;
177 font-size: 1.25rem;
178 text-decoration: none;
179 color: var(--detail);
180 }
181
182 .site-logo:hover {
183 opacity: 0.8;
184 text-decoration: none;
185 }
186
187 .link-button {
188 background: none;
189 border: none;
190 color: var(--detail);
191 font-family: "IBM Plex Mono", monospace;
192 font-size: 1rem;
193 cursor: pointer;
194 padding: 0;
195 text-decoration: none;
196 transition: opacity 0.2s ease;
197 }
198
199 .link-button:hover {
200 opacity: 0.6;
201 text-decoration: underline;
202 }
203
204 .nav-form {
205 display: contents;
206 }
207
208 /* Hamburger toggle */
209 .nav-toggle-checkbox {
210 display: none;
211 }
212
213 .nav-toggle-label {
214 display: none;
215 cursor: pointer;
216 padding: 0.5rem;
217 z-index: 11;
218 }
219
220 .nav-toggle-label span {
221 display: block;
222 width: 22px;
223 height: 2px;
224 background: var(--detail);
225 margin: 5px 0;
226 transition: transform 0.2s ease, opacity 0.2s ease;
227 }
228
229 /* ===========================================
230 BUTTONS
231 =========================================== */
232
233 button {
234 color: var(--detail);
235 background: var(--light-background);
236 padding: 6px 12px;
237 border: 1px solid var(--detail);
238 font-family: inherit;
239 cursor: pointer;
240 transition: opacity 0.2s ease;
241 }
242
243 button:hover {
244 opacity: 0.8;
245 }
246
247 button.primary,
248 .btn-primary {
249 background: var(--primary-dark);
250 color: var(--primary-light);
251 border: none;
252 padding: 0.5rem 1rem;
253 font-family: inherit;
254 font-size: 0.85rem;
255 cursor: pointer;
256 transition: opacity 0.2s ease;
257 }
258
259 button.primary:hover,
260 .btn-primary:hover {
261 opacity: 0.8;
262 }
263
264 button.secondary,
265 .btn-secondary {
266 background: var(--surface-muted);
267 color: var(--detail);
268 border: none;
269 padding: 0.5rem 1rem;
270 font-family: "IBM Plex Mono", monospace;
271 font-size: 0.85rem;
272 cursor: pointer;
273 transition: opacity 0.2s ease;
274 }
275
276 button.secondary:hover,
277 .btn-secondary:hover {
278 opacity: 0.8;
279 }
280
281 /* ===========================================
282 FORMS
283 =========================================== */
284
285 form {
286 display: flex;
287 flex-direction: column;
288 gap: 1rem;
289 width: 100%;
290 }
291
292 .form-container {
293 max-width: 600px;
294 background: var(--light-background);
295 padding: 1.5rem;
296 }
297
298 label {
299 font-family: "IBM Plex Mono", monospace;
300 color: var(--detail);
301 font-size: 14px;
302 }
303
304 input[type="text"],
305 input[type="email"],
306 input[type="password"],
307 input[type="number"],
308 textarea,
309 select {
310 width: 100%;
311 background: var(--input-background);
312 border: none;
313 padding: 0.6rem;
314 font-family: "IBM Plex Mono", monospace;
315 font-size: 0.85rem;
316 color: var(--detail);
317 }
318
319 input::placeholder,
320 textarea::placeholder {
321 opacity: 0.5;
322 }
323
324 input[type="text"]:focus,
325 input[type="email"]:focus,
326 input[type="password"]:focus,
327 input[type="number"]:focus,
328 textarea:focus,
329 select:focus {
330 outline: none;
331 border: 2px solid var(--highlight);
332 }
333
334 textarea {
335 min-height: 150px;
336 resize: vertical;
337 }
338
339 textarea.drag-over {
340 border: 2px dashed var(--highlight);
341 background: var(--surface-muted);
342 }
343
344 select {
345 cursor: pointer;
346 }
347
348 input[type="submit"],
349 form button {
350 font-family: "Young Serif", serif;
351 font-size: 16px;
352 color: var(--detail);
353 background: var(--light-background);
354 padding: 10px 20px;
355 border: 1px solid var(--detail);
356 cursor: pointer;
357 }
358
359 input[type="submit"]:hover,
360 form button:hover {
361 background: var(--background);
362 }
363
364 .form-row {
365 display: grid;
366 grid-template-columns: 1fr 1fr;
367 gap: 1rem;
368 }
369
370 .form-group {
371 display: flex;
372 flex-direction: column;
373 gap: 0.25rem;
374 }
375
376 .form-actions {
377 display: flex;
378 gap: 1rem;
379 margin-top: 0.5rem;
380 }
381
382 .form-help {
383 display: block;
384 font-size: 0.8rem;
385 color: var(--text-muted);
386 margin-top: 0.25rem;
387 }
388
389 .input-narrow {
390 width: 6rem;
391 }
392
393 /* ===========================================
394 DIRECTORY TABLE (forum home)
395 =========================================== */
396
397 .directory-table {
398 width: 100%;
399 border-collapse: collapse;
400 font-size: 0.85rem;
401 font-family: "Lato", sans-serif;
402 }
403
404 .directory-table thead {
405 background: var(--surface-muted);
406 }
407
408 .directory-table th {
409 text-align: left;
410 padding: 0.35rem 0.75rem;
411 font-family: "IBM Plex Mono", monospace;
412 font-size: 0.7rem;
413 font-weight: normal;
414 text-transform: uppercase;
415 letter-spacing: 0.05em;
416 color: var(--text-muted);
417 }
418
419 .directory-table tbody tr {
420 transition: background 0.1s ease;
421 }
422
423 .directory-table tbody tr:nth-child(odd) {
424 background: var(--surface-alt);
425 }
426
427 .directory-table tbody tr:nth-child(even) {
428 background: var(--light-background);
429 }
430
431 .directory-table tbody tr:hover {
432 background: var(--surface-muted);
433 }
434
435 .directory-table td {
436 padding: 0.4rem 0.75rem;
437 border-top: 1px solid var(--border);
438 }
439
440 .directory-name {
441 font-family: "Young Serif", serif;
442 font-size: 1rem;
443 }
444
445 .directory-name a {
446 color: var(--detail);
447 text-decoration: none;
448 }
449
450 .directory-name a:hover {
451 text-decoration: underline;
452 }
453
454 .directory-desc {
455 font-size: 0.8rem;
456 color: var(--text-muted);
457 margin-top: 0.1rem;
458 }
459
460 .directory-table .col-creator {
461 white-space: nowrap;
462 width: 130px;
463 font-family: "IBM Plex Mono", monospace;
464 font-size: 0.8rem;
465 }
466
467 .directory-table .col-type {
468 white-space: nowrap;
469 width: 100px;
470 font-family: "IBM Plex Mono", monospace;
471 font-size: 0.8rem;
472 color: var(--text-muted);
473 }
474
475 .directory-table .col-items {
476 white-space: nowrap;
477 width: 60px;
478 text-align: right;
479 font-family: "IBM Plex Mono", monospace;
480 font-size: 0.8rem;
481 color: var(--text-muted);
482 }
483
484 /* ===========================================
485 DATA TABLE (dense thread listings)
486 =========================================== */
487
488 .data-table {
489 width: 100%;
490 border-collapse: collapse;
491 font-size: 0.85rem;
492 font-family: "Lato", sans-serif;
493 margin-bottom: 1rem;
494 }
495
496 .data-table thead {
497 background: var(--surface-muted);
498 }
499
500 .data-table th {
501 text-align: left;
502 padding: 0.35rem 0.75rem;
503 font-family: "IBM Plex Mono", monospace;
504 font-size: 0.7rem;
505 font-weight: normal;
506 text-transform: uppercase;
507 letter-spacing: 0.05em;
508 color: var(--text-muted);
509 }
510
511 .data-table th.sortable {
512 cursor: pointer;
513 transition: background 0.2s ease;
514 user-select: none;
515 }
516
517 .data-table th.sortable:hover {
518 background: var(--border);
519 }
520
521 .data-table th.sortable a {
522 color: inherit;
523 text-decoration: none;
524 display: block;
525 }
526
527 .data-table th.sortable a:hover {
528 text-decoration: none;
529 }
530
531 .data-table th.sort-active {
532 color: var(--detail);
533 }
534
535 .data-table tbody tr {
536 transition: background 0.1s ease;
537 }
538
539 .data-table tbody tr:nth-child(odd) {
540 background: var(--surface-alt);
541 }
542
543 .data-table tbody tr:nth-child(even) {
544 background: var(--light-background);
545 }
546
547 .data-table tbody tr:hover {
548 background: var(--surface-muted);
549 }
550
551 .data-table td {
552 padding: 0.4rem 0.75rem;
553 border-top: 1px solid var(--border);
554 }
555
556 /* Thread-specific table columns */
557 .data-table .thread-title {
558 font-weight: bold;
559 }
560
561 .data-table .thread-title a {
562 color: var(--detail);
563 text-decoration: none;
564 }
565
566 .data-table .thread-title a:hover {
567 text-decoration: underline;
568 }
569
570 .data-table .col-replies,
571 .data-table .col-activity {
572 white-space: nowrap;
573 text-align: right;
574 width: 100px;
575 }
576
577 .data-table .col-author {
578 white-space: nowrap;
579 width: 130px;
580 }
581
582 /* Member list columns */
583 .data-table .col-role {
584 white-space: nowrap;
585 width: 100px;
586 }
587
588 .data-table .col-joined {
589 white-space: nowrap;
590 text-align: right;
591 width: 100px;
592 font-family: "IBM Plex Mono", monospace;
593 font-size: 0.8rem;
594 color: var(--text-muted);
595 }
596
597 /* Pinned row highlight */
598 .data-table tr.pinned {
599 background: var(--surface-muted);
600 }
601
602 .data-table tr.pinned:hover {
603 background: var(--border);
604 }
605
606 /* ===========================================
607 BADGES
608 =========================================== */
609
610 .badge {
611 display: inline-block;
612 padding: 0.15rem 0.4rem;
613 font-size: 0.7rem;
614 font-family: "IBM Plex Mono", monospace;
615 background: var(--primary-dark);
616 color: var(--primary-light);
617 }
618
619 .badge-success {
620 background: var(--success);
621 }
622
623 .badge-warning {
624 background: var(--warning);
625 }
626
627 .badge-danger {
628 background: var(--danger);
629 }
630
631 .badge-muted {
632 background: var(--text-muted);
633 }
634
635 .badge-ban {
636 background: var(--danger);
637 color: var(--primary-light);
638 }
639
640 .badge-mute-type {
641 background: var(--warning);
642 color: var(--primary-light);
643 }
644
645 /* Role badges */
646 .badge-role-owner {
647 background: var(--primary-dark);
648 color: var(--primary-light);
649 }
650
651 .badge-role-moderator {
652 background: var(--warning);
653 color: var(--primary-light);
654 }
655
656 .badge-role-member {
657 background: var(--surface-muted);
658 color: var(--detail);
659 border: 1px solid var(--border);
660 }
661
662 .badge-role-guest {
663 background: var(--surface-muted);
664 color: var(--text-muted);
665 border: 1px solid var(--border);
666 }
667
668 /* Thread status badges — text-only */
669 .badge-pinned {
670 background: var(--surface-muted);
671 color: var(--detail);
672 border: 1px solid var(--border);
673 }
674
675 .badge-locked {
676 background: var(--surface-muted);
677 color: var(--text-muted);
678 border: 1px solid var(--border);
679 }
680
681 /* ===========================================
682 BREADCRUMBS
683 =========================================== */
684
685 .breadcrumb {
686 font-size: 0.8rem;
687 color: var(--text-muted);
688 margin-bottom: 0.5rem;
689 font-family: "IBM Plex Mono", monospace;
690 }
691
692 .breadcrumb a {
693 color: var(--detail);
694 text-decoration: none;
695 }
696
697 .breadcrumb a:hover {
698 text-decoration: underline;
699 }
700
701 .breadcrumb .sep {
702 margin: 0 0.3rem;
703 opacity: 0.5;
704 }
705
706 /* ===========================================
707 POST ITEM (thread view)
708 =========================================== */
709
710 .post-list {
711 display: flex;
712 flex-direction: column;
713 gap: 0;
714 }
715
716 .post-item {
717 padding: 0.75rem 1rem;
718 border-bottom: 1px solid var(--border);
719 }
720
721 .post-item:first-child {
722 border-top: 1px solid var(--border);
723 }
724
725 .post-header {
726 display: flex;
727 justify-content: space-between;
728 align-items: baseline;
729 margin-bottom: 0.25rem;
730 }
731
732 .post-author {
733 font-family: "IBM Plex Mono", monospace;
734 font-weight: bold;
735 font-size: 0.85rem;
736 }
737
738 .post-timestamp {
739 font-family: "IBM Plex Mono", monospace;
740 font-size: 0.75rem;
741 color: var(--text-muted);
742 }
743
744 .post-edited {
745 font-family: "IBM Plex Mono", monospace;
746 font-size: 0.7rem;
747 color: var(--text-muted);
748 font-style: italic;
749 margin-left: 0.5rem;
750 }
751
752 .post-body {
753 font-size: 0.9rem;
754 line-height: 1.5;
755 }
756
757 .post-body p {
758 margin-bottom: 0.5rem;
759 }
760
761 .post-body p:last-child {
762 margin-bottom: 0;
763 }
764
765 .post-body code {
766 font-family: "IBM Plex Mono", monospace;
767 font-size: 0.8rem;
768 background: var(--surface-muted);
769 padding: 0.1rem 0.35rem;
770 }
771
772 .post-body pre {
773 background: var(--primary-dark);
774 color: var(--primary-light);
775 padding: 0.75rem;
776 overflow-x: auto;
777 margin: 0.5rem 0;
778 font-family: "IBM Plex Mono", monospace;
779 font-size: 0.8rem;
780 line-height: 1.5;
781 }
782
783 .post-body pre code {
784 background: none;
785 padding: 0;
786 color: inherit;
787 }
788
789 .post-body blockquote {
790 border-left: 3px solid var(--border);
791 padding-left: 1rem;
792 margin: 0.5rem 0;
793 color: var(--text-muted);
794 }
795
796 .post-body img {
797 max-width: 100%;
798 height: auto;
799 border-radius: 4px;
800 margin: 0.5rem 0;
801 cursor: pointer;
802 }
803
804 /* Post action links (edit/delete) */
805 .post-actions {
806 margin-left: 0.75rem;
807 }
808
809 .post-action-link {
810 font-family: "IBM Plex Mono", monospace;
811 font-size: 0.7rem;
812 color: var(--text-muted);
813 background: none;
814 border: none;
815 padding: 0;
816 cursor: pointer;
817 text-decoration: none;
818 margin-left: 0.5rem;
819 }
820
821 .post-action-link:hover {
822 color: var(--detail);
823 text-decoration: underline;
824 }
825
826 .post-action-delete:hover {
827 color: var(--danger);
828 }
829
830 /* Deleted posts */
831 .post-deleted .post-body {
832 color: var(--text-muted);
833 font-style: italic;
834 }
835
836 /* OP indicator */
837 .post-item.op {
838 background: var(--light-background);
839 }
840
841 /* ===========================================
842 DRAFT INDICATOR
843 =========================================== */
844
845 .draft-indicator {
846 font-family: "IBM Plex Mono", monospace;
847 font-size: 0.75rem;
848 color: var(--text-muted);
849 margin-bottom: 0.25rem;
850 }
851
852 .draft-discard {
853 cursor: pointer;
854 color: var(--text-muted);
855 }
856
857 .draft-discard:hover {
858 color: var(--danger);
859 }
860
861 /* ===========================================
862 REPLY FORM
863 =========================================== */
864
865 .reply-section {
866 padding: 1rem;
867 margin-top: 0.5rem;
868 }
869
870 .reply-section h3 {
871 margin-bottom: 0.75rem;
872 }
873
874 /* ===========================================
875 PAGE HEADER (title + actions row)
876 =========================================== */
877
878 .page-header {
879 display: flex;
880 justify-content: space-between;
881 align-items: center;
882 margin-bottom: 0.5rem;
883 }
884
885 .page-header h1 {
886 text-align: left;
887 font-size: 1.5rem;
888 margin: 0;
889 }
890
891 .page-header h2 {
892 font-size: 1.2rem;
893 margin: 0;
894 }
895
896 /* ===========================================
897 TOAST NOTIFICATIONS
898 =========================================== */
899
900 .toast-container {
901 position: fixed;
902 bottom: 1.5rem;
903 right: 1.5rem;
904 z-index: 1000;
905 display: flex;
906 flex-direction: column;
907 gap: 0.5rem;
908 }
909
910 .toast {
911 background: var(--primary-dark);
912 color: var(--primary-light);
913 padding: 0.6rem 1rem;
914 font-family: "IBM Plex Mono", monospace;
915 font-size: 0.85rem;
916 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
917 animation: toast-in 0.3s ease-out;
918 max-width: 300px;
919 }
920
921 .toast-success {
922 background: var(--success);
923 }
924
925 .toast-error {
926 background: var(--error);
927 }
928
929 .toast-warning {
930 background: var(--warning);
931 }
932
933 .toast-info {
934 background: var(--primary-dark);
935 }
936
937 .toast-retry-btn {
938 background: none;
939 border: 1px solid currentColor;
940 color: inherit;
941 font-family: "IBM Plex Mono", monospace;
942 font-size: 0.75rem;
943 font-weight: 600;
944 padding: 0.1rem 0.4rem;
945 margin-left: 0.75rem;
946 cursor: pointer;
947 }
948
949 .toast-retry-btn:hover {
950 background: rgba(255, 255, 255, 0.15);
951 }
952
953 .toast.fade-out {
954 animation: toast-out 0.3s ease-in forwards;
955 }
956
957 @keyframes toast-in {
958 from { transform: translateX(100%); }
959 to { transform: translateX(0); }
960 }
961
962 @keyframes toast-out {
963 from { transform: translateX(0); }
964 to { transform: translateX(100%); }
965 }
966
967 /* ===========================================
968 SETTINGS PAGE
969 =========================================== */
970
971 .settings-section {
972 margin-bottom: 2rem;
973 }
974
975 .settings-section h3 {
976 margin-bottom: 0.75rem;
977 }
978
979 .settings-table {
980 width: 100%;
981 border-collapse: collapse;
982 font-size: 0.85rem;
983 font-family: "Lato", sans-serif;
984 margin-bottom: 1rem;
985 }
986
987 .settings-table thead {
988 background: var(--surface-muted);
989 }
990
991 .settings-table th {
992 text-align: left;
993 padding: 0.35rem 0.75rem;
994 font-family: "IBM Plex Mono", monospace;
995 font-size: 0.7rem;
996 font-weight: normal;
997 text-transform: uppercase;
998 letter-spacing: 0.05em;
999 color: var(--text-muted);
1000 }
1001
1002 .settings-table tbody tr {
1003 transition: background 0.1s ease;
1004 }
1005
1006 .settings-table tbody tr:nth-child(odd) {
1007 background: var(--surface-alt);
1008 }
1009
1010 .settings-table tbody tr:nth-child(even) {
1011 background: var(--light-background);
1012 }
1013
1014 .settings-table tbody tr:hover {
1015 background: var(--surface-muted);
1016 }
1017
1018 .settings-table td {
1019 padding: 0.4rem 0.75rem;
1020 border-top: 1px solid var(--border);
1021 }
1022
1023 .settings-cat-name {
1024 font-family: "Young Serif", serif;
1025 font-size: 1rem;
1026 }
1027
1028 .settings-cat-desc {
1029 display: block;
1030 font-size: 0.8rem;
1031 color: var(--text-muted);
1032 margin-top: 0.1rem;
1033 }
1034
1035 .settings-mono {
1036 font-family: "IBM Plex Mono", monospace;
1037 font-size: 0.8rem;
1038 color: var(--text-muted);
1039 }
1040
1041 .settings-actions {
1042 white-space: nowrap;
1043 }
1044
1045 /* ===========================================
1046 ACCESSIBILITY
1047 =========================================== */
1048
1049 .skip-to-main {
1050 position: absolute;
1051 top: -100px;
1052 left: 0;
1053 background: var(--primary-dark);
1054 color: var(--primary-light);
1055 padding: 8px;
1056 z-index: 100;
1057 transition: top 0.2s ease;
1058 }
1059
1060 .skip-to-main:focus {
1061 top: 0;
1062 }
1063
1064 *:focus-visible {
1065 outline: 2px solid var(--focus-ring);
1066 outline-offset: 2px;
1067 }
1068
1069 /* ===========================================
1070 PAGINATION
1071 =========================================== */
1072
1073 .pagination {
1074 display: flex;
1075 justify-content: center;
1076 align-items: center;
1077 gap: 1rem;
1078 padding: 0.75rem 0;
1079 font-family: "IBM Plex Mono", monospace;
1080 font-size: 0.85rem;
1081 }
1082
1083 .pagination-link {
1084 color: var(--detail);
1085 text-decoration: none;
1086 padding: 0.3rem 0.6rem;
1087 border: 1px solid var(--border);
1088 background: var(--light-background);
1089 transition: background 0.2s ease;
1090 }
1091
1092 .pagination-link:hover {
1093 background: var(--surface-muted);
1094 text-decoration: none;
1095 }
1096
1097 .pagination-info {
1098 color: var(--text-muted);
1099 }
1100
1101 /* ===========================================
1102 ERROR PAGES
1103 =========================================== */
1104
1105 .error-page {
1106 text-align: center;
1107 padding: 3rem 1rem;
1108 }
1109
1110 .error-page h2 {
1111 font-family: "Young Serif", serif;
1112 font-size: 3rem;
1113 margin-bottom: 0.5rem;
1114 }
1115
1116 .error-page p {
1117 color: var(--text-muted);
1118 margin-bottom: 1.5rem;
1119 }
1120
1121 /* ===========================================
1122 EMPTY STATE
1123 =========================================== */
1124
1125 .empty-state {
1126 text-align: center;
1127 padding: 1rem;
1128 color: var(--text-muted);
1129 font-family: "IBM Plex Mono", monospace;
1130 }
1131
1132 /* ===========================================
1133 SITE FOOTER
1134 =========================================== */
1135
1136 .site-footer {
1137 text-align: center;
1138 padding: 1rem;
1139 margin-top: 1rem;
1140 border-top: 1px solid var(--border);
1141 font-family: "IBM Plex Mono", monospace;
1142 font-size: 0.75rem;
1143 color: var(--text-muted);
1144 }
1145
1146 .site-footer a {
1147 color: var(--detail);
1148 text-decoration: none;
1149 }
1150
1151 .site-footer a:hover {
1152 text-decoration: underline;
1153 }
1154
1155 .site-footer-links {
1156 margin-bottom: 0.5rem;
1157 }
1158
1159 .site-footer-links a {
1160 margin: 0 0.75rem;
1161 }
1162
1163 .footer-sep {
1164 margin: 0 0.4rem;
1165 }
1166
1167 /* ===========================================
1168 FOOTNOTES + IMMUTABLE POSTS
1169 =========================================== */
1170
1171 .post-footnotes {
1172 margin-top: 0.75rem;
1173 padding-top: 0.5rem;
1174 border-top: 1px solid var(--border);
1175 }
1176
1177 .footnote {
1178 font-size: 0.85rem;
1179 color: var(--text-muted);
1180 margin-bottom: 0.5rem;
1181 }
1182
1183 .footnote p {
1184 margin: 0.15rem 0;
1185 }
1186
1187 .footnote-prefix {
1188 font-family: "IBM Plex Mono", monospace;
1189 font-size: 0.75rem;
1190 }
1191
1192 .footnote-form-toggle {
1193 margin-top: 0.5rem;
1194 }
1195
1196 .footnote-form-toggle textarea {
1197 width: 100%;
1198 min-height: 60px;
1199 margin-top: 0.5rem;
1200 }
1201
1202 .badge-unread {
1203 background: var(--highlight);
1204 color: var(--primary-light);
1205 font-size: 0.75rem;
1206 padding: 0.1rem 0.4rem;
1207 border-radius: 3px;
1208 font-family: "IBM Plex Mono", monospace;
1209 }
1210
1211 tr.unread .thread-title a {
1212 font-weight: 700;
1213 }
1214
1215 tr.unread .thread-title::before {
1216 content: "";
1217 display: inline-block;
1218 width: 6px;
1219 height: 6px;
1220 background: var(--highlight);
1221 border-radius: 50%;
1222 margin-right: 0.35rem;
1223 vertical-align: middle;
1224 }
1225
1226 /* Mention indicator on thread listings */
1227 .badge-mention {
1228 color: var(--highlight);
1229 font-size: 0.75rem;
1230 font-weight: 700;
1231 font-family: "IBM Plex Mono", monospace;
1232 background: none;
1233 border: none;
1234 padding: 0;
1235 }
1236
1237 tr.mentioned {
1238 border-left: 3px solid var(--highlight);
1239 }
1240
1241 /* Tracking settings */
1242 .tracking-settings {
1243 display: flex;
1244 align-items: center;
1245 gap: 0.75rem;
1246 margin-bottom: 1rem;
1247 font-size: 0.85rem;
1248 }
1249
1250 .toggle-label {
1251 display: flex;
1252 align-items: center;
1253 gap: 0.4rem;
1254 cursor: pointer;
1255 }
1256
1257 .toggle-checkbox {
1258 accent-color: var(--highlight);
1259 }
1260
1261 /* Info/static page sections */
1262 .info-section h3 {
1263 margin-top: 1.5rem;
1264 margin-bottom: 0.5rem;
1265 }
1266
1267 .info-section ul {
1268 padding-left: 1.5rem;
1269 margin-bottom: 0.75rem;
1270 }
1271
1272 .info-section li {
1273 margin-bottom: 0.3rem;
1274 line-height: 1.5;
1275 }
1276
1277 .tag-filter {
1278 margin-bottom: 1rem;
1279 display: flex;
1280 flex-wrap: wrap;
1281 align-items: center;
1282 gap: 0.35rem;
1283 }
1284
1285 .tag-filter-label {
1286 font-family: "IBM Plex Mono", monospace;
1287 font-size: 0.8rem;
1288 color: var(--text-muted);
1289 margin-right: 0.25rem;
1290 }
1291
1292 .tag-chip {
1293 display: inline-block;
1294 padding: 0.15rem 0.5rem;
1295 font-size: 0.8rem;
1296 border: 1px solid var(--border);
1297 border-radius: 3px;
1298 text-decoration: none;
1299 color: var(--text-primary);
1300 }
1301
1302 .tag-chip:hover {
1303 background: var(--surface-muted);
1304 }
1305
1306 .tag-chip.tag-active {
1307 background: var(--primary-dark);
1308 color: var(--primary-light);
1309 border-color: var(--primary-dark);
1310 }
1311
1312 .tag-badge {
1313 display: inline-block;
1314 font-size: 0.7rem;
1315 padding: 0.05rem 0.35rem;
1316 background: var(--surface-muted);
1317 border-radius: 2px;
1318 margin-left: 0.25rem;
1319 vertical-align: middle;
1320 font-family: "IBM Plex Mono", monospace;
1321 color: var(--text-muted);
1322 }
1323
1324 .tag-fieldset {
1325 border: none;
1326 padding: 0;
1327 }
1328
1329 .tag-fieldset legend {
1330 font-weight: 600;
1331 margin-bottom: 0.35rem;
1332 }
1333
1334 .tag-checkbox {
1335 display: inline-block;
1336 margin-right: 1rem;
1337 font-size: 0.9rem;
1338 cursor: pointer;
1339 }
1340
1341 .flag-form-toggle {
1342 margin-top: 0.5rem;
1343 }
1344
1345 .flag-form {
1346 margin-top: 0.5rem;
1347 display: flex;
1348 flex-direction: column;
1349 gap: 0.35rem;
1350 }
1351
1352 .flag-form label {
1353 font-size: 0.85rem;
1354 cursor: pointer;
1355 }
1356
1357 .flag-form textarea {
1358 width: 100%;
1359 min-height: 40px;
1360 margin-top: 0.25rem;
1361 }
1362
1363 .flag-btn {
1364 align-self: flex-start;
1365 font-size: 0.8rem;
1366 padding: 0.25rem 0.75rem;
1367 }
1368
1369 .post-removed .post-body {
1370 color: var(--text-muted);
1371 font-style: italic;
1372 }
1373
1374 .quote-attribution {
1375 display: block;
1376 font-size: 0.8rem;
1377 font-family: "IBM Plex Mono", monospace;
1378 color: var(--text-muted);
1379 margin-top: 0.25rem;
1380 font-style: normal;
1381 }
1382
1383 .quote-attribution a {
1384 color: var(--text-muted);
1385 text-decoration: none;
1386 }
1387
1388 .quote-attribution a:hover {
1389 text-decoration: underline;
1390 }
1391
1392 .quote-btn {
1393 position: absolute;
1394 z-index: 100;
1395 background: var(--surface);
1396 border: 1px solid var(--border);
1397 padding: 0.25rem 0.5rem;
1398 font-size: 0.75rem;
1399 font-family: "IBM Plex Mono", monospace;
1400 cursor: pointer;
1401 }
1402
1403 .quote-btn:hover {
1404 background: var(--light-background);
1405 }
1406
1407 /* ===========================================
1408 UTILITY CLASSES
1409 =========================================== */
1410
1411 .form-inline { display: inline; }
1412 .form-inline-row { display: inline-flex; gap: 0.25rem; flex-direction: row; align-items: center; }
1413 .btn-secondary { text-decoration: none; }
1414 .section-heading { margin-bottom: 1.5rem; }
1415 .section-heading-top { margin-top: 1.5rem; }
1416 .textarea-short { min-height: 60px; }
1417 .textarea-medium { min-height: 80px; }
1418 .footnote-btn { margin-top: 0.25rem; }
1419 .input-compact { width: 150px; padding: 0.3rem; }
1420 .search-form { flex-direction: row; gap: 0.5rem; align-items: flex-end; }
1421 .flex-1 { flex: 1; }
1422
1423 .profile-header { display: flex; align-items: center; gap: 1.25rem; margin-bottom: 1.5rem; }
1424 .profile-avatar { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; }
1425 .profile-avatar-placeholder {
1426 width: 64px; height: 64px; border-radius: 50%; background: var(--border-color);
1427 display: flex; align-items: center; justify-content: center;
1428 font-size: 1.5rem; font-weight: bold; color: var(--text-muted); flex-shrink: 0;
1429 }
1430 .profile-name { margin: 0; }
1431 .text-muted { color: var(--text-muted); }
1432 .text-muted-sm { color: var(--text-muted); font-size: 0.85rem; }
1433 .text-muted-md { color: var(--text-muted); font-size: 0.9rem; }
1434 .community-desc { margin-bottom: 0.5rem; color: var(--text-muted); }
1435 .activity-category { color: var(--text-muted); font-size: 0.85rem; }
1436
1437 /* ===========================================
1438 LINK PREVIEWS
1439 =========================================== */
1440
1441 .post-link-previews {
1442 margin-top: 0.75rem;
1443 display: flex;
1444 flex-direction: column;
1445 gap: 0.5rem;
1446 }
1447
1448 .link-preview-card {
1449 display: block;
1450 padding: 0.5rem 0.75rem;
1451 border: 1px solid var(--border);
1452 background: var(--light-background);
1453 text-decoration: none;
1454 color: var(--detail);
1455 transition: background 0.2s ease;
1456 }
1457
1458 .link-preview-card:hover {
1459 background: var(--surface-muted);
1460 text-decoration: none;
1461 }
1462
1463 .lp-title {
1464 display: block;
1465 font-family: "IBM Plex Mono", monospace;
1466 font-size: 0.85rem;
1467 font-weight: bold;
1468 }
1469
1470 .lp-desc {
1471 display: block;
1472 font-size: 0.8rem;
1473 color: var(--text-muted);
1474 margin-top: 0.15rem;
1475 }
1476
1477 .lp-url {
1478 display: block;
1479 font-size: 0.7rem;
1480 font-family: "IBM Plex Mono", monospace;
1481 color: var(--text-muted);
1482 margin-top: 0.15rem;
1483 }
1484
1485 /* ===========================================
1486 SEARCH MODAL
1487 =========================================== */
1488
1489 .search-toggle {
1490 font-family: "IBM Plex Mono", monospace;
1491 font-size: 0.85rem;
1492 color: var(--text-muted);
1493 background: none;
1494 border: 1px solid var(--border);
1495 padding: 0.25rem 0.75rem;
1496 cursor: pointer;
1497 transition: opacity 0.2s ease;
1498 }
1499
1500 .search-toggle:hover {
1501 opacity: 0.7;
1502 }
1503
1504 .search-modal {
1505 position: fixed;
1506 top: 0;
1507 left: 0;
1508 right: 0;
1509 bottom: 0;
1510 z-index: 200;
1511 display: flex;
1512 justify-content: center;
1513 padding-top: 10vh;
1514 }
1515
1516 .search-modal[hidden] {
1517 display: none;
1518 }
1519
1520 .search-modal-backdrop {
1521 position: fixed;
1522 top: 0;
1523 left: 0;
1524 right: 0;
1525 bottom: 0;
1526 background: rgba(0, 0, 0, 0.3);
1527 }
1528
1529 .search-modal-content {
1530 position: relative;
1531 width: 100%;
1532 max-width: 600px;
1533 max-height: 70vh;
1534 display: flex;
1535 flex-direction: column;
1536 background: var(--light-background);
1537 border: 1px solid var(--border);
1538 box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
1539 z-index: 1;
1540 }
1541
1542 .search-input {
1543 width: 100%;
1544 padding: 0.75rem 1rem;
1545 font-size: 1rem;
1546 font-family: "IBM Plex Mono", monospace;
1547 background: var(--background);
1548 border: none;
1549 border-bottom: 1px solid var(--border);
1550 color: var(--detail);
1551 outline: none;
1552 }
1553
1554 .search-input:focus {
1555 border-bottom-color: var(--highlight);
1556 }
1557
1558 .search-results-container {
1559 overflow-y: auto;
1560 max-height: calc(70vh - 3rem);
1561 }
1562
1563 .search-results {
1564 list-style: none;
1565 margin: 0;
1566 padding: 0;
1567 }
1568
1569 .search-result {
1570 border-bottom: 1px solid var(--border);
1571 }
1572
1573 .search-result:last-child {
1574 border-bottom: none;
1575 }
1576
1577 .search-result-link {
1578 display: block;
1579 padding: 0.6rem 1rem;
1580 text-decoration: none;
1581 color: var(--detail);
1582 transition: background 0.1s ease;
1583 }
1584
1585 .search-result-link:hover,
1586 .search-result.search-active .search-result-link {
1587 background: var(--surface-muted);
1588 text-decoration: none;
1589 }
1590
1591 .search-result-title {
1592 display: block;
1593 font-weight: bold;
1594 font-size: 0.9rem;
1595 }
1596
1597 .search-result-meta {
1598 display: block;
1599 font-family: "IBM Plex Mono", monospace;
1600 font-size: 0.7rem;
1601 color: var(--text-muted);
1602 margin-top: 0.15rem;
1603 }
1604
1605 .search-result-snippet {
1606 display: block;
1607 font-size: 0.8rem;
1608 color: var(--text-muted);
1609 margin-top: 0.15rem;
1610 overflow: hidden;
1611 text-overflow: ellipsis;
1612 white-space: nowrap;
1613 }
1614
1615 .search-empty {
1616 padding: 1.5rem 1rem;
1617 text-align: center;
1618 color: var(--text-muted);
1619 font-family: "IBM Plex Mono", monospace;
1620 font-size: 0.85rem;
1621 }
1622
1623 /* ===========================================
1624 POST ENDORSEMENTS
1625 =========================================== */
1626
1627 .endorsed {
1628 color: var(--highlight);
1629 font-weight: bold;
1630 }
1631
1632 .endorsement-count {
1633 color: var(--detail);
1634 font-size: 0.85rem;
1635 margin-left: 0.25rem;
1636 }
1637
1638 /* ===========================================
1639 RESPONSIVE — 768px (tablet)
1640 =========================================== */
1641
1642 @media (max-width: 768px) {
1643 .container {
1644 padding: 0.75rem;
1645 }
1646
1647 .padded-page {
1648 padding: 0.75rem;
1649 }
1650
1651 .form-row {
1652 grid-template-columns: 1fr;
1653 }
1654
1655 .data-table th,
1656 .data-table td {
1657 padding: 0.35rem 0.5rem;
1658 font-size: 0.8rem;
1659 }
1660
1661 .directory-table th,
1662 .directory-table td {
1663 padding: 0.35rem 0.5rem;
1664 font-size: 0.8rem;
1665 }
1666
1667 .page-header {
1668 flex-direction: column;
1669 align-items: flex-start;
1670 gap: 0.5rem;
1671 }
1672
1673 /* Hamburger menu */
1674 .nav-toggle-label {
1675 display: block;
1676 }
1677
1678 .site-header nav {
1679 display: none;
1680 position: absolute;
1681 top: 100%;
1682 left: 0;
1683 right: 0;
1684 background: var(--background);
1685 border-bottom: 1px solid var(--border);
1686 padding: 0.75rem 1.25rem;
1687 z-index: 10;
1688 }
1689
1690 .site-header {
1691 position: relative;
1692 }
1693
1694 .nav-toggle-checkbox:checked ~ nav {
1695 display: block;
1696 }
1697
1698 .site-header .nav-links {
1699 flex-direction: column;
1700 gap: 0.75rem;
1701 }
1702
1703 /* Animate hamburger to X */
1704 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(1) {
1705 transform: rotate(45deg) translate(5px, 5px);
1706 }
1707
1708 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(2) {
1709 opacity: 0;
1710 }
1711
1712 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(3) {
1713 transform: rotate(-45deg) translate(5px, -5px);
1714 }
1715
1716 /* Hide less important columns on mobile */
1717 .data-table .col-author {
1718 display: none;
1719 }
1720
1721 .directory-table .col-type,
1722 .directory-table .col-items {
1723 display: none;
1724 }
1725
1726 .col-replies {
1727 width: auto;
1728 }
1729 }
1730
1731 /* ===========================================
1732 RESPONSIVE — 480px (phone)
1733 =========================================== */
1734
1735 @media (max-width: 480px) {
1736 .container {
1737 padding: 0.5rem;
1738 }
1739
1740 .padded-page {
1741 padding: 0.5rem;
1742 }
1743
1744 h1 {
1745 font-size: 1.6rem;
1746 }
1747
1748 .toast-container {
1749 left: 0.75rem;
1750 right: 0.75rem;
1751 }
1752
1753 .toast {
1754 max-width: 100%;
1755 }
1756
1757 .post-header {
1758 flex-direction: column;
1759 gap: 0.2rem;
1760 }
1761 }
1762