WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1/* theme.css — neobrutal component styles for atBB */
2/* All values use var(--token) — no hardcoded colors, sizes, or fonts */
3
4/* ─── Base / Typography ─────────────────────────────────────────────────── */
5
6body {
7 font-family: var(--font-body);
8 font-size: var(--font-size-base);
9 font-weight: var(--font-weight-normal);
10 line-height: var(--line-height-body);
11 color: var(--color-text);
12 background-color: var(--color-bg);
13}
14
15h1,
16h2,
17h3,
18h4,
19h5,
20h6 {
21 font-family: var(--font-heading);
22 font-weight: var(--font-weight-bold);
23 line-height: var(--line-height-heading);
24}
25
26a {
27 color: var(--color-primary);
28 text-decoration: underline;
29 transition: color 0.15s ease;
30}
31
32a:hover {
33 color: var(--color-primary-hover);
34}
35
36code {
37 font-family: var(--font-mono);
38 font-size: var(--font-size-sm);
39 background-color: var(--color-code-bg);
40 color: var(--color-code-text);
41 padding: var(--space-xs) var(--space-sm);
42 border-radius: var(--radius);
43}
44
45pre {
46 font-family: var(--font-mono);
47 font-size: var(--font-size-sm);
48 background-color: var(--color-code-bg);
49 color: var(--color-code-text);
50 padding: var(--space-md);
51 border-radius: var(--radius);
52 overflow-x: auto;
53}
54
55pre code {
56 padding: 0;
57 background: none;
58}
59
60/* ─── Skip Link ────────────────────────────────────────────────────────── */
61
62.skip-link {
63 position: absolute;
64 left: -9999px;
65 top: auto;
66 width: 1px;
67 height: 1px;
68 overflow: hidden;
69 z-index: 1000;
70}
71
72.skip-link:focus {
73 position: fixed;
74 top: var(--space-sm);
75 left: var(--space-sm);
76 width: auto;
77 height: auto;
78 padding: var(--space-sm) var(--space-md);
79 background-color: var(--color-primary);
80 color: var(--color-surface);
81 font-weight: var(--font-weight-bold);
82 border: var(--border-width) solid var(--color-border);
83 box-shadow: var(--button-shadow);
84 text-decoration: none;
85 z-index: 1000;
86}
87
88/* ─── Screen Reader Only ───────────────────────────────────────────────── */
89
90.sr-only {
91 position: absolute;
92 width: 1px;
93 height: 1px;
94 padding: 0;
95 margin: -1px;
96 overflow: hidden;
97 clip: rect(0, 0, 0, 0);
98 white-space: nowrap;
99 border: 0;
100}
101
102/* ─── Focus Styles ─────────────────────────────────────────────────────── */
103
104:focus-visible {
105 outline: 3px solid var(--color-primary);
106 outline-offset: 2px;
107}
108
109:focus:not(:focus-visible) {
110 outline: none;
111}
112
113/* ─── Layout ────────────────────────────────────────────────────────────── */
114
115.site-header {
116 height: var(--nav-height);
117 background-color: var(--color-surface);
118 border-bottom: var(--border-width) solid var(--color-border);
119 display: flex;
120 align-items: center;
121}
122
123.site-header__inner {
124 max-width: var(--content-width);
125 width: 100%;
126 margin: 0 auto;
127 padding: 0 var(--space-md);
128 display: flex;
129 align-items: center;
130 justify-content: space-between;
131}
132
133.site-header__title {
134 font-family: var(--font-heading);
135 font-weight: var(--font-weight-bold);
136 font-size: var(--font-size-lg);
137 color: var(--color-text);
138 text-decoration: none;
139 transition: color 0.15s ease;
140}
141
142.site-header__title:hover {
143 color: var(--color-primary);
144}
145
146.site-header__nav {
147 display: flex;
148 align-items: center;
149 gap: var(--space-md);
150}
151
152.site-header__handle {
153 font-weight: var(--font-weight-bold);
154 font-size: var(--font-size-sm);
155}
156
157.site-header__logout-form {
158 display: inline;
159}
160
161.site-header__logout-btn {
162 cursor: pointer;
163 background: none;
164 border: none;
165 color: var(--color-text-muted);
166 font-family: var(--font-body);
167 font-size: var(--font-size-sm);
168 padding: var(--space-xs) var(--space-sm);
169 text-decoration: underline;
170 transition: color 0.15s ease;
171}
172
173.site-header__logout-btn:hover {
174 color: var(--color-danger);
175}
176
177.site-header__login-link {
178 font-weight: var(--font-weight-bold);
179}
180
181.color-scheme-toggle {
182 cursor: pointer;
183 display: inline-flex;
184 align-items: center;
185 justify-content: center;
186 font-family: var(--font-body);
187 font-size: var(--font-size-base);
188 line-height: 1;
189 border: var(--border-width) solid var(--color-border);
190 border-radius: var(--button-radius);
191 padding: var(--space-xs) var(--space-sm);
192 box-shadow: var(--button-shadow);
193 background-color: var(--color-surface);
194 color: var(--color-text);
195 min-width: 36px;
196 min-height: 36px;
197 transition: transform 0.1s ease, box-shadow 0.1s ease;
198}
199
200.color-scheme-toggle:hover {
201 transform: translate(var(--btn-press-hover), var(--btn-press-hover));
202 box-shadow: var(--btn-press-hover) var(--btn-press-hover) 0 var(--color-shadow);
203}
204
205.color-scheme-toggle:active {
206 transform: translate(var(--btn-press-active), var(--btn-press-active));
207 box-shadow: none;
208}
209
210.content-container {
211 max-width: var(--content-width);
212 margin: 0 auto;
213 padding: var(--space-xl) var(--space-md);
214}
215
216.site-footer {
217 padding: var(--space-lg) var(--space-md);
218 text-align: center;
219 color: var(--color-text-muted);
220 font-size: var(--font-size-sm);
221 border-top: var(--border-width) solid var(--color-border);
222}
223
224/* ─── Mobile Navigation ────────────────────────────────────────────────── */
225
226.mobile-nav {
227 display: block;
228 position: relative;
229}
230
231.mobile-nav__toggle {
232 cursor: pointer;
233 font-size: var(--font-size-lg);
234 list-style: none;
235 padding: var(--space-xs) var(--space-sm);
236 min-width: 44px;
237 min-height: 44px;
238 display: flex;
239 align-items: center;
240 justify-content: center;
241 background: none;
242 border: none;
243}
244
245.mobile-nav__toggle::-webkit-details-marker {
246 display: none;
247}
248
249.mobile-nav__menu {
250 position: absolute;
251 right: 0;
252 top: 100%;
253 background-color: var(--color-surface);
254 border: var(--border-width) solid var(--color-border);
255 box-shadow: var(--card-shadow);
256 padding: var(--space-md);
257 min-width: 200px;
258 z-index: 100;
259 display: flex;
260 flex-direction: column;
261 gap: var(--space-sm);
262}
263
264.desktop-nav {
265 display: none;
266 align-items: center;
267 gap: var(--space-md);
268}
269
270/* ─── Card ──────────────────────────────────────────────────────────────── */
271
272.card {
273 background-color: var(--color-surface);
274 border: var(--border-width) solid var(--color-border);
275 border-radius: var(--card-radius);
276 box-shadow: var(--card-shadow);
277 padding: var(--space-md);
278 transition: transform 0.15s ease, box-shadow 0.15s ease;
279}
280
281/* ─── Button ────────────────────────────────────────────────────────────── */
282
283.btn {
284 cursor: pointer;
285 display: inline-flex;
286 align-items: center;
287 gap: var(--space-sm);
288 font-family: var(--font-body);
289 font-weight: var(--font-weight-bold);
290 font-size: var(--font-size-base);
291 line-height: 1;
292 border: var(--border-width) solid var(--color-border);
293 border-radius: var(--button-radius);
294 padding: var(--space-sm) var(--space-md);
295 box-shadow: var(--button-shadow);
296 background-color: var(--color-surface);
297 color: var(--color-text);
298 text-decoration: none;
299 transition: transform 0.1s ease, box-shadow 0.1s ease;
300 user-select: none;
301}
302
303.btn-primary {
304 background-color: var(--color-primary);
305 color: var(--color-surface);
306}
307
308.btn-secondary {
309 background-color: var(--color-secondary);
310 color: var(--color-surface);
311}
312
313.btn-danger {
314 background-color: var(--color-danger);
315 color: var(--color-surface);
316}
317
318.btn:hover {
319 transform: translate(var(--btn-press-hover), var(--btn-press-hover));
320 box-shadow: var(--btn-press-hover) var(--btn-press-hover) 0 var(--color-shadow);
321}
322
323.btn:active {
324 transform: translate(var(--btn-press-active), var(--btn-press-active));
325 box-shadow: none;
326}
327
328/* ─── Page Header ───────────────────────────────────────────────────────── */
329
330.page-header {
331 display: flex;
332 align-items: center;
333 justify-content: space-between;
334 margin-bottom: var(--space-lg);
335 gap: var(--space-md);
336 padding-bottom: var(--space-md);
337 border-bottom: var(--border-width) solid var(--color-border);
338}
339
340.page-header__text h1 {
341 margin: 0;
342 font-size: var(--font-size-xl);
343}
344
345.page-header__text p {
346 margin: var(--space-xs) 0 0;
347 color: var(--color-text-muted);
348 font-size: var(--font-size-sm);
349}
350
351/* ─── Error Display ─────────────────────────────────────────────────────── */
352
353.error-display {
354 background-color: var(--color-surface);
355 border: var(--border-width) solid var(--color-danger);
356 border-left-width: calc(var(--border-width) * 3);
357 border-radius: var(--radius);
358 padding: var(--space-lg);
359 color: var(--color-danger);
360}
361
362.error-display__message {
363 font-weight: var(--font-weight-bold);
364 font-size: var(--font-size-lg);
365 margin-bottom: var(--space-xs);
366}
367
368.error-display__detail {
369 color: var(--color-text-muted);
370 font-size: var(--font-size-sm);
371}
372
373/* ─── Empty State ───────────────────────────────────────────────────────── */
374
375.empty-state {
376 text-align: center;
377 padding: var(--space-xl) var(--space-md);
378 color: var(--color-text-muted);
379 border: var(--border-width) dashed var(--color-border);
380 margin: var(--space-md) 0;
381}
382
383.empty-state p {
384 font-size: var(--font-size-lg);
385 margin-bottom: var(--space-sm);
386}
387
388.empty-state__action {
389 margin-top: var(--space-md);
390}
391
392/* ─── Loading State (HTMX indicator) ───────────────────────────────────── */
393
394.loading-state {
395 opacity: 0;
396 transition: opacity 0.2s ease;
397 text-align: center;
398 padding: var(--space-md);
399 color: var(--color-text-muted);
400}
401
402.loading-state.htmx-request {
403 opacity: 1;
404}
405
406.htmx-indicator {
407 opacity: 0;
408 transition: opacity 0.2s ease;
409}
410
411.htmx-request .htmx-indicator,
412.htmx-request.htmx-indicator {
413 opacity: 1;
414}
415
416/* ─── Error Page ────────────────────────────────────────────────────────── */
417
418.error-page {
419 text-align: center;
420 padding: var(--space-xl) var(--space-md);
421}
422
423.error-page__code {
424 font-family: var(--font-heading);
425 font-size: 6rem;
426 font-weight: var(--font-weight-bold);
427 line-height: 1;
428 color: var(--color-primary);
429 margin-bottom: var(--space-sm);
430}
431
432.error-page__title {
433 font-size: var(--font-size-xl);
434 margin-bottom: var(--space-sm);
435}
436
437.error-page__message {
438 color: var(--color-text-muted);
439 font-size: var(--font-size-base);
440 margin-bottom: var(--space-lg);
441}
442
443/* ─── Homepage ──────────────────────────────────────────────────────────── */
444
445.category-section {
446 margin-bottom: var(--space-xl);
447}
448
449.category-header {
450 margin: 0 0 var(--space-md) 0;
451 font-size: var(--font-size-lg);
452 padding-bottom: var(--space-sm);
453 border-bottom: var(--border-width) solid var(--color-border);
454}
455
456.board-grid {
457 display: flex;
458 flex-direction: column;
459 gap: var(--space-md);
460}
461
462.board-card {
463 display: block;
464 text-decoration: none;
465 color: inherit;
466}
467
468.board-card:hover .card {
469 transform: translate(-2px, -2px);
470 box-shadow: calc(var(--shadow-offset) + 2px) calc(var(--shadow-offset) + 2px) 0 var(--color-shadow);
471}
472
473.board-card__name {
474 font-weight: var(--font-weight-bold);
475 font-size: var(--font-size-base);
476 margin: 0 0 var(--space-xs) 0;
477}
478
479.board-card__description {
480 margin: 0;
481 color: var(--color-text-muted);
482 font-size: var(--font-size-sm);
483}
484
485/* ─── Forms ─────────────────────────────────────────────────────────────── */
486
487.form-group {
488 display: flex;
489 flex-direction: column;
490 gap: var(--space-xs);
491 margin-bottom: var(--space-md);
492}
493
494.form-group label {
495 font-weight: var(--font-weight-bold);
496 font-size: var(--font-size-sm);
497}
498
499.form-group input,
500.form-group textarea,
501.form-group select {
502 border: var(--input-border);
503 border-radius: var(--input-radius);
504 padding: var(--space-sm) var(--space-md);
505 font-family: var(--font-body);
506 font-size: var(--font-size-base);
507 background-color: var(--color-surface);
508 color: var(--color-text);
509 min-height: 44px;
510}
511
512.form-group textarea {
513 min-height: 120px;
514 resize: vertical;
515}
516
517.form-actions {
518 display: flex;
519 flex-direction: row;
520 gap: var(--space-sm);
521 margin-top: var(--space-md);
522}
523
524.form-error {
525 color: var(--color-danger);
526 font-size: var(--font-size-sm);
527 font-weight: var(--font-weight-bold);
528 margin: var(--space-xs) 0;
529}
530
531.char-count {
532 font-size: var(--font-size-sm);
533 color: var(--color-text-muted);
534}
535
536.char-count[data-over="true"] {
537 color: var(--color-danger);
538 font-weight: var(--font-weight-bold);
539}
540
541.success-banner {
542 background-color: var(--color-success);
543 color: var(--color-surface);
544 padding: var(--space-sm) var(--space-md);
545 margin-bottom: var(--space-md);
546 font-weight: var(--font-weight-bold);
547 border: var(--border-width) solid var(--color-border);
548}
549
550/* ─── Login Form ────────────────────────────────────────────────────────── */
551
552.login-form {
553 max-width: 480px;
554}
555
556.login-form__form {
557 display: flex;
558 flex-direction: column;
559 gap: var(--space-md);
560}
561
562.login-form__label {
563 font-weight: var(--font-weight-bold);
564}
565
566.login-form__input {
567 border: var(--input-border);
568 border-radius: var(--input-radius);
569 padding: var(--space-sm) var(--space-md);
570 font-family: var(--font-body);
571 font-size: var(--font-size-base);
572 background-color: var(--color-surface);
573 color: var(--color-text);
574 min-height: 44px;
575 width: 100%;
576 box-sizing: border-box;
577}
578
579.login-form__hint {
580 color: var(--color-text-muted);
581 font-size: var(--font-size-sm);
582}
583
584.login-form__error {
585 border: var(--border-width) solid var(--color-danger);
586 padding: var(--space-sm) var(--space-md);
587 color: var(--color-danger);
588 font-weight: var(--font-weight-bold);
589}
590
591.login-form__submit {
592 cursor: pointer;
593 display: inline-flex;
594 align-items: center;
595 justify-content: center;
596 gap: var(--space-sm);
597 font-family: var(--font-body);
598 font-weight: var(--font-weight-bold);
599 font-size: var(--font-size-base);
600 line-height: 1;
601 border: var(--border-width) solid var(--color-border);
602 border-radius: var(--button-radius);
603 padding: var(--space-sm) var(--space-md);
604 box-shadow: var(--button-shadow);
605 background-color: var(--color-primary);
606 color: var(--color-surface);
607 text-decoration: none;
608 transition: transform 0.1s ease, box-shadow 0.1s ease;
609 user-select: none;
610}
611
612.login-form__submit:hover {
613 transform: translate(var(--btn-press-hover), var(--btn-press-hover));
614 box-shadow: var(--btn-press-hover) var(--btn-press-hover) 0 var(--color-shadow);
615}
616
617.login-form__submit:active {
618 transform: translate(var(--btn-press-active), var(--btn-press-active));
619 box-shadow: none;
620}
621
622/* ─── Post Cards ────────────────────────────────────────────────────────── */
623
624.post-card {
625 background-color: var(--color-surface);
626 border: var(--border-width) solid var(--color-border);
627 border-left-width: calc(var(--border-width) * 2);
628 border-left-color: var(--color-primary);
629 padding: var(--space-md);
630 margin-bottom: var(--space-md);
631 transition: transform 0.15s ease, box-shadow 0.15s ease;
632}
633
634.post-card--op {
635 border-left-width: calc(var(--border-width) * 3);
636 box-shadow: var(--card-shadow);
637}
638
639.post-card--reply {
640 box-shadow: var(--shadow-offset) var(--shadow-offset) 0 var(--color-shadow);
641}
642
643.post-card__header {
644 display: flex;
645 flex-direction: row;
646 align-items: center;
647 gap: var(--space-sm);
648 margin-bottom: var(--space-sm);
649 flex-wrap: wrap;
650}
651
652.post-card__number {
653 font-weight: var(--font-weight-bold);
654 background-color: var(--color-primary);
655 color: var(--color-surface);
656 padding: var(--space-xs) var(--space-sm);
657 min-width: 2em;
658 text-align: center;
659}
660
661.post-card__author {
662 font-weight: var(--font-weight-bold);
663 font-size: var(--font-size-sm);
664}
665
666.post-card__date {
667 color: var(--color-text-muted);
668 font-size: var(--font-size-sm);
669 margin-left: auto;
670}
671
672.post-card__body {
673 white-space: pre-wrap;
674 word-break: break-word;
675 line-height: var(--line-height-body);
676}
677
678/* ─── Breadcrumb ────────────────────────────────────────────────────────── */
679
680.breadcrumb {
681 font-size: var(--font-size-sm);
682 color: var(--color-text-muted);
683 margin-bottom: var(--space-md);
684}
685
686.breadcrumb a {
687 color: var(--color-text-muted);
688 text-decoration: none;
689}
690
691.breadcrumb a:hover {
692 color: var(--color-primary);
693}
694
695.breadcrumb ol {
696 display: flex;
697 flex-wrap: wrap;
698 gap: 0;
699 list-style: none;
700 padding: 0;
701 margin: 0;
702}
703
704.breadcrumb li {
705 display: flex;
706 align-items: center;
707}
708
709.breadcrumb li + li::before {
710 content: "/";
711 margin: 0 var(--space-sm);
712 color: var(--color-text-muted);
713}
714
715/* ─── Topic Rows ────────────────────────────────────────────────────────── */
716
717.topic-row {
718 display: flex;
719 flex-direction: row;
720 justify-content: space-between;
721 align-items: baseline;
722 gap: var(--space-md);
723 padding: var(--space-md);
724 border: var(--border-width) solid var(--color-border);
725 background-color: var(--color-surface);
726 margin-bottom: var(--space-sm);
727 transition: transform 0.15s ease, box-shadow 0.15s ease;
728}
729
730.topic-row:hover {
731 transform: translate(-1px, -1px);
732 box-shadow: 3px 3px 0 var(--color-shadow);
733}
734
735.topic-row__title {
736 font-weight: var(--font-weight-bold);
737 color: var(--color-text);
738 text-decoration: none;
739 flex: 1;
740 overflow: hidden;
741 text-overflow: ellipsis;
742 white-space: nowrap;
743}
744
745.topic-row__title:hover {
746 color: var(--color-primary);
747}
748
749.topic-row__meta {
750 display: flex;
751 gap: var(--space-sm);
752 color: var(--color-text-muted);
753 font-size: var(--font-size-sm);
754 white-space: nowrap;
755}
756
757/* ─── Topic Locked Banner ───────────────────────────────────────────────── */
758
759.topic-locked-banner {
760 background-color: var(--color-warning);
761 color: var(--color-text);
762 padding: var(--space-sm) var(--space-md);
763 margin-bottom: var(--space-md);
764 font-weight: var(--font-weight-bold);
765 border: var(--border-width) solid var(--color-border);
766 display: flex;
767 align-items: center;
768 gap: var(--space-sm);
769}
770
771.topic-locked-banner__badge {
772 background-color: var(--color-text);
773 color: var(--color-warning);
774 padding: var(--space-xs) var(--space-sm);
775 font-size: var(--font-size-sm);
776 text-transform: uppercase;
777 letter-spacing: 0.05em;
778}
779
780/* ─── Moderation UI ──────────────────────────────────────────────────────── */
781
782.post-card__mod-actions {
783 display: flex;
784 gap: var(--space-sm);
785 margin-top: var(--space-sm);
786 padding-top: var(--space-sm);
787 border-top: var(--border-width) solid var(--color-border);
788}
789
790.mod-btn {
791 font-size: var(--font-size-xs);
792 padding: var(--space-xs) var(--space-sm);
793 border: var(--border-width) solid currentColor;
794 border-radius: var(--radius);
795 cursor: pointer;
796 background: transparent;
797 font-family: inherit;
798 font-weight: var(--font-weight-bold);
799 text-transform: uppercase;
800 letter-spacing: 0.05em;
801}
802
803.mod-btn--hide,
804.mod-btn--lock {
805 color: var(--color-danger);
806}
807
808.mod-btn--hide:hover,
809.mod-btn--lock:hover {
810 background: var(--color-danger);
811 color: var(--color-surface);
812}
813
814.mod-btn--unhide,
815.mod-btn--unlock,
816.mod-btn--ban {
817 color: var(--color-text-muted);
818}
819
820.mod-btn--unhide:hover,
821.mod-btn--unlock:hover,
822.mod-btn--ban:hover {
823 background: var(--color-text-muted);
824 color: var(--color-surface);
825}
826
827.topic-mod-controls {
828 margin-bottom: var(--space-md);
829}
830
831.mod-dialog {
832 border: var(--border-width) solid var(--color-border);
833 border-radius: var(--radius);
834 padding: var(--space-lg);
835 max-width: 480px;
836 width: 90vw;
837 box-shadow: var(--card-shadow);
838 background: var(--color-bg);
839}
840
841.mod-dialog::backdrop {
842 background: rgba(0, 0, 0, 0.5);
843}
844
845.mod-dialog__title {
846 margin-top: 0;
847 margin-bottom: var(--space-md);
848 font-size: var(--font-size-lg);
849}
850
851/* ═══════════════════════════════════════════════════════════════════════════
852 RESPONSIVE BREAKPOINTS (mobile-first)
853 Base = mobile (0-767px), tablet = 768px+, desktop = 1024px+
854 ═══════════════════════════════════════════════════════════════════════════ */
855
856/* ─── Tablet (768px+) ──────────────────────────────────────────────────── */
857
858@media (min-width: 768px) {
859 :root {
860 --content-width: 720px;
861 }
862
863 .topic-row {
864 flex-direction: row;
865 align-items: baseline;
866 }
867
868 .topic-row__title {
869 white-space: nowrap;
870 overflow: hidden;
871 text-overflow: ellipsis;
872 }
873
874 .mobile-nav {
875 display: none;
876 }
877
878 .desktop-nav {
879 display: flex;
880 }
881}
882
883/* ─── Desktop (1024px+) ───────────────────────────────────────────────── */
884
885@media (min-width: 1024px) {
886 :root {
887 --content-width: 960px;
888 --border-width: 3px;
889 --shadow-offset: 4px;
890 --button-shadow: 4px 4px 0 var(--color-shadow);
891 --card-shadow: 6px 6px 0 var(--color-shadow);
892 --btn-press-hover: 2px;
893 --btn-press-active: 4px;
894 --input-border: 3px solid var(--color-border);
895 }
896
897}
898
899/* ─── Mobile-specific overrides ────────────────────────────────────────── */
900
901@media (max-width: 767px) {
902 .page-header {
903 flex-direction: column;
904 align-items: flex-start;
905 }
906
907 .topic-row {
908 flex-direction: column;
909 gap: var(--space-xs);
910 }
911
912 .topic-row__title {
913 white-space: normal;
914 }
915
916 .topic-row__meta {
917 flex-wrap: wrap;
918 }
919
920 .post-card__header {
921 flex-direction: column;
922 align-items: flex-start;
923 gap: var(--space-xs);
924 }
925
926 .post-card__date {
927 margin-left: 0;
928 }
929
930 .login-form {
931 max-width: 100%;
932 }
933
934 .desktop-nav {
935 display: none;
936 }
937
938 .mobile-nav {
939 display: block;
940 }
941}
942
943/* ─── Admin Panel ───────────────────────────────────────────────────────── */
944
945.admin-nav-grid {
946 display: grid;
947 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
948 gap: var(--space-md);
949 margin-top: var(--space-lg);
950}
951
952.admin-nav-card {
953 text-decoration: none;
954 color: inherit;
955 display: block;
956}
957
958.admin-nav-card:hover .card {
959 border-color: var(--color-primary);
960}
961
962.admin-nav-card__icon {
963 font-size: var(--font-size-xl);
964 margin-bottom: var(--space-sm);
965}
966
967.admin-nav-card__title {
968 font-family: var(--font-heading);
969 font-weight: var(--font-weight-bold);
970 font-size: var(--font-size-lg);
971 margin-bottom: var(--space-xs);
972}
973
974.admin-nav-card__description {
975 color: var(--color-text-muted);
976 font-size: var(--font-size-sm);
977}
978
979/* ─── Admin Member Table ─────────────────────────────────────────────────── */
980
981.admin-member-table {
982 width: 100%;
983 border-collapse: collapse;
984 margin-top: var(--space-md);
985}
986
987.admin-member-table th {
988 text-align: left;
989 padding: var(--space-sm) var(--space-md);
990 border-bottom: calc(var(--border-width) * 2) solid var(--color-border);
991 font-weight: var(--font-weight-bold);
992 font-size: var(--font-size-sm);
993 color: var(--color-text-muted);
994 text-transform: uppercase;
995 letter-spacing: 0.05em;
996}
997
998.admin-member-table td {
999 padding: var(--space-sm) var(--space-md);
1000 border-bottom: var(--border-width) solid var(--color-border);
1001 vertical-align: middle;
1002}
1003
1004.admin-member-table tbody tr:last-child td {
1005 border-bottom: none;
1006}
1007
1008.role-badge {
1009 display: inline-block;
1010 padding: var(--space-xs) var(--space-sm);
1011 border: var(--border-width) solid var(--color-border);
1012 font-size: var(--font-size-sm);
1013 font-weight: var(--font-weight-bold);
1014 background-color: var(--color-surface);
1015}
1016
1017.member-row__assign-form {
1018 display: flex;
1019 align-items: center;
1020 gap: var(--space-sm);
1021 flex-wrap: wrap;
1022}
1023
1024.member-row__error {
1025 display: block;
1026 color: var(--color-danger);
1027 font-size: var(--font-size-sm);
1028 font-weight: var(--font-weight-bold);
1029 margin-top: var(--space-xs);
1030}
1031
1032/* ── Structure Management Page ──────────────────────────────────────────── */
1033
1034.structure-page {
1035 display: flex;
1036 flex-direction: column;
1037 gap: var(--space-lg);
1038}
1039
1040.structure-category {
1041 background: var(--color-surface);
1042 border: var(--border-width) solid var(--color-border);
1043 border-radius: var(--radius);
1044 overflow: hidden;
1045}
1046
1047.structure-category__header {
1048 display: flex;
1049 align-items: center;
1050 gap: var(--space-sm);
1051 padding: var(--space-sm) var(--space-md);
1052 background: var(--color-bg);
1053 border-bottom: var(--border-width) solid var(--color-border);
1054}
1055
1056.structure-category__name {
1057 font-weight: var(--font-weight-bold);
1058 font-size: var(--font-size-base);
1059 flex: 1;
1060}
1061
1062.structure-category__meta {
1063 font-size: var(--font-size-sm);
1064 color: var(--color-text-muted);
1065}
1066
1067.structure-category__actions {
1068 display: flex;
1069 gap: var(--space-sm);
1070 flex-shrink: 0;
1071}
1072
1073.structure-boards {
1074 padding: var(--space-sm);
1075 display: flex;
1076 flex-direction: column;
1077 gap: var(--space-sm);
1078}
1079
1080.structure-board {
1081 background: var(--color-bg);
1082 border: var(--border-width) solid var(--color-border);
1083 border-radius: var(--radius);
1084}
1085
1086.structure-board__header {
1087 display: flex;
1088 align-items: center;
1089 gap: var(--space-sm);
1090 padding: var(--space-xs) var(--space-sm);
1091}
1092
1093.structure-board__name {
1094 font-weight: var(--font-weight-bold);
1095 flex: 1;
1096}
1097
1098.structure-board__meta {
1099 font-size: var(--font-size-sm);
1100 color: var(--color-text-muted);
1101}
1102
1103.structure-board__actions {
1104 display: flex;
1105 gap: var(--space-sm);
1106 flex-shrink: 0;
1107}
1108
1109.structure-edit-form {
1110 border-top: var(--border-width) solid var(--color-border);
1111}
1112
1113.structure-edit-form[open] {
1114 display: block;
1115}
1116
1117.structure-edit-form__body {
1118 padding: var(--space-md);
1119 display: flex;
1120 flex-direction: column;
1121 gap: var(--space-sm);
1122}
1123
1124.structure-add-board {
1125 border: var(--border-width) dashed var(--color-border);
1126 border-radius: var(--radius);
1127 background: transparent;
1128}
1129
1130.structure-add-board__trigger {
1131 display: block;
1132 padding: var(--space-xs) var(--space-sm);
1133 cursor: pointer;
1134 color: var(--color-primary);
1135 font-size: var(--font-size-sm);
1136 user-select: none;
1137}
1138
1139.structure-add-board__trigger:hover {
1140 background: var(--color-surface);
1141 border-radius: var(--radius);
1142}
1143
1144.structure-add-category {
1145 margin-top: var(--space-md);
1146}
1147
1148.structure-confirm-dialog {
1149 border-radius: var(--radius);
1150 border: var(--border-width) solid var(--color-border);
1151 padding: var(--space-lg);
1152 max-width: 24rem;
1153}
1154
1155.structure-confirm-dialog::backdrop {
1156 background: rgba(0, 0, 0, 0.4);
1157}
1158
1159.structure-confirm-dialog p {
1160 margin-bottom: var(--space-md);
1161}
1162
1163.dialog-actions {
1164 display: flex;
1165 gap: var(--space-sm);
1166 justify-content: flex-end;
1167}
1168
1169.structure-error-banner {
1170 background: var(--color-surface);
1171 color: var(--color-danger);
1172 border: var(--border-width) solid var(--color-danger);
1173 border-left-width: calc(var(--border-width) * 3);
1174 border-radius: var(--radius);
1175 padding: var(--space-sm) var(--space-md);
1176 margin-bottom: var(--space-md);
1177}
1178
1179.btn-sm {
1180 font-size: var(--font-size-sm);
1181 padding: var(--space-xs) var(--space-sm);
1182}