Skip to main content

max / makenotwork

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