Skip to main content

max / makenotwork

275.7 KB · 11554 lines History Blame Raw
1 /* ============================================================================
2 MNW global stylesheet. Charter: docs/design-system.md.
3
4 Build new features by COMPOSING these primitives, in this order of preference:
5
6 1. Use a UTILITY class for one-off adjustments (.mb-4, .text-sm, .nowrap)
7 2. Use a LAYOUT PRIMITIVE to position content (.container, .stack-row, .field-row, .list-row)
8 3. Use a COMPONENT PRIMITIVE for a UI element (.card, .callout, .badge, .progress-bar, .empty-state, .input--sm, .small)
9 4. Extend a primitive with a modifier (.card--bordered, .callout--warning, .stack-row--bordered)
10 5. ONLY THEN consider a new class, and add it to the right section below
11
12 A new class is a smell, not a goal. Before writing one:
13 - grep this file for the visual shape you want; almost everything is here
14 - if you can't find it, consider whether the shape belongs in the design system
15 (then add it to the appropriate section here AND to docs/design-system.md)
16 - page-scoped rules (`.foo-page .bar`) are a last resort, not a first move
17
18 --------------------------------------------------------------------------
19 FILE STRUCTURE (search by section name for anchor)
20
21 FOUNDATIONS
22 @font-face declarations (top of file)
23 :root tokens color, type, space, radius, shadow
24 Element base h1/h2/h3, p, a, button, input, table
25
26 UTILITIES
27 Spacing (.m-0, .mt-*, .mb-*, .ml-*, .my-*)
28 Sizing (.col-*, .w-*, .maxw-*, .minw-*)
29 Text (.text-sm, .text-xs, .text-center, .text-right, .fw-bold,
30 .nowrap, .muted, .dimmed, .dimmer, .is-faded, .danger-text)
31 State (.hidden, .is-selected, .is-active, .unstyled-link)
32 Shapes (.square-cover, .scroll-x)
33
34 LAYOUT PRIMITIVES (page-scaffolding shapes)
35 .container + .container--narrow / --medium / --wide
36 .stack-row + --bordered / --tight / --top toolbar / header bar
37 .field-row + .form-group.is-grow inline form row
38 .list-row + .list-row-title vertical item list
39 .form-row 2-col grid form
40 .cover-row + .cover-thumb + .cover-empty image picker
41
42 COMPONENT PRIMITIVES (reusable UI blocks)
43 .content-section light-bg page section box
44 .card / .card-muted / .card--bordered / .card--selectable
45 .form-group / .form-section / details.form-section
46 .section-header / .section-lead / .section-group-label
47 .badge + variants (-success/-warning/-danger)
48 .callout + --danger / --warning / --solid-warning
49 .banner + --info / --warning full-bleed page-top notice
50 .alert + -note / -tip / -warning / -caution left-border inline notice
51 .modal + .modal-overlay
52 .empty-state + --compact / --chart / --lg
53 .progress-bar-container + .progress-bar (--slim, --rounded, --highlight)
54 .upload-status + __row + __msg.is-success / .is-error
55 .field-status / .save-status + .success / .error / .saving
56 .toast + .toast--success / --error / --warning
57 .breadcrumb / .pagination
58 .tabs + .tab.is-selected
59
60 CONTROL MODIFIERS (compose onto buttons/inputs)
61 .small / .btn-compact / .btn-link / .btn-tiny button sizes
62 .primary / .secondary / .danger / .saved button intents
63 .input--xs / --sm / --mono / --upper / --numeric input sizes/shapes
64
65 FEATURE SUBAPPS (their own CSS scope)
66 .git-* (git source browser at /source/*)
67 Pricing calculator on /pricing
68 Markdown preview / docs-ui in /docs/*
69
70 PAGE-SCOPED LAYOUTS (when truly page-specific)
71 .item-page / .project-page / .article-page / .purchase-page / .cart-* /
72 .library-page / .feed-page / .discover-page / .landing / .creators-page /
73 .health-page / .import-page / .delete-account-page / .export-page /
74 .receipt-page / .fan-plus-page / .stripe-disclaimer-page / .buy-page /
75 .user-page / .collection-page / .changelog-page / .policy-page /
76 .tag-tree-page / .project-blog-page / .project-paywall-page /
77 .confirm-delete-page / .admin-page / .dashboard-page
78
79 DASHBOARD TABS (one section per tab partial)
80 Per-tab classes scoped under their canonical body class. Use modifier
81 composition where possible; only add tab-specific rules when the shape
82 genuinely diverges from a primitive.
83
84 RESPONSIVE (@media at end of file)
85 768px tablet
86 480px phone
87
88 --------------------------------------------------------------------------
89 When in doubt: read docs/design-system.md first. Update both files together
90 when you add a primitive.
91 ============================================================================ */
92
93 @font-face {
94 font-family: "Young Serif";
95 src: url("/static/fonts/ysrf.woff2") format("woff2"),
96 url("/static/fonts/ysrf.ttf") format("truetype");
97 font-display: swap;
98 }
99
100 @font-face {
101 font-family: "IBM Plex Mono";
102 src: url("/static/fonts/IBMPlexMono-Regular.woff2") format("woff2"),
103 url("/static/fonts/IBMPlexMono-Regular.ttf") format("truetype");
104 font-weight: normal;
105 font-display: swap;
106 }
107
108 @font-face {
109 font-family: "IBM Plex Mono";
110 src: url("/static/fonts/IBMPlexMono-Bold.woff2") format("woff2"),
111 url("/static/fonts/IBMPlexMono-Bold.ttf") format("truetype");
112 font-weight: bold;
113 font-display: swap;
114 }
115
116 @font-face {
117 font-family: "Lato";
118 src: url("/static/fonts/Lato-Regular.woff2") format("woff2"),
119 url("/static/fonts/Lato-Regular.ttf") format("truetype");
120 font-weight: normal;
121 font-display: swap;
122 }
123
124 @font-face {
125 font-family: "Lato";
126 src: url("/static/fonts/Lato-Bold.woff2") format("woff2"),
127 url("/static/fonts/Lato-Bold.ttf") format("truetype");
128 font-weight: bold;
129 font-display: swap;
130 }
131
132 :root {
133 /* Typography (three-tier system) */
134 --font-heading: "Young Serif", serif;
135 --font-mono: "IBM Plex Mono", monospace;
136 --font-body: "Lato", sans-serif;
137
138 /* --------------------------------------------------------------------
139 INTENT LAYER, the shared theme vocabulary (themeable)
140
141 These are the intent tokens emitted by theme_common::intent_css_vars():
142 colors declared by ROLE (surface/content/action/status/line/category),
143 plus the derived interactive states (hover/active/selection/row-stripe/
144 contrast) the crate computes once for every product. The values below
145 are the platform default (shared/themes/makenotwork.toml resolved) so
146 non-creator pages render without injection; creator profile/project/item
147 pages inject a <style> that supersedes this block with the chosen theme.
148 Generated. Keep in sync with `cargo run --example dump_intents makenotwork`.
149 -------------------------------------------------------------------- */
150 --surface-page: #ede8e1;
151 --surface-raised: #f5f0eb;
152 --surface-sunken: #ddd7c5;
153 --surface-overlay: #f4f0eb;
154 --content: #3d3530;
155 --content-secondary: #5c554f;
156 --content-muted: #8a8480;
157 --content-on-action: #ffffff;
158 --action: #6c5ce7;
159 --action-hover: #7a6cf8;
160 --danger: #c0392b;
161 --success: #27ae60;
162 --warning: #f59e0b;
163 --info: #17a2b8;
164 --border: #d0cbb8;
165 --border-strong: #c0bba8;
166 --focus-ring: #6c5ce7;
167 --hover-surface: #ddd7c5;
168 --category-one: #c0392b;
169 --category-two: #27ae60;
170 --category-three: #6c5ce7;
171 --category-four: #f59e0b;
172 --category-five: #a29bfe;
173 --category-six: #17a2b8;
174 --overlay: rgba(3, 2, 0, 0.5);
175
176 /* --------------------------------------------------------------------
177 APP-LOCAL CONSTANTS, not theme colors, not derivable from intents.
178
179 Component CSS references the intent tokens above directly (no brand
180 aliases). Status backgrounds and the faint accent tint derive from the
181 intents inline via color-mix(); these few stay fixed:
182 - pure black/white contrast anchors
183 - Stripe's brand color (an external constant)
184 - diff add/del, a hard readability convention that must not re-theme
185 -------------------------------------------------------------------- */
186 --primary-dark: #000000;
187 --primary-light: #ffffff;
188 --stripe: #635BFF;
189
190 /* Diff / code review, fixed green-add / red-del convention */
191 --diff-add: #2d7d2d;
192 --diff-add-bg: rgba(45, 125, 45, 0.08);
193 --diff-del: #a83232;
194 --diff-del-bg: rgba(168, 50, 50, 0.08);
195
196 /* Spacing scale (charter: docs/design-system.md) */
197 --space-1: 0.25rem;
198 --space-2: 0.5rem;
199 --space-3: 0.75rem;
200 --space-4: 1rem;
201 --space-5: 1.5rem;
202 --space-6: 2rem;
203 --space-7: 3rem;
204 --space-8: 4rem;
205
206 /* Radius scale */
207 --radius-sm: 2px;
208 --radius-md: 4px;
209 --radius-round: 50%;
210
211 /* Shadow scale.
212 --shadow-1/-2/-3 are blurred elevation (true floating: popovers,
213 dropdowns, modals). --shadow-raised/-card/-inset are hard-offset
214 "sticker on paper" depth for everyday affordance, buttons feel
215 pressable, cards feel layered, inputs feel recessed. Pick by role:
216 blurred = floats over page, hard-offset = is part of page. */
217 --shadow-edge: #bbb; /* heavier, pressable (button, tab) */
218 --shadow-edge-soft: #ddd; /* lighter, surface (card, input) */
219 --shadow-raised: 2px 2px var(--shadow-edge);
220 --shadow-card: 2px 2px var(--shadow-edge-soft);
221 --shadow-inset: inset 2px 2px var(--shadow-edge-soft);
222 --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.06);
223 --shadow-2: 0 2px 8px rgba(0, 0, 0, 0.10);
224 --shadow-3: 0 4px 12px rgba(0, 0, 0, 0.15);
225 }
226
227 /* Reset */
228 * {
229 margin: 0;
230 padding: 0;
231 box-sizing: border-box;
232 }
233
234 /* Base styles */
235 body {
236 margin: 0;
237 background-color: var(--surface-page);
238 color: var(--content);
239 font-family: var(--font-body);
240 line-height: 1.6;
241 }
242
243 /* Padded page layout for most content pages */
244 .padded-page {
245 padding: 1.5rem;
246 }
247
248 /* Centered page layout for landing, login, signup */
249 .centered-page {
250 display: flex;
251 flex-direction: column;
252 justify-content: center;
253 align-items: center;
254 min-height: 100vh;
255 gap: 2rem;
256 }
257
258 .centered-page h1 {
259 font-size: 4.5rem;
260 }
261
262 .message-container {
263 max-width: 500px;
264 text-align: center;
265 }
266
267 .centered-wrapper {
268 justify-content: center;
269 text-align: center;
270 }
271
272 h1 {
273 font-family: var(--font-heading);
274 font-weight: normal;
275 color: var(--content);
276 text-align: center;
277 font-size: 2.5rem;
278 }
279
280 h2,
281 h3 {
282 font-family: var(--font-mono);
283 font-weight: normal;
284 color: var(--content);
285 }
286
287 /* Heading classes (charter: docs/design-system.md, every h1/h2 in a
288 template must carry one of these so the role is explicit).
289
290 .brand-h1 the "Makenot.work" wordmark on auth/wizard pages.
291 .page-title page-level h1 (Young Serif, centered).
292 .subtitle-h2 page subtitle h2 used under .brand-h1 in auth/wizards.
293 .subsection-title, h2 inside dashboards, tabs, and prose partials
294 (mono, no border, the default-h2 role made explicit).
295 .section-header h2 prose sub-section heading with bottom border
296 (existing rule, see SECTIONS block). */
297 .brand-h1,
298 .page-title {
299 font-family: var(--font-heading);
300 font-weight: normal;
301 color: var(--content);
302 text-align: center;
303 font-size: 2.5rem;
304 }
305
306 .subtitle-h2 {
307 font-family: var(--font-mono);
308 font-weight: normal;
309 color: var(--content);
310 text-align: center;
311 font-size: 1.5rem;
312 }
313
314 .subsection-title {
315 font-family: var(--font-mono);
316 font-weight: normal;
317 color: var(--content);
318 }
319
320 p {
321 font-family: var(--font-body);
322 color: var(--content);
323 }
324
325 a {
326 color: var(--content);
327 text-decoration: none;
328 }
329
330 a:hover {
331 text-decoration: underline;
332 }
333
334 /* The signature dot */
335 .dot {
336 color: var(--action);
337 }
338
339 /* Container, default 1200px max-width. Modifier classes for narrower pages,
340 or comma-grouped page-scoped overrides below for body-class-based control. */
341 .container {
342 max-width: 1200px;
343 margin: 0 auto;
344 padding: 2rem;
345 }
346 .container--narrow { max-width: 600px; }
347 .container--medium { max-width: 800px; }
348 .container--wide { max-width: 900px; }
349
350 /* Per-page container width overrides (selected via body class). One rule
351 per width tier; new pages should add their body class here rather than
352 defining a new .foo-page .container rule. */
353 .delete-account-page .container,
354 .receipt-page .container,
355 .user-page .container { max-width: 600px; margin: 0 auto; }
356
357 .import-page .container,
358 .export-page .container { max-width: 800px; margin: 0 auto; }
359
360 .fan-plus-page .container,
361 .feed-page .container,
362 .creators-page .container { max-width: 900px; margin: 0 auto; }
363
364 /* ===========================================
365 BUTTONS
366 =========================================== */
367
368 button {
369 color: var(--content);
370 background: var(--surface-overlay);
371 padding: 6px 12px;
372 border: 1px solid var(--content);
373 font-family: inherit;
374 cursor: pointer;
375 box-shadow: var(--shadow-raised);
376 transition: box-shadow 0.1s ease, transform 0.05s ease;
377 }
378
379 button:hover {
380 box-shadow: 3px 3px var(--shadow-edge);
381 }
382
383 button:active {
384 box-shadow: none;
385 transform: translate(2px, 2px);
386 }
387
388 .btn-primary {
389 background: var(--primary-dark);
390 color: var(--primary-light);
391 border: none;
392 padding: 0.75rem 1.5rem;
393 font-family: inherit;
394 font-size: 1rem;
395 cursor: pointer;
396 box-shadow: var(--shadow-raised);
397 transition: box-shadow 0.1s ease, transform 0.05s ease;
398 display: inline-block;
399 text-decoration: none;
400 }
401
402 .btn-primary:hover {
403 box-shadow: 3px 3px var(--shadow-edge);
404 text-decoration: none;
405 }
406
407 .btn-primary:active {
408 box-shadow: none;
409 transform: translate(2px, 2px);
410 }
411
412 .btn-secondary {
413 background: var(--surface-sunken);
414 color: var(--content);
415 border: none;
416 padding: 0.75rem 1.5rem;
417 font-family: var(--font-mono);
418 font-size: 1rem;
419 cursor: pointer;
420 box-shadow: var(--shadow-raised);
421 transition: box-shadow 0.1s ease, transform 0.05s ease;
422 display: inline-block;
423 text-decoration: none;
424 }
425
426 .btn-secondary:hover {
427 box-shadow: 3px 3px var(--shadow-edge);
428 text-decoration: none;
429 }
430
431 .btn-secondary:active {
432 box-shadow: none;
433 transform: translate(2px, 2px);
434 }
435
436 .btn-danger {
437 background: var(--danger);
438 color: var(--primary-light);
439 border: none;
440 padding: 0.75rem 1.5rem;
441 font-family: var(--font-mono);
442 font-size: 1rem;
443 cursor: pointer;
444 box-shadow: var(--shadow-raised);
445 transition: box-shadow 0.1s ease, transform 0.05s ease;
446 display: inline-block;
447 text-decoration: none;
448 }
449
450 .btn-danger:hover {
451 box-shadow: 3px 3px var(--shadow-edge);
452 text-decoration: none;
453 }
454
455 .btn-danger:active {
456 box-shadow: none;
457 transform: translate(2px, 2px);
458 }
459
460 /* Disabled state for all button variants (charter rule).
461 Applies whether disabled via attribute or aria-disabled. */
462 button:disabled,
463 button[aria-disabled="true"],
464 .btn-primary:disabled,
465 .btn-secondary:disabled,
466 .btn-danger:disabled {
467 opacity: 0.5;
468 cursor: not-allowed;
469 box-shadow: none;
470 transform: none;
471 }
472
473 /* Button size + style modifiers (charter: docs/design-system.md).
474 Use these on top of .btn-primary / -secondary / -danger.
475
476 .btn--large large CTA padding bump.
477 .btn--icon square icon-only / micro button (small padding,
478 tight line-height).
479 .btn--link visually a link, semantically a button (no bg/
480 border, opacity-fade hover, mono).
481
482 Some surfaces have tuned button variants that are NOT compositions
483 of these modifiers and keep their own classes:
484 .big-button Young Serif 200×60 anchor on splash pages.
485 .order-btn list reorder up/down (with active flash).
486 .play-button circular media-player play control.
487 .speed-button segment in media-player speed group.
488 .shortcuts-help-btn, 1.5rem square help glyph in toolbars.
489 .toast-retry-btn inline bordered button inside a toast,
490 uses currentColor to inherit toast tone.
491 These are documented variants, not deprecation targets. */
492 .btn--large {
493 padding: 1rem 2.25rem;
494 font-size: 1.125rem;
495 }
496
497 .btn--icon {
498 padding: var(--space-1) var(--space-2);
499 font-size: 0.85rem;
500 line-height: 1;
501 min-width: 1.75rem;
502 }
503
504 .btn--link {
505 background: none;
506 color: var(--content);
507 border: none;
508 padding: 0;
509 font-family: var(--font-mono);
510 font-size: 1rem;
511 cursor: pointer;
512 /* Link semantics, flat, no depth. Overrides the shadow that would
513 otherwise cascade from `button` / `form button` when a .btn--link
514 happens to be a <button> inside a <form> (e.g. logout). */
515 box-shadow: none;
516 transition: opacity 0.2s ease;
517 }
518
519 .btn--link:hover {
520 opacity: 0.6;
521 box-shadow: none;
522 }
523
524 .btn--link:active {
525 box-shadow: none;
526 transform: none;
527 }
528
529 /* Menu / disclosure openers, buttons whose job is to reveal a menu,
530 filter panel, expander, or popover. They navigate UI, they don't
531 commit anything, so they override the base `button` depth-lift back
532 to flat. Add new opener selectors here as they appear. */
533 .context-menu-btn,
534 .discover-filter-toggle,
535 .tip-toggle,
536 .bundle-toggle {
537 box-shadow: none;
538 }
539
540 .context-menu-btn:hover,
541 .discover-filter-toggle:hover,
542 .tip-toggle:hover,
543 .bundle-toggle:hover {
544 box-shadow: none;
545 }
546
547 .context-menu-btn:active,
548 .discover-filter-toggle:active,
549 .tip-toggle:active,
550 .bundle-toggle:active {
551 box-shadow: none;
552 transform: none;
553 }
554
555 /* ===========================================
556 FORMS
557 =========================================== */
558
559 form {
560 display: flex;
561 flex-direction: column;
562 gap: 1rem;
563 width: 100%;
564 }
565
566 .form-container {
567 max-width: 400px;
568 background: var(--surface-overlay);
569 padding: 2rem;
570 }
571
572 label {
573 font-family: var(--font-mono);
574 color: var(--content);
575 font-size: 14px;
576 }
577
578 input[type="text"],
579 input[type="email"],
580 input[type="password"],
581 input[type="number"],
582 input[type="date"],
583 textarea,
584 select {
585 width: 100%;
586 background: var(--surface-sunken);
587 border: 1px solid var(--border);
588 padding: 0.75rem;
589 font-family: var(--font-mono);
590 font-size: 0.9rem;
591 color: var(--content);
592 box-shadow: var(--shadow-inset);
593 }
594
595 input::placeholder,
596 textarea::placeholder {
597 opacity: 0.5;
598 }
599
600 input[type="text"]:focus,
601 input[type="email"]:focus,
602 input[type="password"]:focus,
603 input[type="number"]:focus,
604 textarea:focus,
605 select:focus {
606 outline: none;
607 border: 1px solid var(--action);
608 }
609
610 textarea {
611 min-height: 100px;
612 resize: vertical;
613 }
614
615 select {
616 cursor: pointer;
617 }
618
619 input[type="submit"],
620 form button {
621 font-family: var(--font-heading);
622 font-size: 16px;
623 color: var(--content);
624 background: var(--surface-overlay);
625 padding: 12px 24px;
626 border: 1px solid var(--content);
627 cursor: pointer;
628 box-shadow: var(--shadow-raised);
629 transition: box-shadow 0.1s ease, transform 0.05s ease, background 0.2s ease;
630 }
631
632 input[type="submit"]:hover,
633 form button:hover {
634 background: var(--surface-page);
635 box-shadow: 3px 3px var(--shadow-edge);
636 }
637
638 input[type="submit"]:active,
639 form button:active {
640 box-shadow: none;
641 transform: translate(2px, 2px);
642 }
643
644 .form-group {
645 margin-bottom: 1.5rem;
646 }
647
648 .form-group label {
649 display: block;
650 margin-bottom: 0.5rem;
651 font-size: 0.9rem;
652 }
653
654 .form-group input,
655 .form-group textarea,
656 .form-group select {
657 width: 100%;
658 }
659
660 .form-row {
661 display: grid;
662 grid-template-columns: 1fr 1fr;
663 gap: 1rem;
664 }
665
666 .hint {
667 font-size: 0.85rem;
668 opacity: 0.6;
669 margin-top: 0.5rem;
670 }
671
672 /* Field-level validation error, paired with .form-group--error.
673 Canonical: `partials/_ui.html` ui::form_field macro. */
674 .form-group--error label {
675 color: var(--danger);
676 }
677
678 .form-group--error input,
679 .form-group--error textarea,
680 .form-group--error select {
681 border-color: var(--danger);
682 }
683
684 .field-error {
685 font-size: 0.85rem;
686 color: var(--danger);
687 margin-top: var(--space-2);
688 }
689
690 /* Loading skeleton placeholder.
691 Canonical: `partials/_ui.html` ui::loading_skeleton macro. */
692 .loading-skeleton {
693 background: var(--surface-sunken);
694 border-radius: var(--radius-md);
695 animation: skeleton-pulse 1.2s ease-in-out infinite;
696 }
697
698 .loading-skeleton--row {
699 height: 1.25rem;
700 margin: var(--space-2) 0;
701 }
702
703 .loading-skeleton--card {
704 height: 8rem;
705 margin: var(--space-3) 0;
706 }
707
708 .loading-skeleton--list .loading-skeleton--row + .loading-skeleton--row {
709 margin-top: var(--space-2);
710 }
711
712 @keyframes skeleton-pulse {
713 0%, 100% { opacity: 0.5; }
714 50% { opacity: 0.9; }
715 }
716
717 /* Checkbox group */
718 .checkbox-group {
719 display: flex;
720 align-items: start;
721 gap: 0.75rem;
722 cursor: pointer;
723 transition: background 0.2s ease;
724 margin-bottom: 0.5rem;
725 }
726
727 .checkbox-group input[type="checkbox"] {
728 width: auto;
729 margin-top: 0.25rem;
730 margin-bottom: 0.25rem;
731 cursor: pointer;
732 }
733 /* Radio group */
734 .radio-group {
735 display: flex;
736 flex-direction: column;
737 gap: 0.75rem;
738 margin-top: 0.5rem;
739 }
740 /* ===========================================
741 TABS
742 =========================================== */
743
744 .tabs {
745 display: flex;
746 flex-wrap: nowrap;
747 gap: 0;
748 margin-bottom: 0;
749 }
750
751 .tab {
752 background: var(--surface-sunken);
753 color: var(--content);
754 border: none;
755 padding: 0.75rem 2rem;
756 font-family: var(--font-mono);
757 font-size: 1rem;
758 cursor: pointer;
759 /* Tabs navigate, they don't commit, stay flat. Overrides the base
760 `button` shadow if a tab is a <button>. */
761 box-shadow: none;
762 transition:
763 background 0.2s ease,
764 opacity 0.2s ease;
765 opacity: 0.6;
766 white-space: nowrap;
767 flex-shrink: 0;
768 }
769
770 .tab.is-selected {
771 background: var(--surface-overlay);
772 opacity: 1;
773 }
774
775 .tab:hover {
776 opacity: 1;
777 }
778
779 .tab-more-wrap {
780 position: relative;
781 flex-shrink: 0;
782 }
783
784 .tab-overflow-menu {
785 position: absolute;
786 top: 100%;
787 right: 0;
788 z-index: 10;
789 background: var(--surface-page);
790 border: 1px solid var(--border);
791 min-width: 180px;
792 box-shadow: var(--shadow-2);
793 }
794
795 .tab-overflow-menu .tab {
796 display: block;
797 width: 100%;
798 text-align: left;
799 padding: 0.6rem 1rem;
800 opacity: 0.7;
801 }
802
803 .tab-overflow-menu .tab:hover {
804 opacity: 1;
805 }
806
807 .tab-overflow-menu .tab.is-selected {
808 opacity: 1;
809 }
810
811 .tab-content {
812 display: none;
813 background: var(--surface-overlay);
814 padding: 2rem;
815 }
816
817 .tab-content.active {
818 display: block;
819 }
820
821 /* ===========================================
822 TABLES
823 =========================================== */
824
825 .data-table {
826 width: 100%;
827 border-collapse: collapse;
828 font-size: 0.9rem;
829 font-family: var(--font-body);
830 margin-bottom: 1rem;
831 }
832
833 .data-table thead {
834 background: var(--surface-sunken);
835 }
836
837 .data-table th {
838 text-align: left;
839 padding: 0.75rem 1rem;
840 font-weight: normal;
841 }
842
843 .data-table th.sortable {
844 cursor: pointer;
845 transition: background 0.2s ease;
846 user-select: none;
847 }
848
849 .data-table th.sortable:hover {
850 background: var(--border);
851 }
852
853 .data-table th.sortable::after {
854 content: " ^";
855 opacity: 0.3;
856 font-size: 0.8rem;
857 }
858
859 .data-table tbody tr {
860 transition: background 0.1s ease;
861 }
862
863 .data-table tbody tr:nth-child(odd) {
864 background: var(--surface-overlay);
865 }
866
867 .data-table tbody tr:nth-child(even) {
868 background: var(--surface-overlay);
869 }
870
871 .data-table tbody tr:hover {
872 background: var(--surface-sunken);
873 }
874
875 .data-table td {
876 padding: 0.75rem 1rem;
877 border-top: 1px solid var(--border);
878 }
879
880 /* ===========================================
881 COMPACT TABLES (dashboard/admin, lighter than .data-table)
882 =========================================== */
883
884 .compact-table {
885 width: 100%;
886 border-collapse: collapse;
887 }
888
889 .compact-table thead tr {
890 font-size: 0.85rem;
891 opacity: 0.7;
892 }
893
894 .compact-table th {
895 padding: 0.5rem 0.75rem;
896 text-align: left;
897 }
898
899 .compact-table td {
900 padding: 0.75rem;
901 }
902
903 .compact-table tbody tr {
904 border-bottom: 1px solid var(--border);
905 }
906
907 /* ===========================================
908 UTILITIES
909 =========================================== */
910
911 .text-sm { font-size: 0.85rem; }
912 .text-xs { font-size: 0.8rem; }
913 .muted { opacity: 0.7; }
914 .dimmed { opacity: 0.6; }
915 .dimmer { opacity: 0.5; }
916 .meta { font-size: 0.85rem; opacity: 0.7; }
917 .nowrap { white-space: nowrap; }
918 .scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
919 .text-center { text-align: center; }
920 .text-right { text-align: right; }
921 .fw-bold { font-weight: bold; }
922 .unstyled-link { text-decoration: none; color: inherit; }
923 .square-cover { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
924
925 /* Spacing utilities (mapped to --space-* scale).
926 mt = margin-top, mb = margin-bottom, my = vertical, mx = horizontal,
927 m0 = margin reset. Use sparingly; prefer parent layout primitives. */
928 .m-0 { margin: 0; }
929 .mt-0 { margin-top: 0; }
930 .mt-2 { margin-top: var(--space-2); }
931 .mt-3 { margin-top: var(--space-3); }
932 .mt-4 { margin-top: var(--space-4); }
933 .mt-5 { margin-top: var(--space-5); }
934 .mt-6 { margin-top: var(--space-6); }
935 .mb-0 { margin-bottom: 0; }
936 .mb-2 { margin-bottom: var(--space-2); }
937 .mb-3 { margin-bottom: var(--space-3); }
938 .mb-4 { margin-bottom: var(--space-4); }
939 .mb-5 { margin-bottom: var(--space-5); }
940 .mb-6 { margin-bottom: var(--space-6); }
941 .my-2 { margin-top: var(--space-2); margin-bottom: var(--space-2); }
942 .my-3 { margin-top: var(--space-3); margin-bottom: var(--space-3); }
943 .my-4 { margin-top: var(--space-4); margin-bottom: var(--space-4); }
944
945 /* Min-width utilities for tables inside .scroll-x wrappers. */
946 .minw-300 { min-width: 300px; }
947 .minw-400 { min-width: 400px; }
948 .minw-500 { min-width: 500px; }
949 .minw-600 { min-width: 600px; }
950 .minw-700 { min-width: 700px; }
951 .minw-800 { min-width: 800px; }
952
953 /* Compact button sizes. Canonical: .small (broad use, 0.25rem 0.6rem 0.8rem).
954 The tiny / row-btn / cart-row-btn aliases are visually equivalent, within
955 sub-pixel of each other in the original templates, and folded into .small. */
956 .small { padding: 0.25rem 0.6rem; font-size: 0.8rem; }
957
958 /* Canonical empty-state primitive. Use modifiers for tight/sized contexts.
959 Markup: <div class="empty-state">…</div> (optionally with .empty-state--compact
960 inside dropdowns or .empty-state--chart inside a fixed-height chart slot). */
961 .empty-state { text-align: center; padding: 2rem; opacity: 0.6; }
962 .empty-state--compact { padding: 0.75rem; font-size: 0.9rem; }
963 .empty-state--chart { height: 200px; padding: 0; display: flex; align-items: center; justify-content: center; opacity: 0.5; }
964 .empty-state-hint { font-family: var(--font-mono); font-size: 0.8rem; margin-top: 0.5rem; opacity: 0.6; }
965
966 .tab-docs {
967 display: flex;
968 justify-content: flex-end;
969 margin-bottom: 1rem;
970 }
971
972 .tab-docs a {
973 font-family: var(--font-mono);
974 font-size: 0.8rem;
975 opacity: 0.5;
976 transition: opacity 0.2s ease;
977 }
978
979 .tab-docs a:hover {
980 opacity: 1;
981 }
982
983 /* ===========================================
984 BADGES
985 =========================================== */
986
987 .badge {
988 display: inline-block;
989 padding: 0.2rem 0.5rem;
990 font-size: 0.75rem;
991 font-family: var(--font-mono);
992 background: var(--primary-dark);
993 color: var(--primary-light);
994 }
995
996 .badge-success,
997 .badge.active,
998 .badge.complete {
999 background: var(--success);
1000 }
1001
1002 .badge-warning,
1003 .badge.pending,
1004 .badge.draft {
1005 background: var(--warning);
1006 }
1007
1008 .badge-danger,
1009 .badge.failed {
1010 background: var(--danger);
1011 }
1012
1013 .badge.current {
1014 background: var(--success);
1015 }
1016
1017 .badge.suppressed {
1018 background: var(--warning);
1019 }
1020
1021 .badge.suspended {
1022 background: color-mix(in oklch, var(--danger) 10%, var(--surface-page));
1023 color: var(--danger);
1024 }
1025
1026 .badge.free {
1027 background: var(--action);
1028 color: var(--primary-light);
1029 }
1030
1031 /* AI disclosure tier badges. See site-docs/public/about/generative-ai.md.
1032 Colors track the brand palette, violet for the cleanest case,
1033 warm-tan for disclosed-AI-use, charcoal for primarily-generated.
1034 Deliberately not red/yellow/green; this is disclosure, not alarm. */
1035 .badge.ai-tier {
1036 letter-spacing: 0.02em;
1037 }
1038 .badge.ai-tier-handmade {
1039 background: var(--action);
1040 color: var(--primary-light);
1041 }
1042 .badge.ai-tier-assisted {
1043 background: var(--warning);
1044 color: var(--primary-light);
1045 }
1046 .badge.ai-tier-generated {
1047 background: var(--content);
1048 color: var(--primary-light);
1049 }
1050
1051 .item-ai-tier {
1052 margin: 0.25rem 0 0.75rem;
1053 }
1054
1055 .ai-disclosure {
1056 margin: 0.75rem 0;
1057 padding: 0.75rem 1rem;
1058 background: var(--surface-sunken);
1059 border-left: 3px solid var(--warning);
1060 }
1061 .ai-disclosure-label {
1062 font-family: var(--font-mono);
1063 font-size: 0.75rem;
1064 text-transform: uppercase;
1065 letter-spacing: 0.05em;
1066 color: var(--content-muted);
1067 margin-bottom: 0.25rem;
1068 }
1069 .ai-disclosure-text {
1070 font-size: 0.9rem;
1071 color: var(--content);
1072 }
1073
1074 /* Discover row: plain text mention per design decision 2026-06-03:
1075 no pill in the row, so fans skim the listing without disclosure noise
1076 and use the explicit filter when they care. */
1077 .discover-row-ai-tier {
1078 font-family: var(--font-mono);
1079 font-size: 0.75rem;
1080 color: var(--content-muted);
1081 }
1082
1083 /* ===========================================
1084 TAGS
1085 =========================================== */
1086
1087 .tag {
1088 display: inline-block;
1089 background: var(--primary-dark);
1090 color: var(--primary-light);
1091 padding: 0.2rem 0.4rem;
1092 font-size: 0.75rem;
1093 margin-right: 0.25rem;
1094 }
1095
1096 .tag-input {
1097 background: var(--surface-sunken);
1098 padding: 0.5rem;
1099 margin-bottom: 0.5rem;
1100 display: flex;
1101 flex-wrap: wrap;
1102 gap: 0.5rem;
1103 min-height: 40px;
1104 }
1105
1106 .tag-input .tag {
1107 display: flex;
1108 align-items: center;
1109 gap: 0.5rem;
1110 padding: 0.25rem 0.5rem;
1111 font-size: 0.85rem;
1112 }
1113
1114 .tag-input .tag button {
1115 background: none;
1116 border: none;
1117 color: var(--primary-light);
1118 cursor: pointer;
1119 padding: 0;
1120 font-size: 1rem;
1121 }
1122
1123 /* ===========================================
1124 CARDS
1125 =========================================== */
1126
1127 /* Canonical card primitive (charter: docs/design-system.md).
1128 Variants:
1129 .card filled, hover-step (default content card).
1130 .card.card-muted surface-muted fill, no hover (dashboard stat / analytics blocks).
1131 .card.card--bordered bordered, padded, no fill (marketing cards: feature/tier/use-case).
1132 .card.card--selectable radio-card pattern; pair with .is-selected.
1133 .card.card--grid grid-cell card (discover grid).
1134 Legacy class names (.stat-card, .analytics-card, .feature-card, .tier-card,
1135 .use-case-card) are aliased to these recipes below, templates migrate at
1136 their own pace. */
1137 .card {
1138 background: var(--surface-overlay);
1139 padding: 1.5rem;
1140 margin-bottom: 1rem;
1141 text-decoration: none;
1142 color: var(--content);
1143 display: block;
1144 border: 1px solid var(--border);
1145 box-shadow: var(--shadow-card);
1146 transition: background 0.2s ease;
1147 }
1148
1149 .card:hover {
1150 background: var(--surface-sunken);
1151 }
1152
1153 /* Muted card primitive. */
1154 .card-muted {
1155 background: var(--surface-sunken);
1156 padding: 1.5rem;
1157 }
1158 /* Bordered card (.card--bordered alias for .feature-card, .tier-card, .use-case-card, .fork-card). */
1159 .card--bordered,
1160 .feature-card,
1161 .tier-card,
1162 .use-case-card,
1163 .fork-card {
1164 background: transparent;
1165 padding: 1rem;
1166 border: 1px solid var(--border);
1167 margin-bottom: 0;
1168 }
1169 .use-case-card { padding: 1.25rem; }
1170 .fork-card { padding: 1.5rem; display: flex; flex-direction: column; }
1171
1172 .card-title {
1173 font-size: 1.2rem;
1174 margin-bottom: 0.5rem;
1175 font-family: var(--font-heading);
1176 }
1177
1178 .card-meta {
1179 font-size: 0.85rem;
1180 color: var(--content-muted);
1181 margin-bottom: 0.5rem;
1182 font-family: var(--font-mono);
1183 }
1184
1185 .card-description {
1186 font-size: 0.9rem;
1187 opacity: 0.8;
1188 font-family: var(--font-body);
1189 }
1190
1191 /* ===========================================
1192 STATS
1193 =========================================== */
1194
1195 .stats-grid {
1196 display: grid;
1197 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1198 gap: 1rem;
1199 margin-bottom: 1.5rem;
1200 }
1201
1202 .stats-row {
1203 display: flex;
1204 gap: 1.5rem;
1205 margin: 1.5rem 0;
1206 }
1207
1208 .stat-box {
1209 background: var(--surface-overlay);
1210 padding: 1rem 1.5rem;
1211 flex: 1;
1212 text-align: center;
1213 }
1214
1215 .stat-box .number {
1216 font-family: var(--font-heading);
1217 font-weight: bold;
1218 font-size: 1.5rem;
1219 }
1220
1221 .stat-box .label {
1222 font-size: 0.8rem;
1223 opacity: 0.7;
1224 }
1225
1226 /* .stat-card base recipe defined above with .card-muted */
1227
1228 .stat-label {
1229 font-size: 0.85rem;
1230 opacity: 0.7;
1231 margin-bottom: 0.25rem;
1232 }
1233
1234 .stat-value {
1235 font-size: 1.5rem;
1236 }
1237
1238 .stat-change {
1239 font-size: 0.85rem;
1240 opacity: 0.6;
1241 }
1242
1243 .stat-change.positive {
1244 color: var(--success);
1245 }
1246
1247 .stat-change.negative {
1248 color: var(--danger);
1249 }
1250
1251 /* ===========================================
1252 FILTER BAR
1253 =========================================== */
1254
1255 .filter-bar {
1256 display: flex;
1257 gap: 0.5rem;
1258 margin: 1.5rem 0;
1259 flex-wrap: wrap;
1260 align-items: center;
1261 }
1262
1263 .filter-bar > .label {
1264 font-size: 0.85rem;
1265 opacity: 0.7;
1266 margin-right: 0.5rem;
1267 }
1268
1269 .filter-bar button {
1270 padding: 0.3rem 0.8rem;
1271 font-size: 0.85rem;
1272 }
1273
1274 /* ===========================================
1275 DISCUSSION SECTION
1276 =========================================== */
1277
1278 /* Sits inside the parent container; previously had max-width: 720px and
1279 margin: 2rem auto, which looked indented on wide pages (.library-page,
1280 .item-page) where every neighbouring card filled the container. Let the
1281 parent dictate width, article-page already constrains via
1282 .article-container; player pages have their own narrow layout. */
1283 .discussion-section {
1284 margin: 2rem 0;
1285 padding: 1.5rem;
1286 border: 1px solid var(--border);
1287 font-family: var(--font-mono);
1288 }
1289
1290 .discussion-section h3 {
1291 font-family: var(--font-heading);
1292 font-size: 1.25rem;
1293 margin: 0 0 0.5rem;
1294 }
1295
1296 .discussion-section p {
1297 margin: 0 0 0.75rem;
1298 color: var(--content-muted);
1299 font-size: 0.875rem;
1300 }
1301
1302 .discussion-section a {
1303 color: var(--action);
1304 text-decoration: none;
1305 font-size: 0.875rem;
1306 }
1307
1308 /* ===========================================
1309 INFO & WARNING BOXES
1310 =========================================== */
1311
1312 /* Notification surface roles (charter: docs/design-system.md).
1313 Five distinct components. Keep them distinct, don't merge:
1314 .toast transient, JS-dismissible, bottom-right corner.
1315 .banner full-bleed page-top notice (sandbox, restart,
1316 founder pricing). One short sentence + optional link.
1317 .alert inline directive callout with uppercase mono title
1318 (NOTE / TIP / IMPORTANT / WARNING / CAUTION). Used in
1319 docs and longer-form bodies.
1320 .info-box informational headed block with h3 + bullet list
1321 inside forms / wizards (distinct register from .alert).
1322 .warning-box loud yellow-on-yellow attention-grabber for
1323 page-level warnings (delete confirms, account
1324 warnings). Louder than .alert-warning intentionally.
1325 .error-message inline form-field error; hidden by default, shown
1326 with .is-active. Distinct from page-level .alert. */
1327 .info-box {
1328 background: var(--surface-sunken);
1329 padding: 1rem;
1330 margin-bottom: 1rem;
1331 font-size: 0.9rem;
1332 font-family: var(--font-body);
1333 }
1334
1335 .info-box h3 {
1336 font-size: 1rem;
1337 font-weight: normal;
1338 margin-bottom: 0.5rem;
1339 }
1340
1341 .info-box ul {
1342 list-style: none;
1343 margin-top: 0.5rem;
1344 }
1345
1346 .info-box li {
1347 padding: 0.25rem 0;
1348 }
1349
1350 .info-box li::before {
1351 content: "- ";
1352 opacity: 0.5;
1353 }
1354
1355 .warning-box {
1356 background: var(--warning);
1357 color: var(--primary-light);
1358 padding: 1rem;
1359 margin-bottom: 1rem;
1360 font-size: 0.9rem;
1361 font-family: var(--font-body);
1362 }
1363
1364 .error-message {
1365 font-family: var(--font-mono);
1366 color: var(--danger);
1367 background: color-mix(in oklch, var(--danger) 10%, var(--surface-page));
1368 padding: 12px;
1369 border: 1px solid var(--danger);
1370 border-radius: 2px;
1371 text-align: center;
1372 font-size: 14px;
1373 display: none;
1374 }
1375
1376 /* Full-page error layout (templates/pages/error.html). Distinct from
1377 the inline `.error-message` form-error class above; named to avoid
1378 collision. */
1379 .error-page {
1380 min-height: 100vh;
1381 display: flex;
1382 align-items: center;
1383 justify-content: center;
1384 padding: var(--space-6);
1385 background: var(--surface-page);
1386 }
1387
1388 .error-container {
1389 text-align: center;
1390 max-width: 560px;
1391 }
1392
1393 .error-status {
1394 font-size: 0.85rem;
1395 font-weight: 600;
1396 letter-spacing: 0.08em;
1397 text-transform: uppercase;
1398 color: var(--content-muted);
1399 margin-bottom: var(--space-4);
1400 }
1401
1402 .error-page-message {
1403 font-size: 1.5rem;
1404 line-height: 1.4;
1405 color: var(--content);
1406 margin-bottom: var(--space-6);
1407 }
1408
1409 .error-actions {
1410 display: flex;
1411 gap: var(--space-4);
1412 justify-content: center;
1413 }
1414
1415 .error-actions a.primary,
1416 .error-actions a.secondary {
1417 text-decoration: none;
1418 }
1419
1420 /* Minimal direct-purchase page (templates/pages/buy.html). Standalone
1421 page used for link-in-bio sharing, no site chrome, just a card.
1422 Scoped under .buy-page so the rules don't bleed into the rest of
1423 the app. Tokenized; previously lived as a page-isolated <style>. */
1424 .buy-page {
1425 min-height: 100vh;
1426 display: flex;
1427 align-items: center;
1428 justify-content: center;
1429 padding: var(--space-6);
1430 }
1431
1432 .buy-page .buy-card {
1433 background: var(--surface-overlay);
1434 border-radius: 12px;
1435 padding: var(--space-6);
1436 max-width: 420px;
1437 width: 100%;
1438 box-shadow: var(--shadow-3);
1439 }
1440
1441 .buy-page .cover,
1442 .buy-page .no-cover {
1443 width: 100%;
1444 aspect-ratio: 1;
1445 max-height: 280px;
1446 border-radius: 8px;
1447 margin-bottom: var(--space-5);
1448 background: var(--surface-raised);
1449 }
1450
1451 .buy-page .cover {
1452 object-fit: cover;
1453 }
1454
1455 .buy-page .no-cover {
1456 display: flex;
1457 align-items: center;
1458 justify-content: center;
1459 font-size: 3rem;
1460 opacity: 0.2;
1461 }
1462
1463 .buy-page h1 {
1464 text-align: left;
1465 font-size: 1.4rem;
1466 margin-bottom: var(--space-1);
1467 }
1468
1469 .buy-page .creator {
1470 font-family: var(--font-mono);
1471 font-size: 0.85rem;
1472 opacity: 0.6;
1473 margin-bottom: var(--space-5);
1474 }
1475
1476 .buy-page .creator a {
1477 color: inherit;
1478 }
1479
1480 .buy-page .price {
1481 font-family: var(--font-mono);
1482 font-size: 1.3rem;
1483 margin-bottom: var(--space-5);
1484 }
1485
1486 .buy-page .description {
1487 font-size: 0.9rem;
1488 line-height: 1.5;
1489 opacity: 0.8;
1490 margin-bottom: var(--space-5);
1491 max-height: 4.5em;
1492 overflow: hidden;
1493 }
1494
1495 .buy-page .buy-btn {
1496 display: block;
1497 width: 100%;
1498 padding: 14px;
1499 background: var(--action);
1500 color: var(--primary-light);
1501 border: none;
1502 border-radius: 6px;
1503 font-size: 1rem;
1504 font-weight: 600;
1505 cursor: pointer;
1506 text-align: center;
1507 text-decoration: none;
1508 transition: opacity 0.2s ease;
1509 }
1510
1511 .buy-page .buy-btn:hover {
1512 opacity: 0.85;
1513 }
1514
1515 .buy-page .buy-btn:disabled {
1516 opacity: 0.6;
1517 cursor: wait;
1518 }
1519
1520 .buy-page .pwyw-input {
1521 display: flex;
1522 align-items: center;
1523 gap: var(--space-1);
1524 margin-bottom: var(--space-4);
1525 }
1526
1527 .buy-page .pwyw-input input {
1528 width: 100px;
1529 padding: 8px;
1530 border: 1px solid var(--border);
1531 border-radius: var(--radius-md);
1532 font-size: 1rem;
1533 }
1534
1535 .buy-page .note {
1536 font-size: 0.8rem;
1537 opacity: 0.5;
1538 text-align: center;
1539 margin-top: var(--space-4);
1540 }
1541
1542 .buy-page .note a {
1543 color: var(--action);
1544 }
1545
1546 .buy-page .footer {
1547 text-align: center;
1548 margin-top: var(--space-5);
1549 padding-top: var(--space-4);
1550 border-top: 1px solid var(--border);
1551 font-size: 0.8rem;
1552 opacity: 0.5;
1553 }
1554
1555 .buy-page .footer a {
1556 color: inherit;
1557 }
1558
1559 /* Sectioned content (templates/pages/item.html, project.html,
1560 library_downloads.html). Tab+panel pattern shared by all three
1561 pages, kept global, NOT scoped under .item-page. */
1562 .section-tabs {
1563 display: flex;
1564 gap: 0;
1565 border-bottom: 1px solid var(--border);
1566 margin-bottom: var(--space-5);
1567 }
1568
1569 .section-tab {
1570 background: none;
1571 border: none;
1572 padding: 0.6rem 1.2rem;
1573 cursor: pointer;
1574 font-size: 0.95rem;
1575 opacity: 0.6;
1576 border-bottom: 2px solid transparent;
1577 font-family: var(--font-body);
1578 color: var(--content);
1579 }
1580
1581 .section-tab.is-selected {
1582 opacity: 1;
1583 border-bottom-color: var(--content);
1584 }
1585
1586 .section-tab:hover { opacity: 0.9; }
1587
1588 /* .section-panel.active is a visibility toggle (display: none / block),
1589 not a selection, kept as .active. */
1590 .section-panel { display: none; }
1591 .section-panel.active { display: block; }
1592 .section-panel p { margin-bottom: var(--space-4); }
1593 .section-panel ul,
1594 .section-panel ol {
1595 margin-left: var(--space-5);
1596 margin-bottom: var(--space-4);
1597 }
1598 .section-panel li { margin-bottom: var(--space-2); }
1599 .section-panel h1,
1600 .section-panel h2,
1601 .section-panel h3 {
1602 margin-top: var(--space-4);
1603 margin-bottom: var(--space-2);
1604 }
1605 .section-panel pre {
1606 background: var(--surface-sunken);
1607 padding: var(--space-4);
1608 overflow-x: auto;
1609 margin-bottom: var(--space-4);
1610 }
1611 .section-panel code { font-size: 0.9rem; }
1612
1613 /* Item detail page (templates/pages/item.html). Scoped under .item-page
1614 body class so the .item-title / .item-meta / .item-price / .item-footer
1615 names don't collide with the store-front item-card on project.html. */
1616 .item-page .item-layout {
1617 display: grid;
1618 grid-template-columns: 400px 1fr;
1619 gap: var(--space-6);
1620 margin-bottom: var(--space-6);
1621 }
1622
1623 .item-page .item-layout.no-media { grid-template-columns: 1fr; }
1624
1625 .item-page .item-title {
1626 font-size: 2rem;
1627 margin-bottom: var(--space-2);
1628 }
1629
1630 .item-page .item-creator {
1631 font-size: 1rem;
1632 opacity: 0.7;
1633 margin-bottom: var(--space-5);
1634 }
1635
1636 .item-page .item-creator a { color: var(--content); }
1637
1638 .item-page .item-price {
1639 font-size: 2.5rem;
1640 margin-bottom: var(--space-5);
1641 }
1642
1643 .item-page .item-meta {
1644 display: grid;
1645 grid-template-columns: 1fr 1fr;
1646 gap: var(--space-4);
1647 margin-bottom: var(--space-5);
1648 padding-bottom: var(--space-5);
1649 border-bottom: 1px solid var(--border);
1650 }
1651
1652 .item-page .meta-item { font-size: 0.9rem; }
1653 .item-page .meta-label { opacity: 0.7; margin-bottom: var(--space-1); }
1654 .item-page .meta-value { font-weight: bold; }
1655
1656 .item-page .item-tags { margin-bottom: var(--space-5); }
1657
1658 /* purchase-box uses .card-muted for the box; only its h3/ul/li specifics remain. */
1659 .purchase-box h3 {
1660 font-size: 1rem;
1661 font-weight: normal;
1662 margin-bottom: var(--space-4);
1663 }
1664 .purchase-box ul { list-style: none; margin-bottom: var(--space-4); }
1665 .purchase-box li { padding: var(--space-1) 0; }
1666 .purchase-box li::before {
1667 content: "→ ";
1668 opacity: 0.5;
1669 }
1670
1671 .item-page .btn-primary {
1672 width: 100%;
1673 padding: var(--space-4) var(--space-6);
1674 font-size: 1.1rem;
1675 }
1676
1677 .item-page .btn-secondary {
1678 width: 100%;
1679 margin-top: var(--space-2);
1680 }
1681
1682 .item-page .payment-note {
1683 font-size: 0.85rem;
1684 opacity: 0.6;
1685 text-align: center;
1686 margin-top: var(--space-4);
1687 }
1688
1689 /* bundle-child uses .list-row co-class; only the gap-4 override remains. */
1690 .bundle-child { gap: var(--space-4); padding: var(--space-3) 0; }
1691
1692 .item-page .bundle-child-type {
1693 font-size: 0.8rem;
1694 padding: 0.2rem 0.6rem;
1695 background: var(--surface-sunken);
1696 white-space: nowrap;
1697 }
1698
1699 .item-page .bundle-child-title { flex: 1; }
1700 .item-page .bundle-child-title a { color: var(--content); }
1701 .item-page .bundle-child-price { font-size: 0.9rem; opacity: 0.7; }
1702
1703 .item-page .bundle-notice {
1704 background: var(--surface-sunken);
1705 padding: var(--space-5);
1706 margin-bottom: var(--space-5);
1707 text-align: center;
1708 }
1709
1710 .item-page .bundle-notice a { color: var(--content); }
1711
1712 .item-page .item-description p { margin-bottom: var(--space-4); text-align: left; }
1713 .item-page .item-description ul { margin-left: var(--space-5); margin-bottom: var(--space-4); }
1714 .item-page .item-description li { margin-bottom: var(--space-2); }
1715
1716 .item-page .features-grid {
1717 display: grid;
1718 grid-template-columns: repeat(2, 1fr);
1719 gap: var(--space-5);
1720 }
1721 .item-page .version-number { font-size: 1.1rem; }
1722 .item-page .item-footer {
1723 margin-top: 3rem;
1724 padding-top: var(--space-6);
1725 border-top: 1px solid var(--border);
1726 text-align: center;
1727 opacity: 0.6;
1728 font-size: 0.85rem;
1729 }
1730
1731 .item-page .item-footer a { color: var(--content); }
1732
1733 @media (max-width: 768px) {
1734 .item-page .item-layout { grid-template-columns: 1fr; }
1735 .item-page .features-grid { grid-template-columns: 1fr; }
1736 }
1737
1738 @media (max-width: 480px) {
1739 .item-page .item-title { font-size: 1.5rem; }
1740 .item-page .item-price { font-size: 1.8rem; }
1741 .item-page .item-meta { grid-template-columns: 1fr; gap: var(--space-2); }
1742 .item-page .item-media,
1743 .item-page .item-details { padding: var(--space-4); }
1744 .item-page .item-description { padding: var(--space-4); }
1745 .item-page .item-description h2 { font-size: 1.2rem; }
1746 .item-page .purchase-box { padding: var(--space-4); }
1747 }
1748
1749 /* Project store-front page (templates/pages/project.html). Scoped under
1750 .project-page body class, `.item-card`, `.item-title`, `.item-meta`,
1751 `.item-price`, etc. here mean store-front item cards, distinct from
1752 the item-detail-page versions scoped under .item-page above. */
1753 .project-page .store-header { margin-bottom: 3rem; }
1754 .project-page .store-title { font-size: 3rem; margin-bottom: var(--space-2); }
1755 .project-page .store-meta {
1756 font-size: 0.9rem;
1757 opacity: 0.7;
1758 margin-bottom: var(--space-5);
1759 }
1760 .project-page .store-meta a { color: var(--content); }
1761 .project-page .store-description {
1762 font-size: 1.1rem;
1763 max-width: 800px;
1764 margin-bottom: var(--space-6);
1765 text-align: left;
1766 }
1767 .project-page .store-actions {
1768 display: flex;
1769 gap: var(--space-4);
1770 flex-wrap: wrap;
1771 }
1772
1773 .project-page .items-section { margin-bottom: 3rem; }
1774
1775 .project-page .items-grid {
1776 display: grid;
1777 grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
1778 gap: var(--space-6);
1779 }
1780
1781 .project-page .item-card {
1782 background: var(--surface-overlay);
1783 transition: background 0.2s ease;
1784 cursor: pointer;
1785 display: flex;
1786 flex-direction: column;
1787 height: 100%;
1788 }
1789
1790 .project-page .item-card:hover { background: var(--surface-sunken); }
1791
1792 .project-page a.item-thumbnail {
1793 width: 100%;
1794 height: 300px;
1795 background: var(--border);
1796 display: flex;
1797 align-items: center;
1798 justify-content: center;
1799 font-size: 3rem;
1800 opacity: 0.3;
1801 text-decoration: none;
1802 }
1803
1804 .project-page a.item-thumbnail:hover { opacity: 0.5; }
1805
1806 .project-page .item-content {
1807 padding: var(--space-5);
1808 display: flex;
1809 flex-direction: column;
1810 flex-grow: 1;
1811 }
1812
1813 .project-page .item-title {
1814 font-size: 1.2rem;
1815 margin-bottom: var(--space-2);
1816 font-family: var(--font-heading);
1817 font-weight: bold;
1818 }
1819
1820 .project-page .item-title a { color: inherit; text-decoration: none; }
1821 .project-page .item-title a:hover { text-decoration: underline; }
1822
1823 .project-page .item-meta {
1824 font-size: 0.85rem;
1825 opacity: 0.7;
1826 margin-bottom: var(--space-4);
1827 }
1828
1829 .project-page .item-tags { margin-bottom: var(--space-4); }
1830
1831 .project-page .item-description {
1832 font-size: 0.9rem;
1833 margin-bottom: var(--space-4);
1834 opacity: 0.8;
1835 text-align: left;
1836 flex-grow: 1;
1837 }
1838
1839 .project-page .item-footer {
1840 display: flex;
1841 justify-content: space-between;
1842 align-items: center;
1843 margin-top: auto;
1844 }
1845
1846 .project-page .item-price { font-size: 1.3rem; }
1847 .project-page .item-stats { font-size: 0.85rem; opacity: 0.6; }
1848
1849 .project-page .store-footer {
1850 margin-top: 4rem;
1851 padding-top: var(--space-6);
1852 border-top: 1px solid var(--border);
1853 opacity: 0.6;
1854 }
1855
1856 .project-page .store-footer a { color: var(--content); }
1857
1858 .project-page .item-content .btn-primary,
1859 .project-page .item-content .btn-secondary {
1860 width: 100%;
1861 margin-top: var(--space-4);
1862 }
1863
1864 /* project.html allows .section-tabs to wrap (other pages don't). */
1865 .project-page .section-tabs { flex-wrap: wrap; }
1866
1867 .project-page .tiers-section { margin-bottom: 3rem; }
1868
1869 .project-page .tiers-grid {
1870 display: grid;
1871 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
1872 gap: var(--space-5);
1873 }
1874
1875 .project-page .tier-card {
1876 background: var(--surface-overlay);
1877 padding: var(--space-6);
1878 display: flex;
1879 flex-direction: column;
1880 }
1881
1882 .project-page .tier-name {
1883 font-family: var(--font-heading);
1884 font-weight: bold;
1885 font-size: 1.3rem;
1886 margin-bottom: var(--space-2);
1887 }
1888
1889 .project-page .tier-price {
1890 font-size: 1.5rem;
1891 margin-bottom: var(--space-4);
1892 }
1893
1894 .project-page .tier-description {
1895 font-size: 0.9rem;
1896 opacity: 0.8;
1897 margin-bottom: var(--space-5);
1898 flex-grow: 1;
1899 text-align: left;
1900 }
1901
1902 .project-page .tier-card form { margin-top: auto; }
1903 .project-page .tier-card button,
1904 .project-page .tier-card .btn-primary { width: 100%; }
1905
1906 .project-page .tier-active-badge {
1907 font-size: 0.85rem;
1908 padding: var(--space-2) var(--space-4);
1909 background: var(--surface-sunken);
1910 text-align: center;
1911 opacity: 0.7;
1912 }
1913
1914 @media (max-width: 480px) {
1915 .project-page .store-title { font-size: 2rem; }
1916 .project-page .items-grid { grid-template-columns: 1fr; }
1917 .project-page a.item-thumbnail { height: 200px; }
1918 .project-page .store-description { font-size: 1rem; }
1919 .project-page .tiers-grid { grid-template-columns: 1fr; }
1920 }
1921
1922 /* Library downloads page (templates/pages/library_downloads.html).
1923 Scoped under .library-page body class. Class names like .item-footer,
1924 .bundle-child, etc. overlap with .item-page; the scope keeps them
1925 distinct. */
1926 .library-page .library-header {
1927 display: grid;
1928 grid-template-columns: 200px 1fr;
1929 gap: var(--space-5);
1930 margin-bottom: var(--space-6);
1931 align-items: center;
1932 }
1933
1934 .library-page .library-header.no-cover { grid-template-columns: 1fr; }
1935
1936 .library-page .library-cover img {
1937 width: 100%;
1938 aspect-ratio: 1 / 1;
1939 object-fit: cover;
1940 display: block;
1941 }
1942
1943 .library-page .library-title {
1944 font-size: 2rem;
1945 margin-bottom: var(--space-1);
1946 }
1947
1948 /* Byline sits under the centered H1 (global `h1 { text-align: center }`),
1949 so center it too, otherwise it floats flush-left while the title is
1950 centered above. Same for the back-link breadcrumb. When a cover is
1951 present the grid scope below restores left-alignment in the text column. */
1952 .library-page .library-creator {
1953 font-size: 0.95rem;
1954 opacity: 0.7;
1955 margin-bottom: var(--space-4);
1956 text-align: center;
1957 }
1958
1959 .library-page .library-creator a { color: var(--content); }
1960
1961 .library-page .library-back {
1962 font-size: 0.85rem;
1963 opacity: 0.7;
1964 text-align: center;
1965 }
1966 .library-page .library-back a { color: var(--content); }
1967
1968 /* When a cover is present, the title block sits in the right grid column;
1969 left-align in that context so the column reads as a coherent block next
1970 to the cover instead of a centered island. */
1971 .library-page .library-header:not(.no-cover) .library-title,
1972 .library-page .library-header:not(.no-cover) .library-creator {
1973 text-align: left;
1974 }
1975
1976 .library-page .downloads-hero h2 {
1977 font-size: 1.5rem;
1978 margin-bottom: var(--space-4);
1979 padding-bottom: var(--space-2);
1980 border-bottom: 1px solid var(--border);
1981 }
1982
1983 .library-page .download-row {
1984 display: flex;
1985 align-items: center;
1986 gap: var(--space-4);
1987 padding: 0.6rem 0;
1988 border-bottom: 1px solid var(--border);
1989 }
1990
1991 .library-page .download-row:last-child { border-bottom: none; }
1992
1993 .library-page .download-version {
1994 min-width: 4em;
1995 font-family: var(--font-mono);
1996 font-size: 0.9rem;
1997 }
1998
1999 .library-page .download-label { flex: 1; }
2000
2001 .library-page .download-size {
2002 font-size: 0.85rem;
2003 opacity: 0.6;
2004 min-width: 5em;
2005 text-align: right;
2006 }
2007
2008 .library-page .download-notice {
2009 background: var(--surface-sunken);
2010 padding: var(--space-5);
2011 margin-bottom: var(--space-6);
2012 font-size: 0.85rem;
2013 opacity: 0.8;
2014 }
2015
2016 .library-page .download-notice strong { font-family: var(--font-mono); }
2017
2018 /* Inline download list on library_audio.html / library_video.html
2019 (below the media player). */
2020
2021 .library-page .library-downloads h3 {
2022 font-size: 1.1rem;
2023 margin-bottom: var(--space-4);
2024 }
2025
2026 .library-page .library-section h2 {
2027 font-size: 1.3rem;
2028 margin-bottom: var(--space-4);
2029 padding-bottom: var(--space-2);
2030 border-bottom: 1px solid var(--border);
2031 }
2032
2033 .library-page .bundle-child {
2034 display: flex;
2035 align-items: center;
2036 gap: var(--space-4);
2037 padding: var(--space-3) 0;
2038 border-bottom: 1px solid var(--border);
2039 }
2040
2041 .library-page .bundle-child:last-child { border-bottom: none; }
2042
2043 .library-page .bundle-child-type {
2044 font-size: 0.8rem;
2045 padding: 0.2rem 0.6rem;
2046 background: var(--surface-sunken);
2047 white-space: nowrap;
2048 }
2049
2050 .library-page .bundle-child-title { flex: 1; }
2051 .library-page .bundle-child-title a { color: var(--content); }
2052
2053 .library-page .item-footer {
2054 margin-top: 3rem;
2055 padding-top: var(--space-6);
2056 border-top: 1px solid var(--border);
2057 text-align: center;
2058 opacity: 0.6;
2059 font-size: 0.85rem;
2060 }
2061
2062 .library-page .item-footer a { color: var(--content); }
2063
2064 @media (max-width: 600px) {
2065 .library-page .library-header { grid-template-columns: 1fr; }
2066 .library-page .library-cover img { max-width: 200px; }
2067 }
2068
2069 /* Article reader pages (templates/pages/text_reader.html, blog_post.html,
2070 library_text.html). Long-form article layout, centered narrow column,
2071 author header, large heading, magazine-style body type. Scoped under
2072 .article-page body class. */
2073 .article-page .article-container {
2074 max-width: 680px;
2075 margin: 0 auto;
2076 padding: 3rem 1.5rem 5rem;
2077 }
2078
2079 .article-page .author-header {
2080 display: flex;
2081 align-items: center;
2082 gap: var(--space-4);
2083 margin-bottom: var(--space-6);
2084 }
2085
2086 .article-page .author-avatar {
2087 width: 48px;
2088 height: 48px;
2089 background: var(--surface-sunken);
2090 border-radius: var(--radius-round);
2091 display: flex;
2092 align-items: center;
2093 justify-content: center;
2094 font-family: var(--font-heading);
2095 font-size: 1.25rem;
2096 color: var(--content);
2097 }
2098
2099 .article-page .author-info { flex: 1; }
2100
2101 .article-page .author-name {
2102 font-family: var(--font-mono);
2103 font-size: 1rem;
2104 color: var(--content);
2105 }
2106
2107 .article-page .author-name a {
2108 color: inherit;
2109 text-decoration: none;
2110 }
2111
2112 .article-page .author-name a:hover { text-decoration: underline; }
2113
2114 .article-page .article-meta {
2115 font-family: var(--font-mono);
2116 font-size: 0.875rem;
2117 color: var(--content-muted);
2118 }
2119
2120 .article-page .article-title {
2121 font-family: var(--font-heading);
2122 font-size: 2.5rem;
2123 font-weight: normal;
2124 line-height: 1.2;
2125 margin-bottom: var(--space-5);
2126 color: var(--content);
2127 text-align: left;
2128 }
2129
2130 .article-page .article-deck {
2131 font-family: var(--font-mono);
2132 font-size: 1.25rem;
2133 color: var(--content-muted);
2134 margin-bottom: 2.5rem;
2135 line-height: 1.6;
2136 }
2137
2138 .article-page .article-body {
2139 font-family: var(--font-body);
2140 font-size: 1.125rem;
2141 line-height: 1.9;
2142 }
2143
2144 .article-page .article-body p { margin-bottom: var(--space-5); }
2145
2146 .article-page .article-body h1 {
2147 font-family: var(--font-heading);
2148 font-size: 2rem;
2149 font-weight: normal;
2150 margin-top: 3rem;
2151 margin-bottom: var(--space-4);
2152 color: var(--content);
2153 text-align: left;
2154 }
2155
2156 .article-page .article-body h2 {
2157 font-family: var(--font-mono);
2158 font-size: 1.75rem;
2159 font-weight: normal;
2160 margin-top: 3rem;
2161 margin-bottom: var(--space-4);
2162 color: var(--content);
2163 }
2164
2165 .article-page .article-body h3 {
2166 font-family: var(--font-mono);
2167 font-size: 1.375rem;
2168 font-weight: normal;
2169 margin-top: 2.5rem;
2170 margin-bottom: var(--space-3);
2171 color: var(--content);
2172 }
2173
2174 .article-page .article-body blockquote {
2175 border-left: 3px solid var(--action);
2176 padding-left: var(--space-5);
2177 margin: var(--space-6) 0;
2178 font-style: italic;
2179 color: var(--content-muted);
2180 }
2181
2182 .article-page .article-body ul,
2183 .article-page .article-body ol {
2184 margin-bottom: var(--space-5);
2185 padding-left: var(--space-5);
2186 }
2187
2188 .article-page .article-body li { margin-bottom: var(--space-2); }
2189
2190 .article-page .article-body a {
2191 color: var(--action);
2192 text-decoration: underline;
2193 text-decoration-color: rgba(108, 92, 231, 0.4);
2194 text-underline-offset: 2px;
2195 }
2196
2197 .article-page .article-body a:hover {
2198 text-decoration-color: var(--action);
2199 }
2200
2201 .article-page .article-body strong { font-weight: bold; }
2202 .article-page .article-body em { font-style: italic; }
2203
2204 .article-page .article-body code {
2205 font-family: var(--font-mono);
2206 background: var(--surface-sunken);
2207 padding: 0.125rem 0.375rem;
2208 font-size: 0.9em;
2209 }
2210
2211 .article-page .article-body pre {
2212 background: var(--surface-sunken);
2213 padding: var(--space-4);
2214 overflow-x: auto;
2215 margin-bottom: var(--space-5);
2216 }
2217
2218 .article-page .article-body pre code {
2219 background: none;
2220 padding: 0;
2221 }
2222
2223 .article-page .article-body hr {
2224 border: none;
2225 text-align: center;
2226 margin: 3rem 0;
2227 }
2228
2229 .article-page .article-body hr::before {
2230 content: "* * *";
2231 color: var(--content-muted);
2232 letter-spacing: 1rem;
2233 }
2234
2235 .article-page .article-footer {
2236 margin-top: 4rem;
2237 padding-top: var(--space-6);
2238 border-top: 1px solid var(--border);
2239 }
2240
2241 .article-page .author-bio {
2242 display: flex;
2243 gap: var(--space-4);
2244 padding: var(--space-5);
2245 background: var(--surface-overlay);
2246 }
2247
2248 .article-page .author-bio .author-avatar {
2249 width: 64px;
2250 height: 64px;
2251 font-size: 1.5rem;
2252 flex-shrink: 0;
2253 }
2254
2255 .article-page .author-bio-content { flex: 1; }
2256
2257 .article-page .author-bio-name {
2258 font-family: var(--font-mono);
2259 font-size: 1.125rem;
2260 margin-bottom: var(--space-2);
2261 }
2262
2263 .article-page .author-bio-name a {
2264 color: inherit;
2265 text-decoration: none;
2266 }
2267
2268 .article-page .author-bio-name a:hover { text-decoration: underline; }
2269
2270 .article-page .article-tags {
2271 margin-top: var(--space-6);
2272 display: flex;
2273 gap: var(--space-2);
2274 flex-wrap: wrap;
2275 }
2276
2277 .article-page .article-tag {
2278 font-family: var(--font-mono);
2279 background: var(--surface-sunken);
2280 color: var(--content);
2281 padding: 0.375rem 0.75rem;
2282 font-size: 0.8125rem;
2283 text-decoration: none;
2284 }
2285
2286 .article-page .text-reader-footer {
2287 font-family: var(--font-mono);
2288 text-align: center;
2289 padding: var(--space-6);
2290 font-size: 0.875rem;
2291 color: var(--content-muted);
2292 border-top: 1px solid var(--border);
2293 }
2294
2295 .article-page .text-reader-footer a {
2296 color: var(--content);
2297 text-decoration: none;
2298 }
2299
2300 .article-page .text-reader-footer a:hover { text-decoration: underline; }
2301
2302 /* Blog-specific: nav crumb above the article. */
2303 .article-page .blog-nav {
2304 font-family: var(--font-mono);
2305 font-size: 0.875rem;
2306 margin-bottom: var(--space-6);
2307 }
2308
2309 .article-page .blog-nav a { color: var(--content); text-decoration: none; }
2310 .article-page .blog-nav a:hover { text-decoration: underline; }
2311
2312 @media (max-width: 600px) {
2313 .article-page .article-title { font-size: 2rem; }
2314 .article-page .article-deck { font-size: 1.125rem; }
2315 .article-page .article-body { font-size: 1rem; }
2316 }
2317
2318 /* Admin dashboards (templates/dashboards/admin-*.html). Every admin
2319 page had a duplicate `h1 { font-size: 2rem; margin-bottom: 0.5rem; }`
2320 inline, consolidated here. */
2321
2322 /* System health dashboard (templates/pages/health.html). */
2323 .health-page {
2324 padding: var(--space-6);
2325 }
2326
2327 .health-page .health-container {
2328 max-width: 900px;
2329 margin: 0 auto;
2330 }
2331
2332 .health-page .health-grid {
2333 display: grid;
2334 grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
2335 gap: var(--space-5);
2336 margin-bottom: var(--space-6);
2337 }
2338
2339 .health-page .health-card {
2340 background: var(--surface-sunken);
2341 padding: var(--space-5);
2342 }
2343
2344 .health-page .health-card h3 {
2345 font-family: var(--font-mono);
2346 font-size: 0.9rem;
2347 margin-bottom: var(--space-4);
2348 display: flex;
2349 align-items: center;
2350 gap: var(--space-2);
2351 }
2352
2353 .health-page .status-indicator {
2354 width: 10px;
2355 height: 10px;
2356 border-radius: var(--radius-round);
2357 display: inline-block;
2358 }
2359
2360 .health-page .status-ok { background: var(--success); }
2361 .health-page .status-warn { background: var(--warning); }
2362 .health-page .status-error { background: var(--danger); }
2363 .health-page .status-unknown { background: var(--content-muted); }
2364
2365 .health-page .health-card dl {
2366 display: grid;
2367 grid-template-columns: auto 1fr;
2368 gap: var(--space-2) var(--space-4);
2369 font-size: 0.85rem;
2370 }
2371
2372 .health-page .health-card dt { opacity: 0.7; }
2373 .health-page .health-card dd {
2374 font-family: var(--font-mono);
2375 text-align: right;
2376 }
2377
2378 .health-page .section-title {
2379 font-family: var(--font-mono);
2380 font-size: 1rem;
2381 margin: var(--space-6) 0 var(--space-4);
2382 padding-bottom: var(--space-2);
2383 border-bottom: 1px solid var(--border);
2384 }
2385 .health-page .test-list {
2386 list-style: none;
2387 padding: 0;
2388 margin: 0;
2389 }
2390
2391 .health-page .test-list li {
2392 display: flex;
2393 justify-content: space-between;
2394 padding: var(--space-2) 0;
2395 border-bottom: 1px solid var(--border);
2396 font-size: 0.85rem;
2397 }
2398
2399 .health-page .test-list li:last-child { border-bottom: none; }
2400
2401 .health-page .test-name { font-family: var(--font-mono); }
2402
2403 .health-page .test-pass { color: var(--success); }
2404 .health-page .test-fail { color: var(--danger); }
2405 .health-page .summary-bar {
2406 display: flex;
2407 gap: var(--space-6);
2408 padding: var(--space-4);
2409 background: var(--surface-sunken);
2410 margin-bottom: var(--space-6);
2411 font-family: var(--font-mono);
2412 font-size: 0.9rem;
2413 }
2414
2415 .health-page .summary-item {
2416 display: flex;
2417 align-items: center;
2418 gap: var(--space-2);
2419 }
2420
2421 .health-page .timestamp {
2422 font-size: 0.8rem;
2423 opacity: 0.6;
2424 text-align: right;
2425 margin-top: var(--space-6);
2426 }
2427
2428 .health-page details.check-list {
2429 background: var(--surface-overlay);
2430 padding: var(--space-5);
2431 margin-bottom: var(--space-6);
2432 }
2433
2434 .health-page details.check-list summary {
2435 font-family: var(--font-mono);
2436 font-size: 0.9rem;
2437 cursor: pointer;
2438 list-style: none;
2439 display: flex;
2440 align-items: center;
2441 gap: var(--space-2);
2442 }
2443
2444 .health-page details.check-list summary::-webkit-details-marker { display: none; }
2445
2446 .health-page details.check-list summary::before {
2447 content: "â–¶";
2448 font-size: 0.6rem;
2449 transition: transform 0.15s;
2450 }
2451
2452 .health-page details.check-list[open] summary::before {
2453 transform: rotate(90deg);
2454 }
2455
2456 .health-page details.check-list .test-list {
2457 margin-top: var(--space-4);
2458 }
2459 /* Import data wizard (templates/dashboards/dashboard-import.html).
2460 Page-specific upload + column-mapping + progress flow. Migration also
2461 fixed token bypasses: --border-color → --border, --accent → --highlight,
2462 --success-background → --success-bg, --error-background → --error-bg. */
2463
2464 .import-page .back-link {
2465 display: inline-block;
2466 margin-bottom: var(--space-5);
2467 font-size: 0.9rem;
2468 opacity: 0.7;
2469 }
2470
2471 .import-page .back-link:hover { opacity: 1; }
2472
2473 .import-page .form-group { margin-bottom: var(--space-5); }
2474
2475 .import-page .form-group label {
2476 display: block;
2477 font-family: var(--font-mono);
2478 font-size: 0.9rem;
2479 font-weight: bold;
2480 margin-bottom: var(--space-2);
2481 }
2482
2483 .import-page .form-group select,
2484 .import-page .form-group input[type="file"] {
2485 width: 100%;
2486 padding: var(--space-2);
2487 font-size: 0.9rem;
2488 border: 1px solid var(--border);
2489 background: var(--surface-page);
2490 }
2491
2492 .import-page .csv-preview {
2493 margin-top: var(--space-4);
2494 overflow-x: auto;
2495 }
2496
2497 .import-page .csv-preview table {
2498 width: 100%;
2499 border-collapse: collapse;
2500 font-size: 0.85rem;
2501 }
2502
2503 .import-page .csv-preview th,
2504 .import-page .csv-preview td {
2505 padding: 0.4rem 0.6rem;
2506 border: 1px solid var(--border);
2507 text-align: left;
2508 }
2509
2510 .import-page .csv-preview th {
2511 background: var(--surface-sunken);
2512 font-family: var(--font-mono);
2513 }
2514
2515 .import-page .column-mapping { margin-top: var(--space-4); }
2516
2517 .import-page .mapping-row {
2518 display: flex;
2519 align-items: center;
2520 gap: var(--space-4);
2521 margin-bottom: var(--space-2);
2522 }
2523
2524 .import-page .mapping-row label {
2525 min-width: 100px;
2526 font-size: 0.85rem;
2527 font-family: var(--font-mono);
2528 margin-bottom: 0;
2529 }
2530
2531 .import-page .mapping-row select {
2532 flex: 1;
2533 padding: 0.3rem;
2534 font-size: 0.85rem;
2535 }
2536
2537 .import-page .progress-stats {
2538 display: flex;
2539 gap: var(--space-6);
2540 font-size: 0.85rem;
2541 font-family: var(--font-mono);
2542 }
2543
2544 .import-page .progress-stats .stat-value { font-weight: bold; }
2545
2546 .import-page .import-result {
2547 padding: var(--space-4);
2548 margin-bottom: var(--space-4);
2549 font-size: 0.9rem;
2550 }
2551
2552 .import-page .import-result.success { background: color-mix(in oklch, var(--success) 12%, var(--surface-page)); }
2553 .import-page .import-result.error { background: color-mix(in oklch, var(--danger) 10%, var(--surface-page)); }
2554
2555 .import-page .error-log {
2556 margin-top: var(--space-4);
2557 padding: var(--space-2);
2558 background: var(--surface-sunken);
2559 font-family: var(--font-mono);
2560 font-size: 0.8rem;
2561 max-height: 200px;
2562 overflow-y: auto;
2563 white-space: pre-wrap;
2564 }
2565
2566 .import-page .import-history { margin-top: var(--space-6); }
2567
2568 .import-page .history-table {
2569 width: 100%;
2570 border-collapse: collapse;
2571 font-size: 0.85rem;
2572 }
2573
2574 .import-page .history-table th,
2575 .import-page .history-table td {
2576 padding: var(--space-2);
2577 border-bottom: 1px solid var(--border);
2578 text-align: left;
2579 }
2580
2581 .import-page .history-table th {
2582 font-family: var(--font-mono);
2583 font-weight: bold;
2584 }
2585
2586 .import-page .status-badge {
2587 display: inline-block;
2588 padding: 0.15rem 0.5rem;
2589 font-size: 0.8rem;
2590 font-family: var(--font-mono);
2591 }
2592
2593 .import-page .status-badge.completed { color: var(--success); }
2594 .import-page .status-badge.processing { color: var(--action); }
2595 .import-page .status-badge.failed { color: var(--danger); }
2596 .import-page .status-badge.pending { opacity: 0.6; }
2597
2598 .import-page .import-note {
2599 background: var(--surface-sunken);
2600 padding: var(--space-4);
2601 margin-top: var(--space-6);
2602 font-size: 0.9rem;
2603 }
2604
2605 .import-page .import-note h3 {
2606 font-family: var(--font-mono);
2607 font-size: 0.9rem;
2608 margin-bottom: var(--space-2);
2609 }
2610
2611 /* Delete account page (templates/dashboards/dashboard-delete-account.html).
2612 Overrides .warning-box to use --danger (delete is danger, not warning)
2613 and the .form-status partial styling. Scoped to keep the global versions
2614 intact for other pages. */
2615
2616 .delete-account-page .warning-box {
2617 background: var(--danger);
2618 color: var(--primary-light);
2619 padding: var(--space-5);
2620 margin-bottom: var(--space-6);
2621 }
2622
2623 .delete-account-page .warning-box h3 {
2624 font-family: var(--font-mono);
2625 font-size: 1rem;
2626 margin-bottom: var(--space-2);
2627 }
2628
2629 .delete-account-page .warning-box ul {
2630 margin: var(--space-2) 0 0 var(--space-5);
2631 font-size: 0.9rem;
2632 }
2633
2634 .delete-account-page .warning-box li { margin-bottom: var(--space-1); }
2635
2636 .delete-account-page .export-prompt {
2637 background: var(--surface-sunken);
2638 padding: var(--space-5);
2639 margin-bottom: var(--space-6);
2640 }
2641
2642 .delete-account-page .export-prompt h3 {
2643 font-family: var(--font-mono);
2644 font-size: 1rem;
2645 margin-bottom: var(--space-2);
2646 }
2647
2648 .delete-account-page .export-prompt p {
2649 font-size: 0.9rem;
2650 margin-bottom: var(--space-4);
2651 }
2652
2653 .delete-account-page .delete-form {
2654 background: var(--surface-overlay);
2655 padding: var(--space-5);
2656 }
2657
2658 .delete-account-page .delete-form .form-group { margin-bottom: var(--space-5); }
2659
2660 .delete-account-page .delete-form label {
2661 display: block;
2662 margin-bottom: var(--space-2);
2663 font-family: var(--font-mono);
2664 font-size: 0.9rem;
2665 }
2666
2667 .delete-account-page .delete-form .hint {
2668 font-size: 0.85rem;
2669 opacity: 0.7;
2670 margin-top: var(--space-1);
2671 }
2672
2673 .delete-account-page .delete-form input[type="text"] {
2674 width: 100%;
2675 padding: var(--space-3);
2676 font-size: 1rem;
2677 border: 2px solid var(--border);
2678 background: var(--surface-sunken);
2679 }
2680
2681 .delete-account-page .delete-form input[type="text"]:focus {
2682 border-color: var(--danger);
2683 outline: none;
2684 }
2685
2686 .delete-account-page .back-link {
2687 display: inline-block;
2688 margin-bottom: var(--space-5);
2689 font-size: 0.9rem;
2690 opacity: 0.7;
2691 }
2692
2693 .delete-account-page .back-link:hover { opacity: 1; }
2694
2695 .delete-account-page .form-actions {
2696 display: flex;
2697 gap: var(--space-4);
2698 align-items: center;
2699 }
2700
2701 .delete-account-page .form-status { font-size: 0.9rem; }
2702 .delete-account-page .form-status.error { color: var(--danger); }
2703 .delete-account-page .form-status.success { color: var(--success); }
2704
2705 /* Export data page (templates/dashboards/dashboard-export.html).
2706 `.export-card` and its inner classes (`-info`, `-title`, `-desc`, `-meta`)
2707 are intentionally page-scoped: this is a row-layout card (info on left,
2708 action button on right, flex justify-between) that doesn't fit `.card-muted`
2709 cleanly. Background uses `--light-background` rather than `--surface-muted`
2710 for visual distinction from the surrounding dashboard surface. */
2711
2712 .export-page .export-cards {
2713 display: grid;
2714 gap: var(--space-4);
2715 }
2716
2717 .export-page .export-card {
2718 background: var(--surface-overlay);
2719 padding: var(--space-5);
2720 display: flex;
2721 justify-content: space-between;
2722 align-items: flex-start;
2723 gap: var(--space-4);
2724 }
2725
2726 .export-page .export-card-info { flex: 1; }
2727
2728 .export-page .export-card-title {
2729 font-family: var(--font-mono);
2730 font-weight: bold;
2731 font-size: 1.1rem;
2732 margin-bottom: var(--space-2);
2733 }
2734
2735 .export-page .export-card-desc {
2736 font-size: 0.9rem;
2737 opacity: 0.8;
2738 margin-bottom: var(--space-2);
2739 }
2740
2741 .export-page .export-card-meta {
2742 font-size: 0.8rem;
2743 opacity: 0.6;
2744 }
2745
2746 .export-page .export-card button { white-space: nowrap; }
2747
2748 .export-page .export-note {
2749 background: var(--surface-sunken);
2750 padding: var(--space-4);
2751 margin-top: var(--space-6);
2752 font-size: 0.9rem;
2753 }
2754
2755 .export-page .export-note h3 {
2756 font-family: var(--font-mono);
2757 font-size: 0.9rem;
2758 margin-bottom: var(--space-2);
2759 }
2760
2761 .export-page .back-link {
2762 display: inline-block;
2763 margin-bottom: var(--space-5);
2764 font-size: 0.9rem;
2765 opacity: 0.7;
2766 }
2767
2768 .export-page .back-link:hover { opacity: 1; }
2769
2770 .export-page .export-status {
2771 margin-top: var(--space-2);
2772 font-size: 0.85rem;
2773 }
2774
2775 .export-page .export-status.success { color: var(--success); }
2776 .export-page .export-status.error { color: var(--danger); }
2777
2778 /* Receipt page (templates/pages/receipt.html). */
2779
2780 .receipt-page .receipt-header {
2781 display: flex;
2782 justify-content: space-between;
2783 align-items: flex-start;
2784 margin-bottom: var(--space-6);
2785 padding-bottom: var(--space-5);
2786 border-bottom: 1px solid var(--border);
2787 }
2788
2789 .receipt-page .receipt-row {
2790 display: flex;
2791 justify-content: space-between;
2792 padding: var(--space-2) 0;
2793 font-size: 0.95rem;
2794 }
2795
2796 .receipt-page .receipt-row.total {
2797 font-weight: bold;
2798 font-size: 1.1rem;
2799 border-top: 1px solid var(--border);
2800 padding-top: var(--space-4);
2801 margin-top: var(--space-2);
2802 }
2803
2804 .receipt-page .receipt-label { opacity: 0.7; }
2805
2806 .receipt-page .receipt-footer {
2807 margin-top: var(--space-6);
2808 padding-top: var(--space-5);
2809 border-top: 1px solid var(--border);
2810 font-size: 0.85rem;
2811 opacity: 0.6;
2812 }
2813
2814 .receipt-page .back-link {
2815 display: inline-block;
2816 margin-bottom: var(--space-5);
2817 font-size: 0.9rem;
2818 opacity: 0.7;
2819 }
2820
2821 .receipt-page .back-link:hover { opacity: 1; }
2822
2823 @media print {
2824 .receipt-page .back-link,
2825 .receipt-page .site-header,
2826 .receipt-page .print-btn { display: none !important; }
2827 .receipt-page .receipt-box { border: 1px solid var(--border); }
2828 }
2829
2830 /* Fan+ subscription page (templates/pages/fan_plus.html). */
2831 .fan-plus-page h1 { font-size: 2.5rem; margin-bottom: var(--space-2); }
2832 .fan-plus-page h2 { font-size: 1.5rem; margin-top: var(--space-6); margin-bottom: var(--space-4); }
2833
2834 .fan-plus-page .fan-plus-section { margin-bottom: var(--space-6); line-height: 1.7; }
2835 .fan-plus-page .fan-plus-section ul { padding-left: var(--space-5); margin: var(--space-3) 0; }
2836 .fan-plus-page .fan-plus-section li { margin-bottom: var(--space-2); }
2837
2838 .fan-plus-page .price-callout {
2839 font-size: 1.3rem;
2840 font-family: var(--font-mono);
2841 margin: var(--space-5) 0;
2842 }
2843
2844 .fan-plus-page .subscribe-form { margin: var(--space-6) 0; }
2845
2846 .fan-plus-page .subscribe-btn {
2847 display: inline-block;
2848 padding: var(--space-3) var(--space-6);
2849 background: var(--action);
2850 color: var(--primary-light);
2851 border: none;
2852 font-size: 1.1rem;
2853 cursor: pointer;
2854 font-family: var(--font-mono);
2855 }
2856
2857 .fan-plus-page .subscribe-btn:hover { opacity: 0.9; }
2858
2859 .fan-plus-page .status-box {
2860 padding: var(--space-5);
2861 background: var(--surface-overlay);
2862 margin: var(--space-5) 0;
2863 }
2864
2865 .fan-plus-page .status-box p { margin: var(--space-2) 0; }
2866
2867 .fan-plus-page .success-banner {
2868 padding: var(--space-4) var(--space-5);
2869 background: color-mix(in oklch, var(--success) 12%, var(--surface-page));
2870 margin-bottom: var(--space-5);
2871 font-family: var(--font-mono);
2872 }
2873
2874 .fan-plus-page .login-link { font-family: var(--font-mono); }
2875
2876 /* Purchase confirmation page (templates/pages/purchase.html). */
2877 .purchase-page .container {
2878 max-width: 800px;
2879 margin: var(--space-6) auto;
2880 padding: 0 var(--space-6);
2881 }
2882
2883 .purchase-page .tagline {
2884 font-size: 0.85rem;
2885 opacity: 0.7;
2886 margin-bottom: var(--space-6);
2887 text-align: center;
2888 }
2889
2890 .purchase-page .checkout-box { margin-bottom: var(--space-5); }
2891
2892 .purchase-page h2 { font-size: 1.8rem; margin-bottom: var(--space-2); }
2893
2894 .purchase-page .step-indicator {
2895 font-size: 0.85rem;
2896 opacity: 0.6;
2897 margin-bottom: var(--space-5);
2898 }
2899
2900 .purchase-page .item-summary {
2901 background: var(--surface-page);
2902 padding: var(--space-5);
2903 margin-bottom: var(--space-5);
2904 display: flex;
2905 gap: var(--space-5);
2906 }
2907
2908 .purchase-page .item-thumbnail {
2909 width: 120px;
2910 height: 120px;
2911 background: var(--surface-sunken);
2912 flex-shrink: 0;
2913 display: flex;
2914 align-items: center;
2915 justify-content: center;
2916 font-size: 3rem;
2917 opacity: 0.3;
2918 }
2919
2920 .purchase-page .item-details { flex: 1; }
2921
2922 .purchase-page .item-title {
2923 font-size: 1.2rem;
2924 margin-bottom: var(--space-2);
2925 font-family: var(--font-heading);
2926 font-weight: bold;
2927 }
2928
2929 .purchase-page .item-creator {
2930 font-size: 0.9rem;
2931 opacity: 0.7;
2932 margin-bottom: var(--space-4);
2933 }
2934
2935 .purchase-page .item-creator a { color: var(--content); }
2936 .purchase-page .item-description { font-size: 0.9rem; opacity: 0.8; }
2937
2938 .purchase-page .price-breakdown {
2939 background: var(--surface-page);
2940 padding: var(--space-5);
2941 margin-bottom: var(--space-5);
2942 }
2943
2944 .purchase-page .price-breakdown h2 { font-size: 1.1rem; margin-bottom: var(--space-4); }
2945
2946 .purchase-page .price-row {
2947 display: flex;
2948 justify-content: space-between;
2949 padding: var(--space-2) 0;
2950 border-bottom: 1px solid var(--border);
2951 }
2952
2953 .purchase-page .price-row:last-child {
2954 border-bottom: none;
2955 margin-top: var(--space-2);
2956 font-size: 1.2rem;
2957 padding-top: var(--space-4);
2958 border-top: 2px solid var(--border);
2959 }
2960
2961 .purchase-page .price-row.total { font-weight: bold; }
2962
2963 .purchase-page .payment-section { margin-bottom: var(--space-5); }
2964 .purchase-page .payment-section h2 { font-size: 1.1rem; margin-bottom: var(--space-4); }
2965
2966 .purchase-page .btn-primary { width: 100%; }
2967 .purchase-page .btn-secondary { width: 100%; margin-top: var(--space-4); }
2968
2969 .purchase-page .security-note {
2970 font-size: 0.85rem;
2971 opacity: 0.6;
2972 text-align: center;
2973 margin-top: var(--space-4);
2974 }
2975
2976 /* Replaces inline styles in pages/purchase.html. */
2977 .purchase-page h1 { text-align: center; }
2978
2979 .purchase-page .price-breakdown-note {
2980 margin-top: var(--space-2);
2981 font-size: 0.8rem;
2982 opacity: 0.6;
2983 }
2984
2985 .purchase-page .creator-breakdown {
2986 background: var(--surface-page);
2987 padding: var(--space-4) var(--space-5);
2988 margin-bottom: var(--space-5);
2989 font-size: 0.9rem;
2990 }
2991 .purchase-page .creator-breakdown h2 {
2992 font-size: 0.95rem;
2993 margin-bottom: var(--space-3);
2994 opacity: 0.7;
2995 }
2996 .purchase-page .creator-breakdown .price-row { opacity: 0.8; }
2997 .purchase-page .creator-breakdown .price-row.is-total {
2998 opacity: 1;
2999 font-weight: bold;
3000 border-top: 1px solid var(--border);
3001 margin-top: var(--space-2);
3002 padding-top: var(--space-2);
3003 /* override .price-row:last-child upsize */
3004 font-size: inherit;
3005 border-bottom: none;
3006 }
3007 .purchase-page .creator-breakdown .platform-fee-amount { color: var(--content); }
3008 .purchase-page .creator-breakdown-note {
3009 margin-top: var(--space-3);
3010 font-size: 0.85rem;
3011 opacity: 0.6;
3012 }
3013
3014 .purchase-page .payment-section-lead {
3015 margin-bottom: var(--space-5);
3016 opacity: 0.8;
3017 }
3018
3019 .purchase-page .pending-checkout {
3020 margin-bottom: var(--space-5);
3021 background: var(--surface-sunken);
3022 padding: 1rem 1.25rem;
3023 }
3024 .purchase-page .pending-checkout p { margin: 0 0 var(--space-3); }
3025 .purchase-page .pending-checkout p.is-sub {
3026 font-size: 0.9rem;
3027 opacity: 0.8;
3028 }
3029 .purchase-page .pending-checkout form { margin: 0; }
3030
3031 /* Checkout form field wrappers. */
3032 .purchase-page .checkout-field { margin-bottom: var(--space-4); }
3033 .purchase-page .checkout-field-label {
3034 font-size: 0.85rem;
3035 display: block;
3036 margin-bottom: 0.25rem;
3037 }
3038 .purchase-page .pwyw-row {
3039 display: flex;
3040 align-items: center;
3041 gap: 0.25rem;
3042 }
3043 .purchase-page .pwyw-symbol { font-size: 1.1rem; }
3044 .purchase-page .pwyw-input { width: 120px; }
3045 .purchase-page .pwyw-min-note {
3046 font-size: 0.8rem;
3047 opacity: 0.6;
3048 margin-top: 0.25rem;
3049 }
3050 .purchase-page .promo-input {
3051 width: 200px;
3052 text-transform: uppercase;
3053 }
3054 .purchase-page .share-contact-label {
3055 font-size: 0.85rem;
3056 display: flex;
3057 align-items: center;
3058 gap: 0.4rem;
3059 cursor: pointer;
3060 }
3061 .purchase-page .share-contact-checkbox { width: auto; }
3062
3063 .purchase-page .cart-alt-link {
3064 text-align: center;
3065 margin-top: var(--space-3);
3066 font-size: 0.85rem;
3067 opacity: 0.7;
3068 }
3069 .purchase-page .guest-hint {
3070 font-size: 0.8rem;
3071 opacity: 0.6;
3072 margin-top: var(--space-3);
3073 text-align: center;
3074 }
3075 .purchase-page .guest-login-prompt {
3076 font-size: 0.8rem;
3077 margin-top: var(--space-2);
3078 text-align: center;
3079 }
3080
3081 /* ===========================================
3082 PROJECT SETTINGS TAB
3083 (replaces inline styles in partials/tabs/project_settings.html and
3084 related innerHTML in static/project-sections.js)
3085 =========================================== */
3086
3087 .proj-image-hint {
3088 font-size: 0.85rem;
3089 opacity: 0.7;
3090 margin: 0 0 var(--space-2);
3091 }
3092
3093 /* Canonical inline form-status text following a Save / Change button.
3094 Two class names because templates evolved with both. They're aliases.
3095 States via .success / .error / .saving modifier. */
3096 .field-status,
3097 .save-status {
3098 margin-left: var(--space-2);
3099 font-size: 0.85rem;
3100 }
3101 .field-status.success, .save-status.success { color: var(--success); }
3102 .field-status.error, .save-status.error { color: var(--danger); }
3103 .field-status.saving, .save-status.saving { opacity: 0.6; }
3104
3105 /* Muted lead paragraph above a form button (monetization / features / delete). */
3106 .section-lead {
3107 margin-bottom: var(--space-4);
3108 opacity: 0.7;
3109 text-align: left;
3110 }
3111
3112 /* Large intro paragraph under a page h1 (creators, policy, changelog, fan_plus). */
3113 .page-intro {
3114 font-size: 1.1rem;
3115 margin-bottom: var(--space-6);
3116 line-height: 1.6;
3117 }
3118
3119 .subscription-note p {
3120 opacity: 0.7;
3121 font-size: 0.9rem;
3122 }
3123
3124 .features-grid-status {
3125 margin-top: var(--space-2);
3126 display: inline-block;
3127 }
3128
3129 /* "Pages" disclosure (project-level markdown sections). */
3130 .pages-toggle { margin-top: var(--space-6); }
3131 .pages-toggle > summary { cursor: pointer; }
3132 .pages-toggle > summary h2 { display: inline; }
3133 .pages-intro {
3134 font-size: 0.85rem;
3135 opacity: 0.7;
3136 margin: 0.75rem 0 var(--space-4);
3137 }
3138
3139 /* psection-* mirrors section-mgmt-* (used by item_details) but psection
3140 class hooks are also queried by static/project-sections.js. */
3141 .psection-row-title { flex: 1; font-weight: bold; }
3142 .psection-row-anchor { font-size: 0.75rem; opacity: 0.6; }
3143 .psection-row-length { font-size: 0.8rem; opacity: 0.6; }
3144
3145 .psection-edit-btn,
3146 .psection-del-btn {
3147 padding: 0.25rem 0.6rem;
3148 font-size: 0.8rem;
3149 }
3150
3151 .psection-add-details { margin-top: var(--space-4); }
3152 .psection-add-details > summary {
3153 cursor: pointer;
3154 font-size: 0.95rem;
3155 }
3156 .psection-add-fields { margin-top: var(--space-3); }
3157
3158 .psection-edit-modal {
3159 margin-top: var(--space-4);
3160 padding: var(--space-4);
3161 background: var(--surface-sunken);
3162 }
3163 .psection-edit-actions {
3164 display: flex;
3165 gap: var(--space-2);
3166 }
3167
3168 /* ===========================================
3169 CART PAGE (replaces inline styles in pages/cart.html)
3170 =========================================== */
3171
3172 .cart-empty {
3173 text-align: center;
3174 padding: 3rem 1rem;
3175 }
3176 .cart-empty-hint {
3177 font-size: 0.9rem;
3178 opacity: 0.7;
3179 margin-bottom: var(--space-5);
3180 }
3181
3182 /* Multi-creator summary bar (only renders when seller_groups.len() > 1). */
3183 .cart-multi-bar-note {
3184 opacity: 0.7;
3185 margin-left: var(--space-2);
3186 }
3187 .cart-multi-bar-form {
3188 display: flex;
3189 align-items: center;
3190 gap: var(--space-3);
3191 }
3192 .cart-share-label {
3193 font-size: 0.85rem;
3194 display: flex;
3195 align-items: center;
3196 gap: var(--space-2);
3197 }
3198
3199 /* Per-seller group card. */
3200 .cart-group { margin-bottom: var(--space-6); }
3201 .cart-group-title { margin-bottom: 0.25rem; }
3202 .cart-group-count {
3203 font-size: 0.85rem;
3204 opacity: 0.6;
3205 margin-bottom: var(--space-4);
3206 }
3207
3208 /* PWYW editable price cell. */
3209 .cart-pwyw-cell {
3210 display: flex;
3211 align-items: center;
3212 justify-content: flex-end;
3213 gap: 0.25rem;
3214 }
3215 .cart-pwyw-symbol { font-size: 0.9rem; }
3216
3217 /* Compact action button used in cart/wishlist tables. */
3218
3219 /* Bottom summary row of each seller group. */
3220 .cart-group-summary {
3221 margin-top: var(--space-4);
3222 display: flex;
3223 justify-content: space-between;
3224 align-items: center;
3225 flex-wrap: wrap;
3226 gap: var(--space-3);
3227 }
3228 .cart-subtotal {
3229 font-family: var(--font-heading);
3230 font-size: 1.1rem;
3231 }
3232 .cart-fee-line {
3233 font-size: 0.85rem;
3234 opacity: 0.6;
3235 }
3236 .cart-savings {
3237 font-size: 0.85rem;
3238 color: var(--action);
3239 margin-top: 0.25rem;
3240 }
3241 .cart-stripe-not-ready {
3242 font-size: 0.9rem;
3243 opacity: 0.6;
3244 }
3245
3246 /* Checkout form within a seller group. */
3247 .cart-promo-row { margin-bottom: var(--space-2); }
3248 .cart-checkout-share {
3249 display: flex;
3250 align-items: center;
3251 gap: var(--space-2);
3252 font-size: 0.85rem;
3253 margin-bottom: var(--space-2);
3254 }
3255
3256 /* Wishlist suggestions section below the cart. */
3257 .cart-wishlist { margin-top: var(--space-6); }
3258
3259 /* Generic "faded out" row state, used by Add-to-Cart click handler in cart.html
3260 to indicate the wishlist row has been moved into the cart. */
3261 .is-faded { opacity: 0.4; }
3262
3263 /* ===========================================
3264 PROFILE TAB (replaces inline styles in partials/tabs/user_profile.html)
3265 =========================================== */
3266
3267 /* Inline form row: input(s) + button laid out horizontally, bottom-aligned.
3268 Distinct from .form-row (which is a 1fr 1fr grid). */
3269 .field-row {
3270 display: flex;
3271 gap: var(--space-3);
3272 align-items: flex-end;
3273 }
3274 .field-row > .form-group { margin-bottom: 0; }
3275 .field-row > .form-group.is-grow { flex: 1; }
3276 .field-row > .form-group.is-grow-2 { flex: 2; }
3277 .field-row > button { margin-bottom: 0; }
3278
3279 /* Custom domain section. */
3280 .profile-domain-header { margin-bottom: var(--space-4); }
3281 .profile-domain-status {
3282 margin-left: var(--space-2);
3283 }
3284 .profile-domain-status.is-verified { color: var(--success); }
3285 .profile-domain-status.is-pending { color: var(--warning); }
3286
3287 .dns-row {
3288 display: flex;
3289 align-items: center;
3290 gap: var(--space-2);
3291 margin-bottom: var(--space-2);
3292 }
3293 .dns-row:last-of-type { margin-bottom: 0; }
3294 .dns-row-label {
3295 font-size: 0.8rem;
3296 opacity: 0.7;
3297 min-width: 70px;
3298 }
3299 .dns-row-value {
3300 font-size: 0.85rem;
3301 flex: 1;
3302 }
3303 .dns-row-copy {
3304 padding: 0.15rem 0.5rem;
3305 font-size: 0.75rem;
3306 }
3307 .profile-domain-actions {
3308 display: flex;
3309 gap: var(--space-3);
3310 }
3311 .profile-domain-result { margin-top: var(--space-3); }
3312 .profile-domain-lead {
3313 font-size: 0.9rem;
3314 opacity: 0.8;
3315 }
3316 .profile-domain-add-result { margin-top: var(--space-3); }
3317
3318 /* Personal feed row: URL input + Copy button. */
3319 .profile-feed-row {
3320 display: flex;
3321 gap: var(--space-2);
3322 align-items: center;
3323 }
3324 .profile-feed-input {
3325 flex: 1;
3326 font-size: 0.85rem;
3327 font-family: var(--font-mono);
3328 opacity: 0.8;
3329 }
3330 .profile-feed-lead { margin-bottom: var(--space-3); }
3331
3332 .purchase-page .checkout-footer {
3333 margin-top: var(--space-6);
3334 padding-top: var(--space-5);
3335 border-top: 1px solid var(--border);
3336 opacity: 0.6;
3337 text-align: center;
3338 font-size: 0.85rem;
3339 }
3340
3341 .purchase-page .checkout-footer a { color: var(--content); }
3342
3343 @media (max-width: 480px) {
3344 .purchase-page .container { padding: 0 var(--space-3); }
3345 .purchase-page .item-summary { flex-direction: column; }
3346 .purchase-page .item-thumbnail { width: 100%; height: 160px; }
3347 .purchase-page .checkout-box { padding: var(--space-5); }
3348 .purchase-page h2 { font-size: 1.4rem; }
3349 }
3350
3351 /* Feed page (templates/pages/feed.html). Compact tabular layout of
3352 items from followed users / projects / tags. */
3353 .feed-page .page-title { font-size: 1.5rem; margin-bottom: var(--space-4); }
3354 .feed-page .feed-meta { font-size: 0.8rem; opacity: 0.6; margin-bottom: var(--space-3); }
3355
3356 .feed-page .table-header {
3357 display: grid;
3358 grid-template-columns: 50px 1fr 100px 70px 70px;
3359 gap: var(--space-2);
3360 padding: var(--space-2) var(--space-3);
3361 background: var(--surface-overlay);
3362 font-size: 0.75rem;
3363 opacity: 0.7;
3364 text-transform: uppercase;
3365 letter-spacing: 0.03em;
3366 }
3367
3368 .feed-page .col-right { text-align: right; }
3369
3370 .feed-page .results-table {
3371 border: 1px solid var(--border);
3372 border-top: none;
3373 }
3374
3375 .feed-page .table-row {
3376 display: grid;
3377 grid-template-columns: 50px 1fr 100px 70px 70px;
3378 gap: var(--space-2);
3379 padding: 0.4rem var(--space-3);
3380 align-items: center;
3381 text-decoration: none;
3382 color: var(--content);
3383 font-size: 0.85rem;
3384 border-bottom: 1px solid var(--border);
3385 transition: background 0.1s ease;
3386 }
3387
3388 .feed-page .table-row:last-child { border-bottom: none; }
3389 .feed-page .table-row:nth-child(odd) { background: var(--surface-overlay); }
3390 .feed-page .table-row:nth-child(even) { background: var(--surface-overlay); }
3391 .feed-page .table-row:hover { background: var(--surface-sunken); }
3392
3393 .feed-page .item-name-cell {
3394 display: flex;
3395 flex-direction: column;
3396 gap: 0.1rem;
3397 min-width: 0;
3398 }
3399
3400 .feed-page .item-name {
3401 white-space: nowrap;
3402 overflow: hidden;
3403 text-overflow: ellipsis;
3404 }
3405
3406 .feed-page .item-creator { font-size: 0.75rem; opacity: 0.5; }
3407
3408 .feed-page .badge {
3409 text-transform: uppercase;
3410 letter-spacing: 0.03em;
3411 background: var(--surface-sunken);
3412 }
3413
3414 .feed-page .empty-state {
3415 text-align: center;
3416 padding: 3rem var(--space-5);
3417 background: var(--surface-overlay);
3418 border: 1px solid var(--border);
3419 }
3420
3421 .feed-page .empty-state h2 { font-size: 1.3rem; margin-bottom: var(--space-2); }
3422 .feed-page .empty-state p { opacity: 0.7; margin-bottom: var(--space-5); }
3423
3424 .feed-page .pagination {
3425 display: flex;
3426 gap: var(--space-1);
3427 justify-content: center;
3428 margin-top: var(--space-4);
3429 }
3430
3431 .feed-page .pagination a,
3432 .feed-page .pagination span {
3433 padding: 0.4rem 0.7rem;
3434 font-size: 0.85rem;
3435 text-decoration: none;
3436 color: var(--content);
3437 border: 1px solid var(--border);
3438 }
3439
3440 .feed-page .pagination span.current {
3441 background: var(--primary-dark);
3442 color: var(--primary-light);
3443 border-color: var(--primary-dark);
3444 }
3445
3446 .feed-page .pagination a:hover { background: var(--surface-sunken); }
3447
3448 @media (max-width: 600px) {
3449 .feed-page .table-header,
3450 .feed-page .table-row { grid-template-columns: 1fr 70px; }
3451 .feed-page .table-header span:nth-child(1),
3452 .feed-page .table-row .badge:first-child,
3453 .feed-page .table-header span:nth-child(3),
3454 .feed-page .table-header span:nth-child(4),
3455 .feed-page .table-row span:nth-child(3),
3456 .feed-page .table-row span:nth-child(4) { display: none; }
3457 }
3458
3459 /* (Stripe Connect disclaimer page rules defined in the canonical
3460 STRIPE DISCLAIMER PAGE section near end of file.) */
3461
3462 /* User profile page (templates/pages/user.html). */
3463 .user-page .profile-header { text-align: center; margin-bottom: 3rem; }
3464
3465 .user-page .profile-avatar {
3466 width: 120px;
3467 height: 120px;
3468 background: var(--surface-overlay);
3469 margin: 0 auto var(--space-4);
3470 display: flex;
3471 align-items: center;
3472 justify-content: center;
3473 font-size: 3rem;
3474 opacity: 0.5;
3475 }
3476
3477 .user-page .profile-name { font-size: 2rem; margin-bottom: var(--space-2); }
3478
3479 .user-page .profile-username {
3480 font-size: 0.9rem;
3481 opacity: 0.7;
3482 margin-bottom: var(--space-4);
3483 }
3484
3485 .user-page .profile-bio {
3486 font-size: 1rem;
3487 max-width: 500px;
3488 margin: 0 auto;
3489 text-align: center;
3490 }
3491
3492 .user-page .links-section { margin-bottom: var(--space-6); }
3493 .user-page .link-item { text-align: center; }
3494
3495 .user-page .link-title {
3496 font-size: 1.1rem;
3497 margin-bottom: var(--space-1);
3498 font-family: var(--font-heading);
3499 font-weight: bold;
3500 }
3501
3502 .user-page .link-description { font-size: 0.85rem; opacity: 0.7; }
3503
3504 .user-page .project-title {
3505 font-size: 1.1rem;
3506 margin-bottom: var(--space-2);
3507 font-family: var(--font-heading);
3508 font-weight: bold;
3509 }
3510
3511 .user-page .project-meta {
3512 font-size: 0.85rem;
3513 opacity: 0.7;
3514 margin-bottom: var(--space-2);
3515 }
3516
3517 .user-page .project-description { font-size: 0.9rem; opacity: 0.8; }
3518
3519 /* Creators / become-a-creator page (templates/pages/creators.html). */
3520 .creators-page h1 { font-size: 2.5rem; margin-bottom: var(--space-2); }
3521 .creators-page h2 { font-size: 1.5rem; margin-top: var(--space-6); margin-bottom: var(--space-4); }
3522
3523 .creators-page .how-it-works { margin-bottom: var(--space-6); }
3524 .creators-page .how-it-works ol { padding-left: var(--space-5); line-height: 1.8; }
3525
3526 .creators-page .stats-row { gap: var(--space-6); margin: var(--space-6) 0; }
3527 .creators-page .stat-box { padding: var(--space-5); }
3528 .creators-page .stat-box .number { font-size: 2rem; }
3529 .creators-page .stat-box .label { font-size: 0.85rem; margin-top: var(--space-1); }
3530
3531 .creators-page .wave-table {
3532 width: 100%;
3533 border-collapse: collapse;
3534 margin: var(--space-4) 0;
3535 }
3536
3537 .creators-page .wave-table th,
3538 .creators-page .wave-table td {
3539 padding: var(--space-3) var(--space-4);
3540 text-align: left;
3541 border-bottom: 1px solid var(--border);
3542 }
3543
3544 .creators-page .wave-table th {
3545 font-family: var(--font-mono);
3546 font-size: 0.85rem;
3547 opacity: 0.7;
3548 }
3549
3550 .creators-page .cta {
3551 margin-top: var(--space-6);
3552 padding: var(--space-5);
3553 background: var(--surface-overlay);
3554 text-align: center;
3555 }
3556
3557 .creators-page .cta a { margin: 0 var(--space-2); }
3558
3559 /* Tag tree browse page (templates/pages/tag_tree.html). */
3560 .tag-tree-page .breadcrumbs {
3561 font-size: 0.85rem;
3562 margin-bottom: var(--space-5);
3563 opacity: 0.7;
3564 }
3565 .tag-tree-page .breadcrumbs a { text-decoration: none; color: inherit; }
3566 .tag-tree-page .breadcrumbs a:hover { opacity: 0.6; }
3567 .tag-tree-page .breadcrumbs .sep { margin: 0 0.3rem; opacity: 0.4; }
3568
3569 .tag-tree-page .tag-grid {
3570 display: grid;
3571 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
3572 gap: var(--space-3);
3573 }
3574
3575 .tag-tree-page .tag-card {
3576 background: var(--surface-sunken);
3577 padding: var(--space-3) var(--space-4);
3578 text-decoration: none;
3579 color: var(--content);
3580 border: 1px solid var(--border);
3581 transition: background 0.1s ease;
3582 }
3583
3584 .tag-tree-page .tag-card:hover {
3585 background: var(--surface-sunken);
3586 text-decoration: none;
3587 }
3588
3589 .tag-tree-page .tag-card-name {
3590 font-family: var(--font-heading);
3591 font-weight: bold;
3592 font-size: 0.95rem;
3593 }
3594
3595 .tag-tree-page .tag-card-meta {
3596 font-size: 0.75rem;
3597 opacity: 0.5;
3598 margin-top: var(--space-1);
3599 }
3600
3601 .tag-tree-page .empty-state {
3602 opacity: 0.5;
3603 font-size: 0.9rem;
3604 padding: var(--space-6) 0;
3605 }
3606
3607 /* Confirm delete prompt (templates/pages/confirm_delete.html). Overrides
3608 the global .warning-box to use --danger-bg (matches the delete-account
3609 semantic). Also tokenized previously-broken fallbacks. */
3610 .confirm-delete-page .warning-box {
3611 background: color-mix(in oklch, var(--danger) 10%, var(--surface-page));
3612 border: 1px solid var(--danger);
3613 border-radius: 8px;
3614 padding: var(--space-5);
3615 margin-bottom: var(--space-5);
3616 }
3617
3618 .confirm-delete-page .warning-box p {
3619 margin: 0;
3620 color: var(--danger);
3621 }
3622
3623 /* Project paywall page (templates/pages/project_paywall.html). */
3624 .project-paywall-page .paywall-cover { margin-bottom: var(--space-5); }
3625 .project-paywall-page .paywall-cover img {
3626 width: 120px;
3627 height: 120px;
3628 border-radius: 8px;
3629 object-fit: cover;
3630 }
3631
3632 .project-paywall-page .paywall-title {
3633 font-family: var(--font-heading);
3634 font-size: 3rem;
3635 margin-bottom: var(--space-2);
3636 }
3637
3638 .project-paywall-page .paywall-creator {
3639 font-size: 0.95rem;
3640 opacity: 0.7;
3641 margin-bottom: var(--space-5);
3642 }
3643
3644 .project-paywall-page .paywall-creator a { color: var(--content); }
3645
3646 .project-paywall-page .paywall-description {
3647 font-size: 1.1rem;
3648 max-width: 800px;
3649 margin: 0 auto var(--space-6);
3650 text-align: left;
3651 }
3652
3653 .project-paywall-page .paywall-tiers {
3654 display: grid;
3655 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
3656 gap: var(--space-5);
3657 margin-top: var(--space-5);
3658 text-align: left;
3659 }
3660
3661 .project-paywall-page .paywall-tiers .tier-card {
3662 background: var(--surface-overlay);
3663 padding: var(--space-6);
3664 display: flex;
3665 flex-direction: column;
3666 }
3667
3668 .project-paywall-page .paywall-tiers .tier-card h3 {
3669 font-family: var(--font-heading);
3670 font-weight: bold;
3671 font-size: 1.3rem;
3672 margin-bottom: var(--space-2);
3673 }
3674
3675 .project-paywall-page .paywall-tiers .tier-price {
3676 font-size: 1.5rem;
3677 margin-bottom: var(--space-4);
3678 }
3679
3680 .project-paywall-page .paywall-tiers .tier-card form,
3681 .project-paywall-page .paywall-tiers .tier-card .button { margin-top: auto; }
3682
3683 .project-paywall-page .paywall-tiers .tier-card button,
3684 .project-paywall-page .paywall-tiers .tier-card .button { width: 100%; }
3685
3686 /* Collection detail page (templates/pages/collection.html). */
3687 .collection-page .container { max-width: 700px; }
3688 .collection-page .collection-header { margin-bottom: var(--space-6); }
3689 .collection-page .collection-title { font-size: 2rem; margin-bottom: var(--space-1); }
3690
3691 .collection-page .collection-owner {
3692 font-size: 0.9rem;
3693 opacity: 0.7;
3694 margin-bottom: var(--space-3);
3695 }
3696
3697 .collection-page .collection-description {
3698 font-size: 0.95rem;
3699 opacity: 0.85;
3700 margin-bottom: var(--space-3);
3701 }
3702
3703 .collection-page .collection-meta { font-size: 0.85rem; opacity: 0.6; }
3704
3705 .collection-page .collection-item {
3706 display: flex;
3707 justify-content: space-between;
3708 align-items: flex-start;
3709 padding: var(--space-4);
3710 background: var(--surface-overlay);
3711 margin-bottom: var(--space-2);
3712 }
3713
3714 .collection-page .collection-item-info { flex: 1; }
3715
3716 .collection-page .collection-item-title {
3717 font-family: var(--font-heading);
3718 font-weight: bold;
3719 font-size: 1.05rem;
3720 margin-bottom: var(--space-1);
3721 }
3722
3723 .collection-page .collection-item-title a { text-decoration: none; }
3724
3725 .collection-page .collection-item-meta { font-size: 0.85rem; opacity: 0.7; }
3726
3727 .collection-page .collection-item-price {
3728 font-size: 0.9rem;
3729 white-space: nowrap;
3730 margin-left: var(--space-4);
3731 }
3732
3733 .collection-page .empty-state {
3734 text-align: center;
3735 padding: 3rem var(--space-4);
3736 opacity: 0.6;
3737 }
3738
3739 /* Project blog index page (templates/pages/project_blog.html). */
3740 .project-blog-page .blog-header { margin-bottom: 3rem; }
3741 .project-blog-page .blog-title { font-size: 2.5rem; margin-bottom: var(--space-2); }
3742
3743 .project-blog-page .blog-meta {
3744 font-size: 0.9rem;
3745 opacity: 0.7;
3746 margin-bottom: var(--space-5);
3747 }
3748
3749 .project-blog-page .blog-meta a { color: var(--content); }
3750
3751 .project-blog-page .blog-actions {
3752 display: flex;
3753 gap: var(--space-4);
3754 }
3755
3756 .project-blog-page .posts-list { max-width: 800px; }
3757
3758 .project-blog-page .post-entry {
3759 padding: var(--space-5) 0;
3760 border-bottom: 1px solid var(--border);
3761 }
3762
3763 .project-blog-page .post-entry:first-child { padding-top: 0; }
3764 .project-blog-page .post-title { font-size: 1.5rem; margin-bottom: var(--space-2); }
3765 .project-blog-page .post-title a { color: inherit; text-decoration: none; }
3766 .project-blog-page .post-title a:hover { text-decoration: underline; }
3767
3768 .project-blog-page .post-date {
3769 font-size: 0.85rem;
3770 opacity: 0.6;
3771 font-family: var(--font-mono);
3772 }
3773
3774 .project-blog-page .empty-state { padding: 3rem 0; opacity: 0.6; }
3775
3776 /* Canonical "page-level h1", left-aligned, smaller than the global centered
3777 default. Used by dashboards, admin, health, import, delete-account, export,
3778 receipt. Aliased via comma-grouped selectors so each page picks it up via
3779 its body class without redefining. */
3780 .dashboard-page h1,
3781 .admin-page h1,
3782 .health-page h1,
3783 .import-page h1,
3784 .delete-account-page h1,
3785 .export-page h1,
3786 .receipt-page h1 {
3787 font-size: 2rem;
3788 margin-bottom: var(--space-2);
3789 text-align: left;
3790 }
3791 .delete-account-page h1 { color: var(--danger); }
3792
3793 /* Canonical subtitle under a page h1, muted, with bottom space. */
3794 .health-page .subtitle,
3795 .import-page .subtitle,
3796 .delete-account-page .subtitle,
3797 .export-page .subtitle {
3798 opacity: 0.7;
3799 margin-bottom: var(--space-6);
3800 text-align: left;
3801 }
3802 .health-page .subtitle { text-align: center; }
3803
3804 /* User Settings tab (templates/partials/tabs/user_settings.html).
3805 Left-rail nav layout for the Settings dashboard tab. Selection uses the
3806 canonical .is-selected modifier. */
3807 .settings-layout { display: flex; gap: var(--space-6); }
3808 .settings-nav { flex-shrink: 0; min-width: 140px; }
3809 .settings-nav a {
3810 display: block;
3811 padding: var(--space-2) var(--space-3);
3812 text-decoration: none;
3813 color: var(--content);
3814 opacity: 0.6;
3815 font-family: var(--font-mono);
3816 font-size: 0.9rem;
3817 transition: opacity 0.15s ease;
3818 }
3819 .settings-nav a:hover { opacity: 1; }
3820 .settings-nav a.is-selected { opacity: 1; background: var(--surface-sunken); }
3821 .settings-body { flex: 1; min-width: 0; }
3822 @media (max-width: 768px) {
3823 .settings-layout { flex-direction: column; gap: var(--space-4); }
3824 .settings-nav { display: flex; flex-wrap: wrap; gap: 0; min-width: 0; }
3825 .settings-nav a { padding: 0.4rem 0.6rem; font-size: 0.85rem; }
3826 }.library-page .feed-table-header {
3827 display: grid;
3828 grid-template-columns: 50px 1fr 100px 70px 70px;
3829 gap: var(--space-2);
3830 padding: var(--space-2) var(--space-3);
3831 background: var(--surface-overlay);
3832 font-size: 0.75rem;
3833 opacity: 0.7;
3834 text-transform: uppercase;
3835 letter-spacing: 0.03em;
3836 }
3837 .library-page .feed-col-right { text-align: right; }
3838 .library-page .feed-results-table { border: 1px solid var(--border); border-top: none; }
3839 .library-page .feed-table-row {
3840 display: grid;
3841 grid-template-columns: 50px 1fr 100px 70px 70px;
3842 gap: var(--space-2);
3843 padding: 0.4rem var(--space-3);
3844 align-items: center;
3845 text-decoration: none;
3846 color: var(--content);
3847 font-size: 0.85rem;
3848 border-bottom: 1px solid var(--border);
3849 transition: background 0.1s ease;
3850 }
3851 .library-page .feed-table-row:last-child { border-bottom: none; }
3852 .library-page .feed-table-row:nth-child(odd) { background: var(--surface-overlay); }
3853 .library-page .feed-table-row:nth-child(even) { background: var(--surface-overlay); }
3854 .library-page .feed-table-row:hover { background: var(--surface-sunken); }
3855 .library-page .feed-item-name-cell {
3856 display: flex;
3857 flex-direction: column;
3858 gap: 0.1rem;
3859 min-width: 0;
3860 }
3861 .library-page .feed-item-name {
3862 white-space: nowrap;
3863 overflow: hidden;
3864 text-overflow: ellipsis;
3865 }
3866 .library-page .feed-item-creator { font-size: 0.75rem; opacity: 0.5; }
3867 .library-page .feed-pagination {
3868 display: flex;
3869 gap: var(--space-1);
3870 justify-content: center;
3871 margin-top: var(--space-4);
3872 }
3873 .library-page .feed-pagination a,
3874 .library-page .feed-pagination span {
3875 padding: 0.4rem 0.7rem;
3876 font-size: 0.85rem;
3877 text-decoration: none;
3878 color: var(--content);
3879 border: 1px solid var(--border);
3880 }
3881 .library-page .feed-pagination span.current {
3882 background: var(--primary-dark);
3883 color: var(--primary-light);
3884 border-color: var(--primary-dark);
3885 }
3886 .library-page .feed-pagination a:hover { background: var(--surface-sunken); }
3887 @media (max-width: 600px) {
3888 .library-page .feed-table-header,
3889 .library-page .feed-table-row {
3890 grid-template-columns: 1fr 70px;
3891 }
3892 .library-page .feed-table-header span:nth-child(1),
3893 .library-page .feed-table-row .badge:first-child,
3894 .library-page .feed-table-header span:nth-child(3),
3895 .library-page .feed-table-header span:nth-child(4),
3896 .library-page .feed-table-row span:nth-child(3),
3897 .library-page .feed-table-row span:nth-child(4) {
3898 display: none;
3899 }
3900 }
3901
3902 /* User-level dashboard (templates/dashboards/dashboard-user.html).
3903 Scoped under .dashboard-user-page to avoid colliding with .project-card
3904 / .project-title / .project-meta on the public profile (user.html) and
3905 the user_projects tab partial. */
3906 .dashboard-user-page .stat-value { font-size: 2rem; margin-bottom: var(--space-1); }
3907
3908 .dashboard-user-page .project-card {
3909 background: var(--surface-overlay);
3910 padding: var(--space-5);
3911 margin-bottom: var(--space-4);
3912 display: flex;
3913 justify-content: space-between;
3914 align-items: flex-start;
3915 }
3916
3917 .dashboard-user-page .project-info { flex: 1; }
3918
3919 .dashboard-user-page .project-title {
3920 font-family: var(--font-heading);
3921 font-weight: bold;
3922 font-size: 1.2rem;
3923 margin-bottom: var(--space-1);
3924 }
3925
3926 .dashboard-user-page .project-meta {
3927 font-size: 0.85rem;
3928 opacity: 0.7;
3929 margin-bottom: var(--space-2);
3930 }
3931
3932 .dashboard-user-page .project-stats { font-size: 0.9rem; }
3933 .dashboard-user-page .project-actions {
3934 display: flex;
3935 gap: var(--space-2);
3936 }
3937
3938 .dashboard-user-page .project-actions button {
3939 padding: 0.4rem 0.8rem;
3940 font-size: 0.85rem;
3941 }
3942 @media (max-width: 768px) {
3943 .dashboard-user-page .project-card { flex-direction: column; }
3944 .dashboard-user-page .project-actions { margin-top: var(--space-3); }
3945 }
3946
3947 /* Project dashboard (templates/dashboards/dashboard-project.html). */
3948 .dashboard-project-page .project-meta { font-size: 0.9rem; opacity: 0.7; }
3949 .dashboard-project-page .stat-value { font-size: 2rem; margin-bottom: var(--space-1); }
3950
3951 .dashboard-project-page .content-header {
3952 display: flex;
3953 justify-content: space-between;
3954 align-items: center;
3955 margin-bottom: var(--space-5);
3956 }
3957
3958 .dashboard-project-page .content-header h2 { font-size: 1.3rem; }
3959
3960 .dashboard-project-page .item-thumbnail {
3961 width: 40px;
3962 height: 40px;
3963 background: var(--border);
3964 display: inline-block;
3965 vertical-align: middle;
3966 margin-right: var(--space-2);
3967 }
3968
3969 .dashboard-project-page .item-actions {
3970 display: flex;
3971 gap: var(--space-2);
3972 }
3973
3974 .dashboard-project-page .item-actions button {
3975 padding: 0.4rem 0.8rem;
3976 font-size: 0.85rem;
3977 }
3978
3979 .dashboard-project-page .data-section { margin-bottom: var(--space-6); }
3980
3981 .dashboard-project-page .data-section h2 {
3982 font-size: 1.3rem;
3983 margin-bottom: var(--space-4);
3984 padding-bottom: var(--space-2);
3985 border-bottom: 1px solid var(--border);
3986 }
3987
3988 /* Item dashboard (templates/dashboards/dashboard-item.html). */
3989 .dashboard-item-page .item-meta {
3990 font-size: 0.9rem;
3991 opacity: 0.7;
3992 display: flex;
3993 gap: var(--space-4);
3994 align-items: center;
3995 }
3996
3997 .dashboard-item-page .stat-value { font-size: 1.5rem; }
3998
3999 .dashboard-item-page .section-header {
4000 display: flex;
4001 justify-content: space-between;
4002 align-items: center;
4003 margin-bottom: var(--space-5);
4004 padding-bottom: var(--space-3);
4005 border-bottom: 1px solid var(--border);
4006 }
4007
4008 .dashboard-item-page .section-header h2 { font-size: 1.3rem; }
4009
4010 @media (max-width: 768px) {
4011 .dashboard-item-page .section-header {
4012 flex-direction: column;
4013 align-items: flex-start;
4014 gap: var(--space-3);
4015 }
4016 .dashboard-item-page .section-header .action-buttons { width: 100%; }
4017 }
4018
4019 /* Blog editor dashboard (templates/dashboards/dashboard-blog-editor.html). */
4020 .blog-editor .editor-form { max-width: 800px; }
4021 .blog-editor .editor-form .form-group { margin-bottom: var(--space-5); }
4022 .blog-editor .editor-form textarea {
4023 font-family: var(--font-mono);
4024 font-size: 0.9rem;
4025 min-height: 400px;
4026 resize: vertical;
4027 }
4028
4029 /* Changelog page (templates/pages/changelog.html). */
4030 .changelog-page .container { max-width: 900px; margin: 0 auto; }
4031 .changelog-page h1 { font-size: 2.5rem; margin-bottom: var(--space-2); }
4032 .changelog-page .changelog-entry {
4033 margin-bottom: 2.5rem;
4034 padding-bottom: var(--space-6);
4035 border-bottom: 1px solid var(--border);
4036 }
4037 .changelog-page .changelog-entry:last-child { border-bottom: none; }
4038 .changelog-page .changelog-date {
4039 font-family: var(--font-mono);
4040 font-size: 0.9rem;
4041 opacity: 0.6;
4042 margin-bottom: var(--space-2);
4043 }
4044 .changelog-page .changelog-entry h2 { font-size: 1.3rem; margin-bottom: var(--space-3); }
4045 .changelog-page .changelog-entry ul {
4046 padding-left: var(--space-5);
4047 margin: var(--space-2) 0;
4048 line-height: 1.7;
4049 }
4050 .changelog-page .changelog-entry li { margin-bottom: var(--space-1); }
4051
4052 /* Policy page (templates/pages/policy.html). */
4053 .policy-page .container { max-width: 900px; margin: 0 auto; }
4054 .policy-page h1 { font-size: 2.5rem; margin-bottom: var(--space-2); }
4055 .policy-page h2 {
4056 font-size: 1.5rem;
4057 margin-top: var(--space-6);
4058 margin-bottom: var(--space-4);
4059 }
4060 .policy-page .policy-section { margin-bottom: var(--space-6); line-height: 1.7; }
4061 .policy-page .policy-section ul {
4062 padding-left: var(--space-5);
4063 margin: var(--space-3) 0;
4064 }
4065 .policy-page .policy-section li { margin-bottom: var(--space-1); }
4066 .policy-page .contact {
4067 margin-top: var(--space-6);
4068 padding: var(--space-5);
4069 background: var(--surface-overlay);
4070 }
4071
4072 /* Admin page extras (in addition to global .admin-page h1). */
4073 .admin-page .metrics-grid {
4074 display: grid;
4075 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
4076 gap: var(--space-4);
4077 margin-bottom: var(--space-6);
4078 }
4079
4080 .admin-page .metric-card {
4081 padding: var(--space-4);
4082 border: 1px solid var(--border);
4083 border-radius: var(--radius-md);
4084 }
4085
4086 .admin-page .metric-card .value {
4087 font-size: 1.8rem;
4088 font-family: var(--font-mono);
4089 font-weight: 600;
4090 }
4091
4092 .admin-page .metric-card .label {
4093 font-size: 0.85rem;
4094 color: var(--content-muted);
4095 margin-top: var(--space-1);
4096 }
4097
4098 .admin-page .metric-card.warn .value { color: var(--warning); }
4099 .admin-page .metric-card.error .value { color: var(--danger); }
4100
4101 .admin-page .section-heading {
4102 font-size: 1.2rem;
4103 margin: var(--space-5) 0 var(--space-3);
4104 font-family: var(--font-mono);
4105 }
4106
4107 /* Scan pipeline dashboard. See docs/scan-pipeline-audit.md § 5. */
4108
4109 .admin-scan-section {
4110 margin-top: var(--space-6);
4111 }
4112
4113 .admin-section-header {
4114 display: flex;
4115 justify-content: space-between;
4116 align-items: baseline;
4117 margin-bottom: var(--space-3);
4118 gap: var(--space-3);
4119 }
4120
4121 .admin-section-header h2 {
4122 font-size: 1.1rem;
4123 font-family: var(--font-mono);
4124 margin: 0;
4125 }
4126
4127 .layer-health-grid {
4128 display: grid;
4129 grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
4130 gap: var(--space-3);
4131 }
4132
4133 .layer-health-card {
4134 padding: var(--space-3);
4135 border: 1px solid var(--border);
4136 border-radius: var(--radius-md);
4137 border-left-width: 4px;
4138 font-size: 0.85rem;
4139 }
4140
4141 .layer-health-card .layer-name {
4142 font-family: var(--font-mono);
4143 font-weight: 600;
4144 font-size: 0.95rem;
4145 margin-bottom: var(--space-2);
4146 }
4147
4148 .layer-health-card .layer-stat {
4149 display: flex;
4150 justify-content: space-between;
4151 margin-bottom: 2px;
4152 }
4153
4154 .layer-health-card .layer-stat .dimmed {
4155 color: var(--content-muted);
4156 }
4157
4158 .layer-health-card.layer-ok { border-left-color: var(--success, #527a3e); }
4159 .layer-health-card.layer-degraded { border-left-color: var(--warning); }
4160 .layer-health-card.layer-down { border-left-color: var(--danger); }
4161
4162 .layer-chips {
4163 display: flex;
4164 flex-wrap: wrap;
4165 gap: 4px;
4166 max-width: 360px;
4167 }
4168
4169 .layer-chip {
4170 display: inline-block;
4171 font-family: var(--font-mono);
4172 font-size: 0.7rem;
4173 padding: 1px 6px;
4174 border-radius: var(--radius-sm);
4175 border: 1px solid transparent;
4176 cursor: help;
4177 line-height: 1.4;
4178 }
4179
4180 .layer-chip-pass { background: #e6f0dc; border-color: #c4d8a8; color: #3a5a2a; }
4181 .layer-chip-skip { background: var(--surface-page); border-color: var(--border); color: var(--content-muted); }
4182 .layer-chip-fail { background: color-mix(in oklch, var(--danger) 10%, var(--surface-page)); border-color: var(--danger); color: var(--danger); font-weight: 600; }
4183 .layer-chip-error { background: color-mix(in oklch, var(--warning) 14%, var(--surface-page)); border-color: var(--warning); color: var(--warning); font-weight: 600; }
4184
4185 .scan-history-grid table { font-size: 0.85rem; }
4186
4187 .scan-history-grid summary {
4188 cursor: pointer;
4189 font-family: var(--font-mono);
4190 padding: var(--space-2) 0;
4191 user-select: none;
4192 }
4193
4194 .scan-row-meta {
4195 font-size: 0.75rem;
4196 color: var(--content-muted);
4197 margin-top: 2px;
4198 }
4199
4200 .audit-filter-form {
4201 display: flex;
4202 flex-wrap: wrap;
4203 align-items: flex-end;
4204 gap: var(--space-3);
4205 padding: var(--space-3) 0;
4206 margin-bottom: var(--space-3);
4207 border-bottom: 1px solid var(--border);
4208 }
4209
4210 .audit-filter-form label {
4211 display: flex;
4212 flex-direction: column;
4213 gap: 2px;
4214 }
4215
4216 .audit-filter-form input,
4217 .audit-filter-form select {
4218 font-size: 0.9rem;
4219 }
4220
4221 .layer-chips-cell { vertical-align: top; }
4222
4223 .layer-detail-disclosure {
4224 margin-top: var(--space-2);
4225 }
4226
4227 .layer-detail-disclosure summary {
4228 cursor: pointer;
4229 user-select: none;
4230 padding: 2px 0;
4231 }
4232
4233 .layer-detail-list {
4234 margin: var(--space-2) 0 0;
4235 display: grid;
4236 grid-template-columns: max-content 1fr;
4237 gap: 2px var(--space-3);
4238 font-size: 0.8rem;
4239 }
4240
4241 .layer-detail-list dt {
4242 font-family: var(--font-mono);
4243 }
4244
4245 .layer-detail-list dd {
4246 margin: 0;
4247 color: var(--content-muted);
4248 word-break: break-word;
4249 }
4250
4251 .admin-page table {
4252 width: 100%;
4253 border-collapse: collapse;
4254 font-size: 0.9rem;
4255 }
4256
4257 .admin-page th,
4258 .admin-page td {
4259 text-align: left;
4260 padding: 0.4rem 0.6rem;
4261 border-bottom: 1px solid var(--border);
4262 }
4263
4264 .admin-page th {
4265 font-family: var(--font-mono);
4266 font-size: 0.8rem;
4267 text-transform: uppercase;
4268 color: var(--content-muted);
4269 }
4270
4271 .admin-page td.mono { font-family: var(--font-mono); }
4272
4273 .admin-page .refresh-note {
4274 font-size: 0.8rem;
4275 color: var(--content-muted);
4276 margin-bottom: var(--space-4);
4277 font-family: var(--font-mono);
4278 }
4279
4280 .admin-page .appeal-count {
4281 font-size: 0.9rem;
4282 opacity: 0.7;
4283 margin-bottom: var(--space-5);
4284 }
4285
4286 .admin-page .decide-form {
4287 display: flex;
4288 gap: var(--space-2);
4289 align-items: flex-end;
4290 flex-wrap: wrap;
4291 }
4292
4293 .admin-page .decide-form textarea {
4294 min-width: 200px;
4295 font-size: 0.85rem;
4296 }
4297
4298 .admin-page .suspend-form {
4299 display: flex;
4300 gap: var(--space-2);
4301 align-items: flex-end;
4302 }
4303
4304 .admin-page .suspend-form input[type="text"] {
4305 min-width: 200px;
4306 font-size: 0.85rem;
4307 }
4308
4309 .admin-page .lottery-form {
4310 background: var(--surface-overlay);
4311 padding: var(--space-5);
4312 margin: var(--space-5) 0;
4313 display: flex;
4314 gap: var(--space-4);
4315 align-items: flex-end;
4316 }
4317
4318 .admin-page .lottery-form .form-group { margin-bottom: 0; }
4319
4320 .admin-page .lottery-form label {
4321 font-size: 0.85rem;
4322 display: block;
4323 margin-bottom: var(--space-1);
4324 }
4325
4326 .admin-page .lottery-form input[type="number"] { width: 80px; }
4327
4328 /* Page-top notice (charter primitive, replaces #restart-banner and
4329 the inline sandbox banner in dashboard-project). Full-bleed across
4330 the viewport, monospace, one short sentence + optional action.
4331 Hero callouts on the landing page use `.alert` instead (multi-paragraph). */
4332 .banner {
4333 padding: var(--space-3) var(--space-5);
4334 font-family: var(--font-mono);
4335 font-size: 0.9rem;
4336 text-align: center;
4337 color: var(--content);
4338 }
4339
4340 .banner--info {
4341 background: color-mix(in oklch, var(--action) 8%, transparent);
4342 border-bottom: 2px solid var(--focus-ring);
4343 }
4344
4345 .banner--warning {
4346 background: color-mix(in oklch, var(--warning) 14%, var(--surface-page));
4347 border-bottom: 2px solid var(--warning);
4348 }
4349
4350 .banner a {
4351 color: inherit;
4352 text-decoration: underline;
4353 }
4354
4355 /* ===========================================
4356 SECTIONS
4357 =========================================== */
4358
4359 .section-header {
4360 font-size: 1.5rem;
4361 font-weight: normal;
4362 margin-bottom: 1rem;
4363 padding-bottom: 0.5rem;
4364 border-bottom: 1px solid var(--border);
4365 font-family: var(--font-mono);
4366 }
4367
4368 /* Canonical "page section box", light-background card with padding + bottom
4369 space. One of these in the codebase. Aliased to the per-page class names
4370 that were just relabels of this same shape. Templates can use the alias
4371 name OR add `.content-section` as a co-class. */
4372 .content-section,
4373 .import-page .import-form,
4374 .import-page .import-progress,
4375 .library-page .library-section,
4376 .library-page .library-downloads,
4377 .library-page .downloads-hero,
4378 .receipt-page .receipt-box,
4379 .stripe-disclaimer-page .disclaimer-box,
4380 .project-page .project-sections {
4381 background: var(--surface-overlay);
4382 padding: var(--space-6);
4383 margin-bottom: var(--space-6);
4384 }
4385
4386 /* Variants of the canonical shape that want top-spacing instead of bottom,
4387 or a tighter --space-5 padding. */
4388 .library-page .library-downloads,
4389 .receipt-page .receipt-box { margin-bottom: 0; margin-top: var(--space-5); }
4390 .import-page .import-progress { padding: var(--space-5); margin-bottom: var(--space-4); }
4391 .stripe-disclaimer-page .disclaimer-box { margin-bottom: var(--space-5); }
4392
4393 .form-section {
4394 margin-bottom: 2rem;
4395 }
4396
4397 .section-group-label {
4398 font-family: var(--font-mono);
4399 font-size: 0.8rem;
4400 font-weight: bold;
4401 text-transform: uppercase;
4402 letter-spacing: 0.05em;
4403 color: var(--content-muted);
4404 margin: 2.5rem 0 1rem 0;
4405 padding-top: 1.5rem;
4406 border-top: 2px solid var(--border);
4407 }
4408
4409 .form-section h2 {
4410 font-size: 1.3rem;
4411 font-weight: normal;
4412 margin-bottom: 1rem;
4413 padding-bottom: 0.5rem;
4414 border-bottom: 1px solid var(--border);
4415 }
4416
4417 details.form-section > summary {
4418 cursor: pointer;
4419 list-style: disclosure-closed;
4420 }
4421
4422 details.form-section[open] > summary {
4423 list-style: disclosure-open;
4424 margin-bottom: 1rem;
4425 }
4426
4427 details.form-section > summary > h2 {
4428 display: inline;
4429 }
4430
4431 details.form-section > summary:hover > h2 {
4432 color: var(--content);
4433 }
4434
4435 /* ===========================================
4436 NAVIGATION
4437 =========================================== */
4438
4439 nav {
4440 margin-bottom: 2rem;
4441 }
4442
4443 .nav-links {
4444 display: flex;
4445 gap: 2rem;
4446 flex-wrap: wrap;
4447 }
4448
4449 .nav-links a {
4450 color: var(--content);
4451 text-decoration: none;
4452 font-family: var(--font-mono);
4453 transition: opacity 0.2s ease;
4454 }
4455
4456 .nav-links a:hover {
4457 opacity: 0.6;
4458 }
4459
4460 .shortcuts-help-btn {
4461 font-family: var(--font-mono);
4462 color: var(--content-muted);
4463 font-size: 0.85rem;
4464 width: 1.5rem;
4465 height: 1.5rem;
4466 border: 1px solid var(--border);
4467 border-radius: 3px;
4468 display: inline-flex;
4469 align-items: center;
4470 justify-content: center;
4471 cursor: pointer;
4472 transition: opacity 0.2s ease;
4473 padding: 0;
4474 background: none;
4475 }
4476
4477 .shortcuts-help-btn:hover {
4478 opacity: 0.6;
4479 }
4480
4481 .breadcrumb {
4482 font-size: 0.9rem;
4483 color: var(--content-muted);
4484 margin-bottom: 0.5rem;
4485 font-family: var(--font-mono);
4486 }
4487
4488 .breadcrumb a {
4489 color: var(--content);
4490 text-decoration: none;
4491 }
4492
4493 .breadcrumb a:hover {
4494 text-decoration: underline;
4495 }
4496
4497 /* ===========================================
4498 HEADER & FOOTER
4499 =========================================== */
4500
4501 header {
4502 background: transparent;
4503 border-bottom: none;
4504 padding: 0;
4505 margin-bottom: 2rem;
4506 }
4507
4508 footer {
4509 text-align: center;
4510 font-family: var(--font-mono);
4511 color: var(--content-muted);
4512 }
4513
4514 .profile-footer {
4515 margin-top: 3rem;
4516 padding-top: 1.5rem;
4517 border-top: 1px solid var(--border);
4518 text-align: center;
4519 opacity: 0.6;
4520 font-size: 0.85rem;
4521 }
4522
4523 .profile-footer a {
4524 color: var(--content);
4525 text-decoration: none;
4526 }
4527
4528 .profile-footer a:hover {
4529 text-decoration: underline;
4530 }
4531
4532 /* Site-wide header */
4533 .site-header {
4534 display: flex;
4535 justify-content: space-between;
4536 align-items: center;
4537 padding: 1rem 1.5rem;
4538 margin-bottom: 1.5rem;
4539 }
4540
4541 .site-header nav {
4542 margin: 0;
4543 }
4544
4545 .site-header .nav-links {
4546 gap: 1.5rem;
4547 }
4548
4549 .site-logo {
4550 font-family: var(--font-heading);
4551 font-size: 1.25rem;
4552 text-decoration: none;
4553 color: var(--content);
4554 }
4555
4556 .site-logo:hover {
4557 opacity: 0.8;
4558 }
4559
4560 .nav-form {
4561 display: contents;
4562 }
4563
4564 /* Header search */
4565 .header-search {
4566 flex: 0 1 220px;
4567 margin: 0 1rem;
4568 }
4569
4570 .header-search input {
4571 width: 100%;
4572 padding: 0.35rem 0.6rem;
4573 font-size: 0.85rem;
4574 font-family: var(--font-mono);
4575 border: 1px solid var(--border);
4576 background: var(--surface-page);
4577 color: var(--content);
4578 border-radius: 3px;
4579 }
4580
4581 .header-search input:focus {
4582 outline: 2px solid var(--focus-ring);
4583 outline-offset: -1px;
4584 }
4585
4586 /* Hamburger toggle, hidden by default, shown at 768px */
4587 .nav-toggle-checkbox {
4588 display: none;
4589 }
4590
4591 .nav-toggle-label {
4592 display: none;
4593 cursor: pointer;
4594 padding: 0.5rem;
4595 z-index: 11;
4596 }
4597
4598 .nav-toggle-label span {
4599 display: block;
4600 width: 22px;
4601 height: 2px;
4602 background: var(--content);
4603 margin: 5px 0;
4604 transition: transform 0.2s ease, opacity 0.2s ease;
4605 }
4606
4607 /* ===========================================
4608 LAYOUT UTILITIES
4609 =========================================== */
4610
4611 .action-buttons {
4612 display: flex;
4613 gap: 1rem;
4614 flex-wrap: wrap;
4615 }
4616 /* ===========================================
4617 SPECIFIC COMPONENTS
4618 =========================================== */
4619
4620 /* Login container */
4621 .login-container {
4622 display: flex;
4623 flex-direction: column;
4624 max-width: 400px;
4625 width: 100%;
4626 margin: 0 auto;
4627 background: var(--surface-overlay);
4628 padding: 2rem;
4629 }
4630 /* Logo */
4631 .logo {
4632 font-family: var(--font-heading);
4633 color: var(--content);
4634 font-size: 24px;
4635 }
4636
4637 .tagline {
4638 font-family: var(--font-mono);
4639 color: var(--content-muted);
4640 text-align: center;
4641 }
4642
4643 .centered-page .tagline {
4644 margin-bottom: 0.25rem;
4645 }
4646 /* Skip link */
4647 .skip-link {
4648 text-align: center;
4649 margin-top: 1rem;
4650 }
4651
4652 .skip-link a {
4653 color: var(--primary-dark);
4654 text-decoration: none;
4655 font-size: 0.9rem;
4656 opacity: 0.7;
4657 }
4658
4659 .skip-link a:hover {
4660 text-decoration: underline;
4661 }
4662
4663 /* Footer link */
4664 .foot-link {
4665 margin-top: 0.5em;
4666 }
4667
4668 /* Status indicators */
4669 .status-indicator {
4670 display: inline-block;
4671 width: 8px;
4672 height: 8px;
4673 background: var(--primary-dark);
4674 margin-right: 0.5rem;
4675 }
4676
4677 .status-indicator.active {
4678 background: var(--success);
4679 }
4680
4681 /* Amount styling */
4682 .amount-in {
4683 color: var(--success);
4684 }
4685
4686 .amount-out {
4687 opacity: 0.7;
4688 }
4689
4690 /* File upload */
4691 .file-upload-area {
4692 background: var(--surface-sunken);
4693 padding: 2rem;
4694 text-align: center;
4695 cursor: pointer;
4696 transition: background 0.2s ease;
4697 margin-bottom: 1rem;
4698 }
4699
4700 .file-upload-area:hover,
4701 .file-upload-area.dragover {
4702 background: var(--border);
4703 }
4704 /* Chart placeholder */
4705 .chart-container {
4706 background: var(--surface-sunken);
4707 padding: 1.5rem;
4708 margin-bottom: 1.5rem;
4709 }
4710
4711 .chart-header {
4712 display: flex;
4713 justify-content: space-between;
4714 align-items: center;
4715 margin-bottom: 1rem;
4716 }
4717
4718 .chart-header h2 {
4719 font-size: 1.2rem;
4720 font-weight: normal;
4721 }
4722
4723 .chart-bars {
4724 display: flex;
4725 align-items: flex-end;
4726 gap: 2px;
4727 height: 200px;
4728 padding: 0 0.5rem;
4729 }
4730
4731 .chart-bar-col {
4732 flex: 1;
4733 display: flex;
4734 flex-direction: column;
4735 align-items: center;
4736 min-width: 0;
4737 cursor: default;
4738 position: relative;
4739 }
4740
4741 .chart-bar-col[data-tooltip]:hover::before {
4742 content: attr(data-tooltip);
4743 position: absolute;
4744 bottom: 100%;
4745 left: 50%;
4746 transform: translateX(-50%);
4747 background: var(--primary-dark);
4748 color: var(--primary-light);
4749 font-size: 0.75rem;
4750 font-family: var(--font-mono);
4751 padding: 0.25rem 0.5rem;
4752 white-space: nowrap;
4753 z-index: 10;
4754 pointer-events: none;
4755 margin-bottom: 0.25rem;
4756 }
4757
4758 .chart-bar {
4759 width: 100%;
4760 background: var(--primary-dark);
4761 min-height: 2px;
4762 transition: opacity 0.15s;
4763 }
4764
4765 .chart-bar-col:hover .chart-bar {
4766 opacity: 0.8;
4767 }
4768
4769 .chart-bar-label {
4770 font-size: 0.7rem;
4771 opacity: 0.5;
4772 margin-top: 0.25rem;
4773 white-space: nowrap;
4774 overflow: hidden;
4775 text-overflow: ellipsis;
4776 max-width: 100%;
4777 }
4778
4779 /* Time selector */
4780 .time-selector {
4781 display: flex;
4782 gap: 0.5rem;
4783 }
4784
4785 .time-selector button {
4786 background: var(--surface-overlay);
4787 border: none;
4788 padding: 0.5rem 1rem;
4789 font-family: inherit;
4790 font-size: 0.85rem;
4791 cursor: pointer;
4792 opacity: 0.6;
4793 }
4794
4795 .time-selector button.is-selected {
4796 opacity: 1;
4797 background: var(--primary-dark);
4798 color: var(--primary-light);
4799 }
4800
4801 /* Analytics */
4802 .analytics-grid {
4803 display: grid;
4804 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
4805 gap: 1.5rem;
4806 margin-bottom: 1.5rem;
4807 }
4808 .analytics-list {
4809 list-style: none;
4810 }
4811
4812 .analytics-list li {
4813 padding: 0.5rem 0;
4814 border-bottom: 1px solid var(--border);
4815 display: flex;
4816 justify-content: space-between;
4817 }
4818
4819 .analytics-list li:last-child {
4820 border-bottom: none;
4821 }
4822
4823 /* Quick actions */
4824 .quick-actions {
4825 background: var(--surface-sunken);
4826 padding: 1.5rem;
4827 }
4828
4829 .quick-actions h2 {
4830 font-size: 1.2rem;
4831 font-weight: normal;
4832 margin-bottom: 1rem;
4833 }
4834
4835 /* Filter controls */
4836 .filter-controls {
4837 display: flex;
4838 gap: 1rem;
4839 margin-bottom: 1rem;
4840 flex-wrap: wrap;
4841 align-items: center;
4842 }
4843
4844 .filter-group {
4845 display: flex;
4846 gap: 0.5rem;
4847 align-items: center;
4848 }
4849 /* UUID styling */
4850 .uuid {
4851 font-family: inherit;
4852 opacity: 0.5;
4853 font-size: 0.85rem;
4854 }
4855 /* ===========================================
4856 HTMX LOADING INDICATORS
4857 =========================================== */
4858
4859 .htmx-indicator {
4860 display: none;
4861 }
4862
4863 .htmx-request .htmx-indicator {
4864 display: inline;
4865 }
4866
4867 .htmx-request.htmx-indicator {
4868 display: inline;
4869 }
4870
4871 /* Loading spinner animation */
4872 @keyframes htmx-spin {
4873 0% { opacity: 0.3; }
4874 50% { opacity: 1; }
4875 100% { opacity: 0.3; }
4876 }
4877
4878 .htmx-indicator {
4879 animation: htmx-spin 1s ease-in-out infinite;
4880 }
4881
4882 /* Disable buttons during request */
4883 .htmx-request button[type="submit"] {
4884 opacity: 0.6;
4885 cursor: wait;
4886 }
4887
4888 /* ===========================================
4889 TOAST NOTIFICATIONS
4890 =========================================== */
4891
4892 .toast-container {
4893 position: fixed;
4894 bottom: 1.5rem;
4895 right: 1.5rem;
4896 z-index: 1000;
4897 display: flex;
4898 flex-direction: column;
4899 gap: 0.5rem;
4900 }
4901
4902 .toast {
4903 background: var(--primary-dark);
4904 color: var(--primary-light);
4905 padding: 0.75rem 1.25rem;
4906 font-family: var(--font-mono);
4907 font-size: 0.9rem;
4908 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
4909 animation: toast-in 0.3s ease-out;
4910 max-width: 300px;
4911 display: flex;
4912 align-items: center;
4913 gap: 0.75rem;
4914 }
4915
4916 .toast-dismiss {
4917 background: none;
4918 border: none;
4919 color: inherit;
4920 font-size: 1.1rem;
4921 cursor: pointer;
4922 opacity: 0.7;
4923 padding: 0;
4924 line-height: 1;
4925 flex-shrink: 0;
4926 }
4927
4928 .toast-dismiss:hover {
4929 opacity: 1;
4930 }
4931
4932 .toast-success {
4933 background: var(--success);
4934 }
4935
4936 .toast-error {
4937 background: var(--danger);
4938 }
4939
4940 .toast-warning {
4941 background: var(--warning);
4942 }
4943
4944 .toast-info {
4945 background: var(--primary-dark);
4946 }
4947
4948 .toast-retry-btn {
4949 background: none;
4950 border: 1px solid currentColor;
4951 color: inherit;
4952 font-family: var(--font-mono);
4953 font-size: 0.8rem;
4954 font-weight: 600;
4955 padding: 0.15rem 0.5rem;
4956 margin-left: 0.75rem;
4957 cursor: pointer;
4958 }
4959
4960 .toast-retry-btn:hover {
4961 background: rgba(255, 255, 255, 0.15);
4962 }
4963
4964 .toast.fade-out {
4965 animation: toast-out 0.3s ease-in forwards;
4966 }
4967
4968 @keyframes toast-in {
4969 from {
4970 transform: translateX(100%);
4971 opacity: 0;
4972 }
4973 to {
4974 transform: translateX(0);
4975 opacity: 1;
4976 }
4977 }
4978
4979 @keyframes toast-out {
4980 from {
4981 transform: translateX(0);
4982 opacity: 1;
4983 }
4984 to {
4985 transform: translateX(100%);
4986 opacity: 0;
4987 }
4988 }
4989
4990 /* ===========================================
4991 "NEW" BADGE (data-new-until)
4992 ===========================================
4993 Applied by whats_new.js while today's date is <= the element's
4994 data-new-until. Renders a small violet dot to the right of the
4995 element's content. Pair with relative-positioned parents. */
4996
4997 .is-new {
4998 position: relative;
4999 }
5000
5001 .is-new::after {
5002 content: "";
5003 position: absolute;
5004 top: -2px;
5005 right: -8px;
5006 width: 6px;
5007 height: 6px;
5008 border-radius: 50%;
5009 background: var(--action);
5010 box-shadow: 0 0 0 2px var(--surface-page);
5011 }
5012
5013 /* ===========================================
5014 RESTART WARNING BANNER
5015 =========================================== */
5016
5017 /* Page-top behavior extensions on top of .banner.banner--warning.
5018 Color / typography come from the .banner primitive. */
5019 #restart-banner {
5020 position: fixed;
5021 top: 0;
5022 left: 0;
5023 right: 0;
5024 z-index: 10000;
5025 padding: 0.6rem 1rem;
5026 animation: banner-slide-down 0.3s ease-out;
5027 }
5028
5029 @keyframes banner-slide-down {
5030 from {
5031 transform: translateY(-100%);
5032 }
5033 to {
5034 transform: translateY(0);
5035 }
5036 }
5037
5038 /* ===========================================
5039 SAVE STATUS INDICATORS
5040 =========================================== */
5041
5042 /* Username availability status */
5043 .username-status {
5044 display: block;
5045 margin-top: 0.25rem;
5046 font-size: 0.85rem;
5047 }
5048
5049 .username-status.available {
5050 color: var(--success);
5051 }
5052
5053 .username-status.taken {
5054 color: var(--danger);
5055 }
5056
5057 /* ===========================================
5058 HTMX TRANSITIONS
5059 =========================================== */
5060
5061 /* Fade in for swapped content */
5062 .htmx-added {
5063 animation: htmx-fade-in 0.2s ease-out;
5064 }
5065
5066 @keyframes htmx-fade-in {
5067 from {
5068 opacity: 0;
5069 }
5070 to {
5071 opacity: 1;
5072 }
5073 }
5074
5075 /* Settling animation for swapped content */
5076 .htmx-settling {
5077 opacity: 0.8;
5078 }
5079
5080 /* Swap animation */
5081 .htmx-swapping {
5082 opacity: 0.5;
5083 transition: opacity 0.2s ease-out;
5084 }
5085
5086 /* ===========================================
5087 ACCESSIBILITY - FOCUS STYLES
5088 =========================================== */
5089
5090 /* Focus-visible for keyboard navigation */
5091 *:focus-visible {
5092 outline: 2px solid var(--focus-ring);
5093 outline-offset: 2px;
5094 }
5095
5096 /* Remove default focus outline since we use focus-visible */
5097 *:focus:not(:focus-visible) {
5098 outline: none;
5099 }
5100
5101 /* Ensure buttons and links are keyboard accessible */
5102 button:focus-visible,
5103 a:focus-visible,
5104 input:focus-visible,
5105 select:focus-visible,
5106 textarea:focus-visible {
5107 outline: 2px solid var(--focus-ring);
5108 outline-offset: 2px;
5109 }
5110
5111 /* Tab focus styles */
5112 .tab:focus-visible {
5113 outline: 2px solid var(--focus-ring);
5114 outline-offset: -2px;
5115 }
5116
5117 /* Canonical "selected" recipe (charter: docs/design-system.md).
5118 Apply `.is-selected` to any interactive container to mark it as the
5119 currently-selected option. `.badge.active` is intentionally distinct.
5120 It expresses completion status, not selection. Visibility toggles
5121 (`.tab-content.active`, `.section-panel.active`, `.editor-panel.active`)
5122 also keep `.active` since they're not selection state. */
5123 .is-selected {
5124 background: color-mix(in oklch, var(--action) 8%, transparent);
5125 border-color: var(--focus-ring);
5126 }
5127
5128 /* Skip to main content link (for screen readers) */
5129 .skip-to-main {
5130 position: absolute;
5131 top: -100px;
5132 left: 0;
5133 background: var(--primary-dark);
5134 color: var(--primary-light);
5135 padding: 8px;
5136 z-index: 100;
5137 transition: top 0.2s ease;
5138 }
5139
5140 .skip-to-main:focus {
5141 top: 0;
5142 }
5143
5144 /* Visually hidden but accessible to screen readers */
5145 .sr-only {
5146 position: absolute;
5147 width: 1px;
5148 height: 1px;
5149 padding: 0;
5150 margin: -1px;
5151 overflow: hidden;
5152 clip: rect(0, 0, 0, 0);
5153 white-space: nowrap;
5154 border: 0;
5155 }
5156
5157 /* Status indicator with text for accessibility */
5158 .status-indicator::after {
5159 content: attr(data-status);
5160 position: absolute;
5161 width: 1px;
5162 height: 1px;
5163 padding: 0;
5164 margin: -1px;
5165 overflow: hidden;
5166 clip: rect(0, 0, 0, 0);
5167 white-space: nowrap;
5168 border: 0;
5169 }
5170
5171 /* ===========================================
5172 PAYWALL
5173 =========================================== */
5174
5175 .paywall-section {
5176 margin: 2rem 0;
5177 padding: 2rem;
5178 background: var(--surface-sunken);
5179 text-align: center;
5180 }
5181
5182 .paywall-box h2 {
5183 font-family: var(--font-heading);
5184 font-weight: normal;
5185 margin-bottom: 0.5rem;
5186 }
5187
5188 .paywall-price {
5189 font-family: var(--font-mono);
5190 font-size: 1.5rem;
5191 margin-bottom: 0.5rem;
5192 }
5193
5194 .paywall-desc {
5195 font-family: var(--font-body);
5196 color: var(--content-muted);
5197 margin-bottom: 1.5rem;
5198 }
5199
5200 .paywall-note {
5201 font-family: var(--font-mono);
5202 font-size: 0.875rem;
5203 color: var(--content-muted);
5204 margin-top: 1rem;
5205 }
5206
5207 .paywall-note a {
5208 color: var(--action);
5209 }
5210
5211 /* ===========================================
5212 MODALS
5213 =========================================== */
5214
5215 .modal-overlay {
5216 position: fixed;
5217 inset: 0;
5218 background: var(--overlay);
5219 display: flex;
5220 align-items: center;
5221 justify-content: center;
5222 z-index: 1000;
5223 }
5224
5225 .modal {
5226 background: var(--surface-page);
5227 padding: 2rem;
5228 max-width: 500px;
5229 width: 90%;
5230 max-height: 90vh;
5231 overflow-y: auto;
5232 }
5233
5234 .modal h2 {
5235 margin-bottom: 1.5rem;
5236 }
5237
5238 .modal .form-actions {
5239 display: flex;
5240 gap: 1rem;
5241 justify-content: flex-end;
5242 margin-top: 1.5rem;
5243 }
5244
5245 /* ===========================================
5246 LINK ROWS (Dashboard Links Section)
5247 =========================================== */
5248
5249 .link-row {
5250 display: flex;
5251 gap: 0.75rem;
5252 align-items: center;
5253 margin-bottom: 0.75rem;
5254 padding: 0.75rem;
5255 background: var(--surface-sunken);
5256 transition: opacity 0.2s ease, background 0.2s ease;
5257 }
5258
5259 .link-row input[type="text"],
5260 .link-row input[type="url"] {
5261 flex: 1;
5262 min-width: 0;
5263 }
5264
5265 .link-row .btn-danger {
5266 padding: 0.5rem 0.75rem;
5267 font-size: 0.85rem;
5268 }
5269
5270 /* Link order buttons */
5271 .link-order-buttons {
5272 display: flex;
5273 flex-direction: column;
5274 gap: 2px;
5275 }
5276
5277 .order-btn {
5278 background: var(--surface-sunken);
5279 border: 1px solid var(--border);
5280 padding: 0.15rem 0.4rem;
5281 font-size: 0.65rem;
5282 line-height: 1;
5283 cursor: pointer;
5284 opacity: 0.6;
5285 transition: opacity 0.15s ease, background 0.15s ease;
5286 }
5287
5288 .order-btn:hover {
5289 opacity: 1;
5290 background: var(--border);
5291 }
5292
5293 .order-btn:active {
5294 background: var(--primary-dark);
5295 color: var(--primary-light);
5296 }
5297
5298 /* ===========================================
5299 TEXT EDITOR
5300 =========================================== */
5301
5302 .text-editor {
5303 width: 100%;
5304 }
5305
5306 .editor-tabs {
5307 display: flex;
5308 gap: 0;
5309 margin-bottom: 0;
5310 }
5311
5312 .editor-tab {
5313 background: var(--surface-sunken);
5314 border: none;
5315 padding: 0.5rem 1.5rem;
5316 font-family: var(--font-mono);
5317 font-size: 0.9rem;
5318 cursor: pointer;
5319 opacity: 0.6;
5320 transition: opacity 0.2s ease, background 0.2s ease;
5321 }
5322
5323 .editor-tab.is-selected {
5324 background: var(--surface-sunken);
5325 opacity: 1;
5326 }
5327
5328 .editor-tab:hover {
5329 opacity: 1;
5330 }
5331
5332 .editor-panel {
5333 display: none;
5334 }
5335
5336 .editor-panel.active {
5337 display: block;
5338 }
5339
5340 .editor-panel textarea {
5341 width: 100%;
5342 min-height: 400px;
5343 padding: 1rem;
5344 font-family: var(--font-mono);
5345 font-size: 0.9rem;
5346 line-height: 1.6;
5347 resize: vertical;
5348 border: none;
5349 background: var(--surface-sunken);
5350 }
5351
5352 .editor-footer {
5353 display: flex;
5354 justify-content: space-between;
5355 padding: 0.5rem 1rem;
5356 background: var(--surface-sunken);
5357 font-size: 0.85rem;
5358 opacity: 0.7;
5359 }
5360
5361 .markdown-preview {
5362 min-height: 400px;
5363 padding: 1.5rem;
5364 background: var(--surface-overlay);
5365 font-family: var(--font-body);
5366 line-height: 1.8;
5367 }
5368
5369 .markdown-preview h1,
5370 .markdown-preview h2,
5371 .markdown-preview h3 {
5372 margin-top: 1.5rem;
5373 margin-bottom: 0.5rem;
5374 }
5375
5376 .markdown-preview h1 {
5377 font-size: 1.8rem;
5378 }
5379
5380 .markdown-preview h2 {
5381 font-size: 1.4rem;
5382 }
5383
5384 .markdown-preview h3 {
5385 font-size: 1.1rem;
5386 }
5387
5388 .markdown-preview p {
5389 margin-bottom: 1rem;
5390 }
5391
5392 .markdown-preview code {
5393 background: var(--surface-sunken);
5394 padding: 0.1rem 0.3rem;
5395 font-family: var(--font-mono);
5396 font-size: 0.9em;
5397 }
5398
5399 /* ===========================================
5400 AUDIO UPLOAD
5401 =========================================== */
5402
5403 .audio-upload {
5404 width: 100%;
5405 }
5406
5407 .current-audio {
5408 display: flex;
5409 justify-content: space-between;
5410 align-items: center;
5411 padding: 1rem;
5412 background: var(--surface-sunken);
5413 margin-bottom: 1rem;
5414 }
5415
5416 .audio-info {
5417 display: flex;
5418 align-items: center;
5419 gap: 1rem;
5420 }
5421
5422 .audio-icon {
5423 font-size: 1.5rem;
5424 opacity: 0.6;
5425 }
5426
5427 .audio-details {
5428 display: flex;
5429 flex-direction: column;
5430 }
5431
5432 .audio-filename {
5433 font-family: var(--font-mono);
5434 font-size: 0.9rem;
5435 }
5436
5437 .audio-duration {
5438 font-size: 0.85rem;
5439 opacity: 0.6;
5440 }
5441
5442 .upload-area .file-upload-area {
5443 padding: 3rem 2rem;
5444 }
5445
5446 .upload-icon {
5447 font-size: 2rem;
5448 opacity: 0.4;
5449 margin-bottom: 0.5rem;
5450 }
5451
5452 .upload-text {
5453 font-size: 1.1rem;
5454 margin-bottom: 0.5rem;
5455 }
5456
5457 .upload-hint {
5458 font-size: 0.85rem;
5459 opacity: 0.6;
5460 }
5461
5462 .upload-progress {
5463 padding: 1.5rem;
5464 background: var(--surface-sunken);
5465 }
5466
5467 .progress-info {
5468 display: flex;
5469 justify-content: space-between;
5470 margin-bottom: 0.75rem;
5471 font-size: 0.9rem;
5472 }
5473
5474 /* Canonical progress bar primitive. One of these in the codebase.
5475 - .progress-bar-container is the track (8px default; --slim = 6px)
5476 - .progress-bar is the fill (success-green default; --highlight = purple)
5477 - Add .progress-bar-container--rounded for the 3px-radius pill variant
5478 Spacing (mb-4 / mt-2 etc.) is added by the caller, not baked in. */
5479 .progress-bar-container {
5480 height: 8px;
5481 background: var(--border);
5482 overflow: hidden;
5483 }
5484 .progress-bar-container--slim { height: 6px; }
5485 .progress-bar-container--rounded { border-radius: 3px; }
5486
5487 .progress-bar {
5488 width: 0%;
5489 height: 100%;
5490 background: var(--success);
5491 transition: width 0.2s ease;
5492 }
5493 .progress-bar--highlight { background: var(--action); }
5494
5495 /* Upload status block (filename + percent label + progress bar). One of these
5496 in the codebase. Used by wizard upload flows and standalone audio/video upload partials. */
5497 .upload-status { margin-top: var(--space-2); }
5498 .upload-status-row {
5499 display: flex;
5500 align-items: center;
5501 gap: var(--space-2);
5502 }
5503 .upload-status-row span { font-size: 0.85rem; }
5504 .upload-status-msg { margin-top: var(--space-2); }
5505 .upload-status-msg.is-success { color: var(--success); }
5506 .upload-status-msg.is-error { color: var(--danger); }
5507
5508 /* Inline progress cell rendered inside a table-row status cell (batch uploads). */
5509 .upload-progress-row {
5510 display: flex;
5511 align-items: center;
5512 gap: 0.4rem;
5513 }
5514 .upload-progress-row .progress-bar-container { flex: 1; min-width: 60px; }
5515 .upload-progress-pct {
5516 font-size: 0.75rem;
5517 min-width: 2.5em;
5518 text-align: right;
5519 }
5520
5521 .upload-success {
5522 padding: 1.5rem;
5523 background: var(--surface-sunken);
5524 text-align: center;
5525 }
5526 .upload-error {
5527 padding: 1.5rem;
5528 background: var(--surface-sunken);
5529 text-align: center;
5530 }
5531
5532 .hidden {
5533 display: none !important;
5534 }
5535
5536 /* ===========================================
5537 VIEW TOGGLE (Grid/List)
5538 =========================================== */
5539
5540 .view-controls {
5541 display: flex;
5542 gap: 0.25rem;
5543 margin-left: auto;
5544 }
5545
5546 .view-btn {
5547 background: var(--surface-sunken);
5548 border: none;
5549 padding: 0.4rem 0.6rem;
5550 font-family: var(--font-mono);
5551 font-size: 0.9rem;
5552 cursor: pointer;
5553 opacity: 0.5;
5554 transition: opacity 0.2s ease;
5555 }
5556
5557 .view-btn:hover {
5558 opacity: 0.8;
5559 }
5560
5561 .view-btn.is-selected {
5562 opacity: 1;
5563 background: var(--primary-dark);
5564 color: var(--primary-light);
5565 }
5566 .results-container.results-list .results-table {
5567 display: block;
5568 }
5569
5570 .results-container.results-list .results-grid {
5571 display: none;
5572 }
5573
5574 .results-container.results-grid .results-table {
5575 display: none;
5576 }
5577
5578 .results-container.results-grid .results-grid {
5579 display: grid;
5580 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
5581 gap: 1.5rem;
5582 border: 1px solid var(--border);
5583 border-top: none;
5584 padding: 1.5rem;
5585 background: var(--surface-overlay);
5586 }
5587
5588 /* Grid cards */
5589 .grid-card {
5590 background: var(--surface-overlay);
5591 text-decoration: none;
5592 color: var(--content);
5593 display: flex;
5594 flex-direction: column;
5595 transition: background 0.2s ease;
5596 }
5597
5598 .grid-card:hover {
5599 background: var(--surface-sunken);
5600 text-decoration: none;
5601 }
5602
5603 .grid-card-thumbnail {
5604 height: 120px;
5605 background: var(--border);
5606 display: flex;
5607 align-items: center;
5608 justify-content: center;
5609 font-size: 0.8rem;
5610 opacity: 0.5;
5611 text-transform: uppercase;
5612 }
5613
5614 .grid-card-content {
5615 padding: 1rem;
5616 display: flex;
5617 flex-direction: column;
5618 gap: 0.25rem;
5619 }
5620
5621 .grid-card-title {
5622 font-family: var(--font-heading);
5623 font-size: 1.1rem;
5624 }
5625
5626 .grid-card-meta {
5627 font-size: 0.85rem;
5628 opacity: 0.6;
5629 }
5630
5631 .grid-card-footer {
5632 display: flex;
5633 justify-content: space-between;
5634 align-items: center;
5635 margin-top: 0.5rem;
5636 font-size: 0.85rem;
5637 }
5638
5639 .grid-card-category {
5640 opacity: 0.6;
5641 }
5642
5643 .grid-card-price {
5644 font-weight: bold;
5645 }
5646
5647 .grid-card-stat {
5648 opacity: 0.6;
5649 }
5650
5651 /* ===========================================
5652 PROJECT PAGE VIEW TOGGLE
5653 =========================================== */
5654
5655 .items-header {
5656 display: flex;
5657 justify-content: space-between;
5658 align-items: center;
5659 margin-bottom: 1.5rem;
5660 }
5661
5662 .items-header .section-header {
5663 margin-bottom: 0;
5664 border-bottom: none;
5665 padding-bottom: 0;
5666 }
5667
5668 /* Grid view is default on project page */
5669 .items-container.items-grid-view .items-grid {
5670 display: grid;
5671 }
5672
5673 .items-container.items-grid-view .items-list {
5674 display: none;
5675 }
5676
5677 .items-container.items-list-view .items-grid {
5678 display: none;
5679 }
5680
5681 .items-container.items-list-view .items-list {
5682 display: block;
5683 }
5684
5685 /* List items styling */
5686 .items-list {
5687 display: none;
5688 }
5689
5690 .list-item {
5691 display: flex;
5692 justify-content: space-between;
5693 align-items: center;
5694 padding: 1rem 1.25rem;
5695 background: var(--surface-overlay);
5696 margin-bottom: 0.5rem;
5697 text-decoration: none;
5698 color: var(--content);
5699 transition: background 0.2s ease;
5700 }
5701
5702 .list-item:hover {
5703 background: var(--surface-sunken);
5704 text-decoration: none;
5705 }
5706
5707 .list-item-info {
5708 display: flex;
5709 flex-direction: column;
5710 gap: 0.25rem;
5711 }
5712
5713 .list-item-title {
5714 font-family: var(--font-heading);
5715 font-size: 1.1rem;
5716 }
5717
5718 .list-item-meta {
5719 font-size: 0.85rem;
5720 opacity: 0.6;
5721 }
5722
5723 .list-item-price {
5724 font-size: 1.1rem;
5725 font-weight: bold;
5726 }
5727
5728 /* ===========================================
5729 LANDING PAGE
5730 =========================================== */
5731
5732 .landing-hero {
5733 max-width: 720px;
5734 width: 100%;
5735 text-align: center;
5736 }
5737
5738 .landing-headline {
5739 font-family: var(--font-heading);
5740 font-size: 1.4rem;
5741 margin-bottom: 0.5rem;
5742 }
5743
5744 .landing-sub {
5745 font-size: 1rem;
5746 line-height: 1.6;
5747 opacity: 0.75;
5748 margin-bottom: 0;
5749 }
5750
5751 .fork-revenue-line {
5752 font-size: 0.9rem;
5753 opacity: 0.8;
5754 margin: 0.75rem 0 0.5rem;
5755 line-height: 1.5;
5756 }
5757
5758 .fork-revenue-line a {
5759 border-bottom: 1px solid transparent;
5760 transition: border-color 0.2s ease;
5761 }
5762
5763 .fork-revenue-line a:hover {
5764 border-bottom-color: currentColor;
5765 }
5766
5767 .landing-fork {
5768 display: grid;
5769 grid-template-columns: 1fr 1fr;
5770 gap: 1rem;
5771 margin-top: 2rem;
5772 text-align: left;
5773 }
5774
5775 .fork-heading {
5776 font-family: var(--font-mono);
5777 font-size: 0.9rem;
5778 font-weight: 600;
5779 text-transform: uppercase;
5780 letter-spacing: 0.05em;
5781 margin-bottom: 1rem;
5782 }
5783
5784 .fork-list {
5785 list-style: none;
5786 margin: 0;
5787 padding: 0;
5788 flex: 1;
5789 }
5790
5791 .fork-list li {
5792 margin-bottom: 0.6rem;
5793 font-size: 0.9rem;
5794 line-height: 1.5;
5795 }
5796
5797 .fork-list strong {
5798 font-family: var(--font-mono);
5799 font-size: 0.8rem;
5800 }
5801
5802 .fork-actions {
5803 margin-top: auto;
5804 padding-top: 1.25rem;
5805 display: flex;
5806 flex-direction: column;
5807 align-items: center;
5808 gap: 0.5rem;
5809 }
5810
5811 .fork-actions .big-button {
5812 width: 100%;
5813 }
5814
5815 .fork-secondary-link {
5816 font-family: var(--font-mono);
5817 font-size: 0.8rem;
5818 opacity: 0.6;
5819 transition: opacity 0.2s ease;
5820 }
5821
5822 .fork-secondary-link:hover {
5823 opacity: 1;
5824 }
5825
5826 .fork-lede {
5827 font-size: 0.95rem;
5828 line-height: 1.55;
5829 margin: 0 0 1rem;
5830 }
5831
5832 .landing-browse-cta {
5833 text-align: center;
5834 margin: 1.25rem 0 0;
5835 }
5836
5837 .landing-mobile-note {
5838 text-align: center;
5839 margin: 0.4rem 0 0;
5840 font-size: 0.8rem;
5841 color: var(--content-muted);
5842 }
5843
5844 .founder-tagline {
5845 font-family: var(--font-body);
5846 font-size: 0.95rem;
5847 line-height: 1.55;
5848 margin: 1.25rem auto 0;
5849 max-width: 560px;
5850 color: var(--content);
5851 display: flex;
5852 flex-direction: column;
5853 align-items: center;
5854 gap: 0.5rem;
5855 }
5856
5857 .landing-velocity {
5858 font-family: var(--font-mono);
5859 font-size: 0.8rem;
5860 text-align: center;
5861 margin: 1rem auto 0;
5862 color: var(--content-muted);
5863 }
5864
5865 .landing-velocity a {
5866 color: var(--content);
5867 text-decoration: none;
5868 border-bottom: 1px solid var(--border);
5869 }
5870
5871 .landing-velocity a:hover {
5872 border-bottom-color: var(--content);
5873 }
5874
5875 .founder-tagline-detail {
5876 display: block;
5877 }
5878
5879 .founder-tagline-mark {
5880 font-family: var(--font-mono);
5881 font-size: 0.75rem;
5882 font-weight: 600;
5883 text-transform: uppercase;
5884 letter-spacing: 0.08em;
5885 color: var(--action);
5886 padding: 0.15rem 0.5rem;
5887 border: 1px solid var(--action);
5888 border-radius: 3px;
5889 white-space: nowrap;
5890 }
5891
5892 .fork-card--founder {
5893 border-color: var(--action);
5894 box-shadow: 0 0 0 1px color-mix(in oklch, var(--action) 8%, transparent);
5895 }
5896
5897 .founder-tier-grid {
5898 display: grid;
5899 grid-template-columns: 1fr 1fr;
5900 gap: 0.4rem 0.75rem;
5901 margin-bottom: 0.85rem;
5902 padding-bottom: 0.85rem;
5903 border-bottom: 1px dashed var(--border);
5904 }
5905
5906 .founder-tier {
5907 display: flex;
5908 flex-direction: column;
5909 gap: 0.1rem;
5910 }
5911
5912 .founder-tier-name {
5913 font-family: var(--font-mono);
5914 font-size: 0.7rem;
5915 font-weight: 600;
5916 text-transform: uppercase;
5917 letter-spacing: 0.05em;
5918 opacity: 0.7;
5919 }
5920
5921 .founder-tier-price {
5922 font-family: var(--font-heading);
5923 font-size: 1rem;
5924 line-height: 1.1;
5925 }
5926
5927 .founder-tier-price del {
5928 opacity: 0.4;
5929 margin-right: 0.25rem;
5930 font-weight: 400;
5931 }
5932
5933 .founder-tier-price strong {
5934 color: var(--action);
5935 font-weight: 700;
5936 }
5937
5938 .founder-tier-unit {
5939 font-family: var(--font-mono);
5940 font-size: 0.75rem;
5941 opacity: 0.6;
5942 margin-left: 0.1rem;
5943 }
5944
5945 .founder-slots {
5946 font-family: var(--font-mono);
5947 font-size: 0.8rem;
5948 margin: 0 0 1rem;
5949 line-height: 1.3;
5950 }
5951
5952 .founder-slots-number {
5953 font-family: var(--font-heading);
5954 font-size: 1.4rem;
5955 color: var(--action);
5956 font-weight: 700;
5957 margin-right: 0.25rem;
5958 }
5959
5960 .founder-slots-cap {
5961 opacity: 0.55;
5962 margin-left: 0.25rem;
5963 }
5964
5965 .founder-slots--cap {
5966 opacity: 0.7;
5967 font-size: 0.75rem;
5968 }
5969
5970 .landing-stats-line {
5971 font-family: var(--font-mono);
5972 font-size: 0.85rem;
5973 opacity: 0.6;
5974 margin-top: 2rem;
5975 }
5976
5977 .landing-stats-line a {
5978 opacity: 0.8;
5979 transition: opacity 0.2s ease;
5980 }
5981
5982 .landing-stats-line a:hover {
5983 opacity: 1;
5984 }
5985
5986 .landing-principles {
5987 margin-top: 2rem;
5988 width: 100%;
5989 }
5990
5991 .landing-use-cases {
5992 margin-top: 2rem;
5993 width: 100%;
5994 }
5995
5996 .use-case-line {
5997 font-family: var(--font-mono);
5998 font-size: 0.85rem;
5999 opacity: 0.7;
6000 letter-spacing: 0.02em;
6001 }
6002
6003 .landing-prose {
6004 font-size: 1.05rem;
6005 line-height: 1.7;
6006 margin-bottom: 0.5rem;
6007 }
6008
6009 .notify-form {
6010 display: flex;
6011 gap: 0.5rem;
6012 max-width: 400px;
6013 margin: 0 auto;
6014 }
6015
6016 .notify-input {
6017 flex: 1;
6018 padding: 0.5rem 0.75rem;
6019 border: 1px solid var(--border);
6020 border-radius: 4px;
6021 font-family: var(--font-body);
6022 font-size: 0.9rem;
6023 background: var(--surface-page);
6024 color: var(--content);
6025 }
6026
6027 .notify-status {
6028 font-family: var(--font-mono);
6029 font-size: 0.8rem;
6030 text-align: center;
6031 margin-top: 0.5rem;
6032 min-height: 1.2em;
6033 }
6034
6035 .notify-status.success {
6036 color: var(--content);
6037 }
6038
6039 .notify-status.error {
6040 color: var(--danger);
6041 }
6042
6043 .section-label {
6044 font-family: var(--font-mono);
6045 font-size: 0.85rem;
6046 letter-spacing: 0.05em;
6047 text-transform: uppercase;
6048 opacity: 0.6;
6049 margin-bottom: 1.25rem;
6050 }
6051
6052 .tier-section {
6053 margin: 2rem 0;
6054 width: 100%;
6055 }
6056 /* Marketing pricing variant of .card--bordered. */
6057 .tier-name {
6058 font-family: var(--font-mono);
6059 font-size: 0.85rem;
6060 font-weight: 600;
6061 margin-bottom: 0.15rem;
6062 }
6063
6064 .tier-price {
6065 font-family: var(--font-heading);
6066 font-size: 1.1rem;
6067 margin-bottom: 0.25rem;
6068 }
6069
6070 .tier-desc {
6071 font-size: 0.85rem;
6072 opacity: 0.7;
6073 }
6074
6075 .tier-card.planned {
6076 opacity: 0.5;
6077 border-style: dashed;
6078 position: relative;
6079 }
6080 .landing-cta {
6081 display: flex;
6082 align-items: center;
6083 justify-content: center;
6084 gap: 2rem;
6085 width: fit-content;
6086 margin: 1.5rem auto 2rem;
6087 }
6088 .secondary-links {
6089 display: flex;
6090 gap: 1.5rem;
6091 justify-content: center;
6092 margin-top: 1rem;
6093 }
6094
6095 .secondary-links a {
6096 font-size: 0.9rem;
6097 opacity: 0.6;
6098 transition: opacity 0.2s ease;
6099 }
6100
6101 .secondary-links a:hover {
6102 opacity: 1;
6103 }
6104 .section-link {
6105 display: block;
6106 margin-top: 0.75rem;
6107 font-family: var(--font-mono);
6108 font-size: 0.8rem;
6109 opacity: 0.55;
6110 transition: opacity 0.2s ease;
6111 }
6112
6113 .section-link:hover {
6114 opacity: 1;
6115 }
6116
6117 .feature-grid {
6118 display: grid;
6119 grid-template-columns: 1fr 1fr;
6120 gap: 0.75rem;
6121 text-align: left;
6122 }
6123
6124 .feature-name {
6125 font-family: var(--font-mono);
6126 font-size: 0.85rem;
6127 font-weight: 600;
6128 margin-bottom: 0.25rem;
6129 }
6130
6131 .feature-desc {
6132 font-size: 0.85rem;
6133 opacity: 0.7;
6134 }
6135
6136 .how-list {
6137 list-style: none;
6138 margin: 0;
6139 padding: 0;
6140 text-align: left;
6141 }
6142
6143 .how-list li {
6144 margin-bottom: 0.6rem;
6145 font-size: 0.95rem;
6146 }
6147
6148 .how-list strong {
6149 font-family: var(--font-mono);
6150 font-size: 0.85rem;
6151 }
6152
6153 .do-rail {
6154 list-style: none;
6155 margin: 2rem 0 1.5rem;
6156 padding: 0;
6157 display: grid;
6158 grid-template-columns: repeat(3, 1fr);
6159 gap: 1rem;
6160 width: 100%;
6161 }
6162
6163 .do-card {
6164 background: transparent;
6165 border: 1px solid var(--border);
6166 padding: 1.25rem;
6167 text-align: left;
6168 display: flex;
6169 flex-direction: column;
6170 }
6171
6172 .do-card-title {
6173 font-family: var(--font-mono);
6174 font-size: 0.9rem;
6175 font-weight: 600;
6176 text-transform: uppercase;
6177 letter-spacing: 0.05em;
6178 margin: 0 0 0.5rem;
6179 }
6180
6181 .do-card-lede {
6182 font-size: 0.92rem;
6183 line-height: 1.5;
6184 opacity: 0.78;
6185 margin: 0 0 0.85rem;
6186 }
6187
6188 .do-card-links {
6189 list-style: none;
6190 margin: auto 0 0;
6191 padding: 0.85rem 0 0;
6192 border-top: 1px solid var(--border);
6193 display: flex;
6194 flex-wrap: wrap;
6195 gap: 0.35rem 0.9rem;
6196 }
6197
6198 .do-card-links a {
6199 font-size: 0.88rem;
6200 border-bottom: 1px solid transparent;
6201 transition: border-color 0.2s ease;
6202 }
6203
6204 .do-card-links a:hover {
6205 border-bottom-color: currentColor;
6206 }
6207
6208 @media (max-width: 640px) {
6209 .do-rail {
6210 grid-template-columns: 1fr;
6211 }
6212 }
6213
6214 .do-card--wide {
6215 margin-top: 2rem;
6216 width: 100%;
6217 }
6218
6219 .contrast-rail {
6220 list-style: none;
6221 margin: 1rem 0 0;
6222 padding: 0;
6223 display: grid;
6224 grid-template-columns: repeat(4, 1fr);
6225 gap: 1rem;
6226 width: 100%;
6227 }
6228
6229 .contrast-card {
6230 border-top: 1px solid var(--border);
6231 padding: 0.75rem 0.25rem 0;
6232 text-align: left;
6233 }
6234
6235 .contrast-card-title {
6236 font-family: var(--font-mono);
6237 font-size: 0.78rem;
6238 letter-spacing: 0.04em;
6239 text-transform: uppercase;
6240 opacity: 0.5;
6241 text-decoration: line-through;
6242 text-decoration-thickness: 1px;
6243 margin: 0 0 0.5rem;
6244 font-weight: 600;
6245 }
6246
6247 .contrast-card-links {
6248 list-style: none;
6249 margin: 0;
6250 padding: 0;
6251 display: flex;
6252 flex-wrap: wrap;
6253 gap: 0.35rem 0.9rem;
6254 }
6255
6256 .contrast-card-links a {
6257 font-size: 0.92rem;
6258 border-bottom: 1px solid transparent;
6259 transition: border-color 0.2s ease;
6260 }
6261
6262 .contrast-card-links a:hover {
6263 border-bottom-color: currentColor;
6264 }
6265
6266 @media (max-width: 640px) {
6267 .contrast-rail {
6268 grid-template-columns: 1fr;
6269 }
6270 }
6271
6272 .explore-links {
6273 display: flex;
6274 flex-wrap: wrap;
6275 gap: 1rem 1.5rem;
6276 justify-content: center;
6277 }
6278
6279 .explore-links a {
6280 font-family: var(--font-mono);
6281 font-size: 0.85rem;
6282 opacity: 0.7;
6283 transition: opacity 0.2s ease;
6284 }
6285
6286 .explore-links a:hover {
6287 opacity: 1;
6288 }
6289
6290 /* ===========================================
6291 PRICING CALCULATOR
6292 =========================================== */
6293
6294 .pricing-page {
6295 max-width: 800px;
6296 }
6297
6298 .pricing-input-wrap {
6299 display: flex;
6300 align-items: baseline;
6301 justify-content: center;
6302 gap: 0.25rem;
6303 }
6304
6305 .pricing-currency {
6306 font-family: var(--font-heading);
6307 font-size: 2.5rem;
6308 opacity: 0.5;
6309 }
6310
6311 .pricing-input {
6312 font-family: var(--font-heading);
6313 font-size: 2.5rem;
6314 width: 5ch;
6315 text-align: center;
6316 background: transparent;
6317 border: none;
6318 border-bottom: 2px solid var(--border);
6319 color: var(--content);
6320 padding: 0.25rem 0;
6321 -moz-appearance: textfield;
6322 }
6323
6324 .pricing-input::-webkit-inner-spin-button,
6325 .pricing-input::-webkit-outer-spin-button {
6326 -webkit-appearance: none;
6327 margin: 0;
6328 }
6329
6330 .pricing-input:focus {
6331 outline: none;
6332 border-bottom-color: var(--action);
6333 }
6334
6335 .pricing-period {
6336 font-family: var(--font-mono);
6337 font-size: 1rem;
6338 opacity: 0.5;
6339 }
6340
6341 .tier-selector {
6342 display: grid;
6343 grid-template-columns: 1fr 1fr;
6344 gap: 0.75rem;
6345 text-align: left;
6346 }
6347
6348 .tier-option {
6349 cursor: pointer;
6350 transition: border-color 0.15s ease;
6351 }
6352
6353 .tier-option input[type="radio"] {
6354 position: absolute;
6355 opacity: 0;
6356 pointer-events: none;
6357 }
6358
6359 .tier-option:focus-within {
6360 outline: 2px solid var(--focus-ring);
6361 outline-offset: 2px;
6362 }
6363
6364 /* Selected tier, driven purely by the checked radio (no JS toggling a
6365 class). The `.is-selected` alias is retained for any server-rendered use. */
6366 .tier-option.is-selected,
6367 .tier-option:has(input[type="radio"]:checked) {
6368 border-color: var(--action);
6369 border-width: 2px;
6370 padding: calc(1rem - 1px);
6371 }
6372
6373 .mnw-summary {
6374 text-align: center;
6375 padding: 1.5rem;
6376 background: var(--surface-overlay);
6377 border: 1px solid var(--border);
6378 }
6379
6380 .mnw-keep {
6381 font-family: var(--font-heading);
6382 font-size: 2.5rem;
6383 margin-bottom: 0.5rem;
6384 }
6385
6386 .mnw-detail {
6387 font-size: 0.9rem;
6388 opacity: 0.7;
6389 }
6390
6391 .data-table .highlight {
6392 background: var(--surface-overlay);
6393 border-left: 3px solid var(--action);
6394 }
6395
6396 .savings-positive {
6397 color: var(--success);
6398 font-weight: 600;
6399 }
6400
6401 .savings-negative {
6402 color: var(--danger);
6403 }
6404
6405 .pricing-disclaimer {
6406 font-size: 0.8rem;
6407 opacity: 0.55;
6408 margin-top: 0.75rem;
6409 line-height: 1.5;
6410 }
6411
6412 .breakeven-note {
6413 font-family: var(--font-mono);
6414 font-size: 0.85rem;
6415 padding: 1rem;
6416 background: var(--surface-overlay);
6417 border-left: 3px solid var(--warning);
6418 line-height: 1.6;
6419 }
6420
6421 /* ===========================================
6422 DOCUMENTATION PAGES
6423 =========================================== */
6424
6425 .doc-container {
6426 max-width: 680px;
6427 margin: 0 auto;
6428 padding: 3rem 1.5rem 5rem;
6429 }
6430
6431 .doc-breadcrumb {
6432 font-family: var(--font-mono);
6433 font-size: 0.875rem;
6434 margin-bottom: 2rem;
6435 }
6436
6437 .doc-breadcrumb a { color: var(--content); text-decoration: none; }
6438 .doc-breadcrumb a:hover { text-decoration: underline; }
6439
6440 .doc-title {
6441 font-family: var(--font-heading);
6442 font-size: 2.5rem;
6443 font-weight: normal;
6444 line-height: 1.2;
6445 margin-bottom: 1.5rem;
6446 color: var(--content);
6447 text-align: left;
6448 }
6449
6450 .doc-body {
6451 font-family: var(--font-body);
6452 font-size: 1.125rem;
6453 line-height: 1.9;
6454 }
6455
6456 .doc-body p { margin-bottom: 1.5rem; }
6457
6458 .doc-body h1 {
6459 font-family: var(--font-heading);
6460 font-size: 2rem;
6461 font-weight: normal;
6462 margin-top: 3rem;
6463 margin-bottom: 1rem;
6464 color: var(--content);
6465 text-align: left;
6466 }
6467
6468 .doc-body h2 {
6469 font-family: var(--font-mono);
6470 font-size: 1.75rem;
6471 font-weight: normal;
6472 margin-top: 3rem;
6473 margin-bottom: 1rem;
6474 color: var(--content);
6475 }
6476
6477 .doc-body h3 {
6478 font-family: var(--font-mono);
6479 font-size: 1.375rem;
6480 font-weight: normal;
6481 margin-top: 2.5rem;
6482 margin-bottom: 0.75rem;
6483 color: var(--content);
6484 }
6485
6486 .doc-body blockquote {
6487 border-left: 3px solid var(--action);
6488 padding-left: 1.5rem;
6489 margin: 2rem 0;
6490 font-style: italic;
6491 color: var(--content-muted);
6492 }
6493
6494 .doc-body ul, .doc-body ol { margin-bottom: 1.5rem; padding-left: 1.5rem; }
6495 .doc-body li { margin-bottom: 0.5rem; }
6496
6497 .doc-body a {
6498 color: var(--action);
6499 text-decoration: underline;
6500 text-decoration-color: rgba(108, 92, 231, 0.4);
6501 text-underline-offset: 2px;
6502 }
6503
6504 .doc-body a:hover { text-decoration-color: var(--action); }
6505 .doc-body strong { font-weight: bold; }
6506 .doc-body em { font-style: italic; }
6507
6508 .doc-body code {
6509 font-family: var(--font-mono);
6510 background: var(--surface-sunken);
6511 padding: 0.125rem 0.375rem;
6512 font-size: 0.9em;
6513 }
6514
6515 .doc-body pre {
6516 background: var(--surface-sunken);
6517 padding: 1rem;
6518 overflow-x: auto;
6519 margin-bottom: 1.5rem;
6520 }
6521
6522 .doc-body pre code { background: none; padding: 0; }
6523
6524 .doc-body hr { border: none; text-align: center; margin: 3rem 0; }
6525 .doc-body hr::before { content: "* * *"; color: var(--content-muted); letter-spacing: 1rem; }
6526
6527 .doc-body table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }
6528 .doc-body th, .doc-body td { padding: 0.75rem 1rem; text-align: left; border-bottom: 1px solid var(--border); }
6529 .doc-body th { font-family: var(--font-mono); font-weight: 600; }
6530
6531 .doc-backlinks {
6532 margin-top: 4rem;
6533 padding-top: 1.5rem;
6534 border-top: 1px solid var(--border);
6535 }
6536
6537 .doc-backlinks-title {
6538 font-family: var(--font-mono);
6539 font-size: 0.875rem;
6540 font-weight: 600;
6541 text-transform: uppercase;
6542 letter-spacing: 0.05em;
6543 color: var(--content-muted);
6544 margin-bottom: 1rem;
6545 }
6546
6547 .doc-backlinks-list {
6548 list-style: none;
6549 margin: 0;
6550 padding: 0;
6551 }
6552
6553 .doc-backlinks-list li { margin-bottom: 0.5rem; }
6554 .doc-backlinks-list a { color: var(--content); text-decoration: none; }
6555 .doc-backlinks-list a:hover { text-decoration: underline; }
6556
6557 .text-reader-footer {
6558 font-family: var(--font-mono);
6559 text-align: center;
6560 padding: 2rem;
6561 font-size: 0.875rem;
6562 color: var(--content-muted);
6563 border-top: 1px solid var(--border);
6564 }
6565
6566 .text-reader-footer a { color: var(--content); text-decoration: none; }
6567 .text-reader-footer a:hover { text-decoration: underline; }
6568
6569 /* Docs index page */
6570 .docs-index {
6571 max-width: 680px;
6572 margin: 0 auto;
6573 padding: 3rem 1.5rem 5rem;
6574 }
6575
6576 .docs-index-title {
6577 font-family: var(--font-heading);
6578 font-size: 2.5rem;
6579 font-weight: normal;
6580 line-height: 1.2;
6581 margin-bottom: 2.5rem;
6582 color: var(--content);
6583 }
6584
6585 .docs-section {
6586 margin-bottom: 2.5rem;
6587 }
6588
6589 .docs-section h2 {
6590 font-family: var(--font-mono);
6591 font-size: 1.25rem;
6592 font-weight: normal;
6593 color: var(--content-muted);
6594 margin-bottom: 0.75rem;
6595 }
6596
6597 .docs-section ul {
6598 list-style: none;
6599 padding: 0;
6600 margin: 0;
6601 }
6602
6603 .docs-section li {
6604 margin-bottom: 0.5rem;
6605 }
6606
6607 .docs-section a {
6608 font-family: var(--font-body);
6609 font-size: 1.125rem;
6610 color: var(--content);
6611 text-decoration: none;
6612 }
6613
6614 .docs-section a:hover {
6615 color: var(--action);
6616 text-decoration: underline;
6617 }
6618
6619 .docs-section details {
6620 margin-bottom: 1rem;
6621 }
6622
6623 .docs-section summary {
6624 font-family: var(--font-mono);
6625 font-size: 1rem;
6626 color: var(--content-muted);
6627 cursor: pointer;
6628 padding: 0.25rem 0;
6629 list-style: disclosure-closed;
6630 }
6631
6632 .docs-section details[open] > summary {
6633 list-style: disclosure-open;
6634 margin-bottom: 0.25rem;
6635 }
6636
6637 .docs-section summary:hover {
6638 color: var(--content);
6639 }
6640
6641 .docs-section details ul {
6642 padding-left: 1.25rem;
6643 }
6644
6645 /* Docs search */
6646 .docs-search-container {
6647 position: relative;
6648 margin-bottom: 2rem;
6649 }
6650 .docs-search-inline {
6651 display: inline-block;
6652 margin-bottom: 0;
6653 margin-left: auto;
6654 float: right;
6655 }
6656 .docs-search-input {
6657 width: 100%;
6658 max-width: 320px;
6659 padding: 0.5rem 0.75rem;
6660 font-family: var(--font-body);
6661 font-size: 0.95rem;
6662 background: var(--surface-sunken);
6663 border: 1px solid var(--border);
6664 color: var(--content);
6665 }
6666 .docs-search-input:focus {
6667 outline: 2px solid var(--action);
6668 border-color: var(--action);
6669 }
6670 .docs-search-input::placeholder { opacity: 0.5; }
6671 .docs-search-results {
6672 position: absolute;
6673 top: 100%;
6674 left: 0;
6675 right: 0;
6676 max-width: 320px;
6677 background: var(--surface-page);
6678 border: 1px solid var(--border);
6679 border-top: none;
6680 max-height: 300px;
6681 overflow-y: auto;
6682 z-index: 20;
6683 box-shadow: 0 4px 8px rgba(0,0,0,0.08);
6684 }
6685 .docs-search-result {
6686 display: flex;
6687 justify-content: space-between;
6688 align-items: baseline;
6689 padding: 0.5rem 0.75rem;
6690 text-decoration: none;
6691 color: var(--content);
6692 font-size: 0.9rem;
6693 border-bottom: 1px solid var(--border);
6694 }
6695 .docs-search-result:last-child { border-bottom: none; }
6696 .docs-search-result:hover { background: var(--surface-sunken); }
6697 .docs-search-result-title { font-family: var(--font-body); }
6698 .docs-search-result-section { font-family: var(--font-mono); font-size: 0.75rem; opacity: 0.5; }.alert .alert-title {
6699 font-family: var(--font-mono);
6700 font-size: 0.85rem;
6701 font-weight: bold;
6702 text-transform: uppercase;
6703 letter-spacing: 0.04em;
6704 margin-bottom: 0.25rem;
6705 }
6706 .alert p:last-child { margin-bottom: 0; }
6707 .alert-note { border-left-color: var(--focus-ring); }
6708 .alert-note .alert-title { color: var(--focus-ring); }
6709 .alert-tip { border-left-color: var(--success); }
6710 .alert-tip .alert-title { color: var(--success); }
6711 .alert-important { border-left-color: var(--action); }
6712 .alert-important .alert-title { color: var(--action); }
6713 .alert-warning { border-left-color: var(--warning); }
6714 .alert-warning .alert-title { color: var(--warning); }
6715 .alert-caution { border-left-color: var(--danger); }
6716 .alert-caution .alert-title { color: var(--danger); }
6717
6718 /* ===========================================
6719 USE CASES PAGE
6720 =========================================== */
6721
6722 .use-cases-page {
6723 max-width: 900px;
6724 margin: 0 auto;
6725 }
6726
6727 .use-cases-intro {
6728 font-size: 1.1rem;
6729 margin-bottom: 2rem;
6730 line-height: 1.6;
6731 }
6732
6733 .use-case-grid {
6734 display: grid;
6735 grid-template-columns: 1fr 1fr 1fr;
6736 gap: 0.75rem;
6737 text-align: left;
6738 }
6739
6740 .use-case-grid-2col {
6741 grid-template-columns: 1fr 1fr;
6742 }
6743
6744 .use-case-card.coming-soon {
6745 border-style: dashed;
6746 opacity: 0.6;
6747 }
6748
6749 .use-case-title {
6750 font-family: var(--font-heading);
6751 font-size: 1.1rem;
6752 margin-bottom: 0.15rem;
6753 }
6754
6755 .use-case-who {
6756 font-family: var(--font-mono);
6757 font-size: 0.8rem;
6758 opacity: 0.6;
6759 margin-bottom: 0.5rem;
6760 }
6761
6762 .use-case-desc {
6763 font-size: 0.9rem;
6764 line-height: 1.5;
6765 margin-bottom: 0.5rem;
6766 }
6767
6768 .use-case-features {
6769 list-style: none;
6770 margin: 0 0 0.75rem;
6771 padding: 0;
6772 }
6773
6774 .use-case-features li {
6775 font-size: 0.85rem;
6776 padding-left: 1rem;
6777 position: relative;
6778 margin-bottom: 0.25rem;
6779 }
6780
6781 .use-case-features li::before {
6782 content: "-";
6783 position: absolute;
6784 left: 0;
6785 opacity: 0.5;
6786 }
6787
6788 .use-case-tier {
6789 font-family: var(--font-mono);
6790 font-size: 0.75rem;
6791 opacity: 0.5;
6792 }
6793
6794 /* ===========================================
6795 RESPONSIVE, 768px (tablet)
6796 =========================================== */
6797
6798 /* ==========================================================================
6799 Git Source Browser
6800 ========================================================================== */
6801
6802 .git-repo-header { margin-bottom: 1.5rem; }
6803 .git-repo-name { font-size: 1.5rem; margin: 0 0 0.25rem; }
6804 .git-repo-name a { color: var(--content); text-decoration: none; }
6805 .git-repo-name a:hover { opacity: 0.6; }
6806 .git-repo-name .sep { opacity: 0.3; margin: 0 0.15rem; }
6807 .git-repo-desc { opacity: 0.6; margin: 0 0 1rem; font-size: 0.9rem; }
6808 .git-clone-url {
6809 font-family: var(--font-mono);
6810 font-size: 0.8rem;
6811 padding: 0.4rem 0.6rem;
6812 background: var(--surface-overlay);
6813 border: 1px solid var(--border);
6814 border-radius: 3px;
6815 display: inline-block;
6816 user-select: all;
6817 margin-bottom: 1rem;
6818 }
6819 .git-linked-project { margin-top: 0.5rem; font-size: 0.9rem; }
6820 .git-linked-project a { color: var(--content); }
6821
6822 /* Ref bar (branch/tag selector + nav links) */
6823 .git-ref-bar {
6824 display: flex;
6825 align-items: center;
6826 gap: 1rem;
6827 margin-bottom: 1rem;
6828 font-size: 0.85rem;
6829 }
6830 .git-ref-select {
6831 font-family: var(--font-mono);
6832 font-size: 0.8rem;
6833 padding: 0.3rem 0.5rem;
6834 background: var(--surface-overlay);
6835 border: 1px solid var(--border);
6836 border-radius: 3px;
6837 }
6838 .git-nav-links { display: flex; gap: 1rem; }
6839 .git-nav-links a { text-decoration: none; color: var(--content); opacity: 0.6; }
6840 .git-nav-links a:hover,
6841 .git-nav-links a.is-selected { opacity: 1; }
6842
6843 /* Breadcrumb navigation */
6844 .git-breadcrumb {
6845 font-family: var(--font-mono);
6846 font-size: 0.85rem;
6847 margin-bottom: 1rem;
6848 }
6849 .git-breadcrumb a { color: var(--content); text-decoration: none; }
6850 .git-breadcrumb a:hover { text-decoration: underline; }
6851 .git-breadcrumb .sep { opacity: 0.3; margin: 0 0.15rem; }
6852
6853 /* File tree table */
6854 .git-tree { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
6855 .git-tree th {
6856 text-align: left;
6857 padding: 0.4rem 0.6rem;
6858 border-bottom: 2px solid var(--border);
6859 font-family: var(--font-mono);
6860 font-size: 0.75rem;
6861 opacity: 0.5;
6862 text-transform: uppercase;
6863 }
6864 .git-tree td { padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--border); }
6865 .git-tree tr:last-child td { border-bottom: none; }
6866 .git-tree .icon { width: 1.5rem; text-align: center; opacity: 0.4; font-family: var(--font-mono); }
6867 .tree-icon-dir { font-weight: 700; color: var(--content); }
6868 .tree-icon-file { font-size: 1.2em; }
6869 .git-tree .name a { text-decoration: none; color: var(--content); }
6870 .git-tree .name a:hover { text-decoration: underline; }
6871 .git-tree .size {
6872 text-align: right;
6873 opacity: 0.5;
6874 font-family: var(--font-mono);
6875 font-size: 0.8rem;
6876 }
6877
6878 /* README rendering */
6879 .git-readme { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
6880 .git-readme h2 { font-size: 1rem; opacity: 0.5; margin-bottom: 1rem; }
6881 .git-readme-body { line-height: 1.6; }
6882 .git-readme-body h1,
6883 .git-readme-body h2,
6884 .git-readme-body h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; }
6885 .git-readme-body pre {
6886 background: var(--surface-overlay);
6887 padding: 0.8rem;
6888 border-radius: 3px;
6889 overflow-x: auto;
6890 font-family: var(--font-mono);
6891 font-size: 0.8rem;
6892 }
6893 .git-readme-body code {
6894 font-family: var(--font-mono);
6895 font-size: 0.85em;
6896 background: var(--surface-overlay);
6897 padding: 0.15rem 0.3rem;
6898 border-radius: 2px;
6899 }
6900 .git-readme-body pre code { background: none; padding: 0; }
6901 .git-readme-body table { border-collapse: collapse; margin: 1rem 0; }
6902 .git-readme-body th,
6903 .git-readme-body td { border: 1px solid var(--border); padding: 0.4rem 0.6rem; }
6904
6905 /* File viewer */
6906 .git-file-header {
6907 display: flex;
6908 justify-content: space-between;
6909 align-items: center;
6910 padding: 0.5rem 0.6rem;
6911 background: var(--surface-overlay);
6912 border: 1px solid var(--border);
6913 border-bottom: none;
6914 border-radius: 3px 3px 0 0;
6915 font-size: 0.8rem;
6916 }
6917 .git-file-meta {
6918 font-family: var(--font-mono);
6919 opacity: 0.6;
6920 }
6921 .git-file-actions a {
6922 font-family: var(--font-mono);
6923 text-decoration: none;
6924 color: var(--content);
6925 opacity: 0.6;
6926 font-size: 0.8rem;
6927 }
6928 .git-file-actions a:hover { opacity: 1; }
6929 .git-file-content {
6930 border: 1px solid var(--border);
6931 border-radius: 0 0 3px 3px;
6932 overflow-x: auto;
6933 }
6934 .git-file-content table { border-collapse: collapse; width: 100%; }
6935 .git-file-content .line-number {
6936 width: 1px;
6937 white-space: nowrap;
6938 padding: 0 0.8rem;
6939 text-align: right;
6940 user-select: none;
6941 opacity: 0.3;
6942 font-family: var(--font-mono);
6943 font-size: 0.8rem;
6944 border-right: 1px solid var(--border);
6945 vertical-align: top;
6946 }
6947 .git-file-content .line-code {
6948 padding: 0 0.8rem;
6949 white-space: pre;
6950 font-family: var(--font-mono);
6951 font-size: 0.8rem;
6952 line-height: 1.5;
6953 }
6954 .git-file-content .line-code span {
6955 font-family: var(--font-mono);
6956 }
6957 .git-binary-notice {
6958 padding: 2rem;
6959 text-align: center;
6960 opacity: 0.5;
6961 font-family: var(--font-mono);
6962 font-size: 0.85rem;
6963 border: 1px solid var(--border);
6964 border-radius: 0 0 3px 3px;
6965 }
6966
6967 /* Syntax highlighting (syntect class-based) */
6968 .git-file-content .source { color: var(--content); }
6969 .git-file-content .keyword,
6970 .git-file-content .storage { color: #8959a8; }
6971 .git-file-content .string { color: #718c00; }
6972 .git-file-content .comment { color: #8e908c; font-style: italic; }
6973 .git-file-content .constant,
6974 .git-file-content .constant.numeric { color: #f5871f; }
6975 .git-file-content .entity.name { color: #4271ae; }
6976 .git-file-content .variable { color: #c82829; }
6977 .git-file-content .support { color: #3e999f; }
6978 .git-file-content .meta.preprocessor { color: #8959a8; }
6979
6980 /* Commit list */
6981 .git-commit-list { list-style: none; }
6982 .git-commit { padding: 0.75rem 0; border-bottom: 1px solid var(--border); }
6983 .git-commit:last-child { border-bottom: none; }
6984 .git-commit-message { font-size: 0.9rem; margin: 0 0 0.3rem; }
6985 .git-commit-message .summary { font-weight: 600; }
6986 .git-commit-meta {
6987 font-family: var(--font-mono);
6988 font-size: 0.75rem;
6989 opacity: 0.5;
6990 display: flex;
6991 gap: 1rem;
6992 flex-wrap: wrap;
6993 }
6994 .git-commit-oid { font-family: var(--font-mono); font-size: 0.75rem; }
6995 .git-commit-oid a { color: var(--content); text-decoration: none; }
6996 .git-commit-oid a:hover { text-decoration: underline; }
6997 .git-pagination {
6998 display: flex;
6999 justify-content: center;
7000 gap: 1rem;
7001 margin-top: 1.5rem;
7002 padding-top: 1rem;
7003 font-size: 0.85rem;
7004 }
7005 .git-pagination a { color: var(--content); text-decoration: none; }
7006 .git-pagination a:hover { text-decoration: underline; }
7007
7008 /* Release items on repo page */
7009 .git-release { margin-bottom: 1.5rem; padding: 1rem; background: var(--surface-overlay); }
7010 .git-release-title { margin: 0 0 0.25rem; font-size: 1.1rem; }
7011 .git-release-title a { color: var(--content); text-decoration: none; }
7012 .git-release-meta { font-size: 0.85rem; opacity: 0.6; margin-bottom: 0.5rem; }
7013 .git-release-desc { font-size: 0.9rem; opacity: 0.8; margin-bottom: 0.75rem; }
7014 .git-release-versions { font-size: 0.8rem; }
7015 .git-release-version {
7016 display: flex;
7017 gap: 0.75rem;
7018 align-items: center;
7019 padding: 0.3rem 0;
7020 border-top: 1px solid var(--border);
7021 }
7022 .git-release-version .version-number { font-family: var(--font-mono); }
7023 .git-release-version .version-badge {
7024 font-size: 0.7rem;
7025 padding: 0.1rem 0.4rem;
7026 background: var(--content);
7027 color: var(--surface-page);
7028 border-radius: 2px;
7029 }
7030 .git-release-version .version-meta { opacity: 0.5; }
7031
7032 /* Git commit detail + diff */
7033 .git-commit-detail { margin-bottom: 1.5rem; }
7034 .git-commit-full-message {
7035 font-family: var(--font-mono);
7036 font-size: 0.85rem;
7037 white-space: pre-wrap;
7038 line-height: 1.5;
7039 padding: 1rem;
7040 background: var(--surface-overlay);
7041 border: 1px solid var(--border);
7042 margin-bottom: 1rem;
7043 }
7044 .git-commit-detail-meta { font-size: 0.85rem; opacity: 0.7; line-height: 1.8; }
7045 .git-commit-detail-meta .git-commit-oid { font-family: var(--font-mono); font-size: 0.8rem; word-break: break-all; }
7046 .git-commit-parents a { font-family: var(--font-mono); color: var(--content); text-decoration: none; }
7047 .git-commit-parents a:hover { text-decoration: underline; }
7048 .git-diff-stats {
7049 font-size: 0.85rem;
7050 padding: 0.75rem 0;
7051 margin-bottom: 1rem;
7052 border-bottom: 1px solid var(--border);
7053 }
7054 .git-diff-stats .additions { color: var(--diff-add); }
7055 .git-diff-stats .deletions { color: var(--diff-del); }
7056 .git-diff-file { margin-bottom: 1.5rem; border: 1px solid var(--border); }
7057 .git-diff-file-header {
7058 display: flex;
7059 align-items: center;
7060 gap: 0.5rem;
7061 padding: 0.5rem 0.75rem;
7062 background: var(--surface-overlay);
7063 border-bottom: 1px solid var(--border);
7064 font-size: 0.85rem;
7065 flex-wrap: wrap;
7066 }
7067 .git-diff-file-header a { color: var(--content); text-decoration: none; }
7068 .git-diff-file-header a:hover { text-decoration: underline; }
7069 .git-diff-file-stats { margin-left: auto; font-size: 0.8rem; }
7070 .git-diff-file-stats .additions { color: var(--diff-add); }
7071 .git-diff-file-stats .deletions { color: var(--diff-del); margin-left: 0.25rem; }
7072 .diff-status-A, .diff-status-D, .diff-status-M, .diff-status-R {
7073 display: inline-block;
7074 width: 1.2rem;
7075 text-align: center;
7076 font-size: 0.75rem;
7077 font-weight: 700;
7078 font-family: var(--font-mono);
7079 border-radius: 2px;
7080 line-height: 1.4;
7081 }
7082 .diff-status-A { background: #d4edda; color: #155724; }
7083 .diff-status-D { background: #f8d7da; color: #721c24; }
7084 .diff-status-M { background: color-mix(in oklch, var(--warning) 14%, var(--surface-page)); color: var(--warning); }
7085 .diff-status-R { background: #d1ecf1; color: #0c5460; }
7086 .git-diff-table {
7087 width: 100%;
7088 border-collapse: collapse;
7089 font-family: var(--font-mono);
7090 font-size: 0.8rem;
7091 table-layout: fixed;
7092 }
7093 .git-diff-hunk-header td {
7094 padding: 0.3rem 0.5rem;
7095 background: color-mix(in oklch, var(--action) 8%, transparent);
7096 color: var(--content);
7097 opacity: 0.6;
7098 font-size: 0.75rem;
7099 }
7100 .git-diff-lineno {
7101 width: 3.5rem;
7102 padding: 0 0.4rem;
7103 text-align: right;
7104 color: var(--content);
7105 opacity: 0.35;
7106 user-select: none;
7107 vertical-align: top;
7108 }
7109 .git-diff-origin {
7110 width: 1rem;
7111 text-align: center;
7112 user-select: none;
7113 vertical-align: top;
7114 }
7115 .git-diff-content {
7116 padding: 0 0.5rem;
7117 white-space: pre-wrap;
7118 word-break: break-all;
7119 }
7120 .git-diff-line-add { background: var(--diff-add-bg); }
7121 .git-diff-line-add .git-diff-origin { color: var(--diff-add); }
7122 .git-diff-line-del { background: var(--diff-del-bg); }
7123 .git-diff-line-del .git-diff-origin { color: var(--diff-del); }
7124 .git-diff-line-ctx { background: transparent; }
7125 .git-diff-truncated { padding: 0.5rem 0.75rem; font-size: 0.8rem; opacity: 0.5; font-style: italic; }
7126
7127 /* Git file view line linking */
7128 .git-file-content .line-number a {
7129 color: inherit;
7130 text-decoration: none;
7131 display: block;
7132 }
7133 .git-file-content .line-number a:hover { opacity: 0.7; }
7134 .git-file-content tr:target td,
7135 .git-file-content tr.highlighted td { background: color-mix(in oklch, var(--action) 8%, transparent); }
7136
7137 /* Git blame view */
7138 .git-blame-content { overflow-x: auto; border: 1px solid var(--border); }
7139 .git-blame-content table { border-collapse: collapse; width: 100%; font-size: 0.8rem; }
7140 .git-blame-info {
7141 padding: 0 0.4rem;
7142 font-family: var(--font-mono);
7143 white-space: nowrap;
7144 width: 4.5rem;
7145 }
7146 .git-blame-info a { color: var(--content); text-decoration: none; }
7147 .git-blame-info a:hover { text-decoration: underline; }
7148 .git-blame-author {
7149 padding: 0 0.3rem;
7150 font-size: 0.75rem;
7151 opacity: 0.5;
7152 white-space: nowrap;
7153 max-width: 8rem;
7154 overflow: hidden;
7155 text-overflow: ellipsis;
7156 }
7157 .git-blame-date {
7158 padding: 0 0.3rem;
7159 font-size: 0.75rem;
7160 opacity: 0.35;
7161 white-space: nowrap;
7162 width: 5.5rem;
7163 }
7164 .git-blame-content .line-number {
7165 padding: 0 0.5rem;
7166 text-align: right;
7167 opacity: 0.35;
7168 user-select: none;
7169 width: 3rem;
7170 font-family: var(--font-mono);
7171 }
7172 .git-blame-content .line-code {
7173 padding: 0 0.5rem;
7174 white-space: pre;
7175 font-family: var(--font-mono);
7176 }
7177 .git-blame-boundary td { border-top: 1px solid var(--border); }
7178
7179 /* Git user repos listing */
7180 .git-repos-list { list-style: none; }
7181 .git-repos-item { padding: 0.75rem 0; border-bottom: 1px solid var(--border); }
7182 .git-repos-item:last-child { border-bottom: none; }
7183 .git-repos-item-header { display: flex; align-items: center; gap: 0.5rem; }
7184 .git-repos-item-name {
7185 font-size: 1.1rem;
7186 font-weight: 600;
7187 color: var(--content);
7188 text-decoration: none;
7189 }
7190 .git-repos-item-name:hover { text-decoration: underline; }
7191 .git-repos-visibility {
7192 font-size: 0.7rem;
7193 padding: 0.1rem 0.4rem;
7194 border: 1px solid var(--border);
7195 border-radius: 2px;
7196 opacity: 0.5;
7197 }
7198 .git-repos-item-desc { font-size: 0.85rem; opacity: 0.6; margin: 0.25rem 0 0; }.git-repos-instructions p { margin-bottom: 0.5rem; }
7199 .git-repos-owner { opacity: 0.6; }
7200 .git-repos-item-name .sep { opacity: 0.4; }
7201 .git-file-log-label {
7202 font-family: var(--font-mono);
7203 font-size: 0.8rem;
7204 opacity: 0.5;
7205 margin-right: 0.25rem;
7206 }
7207
7208 /* Site-wide footer */
7209 .site-footer {
7210 margin-top: 4rem;
7211 padding: 2rem 0;
7212 text-align: center;
7213 font-family: var(--font-mono);
7214 font-size: 0.8rem;
7215 opacity: 0.5;
7216 }
7217 .site-footer-links { margin-bottom: 0.5rem; }
7218 .site-footer-links a { margin: 0 0.75rem; color: inherit; text-decoration: none; }
7219 .site-footer-links a:hover { text-decoration: underline; }
7220
7221 @media (max-width: 768px) {
7222 /* Git browser mobile */
7223 .git-ref-bar { flex-wrap: wrap; gap: 0.5rem; }
7224 .git-repo-name { font-size: 1.2rem; }
7225 .git-clone-url { font-size: 0.75rem; word-break: break-all; }
7226 .git-tree .icon { display: none; }
7227 .git-tree td, .git-tree th { padding: 0.3rem 0.4rem; }
7228 .git-file-header { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
7229 .git-file-content .line-number { padding: 0 0.4rem; }
7230 .git-file-content .line-code { padding: 0 0.4rem; font-size: 0.75rem; }
7231 .git-commit-meta { flex-direction: column; gap: 0.25rem; }
7232 .git-release-version { flex-wrap: wrap; gap: 0.5rem; }
7233 .git-diff-file-header { font-size: 0.8rem; }
7234 .git-diff-table { font-size: 0.7rem; }
7235 .git-diff-lineno { width: 2.5rem; font-size: 0.65rem; }
7236 .git-blame-author { display: none; }
7237 .git-blame-date { display: none; }
7238
7239 .container {
7240 padding: 1.25rem;
7241 }
7242
7243 .padded-page {
7244 padding: 1rem;
7245 }
7246
7247 .form-row {
7248 grid-template-columns: 1fr;
7249 }
7250
7251 .tab {
7252 padding: 0.6rem 1.25rem;
7253 font-size: 0.9rem;
7254 }
7255
7256 .tab-content {
7257 padding: 1.25rem;
7258 }
7259
7260 .data-table th,
7261 .data-table td {
7262 padding: 0.5rem 0.6rem;
7263 font-size: 0.85rem;
7264 }
7265
7266 .modal {
7267 max-width: 95%;
7268 }
7269
7270 .stats-grid {
7271 grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
7272 }
7273
7274 .content-section {
7275 padding: 1.25rem;
7276 }
7277
7278 .action-buttons {
7279 flex-direction: column;
7280 }
7281
7282 .action-buttons button {
7283 width: 100%;
7284 }
7285
7286 .analytics-grid {
7287 grid-template-columns: 1fr;
7288 }
7289
7290 /* Hamburger menu */
7291 .nav-toggle-label {
7292 display: block;
7293 }
7294
7295 .header-search {
7296 display: none;
7297 flex: none;
7298 margin: 0;
7299 width: 100%;
7300 }
7301
7302 .nav-toggle-checkbox:checked ~ .header-search {
7303 display: block;
7304 position: absolute;
7305 top: 100%;
7306 left: 0;
7307 right: 0;
7308 padding: 0.75rem 1.5rem;
7309 background: var(--surface-page);
7310 border-bottom: 1px solid var(--border);
7311 z-index: 11;
7312 }
7313
7314 .site-header nav {
7315 display: none;
7316 position: absolute;
7317 top: 100%;
7318 left: 0;
7319 right: 0;
7320 background: var(--surface-page);
7321 border-bottom: 1px solid var(--border);
7322 padding: 1rem 1.5rem;
7323 z-index: 10;
7324 }
7325
7326 .site-header {
7327 position: relative;
7328 }
7329
7330 .nav-toggle-checkbox:checked ~ nav {
7331 display: block;
7332 }
7333
7334 .site-header .nav-links {
7335 flex-direction: column;
7336 gap: 0.75rem;
7337 }
7338
7339 /* Animate hamburger to X when open */
7340 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(1) {
7341 transform: rotate(45deg) translate(5px, 5px);
7342 }
7343
7344 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(2) {
7345 opacity: 0;
7346 }
7347
7348 .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(3) {
7349 transform: rotate(-45deg) translate(5px, -5px);
7350 }
7351 }
7352
7353 /* Doc pages, mobile */
7354 @media (max-width: 600px) {
7355 .doc-title { font-size: 2rem; }
7356 .doc-body { font-size: 1rem; }
7357 .docs-index-title { font-size: 2rem; }
7358 }
7359
7360 /* ===========================================
7361 RESPONSIVE, 480px (phone)
7362 =========================================== */
7363
7364 @media (max-width: 480px) {
7365 .container {
7366 padding: 0.75rem;
7367 }
7368
7369 .padded-page {
7370 padding: 0.75rem;
7371 }
7372
7373 h1 {
7374 font-size: 1.8rem;
7375 }
7376
7377 .centered-page h1 {
7378 font-size: 3rem;
7379 }
7380
7381 .login-container,
7382 .form-container {
7383 max-width: 100%;
7384 padding: 1.25rem;
7385 }
7386
7387 .big-button {
7388 width: 100%;
7389 }
7390
7391 .stats-grid {
7392 grid-template-columns: repeat(2, 1fr);
7393 }
7394
7395 .tab {
7396 padding: 0.5rem 0.75rem;
7397 font-size: 0.85rem;
7398 }
7399
7400 .tab-content {
7401 padding: 1rem;
7402 }
7403
7404 .content-section {
7405 padding: 1rem;
7406 }
7407
7408 .section-header {
7409 flex-direction: column;
7410 align-items: flex-start;
7411 gap: 0.75rem;
7412 }
7413
7414 /* Landing page (merged from 500px) */
7415 .landing-fork,
7416 .tier-selector,
7417 .feature-grid,
7418 .use-case-grid,
7419 .use-case-grid-2col {
7420 grid-template-columns: 1fr;
7421 }
7422
7423 .explore-links {
7424 flex-direction: column;
7425 align-items: center;
7426 gap: 0.75rem;
7427 }
7428
7429 .pricing-input {
7430 font-size: 2rem;
7431 }
7432
7433 .pricing-currency {
7434 font-size: 2rem;
7435 }
7436
7437 .mnw-keep {
7438 font-size: 2rem;
7439 }
7440
7441 .secondary-links {
7442 flex-direction: column;
7443 align-items: center;
7444 gap: 0.75rem;
7445 }
7446
7447 .landing-cta {
7448 flex-direction: column;
7449 gap: 1rem;
7450 }
7451
7452 .toast-container {
7453 left: 0.75rem;
7454 right: 0.75rem;
7455 bottom: 0.75rem;
7456 }
7457
7458 .toast {
7459 max-width: 100%;
7460 }
7461 }
7462
7463 /* ===========================================
7464 DISCOVER PAGE
7465 =========================================== */
7466
7467 .discover-layout { display: grid; grid-template-columns: 200px 1fr; gap: 1.5rem; }
7468 .discover-layout.no-sidebar { grid-template-columns: 1fr; }
7469 .discover-layout.no-sidebar .discover-sidebar { display: none; }
7470 .discover-sidebar { font-size: 0.85rem; }
7471 .filter-section { margin-bottom: 1.25rem; }
7472 .filter-title { font-family: var(--font-heading); font-weight: bold; font-size: 0.85rem; margin-bottom: 0.5rem; color: var(--content); }
7473 .filter-list { list-style: none; }
7474 /* The row carries selection (`.is-selected` recipe) and hover; the filter itself
7475 is a real <button> child so Enter/Space work without scripting. */
7476 .filter-item { display: flex; align-items: center; gap: 0.3rem; transition: opacity 0.1s ease; }
7477 .filter-item:hover { opacity: 0.6; }
7478 .filter-item.is-selected { font-weight: bold; }
7479 .filter-item .count { opacity: 0.4; font-size: 0.8rem; }
7480 .tag-follow-btn { background: none; border: 1px solid var(--border); cursor: pointer; font-family: var(--font-mono); font-size: 0.7rem; opacity: 0.55; padding: 0.1rem 0.45rem; color: var(--content); }
7481 .tag-follow-btn:hover { opacity: 1; }
7482 .tag-follow-btn.is-selected { opacity: 0.85; border-color: var(--focus-ring); background: color-mix(in oklch, var(--action) 8%, transparent); }
7483 .filter-checkbox { display: flex; align-items: center; gap: 0.4rem; padding: 0.2rem 0; cursor: pointer; }
7484 .filter-checkbox input { width: auto; margin: 0; }
7485 .price-inputs { display: flex; gap: 0.25rem; align-items: center; margin-bottom: 0.5rem; }
7486 .price-inputs input { width: 60px; padding: 0.3rem; font-size: 0.8rem; background: var(--surface-sunken); border: none; }
7487 .price-inputs span { opacity: 0.4; }
7488 .discover-main { min-width: 0; }
7489
7490 /* ---- Discover sidebar: tag spine ----------------------------------------
7491 Tags are the sidebar's structure, not one facet among several, so the spine
7492 reads as the primary surface and .filter-refine below it is subordinate.
7493 Everything here composes existing primitives: .filter-item carries the row
7494 and its .is-selected recipe, .search-suggestions carries the dropdown shell,
7495 .breadcrumb carries the crumb idiom. */
7496 .tag-spine { padding-bottom: var(--space-4); border-bottom: 1px solid var(--border); }
7497
7498 /* Selected tags. Also the active-filter summary, so they use the canonical
7499 selected tint rather than a new colour. */
7500 .tag-chips { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-3); }
7501 .tag-chip { display: flex; align-items: center; gap: var(--space-1); padding: 0.15rem 0.4rem; font-size: 0.8rem; background: color-mix(in oklch, var(--action) 8%, transparent); border: 1px solid var(--focus-ring); }
7502 .tag-chip-label { overflow-wrap: anywhere; }
7503 .tag-chip-remove { text-decoration: none; color: var(--content-secondary); font-size: 1rem; line-height: 1; padding: 0 0.1rem; }
7504 .tag-chip-remove:hover { color: var(--content); }
7505 .tag-chip-clear { background: none; border: 1px dashed var(--border-strong); }
7506 .tag-chip-clear a { text-decoration: none; color: var(--content-secondary); font-size: 0.8rem; }
7507 .tag-chip-clear a:hover { color: var(--content); }
7508
7509 /* Typeahead. Shares the .search-suggestions shell; it toggles with the
7510 `hidden` attribute rather than an inline display, so the shared rule's
7511 display:none has to be overridden when open. */
7512 .tag-combobox { position: relative; margin-bottom: var(--space-3); }
7513 .tag-combobox-input { width: 100%; padding: 0.3rem; font-size: 0.8rem; background: var(--surface-sunken); border: none; }
7514 .tag-suggest-list { list-style: none; }
7515 .tag-suggest-list:not([hidden]) { display: block; }
7516 .tag-suggest-item { gap: var(--space-2); }
7517 .tag-suggest-label { overflow-wrap: anywhere; }
7518
7519 /* Drill-down. A rung either selects (assignable leaf) or navigates (category);
7520 rows with both put the chevron after the label. */
7521 .tag-crumbs { list-style: none; display: flex; flex-wrap: wrap; font-family: var(--font-mono); font-size: 0.75rem; color: var(--content-muted); margin-bottom: var(--space-2); }
7522 .tag-crumbs li + li::before { content: "/"; opacity: 0.4; margin: 0 0.3rem; }
7523 .tag-crumbs a { color: var(--content); text-decoration: none; }
7524 .tag-crumbs a:hover { text-decoration: underline; }
7525 .tag-drill-select { flex: 1; display: flex; align-items: center; gap: var(--space-2); cursor: pointer; padding: 0.15rem 0; }
7526 .tag-drill-select input { width: auto; margin: 0; }
7527 .tag-drill-select span:first-of-type { flex: 1; }
7528 .tag-drill-into { display: flex; align-items: center; gap: var(--space-2); flex: 1; text-decoration: none; color: inherit; padding: 0.15rem 0; }
7529 .tag-drill-into span:first-child { flex: 1; }
7530 .tag-drill-chevron { opacity: 0.4; }
7531
7532 /* ---- Discover sidebar: refine block -------------------------------------
7533 Subordinate to the spine: same controls, quieter. */
7534 .filter-refine { margin-top: var(--space-4); }
7535 .filter-fieldset { border: none; padding: 0; margin: 0; min-width: 0; }
7536 .filter-check { flex: 1; display: flex; align-items: center; gap: var(--space-2); cursor: pointer; padding: 0.15rem 0; }
7537 .filter-check input { width: auto; margin: 0; }
7538 .filter-check span:first-of-type { flex: 1; }
7539
7540 /* A zero-count facet stays visible but inert, so the shape of the catalog
7541 stays legible as filters narrow. No existing rule covers a disabled input
7542 inside a label, so this is the checkbox counterpart of the button rule.
7543 `.is-empty` covers the drill rungs, which are links and carry no input at
7544 all; they were rendering identically to rungs with items. */
7545 .filter-item:has(input:disabled), .filter-item.is-empty { opacity: 0.5; }
7546 .filter-item:has(input:disabled) .filter-check { cursor: not-allowed; }
7547
7548 /* Price buckets are links carrying a range, not form state. */
7549 .price-buckets { margin-top: var(--space-2); }
7550 .price-bucket { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); text-decoration: none; color: inherit; padding: 0.15rem 0; }
7551
7552 .mode-toggle { display: flex; gap: 0.5rem; margin-bottom: 0.75rem; }
7553 .toggle-btn { background: var(--surface-sunken); border: none; padding: 0.4rem 0.8rem; font-size: 0.85rem; font-family: inherit; cursor: pointer; transition: background 0.1s ease, opacity 0.1s ease; }
7554 .toggle-btn:hover { opacity: 0.7; }
7555 .toggle-btn.is-selected { background: var(--primary-dark); color: var(--primary-light); }
7556 .table-controls { background: var(--surface-sunken); display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0.75rem; }
7557 .search-field { flex: 1 1 0; background: var(--surface-page); border: none; padding: 0.5rem 0.75rem; font-family: inherit; font-size: 0.9rem; color: var(--content); min-width: 0; }
7558 .search-field:focus { outline: 2px solid var(--action); }
7559 .search-field::placeholder { opacity: 0.5; }
7560 .table-meta { font-size: 0.75rem; opacity: 0.6; white-space: nowrap; flex-shrink: 0; }
7561 .sort-select { background: var(--surface-page); border: none; padding: 0.3rem 0.4rem; font-size: 0.75rem; font-family: inherit; cursor: pointer; width: auto; flex-shrink: 0; }
7562 .table-header { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: 0.5rem; padding: 0.5rem 0.75rem; background: var(--surface-overlay); font-size: 0.75rem; opacity: 0.7; text-transform: uppercase; letter-spacing: 0.03em; }
7563 .table-header.projects-header { grid-template-columns: 1fr 100px 80px 70px; }
7564 /* Column headers describe the list layout only; hidden when the grid view is active. */
7565 .table-header.is-hidden { display: none; }
7566 .col-right { text-align: right; }
7567 .results-table { border: 1px solid var(--border); border-top: none; }
7568 .table-row { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: 0.5rem; padding: 0.4rem 0.75rem; align-items: center; text-decoration: none; color: var(--content); font-size: 0.85rem; border-bottom: 1px solid var(--border); transition: background 0.1s ease; }
7569 .table-row-item { grid-template-columns: 1fr 30px; padding: 0; gap: 0; }
7570 .table-row-item .table-row-link { display: grid; grid-template-columns: 50px 1fr 100px 70px 70px; gap: 0.5rem; padding: 0.4rem 0.75rem; align-items: center; text-decoration: none; color: inherit; flex: 1; }
7571 .table-row-item .row-save { display: flex; align-items: center; justify-content: center; }
7572 .table-row.project-row { grid-template-columns: 1fr 100px 80px 70px; }
7573 .table-row:last-child { border-bottom: none; }
7574 .table-row:nth-child(odd) { background: var(--surface-overlay); }
7575 .table-row:nth-child(even) { background: var(--surface-overlay); }
7576 .table-row:hover { background: var(--surface-sunken); text-decoration: none; }
7577 .row-type { font-size: 0.7rem; background: var(--surface-sunken); padding: 0.2rem 0.4rem; text-align: center; opacity: 0.7; }
7578 .row-info { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
7579 .row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
7580 .row-creator { font-size: 0.75rem; opacity: 0.5; }.row-category { font-size: 0.8rem; opacity: 0.6; }
7581 .row-price { text-align: right; }
7582 .row-items { text-align: right; opacity: 0.6; font-size: 0.8rem; }
7583 .row-date { text-align: right; opacity: 0.5; font-size: 0.75rem; }.pagination { display: flex; gap: 0.25rem; }
7584 .pagination button { background: var(--surface-page); border: none; padding: 0.3rem 0.6rem; font-size: 0.8rem; cursor: pointer; }
7585 .pagination button:disabled { opacity: 0.3; cursor: not-allowed; }
7586 .pagination button.is-selected { background: var(--primary-dark); color: var(--primary-light); }
7587
7588 /* Issue tabs (open / closed) inside the git browser */
7589 .issue-tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-4); }
7590 .issue-tab {
7591 padding: 0.4rem 0.9rem;
7592 border: 1px solid var(--border);
7593 background: var(--surface-overlay);
7594 font-family: var(--font-mono);
7595 font-size: 0.85rem;
7596 color: var(--content);
7597 text-decoration: none;
7598 opacity: 0.7;
7599 }
7600 .issue-tab:hover { opacity: 1; }
7601 .issue-tab.is-selected {
7602 opacity: 1;
7603 background: color-mix(in oklch, var(--action) 8%, transparent);
7604 border-color: var(--focus-ring);
7605 }
7606 .page-info { opacity: 0.6; }
7607 .padded-page .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 1px solid var(--border); }
7608 .padded-page .page-header h1 { font-size: 1.5rem; text-align: center; position: absolute; left: 50%; transform: translateX(-50%); }
7609 .padded-page .page-header nav { margin: 0; }
7610 .padded-page .page-header .nav-links { gap: 1.5rem; }
7611 .discover-filter-toggle {
7612 display: none;
7613 font-family: var(--font-mono);
7614 font-size: 0.85rem;
7615 padding: 0.4rem 0.8rem;
7616 background: var(--surface-overlay);
7617 border: 1px solid var(--border);
7618 cursor: pointer;
7619 margin-bottom: 1rem;
7620 }
7621
7622 .discover-filter-toggle.active { background: var(--surface-sunken); border-color: var(--border-strong); }
7623
7624 .discover-filter-toggle .filter-count {
7625 background: var(--action);
7626 color: var(--primary-light);
7627 font-size: 0.75rem;
7628 padding: 0.1rem 0.4rem;
7629 border-radius: var(--radius-sm);
7630 margin-left: 0.25rem;
7631 }
7632
7633 @media (max-width: 900px) {
7634 .discover-filter-toggle { display: inline-block; }
7635 .discover-layout { grid-template-columns: 1fr; }
7636 .discover-sidebar { display: none; }
7637 /* Open state lives on the layout, not the sidebar: the sidebar is replaced
7638 by an out-of-band swap on every filter change and would lose the class. */
7639 .discover-layout.filters-open .discover-sidebar { display: block; margin-bottom: 1rem; }
7640 .table-header, .table-row { grid-template-columns: 40px 1fr 60px; }
7641 .table-row-item { grid-template-columns: 1fr 30px; }
7642 .table-row-item .table-row-link { grid-template-columns: 40px 1fr 60px; }
7643 .table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr 70px; }
7644 .row-date, .row-items, .row-category { display: none; }
7645 .table-header span:nth-child(3), .table-header span:nth-child(4), .table-header span:nth-child(5) { display: none; }
7646 .table-header.projects-header span:nth-child(3), .table-header.projects-header span:nth-child(4) { display: none; }
7647 }
7648
7649 @media (max-width: 480px) {
7650 .table-header, .table-row { grid-template-columns: 1fr 60px; }
7651 .table-row-item { grid-template-columns: 1fr 30px; }
7652 .table-row-item .table-row-link { grid-template-columns: 1fr 60px; }
7653 .row-type { display: none; }
7654 .table-header span:first-child { display: none; }
7655 .table-header.projects-header, .table-row.project-row { grid-template-columns: 1fr; }
7656 .table-header.projects-header span:nth-child(2) { display: none; }
7657 .row-price { font-size: 0.8rem; }
7658 .search-field { min-width: 0; width: 100%; }
7659 .table-controls { flex-wrap: wrap; }
7660 .mode-toggle { flex-wrap: wrap; }
7661 .table-footer { flex-direction: column; gap: 0.5rem; align-items: flex-start; }
7662 }
7663
7664 /* ── Feature Cards & Suggestion Input (shared by wizard + settings) ── */
7665
7666 .type-grid {
7667 display: grid;
7668 grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
7669 gap: 0.75rem;
7670 margin-bottom: 1rem;
7671 }
7672
7673 /* Canonical selectable-card primitive. One recipe; per-context size modifiers.
7674 Used by wizard type pickers, pricing-model pickers, content-choice pickers,
7675 monetization-mode pickers, anywhere a radio-like choice is rendered as a card. */
7676 .card--selectable,
7677 .type-card,
7678 .pricing-card,
7679 .content-choice-card {
7680 cursor: pointer;
7681 display: block;
7682 }
7683 .card--selectable input[type="radio"],
7684 .card--selectable input[type="checkbox"],
7685 .type-card input[type="radio"],
7686 .type-card input[type="checkbox"],
7687 .pricing-card input[type="radio"],
7688 .content-choice-card input[type="radio"] {
7689 position: absolute;
7690 opacity: 0;
7691 pointer-events: none;
7692 }
7693
7694 .card--selectable-inner,
7695 .type-card-inner,
7696 .pricing-card-inner {
7697 display: flex;
7698 flex-direction: column;
7699 align-items: center;
7700 justify-content: center;
7701 padding: 1rem 0.75rem;
7702 border: 2px solid var(--border);
7703 border-radius: var(--radius-md);
7704 background: var(--surface-page);
7705 text-align: center;
7706 transition: border-color 0.15s, background 0.15s;
7707 min-height: 60px;
7708 }
7709 /* Variant: column-aligned content (text-heavy pricing cards). */
7710 .pricing-card-inner,
7711 .card--selectable.is-text-heavy .card--selectable-inner {
7712 align-items: stretch;
7713 text-align: left;
7714 padding: 1.25rem;
7715 }
7716
7717 .card--selectable input:checked + .card--selectable-inner,
7718 .card--selectable.is-selected .card--selectable-inner,
7719 .type-card input:checked + .type-card-inner,
7720 .type-card.is-selected .type-card-inner,
7721 .pricing-card input:checked + .pricing-card-inner,
7722 .pricing-card.is-selected .pricing-card-inner,
7723 .content-choice-card.is-selected {
7724 border-color: var(--action);
7725 background: color-mix(in oklch, var(--action) 8%, transparent);
7726 }
7727
7728 .card--selectable:hover .card--selectable-inner,
7729 .type-card:hover .type-card-inner,
7730 .pricing-card:hover .pricing-card-inner,
7731 .content-choice-card:hover {
7732 background: var(--surface-sunken);
7733 }
7734
7735 .card--selectable-label,
7736 .type-card-label,
7737 .pricing-card-label {
7738 font-weight: bold;
7739 font-size: 0.9rem;
7740 }
7741
7742 .card--selectable-desc,
7743 .type-card-desc,
7744 .pricing-card-desc {
7745 font-size: 0.75rem;
7746 color: var(--content-muted);
7747 margin-top: 0.25rem;
7748 }
7749
7750 /* Anchor-styled selectable card (used when the card itself is an `<a>` link
7751 rather than a radio-wrapping label). */
7752 .content-choice-card {
7753 text-decoration: none;
7754 color: inherit;
7755 }
7756
7757 /* Disabled selectable card, visually dimmed, ignores pointer events. */
7758 .card--selectable.is-disabled,
7759 .content-choice-card.is-disabled {
7760 opacity: 0.7;
7761 pointer-events: none;
7762 }
7763
7764 .suggestion-input {
7765 position: relative;
7766 }
7767
7768 .suggestion-dropdown {
7769 display: none;
7770 position: absolute;
7771 top: 100%;
7772 left: 0;
7773 right: 0;
7774 background: var(--surface-page);
7775 border: 1px solid var(--border);
7776 border-top: none;
7777 border-radius: 0 0 var(--radius-md) var(--radius-md);
7778 max-height: 200px;
7779 overflow-y: auto;
7780 z-index: 10;
7781 box-shadow: var(--shadow-2);
7782 }
7783
7784 .suggestion-dropdown.open {
7785 display: block;
7786 }
7787
7788 .suggestion-item,
7789 .tag-suggest-item {
7790 padding: 0.5rem 0.75rem;
7791 cursor: pointer;
7792 font-size: 0.9rem;
7793 }
7794
7795 .suggestion-item:hover {
7796 background: var(--surface-overlay);
7797 }
7798
7799 .suggestion-create {
7800 font-style: italic;
7801 opacity: 0.8;
7802 border-top: 1px solid var(--border);
7803 }
7804
7805 /* ── Tips ── */
7806
7807 .tip-section {
7808 margin-top: 1rem;
7809 text-align: center;
7810 }
7811
7812 .tip-toggle {
7813 font-family: var(--font-mono);
7814 font-size: 0.85rem;
7815 padding: 0.5rem 1.5rem;
7816 background: none;
7817 border: 1px solid var(--content);
7818 color: var(--content);
7819 cursor: pointer;
7820 text-decoration: none;
7821 display: inline-block;
7822 }
7823
7824 .tip-toggle:hover {
7825 background: var(--content);
7826 color: var(--surface-page);
7827 }
7828
7829 .tip-form {
7830 margin-top: 1rem;
7831 display: flex;
7832 flex-direction: column;
7833 gap: 0.75rem;
7834 max-width: 300px;
7835 margin-left: auto;
7836 margin-right: auto;
7837 text-align: left;
7838 }
7839
7840 .tip-form.hidden {
7841 display: none;
7842 }
7843
7844 .tip-amount-row {
7845 display: flex;
7846 align-items: center;
7847 gap: 0.25rem;
7848 }
7849
7850 .tip-amount-row .pricing-currency {
7851 font-size: 1.2rem;
7852 opacity: 0.7;
7853 }
7854
7855 .tip-amount-input {
7856 width: 80px;
7857 font-size: 1.2rem;
7858 padding: 0.4rem 0.5rem;
7859 border: 1px solid var(--border);
7860 background: var(--surface-overlay);
7861 font-family: var(--font-mono);
7862 }
7863
7864 .tip-message-input {
7865 width: 100%;
7866 font-size: 0.85rem;
7867 padding: 0.5rem;
7868 border: 1px solid var(--border);
7869 background: var(--surface-overlay);
7870 font-family: var(--font-body);
7871 resize: vertical;
7872 }
7873
7874 .tip-submit {
7875 font-family: var(--font-mono);
7876 font-size: 0.85rem;
7877 padding: 0.5rem 1rem;
7878 background: var(--content);
7879 color: var(--surface-page);
7880 border: none;
7881 cursor: pointer;
7882 }
7883
7884 .tip-submit:hover {
7885 opacity: 0.85;
7886 }
7887
7888 /* ===========================================
7889 COLLECTION PICKER (shared dropdown)
7890 =========================================== */
7891
7892 .collection-picker-anchor { position: relative; }
7893 .collection-picker {
7894 position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
7895 background: var(--surface-page); border: 1px solid var(--border);
7896 box-shadow: 0 2px 8px rgba(0,0,0,0.12); min-width: 220px;
7897 }
7898 .collection-picker-list { max-height: 200px; overflow-y: auto; padding: 0.25rem 0; }
7899 .collection-picker-item {
7900 display: flex; align-items: center; gap: 0.5rem;
7901 padding: 0.4rem 0.75rem; cursor: pointer; font-size: 0.9rem;
7902 }
7903 .collection-picker-item:hover { background: var(--surface-sunken); }
7904 .collection-picker-loading,
7905 .collection-picker-create { border-top: 1px solid var(--border); padding: 0.5rem 0.75rem; }
7906 .collection-picker-create form { display: flex; gap: 0.5rem; }
7907 .collection-picker-create input { flex: 1; padding: 0.3rem 0.5rem; font-size: 0.85rem; min-width: 0; }
7908 .collection-picker-create button { font-size: 0.85rem; white-space: nowrap; }
7909
7910 /* Save button on discover cards */
7911 .row-save, .grid-card-save {
7912 background: none; border: none; cursor: pointer;
7913 font-size: 0.85rem; padding: 0.2rem 0.4rem; opacity: 0.4;
7914 color: var(--content); transition: opacity 0.15s;
7915 }
7916 .row-save:hover, .grid-card-save:hover { opacity: 1; }
7917 .grid-card-save {
7918 position: absolute; top: 0.4rem; right: 0.4rem; z-index: 2;
7919 background: var(--surface-page); border-radius: 3px; padding: 0.25rem 0.4rem;
7920 box-shadow: 0 1px 3px rgba(0,0,0,0.15); opacity: 0;
7921 }
7922 .grid-card:hover .grid-card-save { opacity: 0.7; }
7923 .grid-card-save:hover { opacity: 1; }
7924
7925 /* Item page save button saved state */
7926 button.saved { border-color: var(--action); color: var(--action); }
7927
7928 /* ===========================================
7929 SEARCH SUGGESTIONS
7930 =========================================== */
7931
7932 .search-wrapper { position: relative; flex: 1; min-width: 0; }
7933 .search-suggestions,
7934 .tag-suggest-list {
7935 display: none; position: absolute; left: 0; right: 0; top: 100%; z-index: 50;
7936 background: var(--surface-page); border: 1px solid var(--border); border-top: none;
7937 box-shadow: 0 4px 12px rgba(0,0,0,0.1); max-height: 280px; overflow-y: auto;
7938 }
7939 .suggestion-item {
7940 display: flex; justify-content: space-between; align-items: center;
7941 padding: 0.5rem 0.75rem; text-decoration: none; color: var(--content);
7942 font-size: 0.85rem; cursor: pointer;
7943 }
7944 .suggestion-item:hover, .suggestion-item.highlighted,
7945 .tag-suggest-item:hover, .tag-suggest-item.highlighted { background: var(--surface-sunken); }
7946 .suggestion-category { font-size: 0.75rem; opacity: 0.5; text-transform: uppercase; letter-spacing: 0.05em; }
7947
7948 /* ===========================================
7949 DOC UI EXAMPLES (embedded live UI in docs)
7950 =========================================== */
7951
7952 .doc-ui {
7953 margin: 1.5rem 0; border: 1px solid var(--border); border-radius: 4px; overflow: hidden;
7954 }
7955 .doc-ui-frame {
7956 padding: 1rem; background: var(--surface-overlay); pointer-events: none; user-select: none;
7957 }
7958 .doc-ui figcaption {
7959 padding: 0.5rem 1rem; font-size: 0.8rem; opacity: 0.6;
7960 border-top: 1px solid var(--border); background: var(--surface-overlay);
7961 font-family: var(--font-mono);
7962 }
7963 .doc-ui-missing {
7964 padding: 1rem; opacity: 0.4; font-style: italic;
7965 }
7966
7967 /* Library "New" badge for items with undownloaded versions */
7968 .badge-new {
7969 background: var(--action); color: var(--primary-light); font-size: 0.7rem;
7970 padding: 0.1rem 0.35rem; border-radius: var(--radius-sm); margin-left: 0.4rem;
7971 vertical-align: middle; font-weight: bold;
7972 }
7973
7974 /* ===========================================
7975 BENEFIT LIST (bulleted feature lists, e.g. Stripe Connect prompt)
7976 =========================================== */
7977 .benefit-list {
7978 list-style: none;
7979 padding: 0;
7980 margin: 0 auto var(--space-5);
7981 max-width: 280px;
7982 text-align: left;
7983 display: flex;
7984 flex-direction: column;
7985 gap: var(--space-2);
7986 }
7987 .benefit-list li {
7988 position: relative;
7989 padding-left: 1.1rem;
7990 font-size: 0.9rem;
7991 }
7992 .benefit-list li::before {
7993 content: "";
7994 position: absolute;
7995 left: 0.15rem;
7996 top: 0.55rem;
7997 width: 6px;
7998 height: 6px;
7999 border-radius: var(--radius-round);
8000 background: var(--success);
8001 }
8002
8003 /* ===========================================
8004 CHECKLIST (setup / onboarding step lists)
8005 =========================================== */
8006 .checklist {
8007 margin-bottom: var(--space-5);
8008 padding: var(--space-4) var(--space-5);
8009 background: var(--surface-overlay);
8010 border: 1px solid var(--border);
8011 }
8012 .checklist-header {
8013 display: flex;
8014 justify-content: space-between;
8015 align-items: center;
8016 margin-bottom: var(--space-3);
8017 }
8018 .checklist-title {
8019 margin: 0;
8020 font-family: var(--font-heading);
8021 font-weight: bold;
8022 }
8023 .checklist-mark {
8024 width: 1.1rem;
8025 height: 1.1rem;
8026 border-radius: var(--radius-round);
8027 border: 2px solid var(--border);
8028 flex-shrink: 0;
8029 box-sizing: border-box;
8030 }
8031 .checklist-mark--done {
8032 border-color: var(--success);
8033 background: var(--success);
8034 }
8035 .checklist-label {
8036 flex: 1;
8037 font-size: 0.9rem;
8038 }
8039 .checklist-label--done {
8040 opacity: 0.5;
8041 text-decoration: line-through;
8042 }
8043
8044 /* ===========================================
8045 PAYMENTS TAB (replaces inline styles in user_payments.html)
8046 =========================================== */
8047 /* Canonical "stack row", title-on-left + actions-on-right header bar.
8048 One primitive; per-context modifiers handle gap, wrap, alignment, margins.
8049 Aliases below cover existing per-tab class names (kept as JS hooks). */
8050 .stack-row,
8051 .content-header,
8052 .user-media-header,
8053 .transactions-header,
8054 .analytics-range-bar,
8055 .cart-multi-bar {
8056 display: flex;
8057 justify-content: space-between;
8058 align-items: center;
8059 flex-wrap: wrap;
8060 gap: var(--space-4);
8061 }
8062 .stack-row--tight { gap: var(--space-3); flex-wrap: nowrap; }
8063 .stack-row--top { align-items: flex-start; }
8064 .stack-row--bordered,
8065 .transactions-header {
8066 margin-bottom: var(--space-4);
8067 padding-bottom: var(--space-3);
8068 border-bottom: 1px solid var(--border);
8069 }
8070 .content-header,
8071 .user-media-header,
8072 .analytics-range-bar { margin-bottom: var(--space-4); }
8073 .cart-multi-bar {
8074 margin-bottom: var(--space-5);
8075 padding: 1rem 1.25rem;
8076 background: var(--surface-sunken);
8077 border: 1px solid var(--border);
8078 }
8079
8080 /* Canonical list row (flex, gap, padding, bottom border). Aliases below cover
8081 the per-tab variants. They exist as JS hooks but share the same look. */
8082 .list-row,
8083 .psection-row,
8084 .section-mgmt-row,
8085 .bundle-picker-row,
8086 .checklist-row {
8087 display: flex;
8088 align-items: center;
8089 gap: var(--space-3);
8090 padding: 0.6rem 0;
8091 border-bottom: 1px solid var(--border);
8092 }
8093 .list-row:last-child,
8094 .psection-row:last-child,
8095 .section-mgmt-row:last-child,
8096 .bundle-picker-row:last-child,
8097 .checklist-row:last-child { border-bottom: none; }
8098 .warn-glyph {
8099 font-size: 1.25rem;
8100 color: var(--warning);
8101 }
8102
8103 .card-h {
8104 margin: 0 0 var(--space-3) 0;
8105 font-size: 1rem;
8106 }
8107
8108 .amount-big {
8109 font-size: 1.25rem;
8110 font-weight: bold;
8111 }
8112
8113 .account-details {
8114 margin-top: var(--space-3);
8115 padding-top: var(--space-3);
8116 border-top: 1px solid var(--border);
8117 }
8118 .account-details summary { cursor: pointer; }
8119 .account-details-id {
8120 font-size: 0.8rem;
8121 opacity: 0.5;
8122 font-family: var(--font-mono);
8123 margin-top: var(--space-1);
8124 }
8125
8126 .stripe-actions {
8127 display: flex;
8128 gap: var(--space-4);
8129 flex-wrap: wrap;
8130 }
8131 .stripe-actions-disconnect { margin-left: auto; }
8132
8133 .payout-stats-grid {
8134 display: grid;
8135 grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
8136 gap: var(--space-4);
8137 margin-top: var(--space-4);
8138 padding-top: var(--space-4);
8139 border-top: 1px solid var(--border);
8140 }
8141
8142 .payouts-disabled-notice {
8143 margin-top: var(--space-4);
8144 padding: var(--space-3);
8145 background: var(--warning);
8146 color: var(--primary-light);
8147 font-size: 0.85rem;
8148 }
8149
8150 .fee-breakdown {
8151 display: grid;
8152 grid-template-columns: 1fr 1fr;
8153 gap: var(--space-2);
8154 font-size: 0.9rem;
8155 }
8156 .fee-row {
8157 display: flex;
8158 justify-content: space-between;
8159 padding: var(--space-2) 0;
8160 border-bottom: 1px solid var(--border);
8161 }
8162
8163 .checkbox-row {
8164 display: flex;
8165 align-items: flex-start;
8166 gap: var(--space-2);
8167 cursor: pointer;
8168 font-size: 0.9rem;
8169 }
8170 .check-inline {
8171 width: auto;
8172 margin-top: 0.2rem;
8173 }
8174
8175 .stripe-connect-prompt { text-align: center; padding: var(--space-5); }
8176 .stripe-logo { opacity: 0.8; }
8177 .stripe-connect-btn {
8178 background: var(--stripe);
8179 padding: var(--space-3) var(--space-6);
8180 }
8181
8182 .export-row {
8183 display: flex;
8184 justify-content: flex-end;
8185 margin-bottom: var(--space-3);
8186 }
8187
8188 .splits-grid {
8189 display: grid;
8190 grid-template-columns: 1fr 1fr;
8191 gap: var(--space-4);
8192 margin-bottom: var(--space-4);
8193 }
8194
8195 .tip-message {
8196 max-width: 300px;
8197 overflow: hidden;
8198 text-overflow: ellipsis;
8199 }
8200
8201 .transactions-title { font-size: 1.2rem; }
8202
8203 /* ===========================================
8204 CREATOR TAB (replaces inline styles in user_creator.html)
8205 =========================================== */
8206 .creator-tab-section {
8207 padding: var(--space-6);
8208 }
8209 .creator-tab-section--centered { text-align: center; }
8210 .creator-tab-section--no-top { padding-top: 0; }
8211
8212 .creator-h2 { font-size: 1.3rem; margin-bottom: var(--space-4); }
8213 .creator-h2--sm { font-size: 1.2rem; }
8214
8215 .creator-section-label {
8216 margin-left: var(--space-6);
8217 margin-right: var(--space-6);
8218 }
8219 .creator-form-section { padding: 0 var(--space-6); }
8220
8221 .creator-plan-box {
8222 background: var(--surface-overlay);
8223 padding: var(--space-4) var(--space-5);
8224 }
8225 .creator-plan-head {
8226 display: flex;
8227 align-items: center;
8228 gap: var(--space-3);
8229 margin-bottom: var(--space-2);
8230 flex-wrap: wrap;
8231 }
8232 .creator-plan-name {
8233 font-family: var(--font-heading);
8234 font-weight: bold;
8235 font-size: 1.1rem;
8236 }
8237
8238 .badge--founder-locked {
8239 background: var(--content);
8240 color: var(--surface-overlay);
8241 }
8242 .badge--founder-pending {
8243 background: var(--surface-sunken);
8244 }
8245
8246 .founder-callout {
8247 background: var(--surface-overlay);
8248 border-left: 3px solid var(--content);
8249 padding: 0.85rem 1rem;
8250 }
8251
8252 .creator-tier-grid {
8253 display: grid;
8254 grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
8255 gap: var(--space-4);
8256 }
8257 .creator-tier-card {
8258 background: var(--surface-overlay);
8259 padding: var(--space-4);
8260 text-align: center;
8261 }
8262 .creator-tier-name {
8263 font-family: var(--font-heading);
8264 font-weight: bold;
8265 font-size: 1rem;
8266 margin-bottom: var(--space-1);
8267 }
8268 .creator-tier-link {
8269 color: inherit;
8270 text-decoration: none;
8271 border-bottom: 1px solid var(--border);
8272 }
8273 .creator-tier-sub {
8274 font-size: 0.75rem;
8275 opacity: 0.7;
8276 }
8277 .creator-tier-storage { font-size: 0.75rem; }
8278 .creator-tier-buttons {
8279 display: flex;
8280 flex-direction: column;
8281 gap: 0.4rem;
8282 }
8283 .creator-tier-btn {
8284 font-size: 0.85rem;
8285 width: 100%;
8286 }
8287
8288 .strike-dim {
8289 opacity: 0.5;
8290 text-decoration: line-through;
8291 }
8292
8293 .storage-box {
8294 background: var(--surface-overlay);
8295 padding: var(--space-4) var(--space-5);
8296 }
8297 .storage-row {
8298 display: flex;
8299 justify-content: space-between;
8300 margin-bottom: var(--space-2);
8301 font-size: 0.9rem;
8302 }
8303 .storage-track {
8304 background: var(--border);
8305 height: 8px;
8306 width: 100%;
8307 overflow: hidden;
8308 }
8309 .storage-fill {
8310 background: var(--action);
8311 height: 100%;
8312 transition: width 0.3s;
8313 }
8314 .storage-fill--full { background: var(--danger); }
8315 .storage-breakdown {
8316 display: grid;
8317 grid-template-columns: 1fr 1fr;
8318 gap: var(--space-1) var(--space-5);
8319 margin-top: var(--space-3);
8320 font-size: 0.85rem;
8321 }
8322
8323 .broadcast-head {
8324 display: flex;
8325 justify-content: space-between;
8326 align-items: flex-start;
8327 }
8328 .broadcast-desc { flex: 1; }
8329 .broadcast-export { margin-left: var(--space-4); }
8330
8331 .creator-divider {
8332 margin: 0 var(--space-6);
8333 border-color: var(--border);
8334 }
8335
8336 .creator-intro { line-height: 1.6; }
8337 .creator-pitch-box {
8338 background: var(--surface-overlay);
8339 padding: var(--space-5);
8340 }
8341
8342 .mono-sm {
8343 font-family: var(--font-mono);
8344 font-size: 0.9rem;
8345 }
8346
8347 /* ===========================================
8348 PROJECT CONTENT TAB (replaces inline styles in project_content.html)
8349 =========================================== */
8350
8351 .empty-state--lg { padding: var(--space-6) var(--space-4); }
8352
8353 .content-filters {
8354 display: flex;
8355 gap: var(--space-3);
8356 margin-bottom: var(--space-4);
8357 align-items: center;
8358 flex-wrap: wrap;
8359 }
8360 .content-filter-search {
8361 flex: 1;
8362 min-width: 180px;
8363 padding: 0.4rem 0.6rem;
8364 font-size: 0.9rem;
8365 }
8366 .content-filter-select {
8367 padding: 0.4rem;
8368 font-size: 0.85rem;
8369 }
8370
8371 .bulk-action-bar {
8372 padding: var(--space-3) var(--space-4);
8373 margin-bottom: var(--space-4);
8374 background: var(--surface-raised);
8375 border: 1px solid var(--border);
8376 border-radius: var(--radius-md);
8377 display: flex;
8378 align-items: center;
8379 gap: var(--space-2);
8380 flex-wrap: wrap;
8381 opacity: 0.4;
8382 }
8383 .bulk-action-bar--active { opacity: 1; }
8384 .bulk-count { font-weight: bold; min-width: 5rem; }
8385 .bulk-deselect { margin-left: auto; }
8386 .danger-text { color: var(--danger); }
8387
8388 .bulk-form {
8389 margin-bottom: var(--space-4);
8390 padding: var(--space-3) var(--space-4);
8391 background: var(--surface-sunken);
8392 border: 1px solid var(--border);
8393 border-radius: var(--radius-md);
8394 }
8395 .bulk-form-row {
8396 display: flex;
8397 gap: var(--space-3);
8398 align-items: end;
8399 }
8400 .bulk-form-label {
8401 font-size: 0.85rem;
8402 display: block;
8403 margin-bottom: var(--space-1);
8404 }
8405
8406 /* Sortable table column header */
8407 .sortable-th { cursor: pointer; }
8408 .sort-arrow { opacity: 0.4; }
8409 .sort-arrow--active { opacity: 1; }
8410
8411 /* Data-table column-width utilities (numeric width hints,
8412 kept as classes to avoid inline `style="width: NN%"`) */
8413 .col-3 { width: 3%; }
8414 .col-5 { width: 5%; }
8415 .col-8 { width: 8%; }
8416 .col-10 { width: 10%; }
8417 .col-12 { width: 12%; }
8418 .col-15 { width: 15%; }
8419 .col-20 { width: 20%; }
8420 .col-32 { width: 32%; }
8421 .col-45 { width: 45%; }
8422
8423 /* Pixel-width utilities for inputs and narrow fixed-width controls.
8424 Use on form inputs that can't be sized by their parent column. */
8425 .w-80 { width: 80px; }
8426 .w-100 { width: 100px; }
8427 .w-120 { width: 120px; }
8428 .w-180 { width: 180px; }
8429 .w-220 { width: 220px; }
8430 .w-260 { width: 260px; }
8431 .w-full { width: 100%; }
8432 .maxw-320 { max-width: 320px; }
8433
8434 /* Canonical input shape modifiers. One base form-input look (defined globally
8435 at line ~365 input[type], textarea, select) plus these size + feature variants.
8436 Apply alongside the per-tab class which acts as a JS hook. */
8437 .input--xs {
8438 padding: 0.25rem 0.4rem;
8439 font-size: 0.85rem;
8440 }
8441 .input--sm {
8442 padding: 0.3rem 0.5rem;
8443 font-size: 0.85rem;
8444 }
8445 .input--mono { font-family: var(--font-mono); }
8446 .input--upper { text-transform: uppercase; }
8447 .input--numeric { text-align: right; }
8448
8449 .order-arrow-btn {
8450 padding: 0.1rem 0.3rem;
8451 font-size: 0.7rem;
8452 line-height: 1;
8453 }
8454
8455 .bundle-toggle {
8456 background: none;
8457 border: none;
8458 cursor: pointer;
8459 padding: 0 0.3rem 0 0;
8460 font-size: 0.8rem;
8461 color: var(--content-muted);
8462 }
8463 .bundle-child-cell { padding-left: 2.5rem; }
8464 .bundle-child-title { opacity: 0.85; }
8465 .bundle-child-arrow {
8466 color: var(--content-muted);
8467 margin-right: 0.3rem;
8468 }
8469
8470 .item-actions {
8471 display: flex;
8472 gap: var(--space-2);
8473 }
8474
8475 .badge--inline-tiny {
8476 font-size: 0.7rem;
8477 margin-left: 0.3rem;
8478 opacity: 0.7;
8479 }
8480
8481 .deleted-items-details { margin-top: var(--space-6); }
8482 .deleted-items-summary {
8483 cursor: pointer;
8484 font-size: 0.95rem;
8485 opacity: 0.7;
8486 }
8487
8488 .section-divider {
8489 margin: var(--space-6) 0;
8490 border: none;
8491 border-top: 1px solid var(--border);
8492 }
8493
8494 .inline-rename-input {
8495 font-weight: bold;
8496 width: 100%;
8497 padding: 0.2rem 0.4rem;
8498 font-size: inherit;
8499 }
8500
8501 /* ===========================================
8502 ITEM DETAILS TAB (replaces inline styles in item_details.html)
8503 =========================================== */
8504
8505 /* Compact button utility (small icon-side actions) */
8506 .btn-compact { padding: 0.4rem 0.8rem; }
8507
8508 .ml-2 { margin-left: var(--space-2); }
8509 .cursor-pointer { cursor: pointer; }
8510 .inline { display: inline; }
8511
8512 .tag-search-wrap { position: relative; }
8513 .tag-suggestions {
8514 position: absolute;
8515 z-index: 10;
8516 background: var(--surface-sunken);
8517 border: 1px solid var(--border);
8518 width: 100%;
8519 max-height: 200px;
8520 overflow-y: auto;
8521 }
8522
8523 .advanced-details { margin-top: var(--space-5); }
8524 .advanced-summary {
8525 cursor: pointer;
8526 font-size: 0.95rem;
8527 opacity: 0.8;
8528 }
8529
8530 /* Bundle table inside item-details */
8531 .bundle-table {
8532 width: 100%;
8533 border-collapse: collapse;
8534 }
8535 .bundle-table-head {
8536 text-align: left;
8537 font-size: 0.8rem;
8538 opacity: 0.7;
8539 text-transform: uppercase;
8540 letter-spacing: 0.03em;
8541 }
8542 .bundle-row { border-bottom: 1px solid var(--border); }
8543 .bundle-cell { padding: var(--space-2); }
8544 .bundle-cell--first { padding-left: 0; }
8545 .bundle-cell--actions { width: 60px; }
8546 .bundle-cell--desc { font-size: 0.85rem; opacity: 0.8; }
8547 .bundle-cell--file { font-size: 0.85rem; }
8548
8549 .bundle-remove-btn {
8550 padding: 0.2rem 0.5rem;
8551 font-size: 0.75rem;
8552 }
8553
8554 .bundle-add-row {
8555 margin-top: var(--space-4);
8556 display: flex;
8557 gap: var(--space-3);
8558 align-items: center;
8559 }
8560
8561 .bundle-existing-details { margin-top: var(--space-4); }
8562 .bundle-existing-summary {
8563 cursor: pointer;
8564 font-size: 0.85rem;
8565 opacity: 0.7;
8566 }
8567 .bundle-existing-row {
8568 margin-top: var(--space-2);
8569 display: flex;
8570 gap: var(--space-2);
8571 align-items: center;
8572 }
8573 .bundle-existing-select {
8574 flex: 1;
8575 padding: 0.4rem;
8576 }
8577
8578 .sections-intro {
8579 font-size: 0.85rem;
8580 opacity: 0.7;
8581 margin: var(--space-3) 0 var(--space-4);
8582 }
8583
8584 .section-mgmt-title {
8585 flex: 1;
8586 font-weight: bold;
8587 }
8588 .section-edit-btn,
8589 .section-del-btn {
8590 padding: 0.25rem 0.6rem;
8591 font-size: 0.8rem;
8592 }
8593
8594 .section-add-details { margin-top: var(--space-4); }
8595 .section-add-summary {
8596 cursor: pointer;
8597 font-size: 0.95rem;
8598 }
8599
8600 .insert-image-btn {
8601 margin-top: var(--space-2);
8602 font-size: 0.85rem;
8603 }
8604
8605 .section-edit-modal {
8606 margin-top: var(--space-4);
8607 padding: var(--space-4);
8608 background: var(--surface-sunken);
8609 }
8610 .section-edit-actions {
8611 display: flex;
8612 gap: var(--space-2);
8613 }
8614
8615 .publish-note {
8616 margin: var(--space-4) 0;
8617 opacity: 0.7;
8618 text-align: left;
8619 }
8620
8621 /* ===========================================
8622 CONTENT WIZARD STEP (replaces inline styles in wizards/steps/item/content.html)
8623 =========================================== */
8624
8625 /* (Wizard upload-status + slim progress moved into canonical .upload-status*
8626 / .progress-bar-container--slim primitives near top of file.) */
8627
8628 /* Bundle items picker, server-rendered rows and JS-appended rows share these. */
8629 .bundle-picker-row-title { flex: 1; }
8630 .bundle-picker-row-type { font-size: 0.8rem; opacity: 0.6; }
8631 .bundle-picker-row-unlisted {
8632 font-size: 0.8rem;
8633 display: flex;
8634 align-items: center;
8635 gap: 0.25rem;
8636 }
8637
8638 /* Batch upload queue table. */
8639 .batch-queue-table {
8640 width: 100%;
8641 border-collapse: collapse;
8642 }
8643 .batch-queue-table thead tr {
8644 border-bottom: 2px solid var(--border);
8645 text-align: left;
8646 }
8647 .batch-queue-table th,
8648 .batch-queue-table td {
8649 padding: 0.4rem 0.5rem;
8650 font-size: 0.85rem;
8651 }
8652 .batch-queue-table th:first-child,
8653 .batch-queue-table td:first-child { padding-left: 0; }
8654 .batch-queue-table th:last-child,
8655 .batch-queue-table td:last-child { padding-right: 0; text-align: right; }
8656 .batch-queue-table tbody tr { border-bottom: 1px solid var(--border); }
8657
8658 .batch-queue-name {
8659 max-width: 150px;
8660 overflow: hidden;
8661 text-overflow: ellipsis;
8662 white-space: nowrap;
8663 }
8664
8665 /* ===========================================
8666 ACCOUNT TAB (replaces inline styles in partials/tabs/user_account.html)
8667 =========================================== */
8668
8669 /* Canonical solid-tint callout (one of these in the codebase).
8670 Distinct from .alert (left-border) and .banner (full-bleed page notice).
8671 Variants:
8672 - .callout--danger (light bg, danger border, moderation, errors)
8673 - .callout--warning (light bg, warning border, DNS, email-not-verified)
8674 - .callout--solid-warning (full saturation warning bg, dark text, partial checkout) */
8675 .callout {
8676 padding: 0.75rem 1rem;
8677 margin-bottom: 1rem;
8678 font-size: 0.9rem;
8679 border: 1px solid;
8680 }
8681 .callout--danger {
8682 background: color-mix(in oklch, var(--danger) 10%, var(--surface-page));
8683 border-color: var(--danger);
8684 }
8685 .callout--warning {
8686 background: color-mix(in oklch, var(--warning) 14%, var(--surface-page));
8687 border-color: var(--warning);
8688 }
8689 .callout--solid-warning {
8690 background: var(--warning);
8691 color: var(--primary-dark);
8692 border-color: transparent;
8693 padding: 1rem 1.25rem;
8694 }
8695 .callout-title { text-transform: capitalize; }
8696 .callout-meta {
8697 opacity: 0.6;
8698 margin-left: 0.5rem;
8699 }
8700 .callout-body { margin: 0.5rem 0 0 0; }
8701 .callout-hint {
8702 font-size: 0.85rem;
8703 margin-top: 0.5rem;
8704 }
8705
8706 .account-mod-history { margin-top: 0.75rem; }
8707 .account-mod-history summary {
8708 cursor: pointer;
8709 font-size: 0.85rem;
8710 opacity: 0.7;
8711 }
8712 .account-mod-history-list { margin-top: 0.5rem; }
8713 .account-mod-history-item {
8714 padding: 0.5rem 0;
8715 border-bottom: 1px solid var(--border);
8716 font-size: 0.85rem;
8717 }
8718 .account-mod-history-reason {
8719 margin: 0.25rem 0 0 0;
8720 opacity: 0.8;
8721 }
8722
8723 .account-tip-card-title {
8724 font-weight: bold;
8725 margin-bottom: 0.5rem;
8726 }
8727 .account-tip-list {
8728 display: flex;
8729 flex-direction: column;
8730 gap: 0.25rem;
8731 opacity: 0.8;
8732 }
8733
8734 /* Resend-verification button needs left spacing from preceding strong. */
8735 .account-resend-btn { margin-left: 0.5rem; }
8736
8737 /* Cluster of small inline forms (manage-billing / cancel / resume). */
8738 .inline-form { display: inline; }
8739
8740 /* Notification preferences, bare fieldset + monospace legend. */
8741 .pref-fieldset {
8742 border: none;
8743 padding: 0;
8744 margin: 0 0 1.25rem 0;
8745 }
8746 .pref-fieldset--last { margin-bottom: 0.5rem; }
8747 .pref-legend {
8748 font-family: var(--font-mono);
8749 font-size: 0.85rem;
8750 font-weight: bold;
8751 margin-bottom: 0.5rem;
8752 }
8753
8754 /* ===========================================
8755 PROJECT CODE TAB (replaces inline styles in partials/tabs/project_code.html)
8756 =========================================== */
8757
8758 .proj-code-docs-link { margin-left: 1rem; }
8759
8760 .proj-code-linked-list { margin-bottom: var(--space-5); }
8761 .proj-code-linked-list > label { margin-bottom: var(--space-2); display: block; }
8762
8763 .proj-code-repo {
8764 margin-bottom: var(--space-4);
8765 padding: var(--space-3);
8766 background: var(--surface-overlay);
8767 }
8768 .proj-code-repo-row {
8769 display: flex;
8770 align-items: center;
8771 gap: var(--space-3);
8772 }
8773 .proj-code-repo-link { flex: 1; }
8774 .proj-code-repo .danger { padding: var(--space-1) var(--space-3); font-size: 0.85rem; }
8775
8776 .proj-code-collab-block {
8777 margin-top: var(--space-2);
8778 padding-top: var(--space-2);
8779 border-top: 1px solid var(--border);
8780 }
8781 .proj-code-collab-label { font-size: 0.85rem; margin-bottom: var(--space-1); display: block; }
8782 .proj-code-collab-row {
8783 display: flex;
8784 align-items: center;
8785 gap: var(--space-2);
8786 margin-bottom: var(--space-1);
8787 font-size: 0.9rem;
8788 }
8789 .proj-code-collab-name { flex: 1; }
8790 .proj-code-collab-readonly { opacity: 0.5; }
8791
8792 .proj-code-add-collab-row {
8793 display: flex;
8794 gap: var(--space-2);
8795 align-items: center;
8796 }
8797 .proj-code-add-collab-row .collab-username-input {
8798 flex: 1;
8799 font-size: 0.85rem;
8800 padding: 0.3rem var(--space-2);
8801 }
8802 .proj-code-add-collab-row .collab-add-btn { white-space: nowrap; }
8803
8804 .proj-code-link-row {
8805 display: flex;
8806 gap: var(--space-2);
8807 align-items: center;
8808 }
8809 .proj-code-link-row #link-repo-select { flex: 1; }
8810 .proj-code-link-row #link-repo-btn { white-space: nowrap; }
8811
8812 .proj-code-create-section {
8813 margin-top: var(--space-5);
8814 padding-top: var(--space-4);
8815 border-top: 1px solid var(--border);
8816 }
8817 .proj-code-create-section #create-repo-name { flex: 1; }
8818 .proj-code-create-section #create-repo-btn { white-space: nowrap; }
8819 .proj-code-create-status { margin-top: var(--space-1); }
8820 .proj-code-create-status.is-error { color: var(--danger); }
8821
8822 .proj-code-disabled {
8823 padding: var(--space-6);
8824 text-align: center;
8825 opacity: 0.7;
8826 }
8827
8828 /* ===========================================
8829 ADMIN REPORT ENTRIES (replaces inline styles in partials/admin_report_entries.html)
8830 =========================================== */
8831
8832 .admin-report-table {
8833 width: 100%;
8834 border-collapse: collapse;
8835 font-size: 0.85rem;
8836 }
8837 .admin-report-table thead tr {
8838 border-bottom: 2px solid var(--border);
8839 text-align: left;
8840 }
8841 .admin-report-table tbody tr {
8842 border-bottom: 1px solid var(--border);
8843 }
8844 .admin-report-table th,
8845 .admin-report-table td {
8846 padding: 0.5rem;
8847 }
8848 .admin-report-table td.admin-report-reason {
8849 max-width: 200px;
8850 overflow: hidden;
8851 text-overflow: ellipsis;
8852 white-space: nowrap;
8853 }
8854 .admin-report-table td.admin-report-date {
8855 white-space: nowrap;
8856 }
8857
8858 .admin-report-target-type {
8859 opacity: 0.5;
8860 font-size: 0.8rem;
8861 }
8862
8863 .admin-report-status-open {
8864 color: var(--action);
8865 font-weight: 600;
8866 }
8867 .admin-report-status-closed { opacity: 0.6; }
8868
8869 .admin-report-resolve-form {
8870 display: inline-flex;
8871 gap: 0.3rem;
8872 align-items: center;
8873 }
8874 .admin-report-resolve-form input[type="text"] {
8875 width: 120px;
8876 padding: 0.2rem 0.4rem;
8877 font-size: 0.8rem;
8878 }
8879 .admin-report-dismiss-form { display: inline; }
8880
8881 .admin-report-admin-notes {
8882 font-size: 0.8rem;
8883 opacity: 0.6;
8884 }
8885
8886 /* ===========================================
8887 PROJECT PROMOTIONS TAB (replaces inline styles in partials/tabs/project_promotions.html)
8888 =========================================== */
8889
8890 .proj-promo-form {
8891 margin-bottom: 2rem;
8892 }
8893
8894 .proj-promo-grid {
8895 display: grid;
8896 grid-template-columns: 1fr 1fr;
8897 gap: 0.75rem 1.5rem;
8898 max-width: 500px;
8899 }
8900
8901 .proj-promo-grid--spaced {
8902 margin-top: 0.75rem;
8903 }
8904
8905 .proj-promo-grid--bordered {
8906 margin-top: 0.75rem;
8907 padding-top: 0.75rem;
8908 border-top: 1px solid var(--border);
8909 }
8910
8911 .proj-promo-trial-fields {
8912 display: none;
8913 max-width: 500px;
8914 margin-top: 0.75rem;
8915 }
8916
8917 .proj-promo-trial-fields.is-visible {
8918 display: block;
8919 }
8920
8921 .proj-promo-grid.is-hidden,
8922 .proj-promo-trial-fields.is-hidden {
8923 display: none;
8924 }
8925
8926 .proj-promo-form .form-group {
8927 margin-bottom: 0;
8928 }
8929
8930 .proj-promo-form .form-group label {
8931 font-size: 0.85rem;
8932 }
8933
8934 .proj-promo-trial-group {
8935 max-width: 240px;
8936 }
8937
8938 .proj-promo-scope {
8939 grid-column: 1 / -1;
8940 }
8941
8942 .proj-promo-actions {
8943 margin-top: 1rem;
8944 }
8945
8946 .proj-promo-hint {
8947 margin-top: 0.5rem;
8948 }
8949
8950 /* ===========================================
8951 PROJECT OVERVIEW TAB (replaces inline styles in partials/tabs/project_overview.html)
8952 =========================================== */
8953
8954 .proj-overview-setup {
8955 margin-bottom: var(--space-4);
8956 padding: 1.25rem;
8957 background: var(--surface-overlay);
8958 border: 1px solid var(--border);
8959 }
8960 .proj-overview-setup-title {
8961 margin: 0 0 var(--space-3) 0;
8962 font-family: var(--font-heading);
8963 font-weight: bold;
8964 }
8965 .proj-overview-setup-row {
8966 display: flex;
8967 align-items: center;
8968 gap: var(--space-3);
8969 padding: var(--space-2) 0;
8970 border-bottom: 1px solid var(--border);
8971 }
8972 .proj-overview-setup-row:last-child { border-bottom: none; }
8973 .proj-overview-setup-check {
8974 color: var(--success);
8975 font-family: var(--font-mono);
8976 font-size: 0.75rem;
8977 text-transform: uppercase;
8978 letter-spacing: 0.04em;
8979 flex-shrink: 0;
8980 }
8981 .proj-overview-setup-bullet {
8982 width: 1.1rem;
8983 height: 1.1rem;
8984 border: 2px solid var(--border);
8985 border-radius: 50%;
8986 flex-shrink: 0;
8987 }
8988 .proj-overview-setup-label {
8989 flex: 1;
8990 font-size: 0.9rem;
8991 }
8992 .proj-overview-setup-label--done {
8993 opacity: 0.5;
8994 text-decoration: line-through;
8995 }
8996 .proj-overview-setup-btn {
8997 font-size: 0.8rem;
8998 padding: 0.25rem 0.6rem;
8999 }
9000
9001 .proj-overview-tools { margin-top: var(--space-6); }
9002 .proj-overview-tools-summary {
9003 cursor: pointer;
9004 font-size: 1rem;
9005 font-family: var(--font-heading);
9006 font-weight: bold;
9007 }
9008 .proj-overview-tools-grid {
9009 display: grid;
9010 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
9011 gap: var(--space-3);
9012 margin-top: var(--space-3);
9013 }
9014 .proj-overview-tool {
9015 background: var(--surface-sunken);
9016 padding: var(--space-3);
9017 }
9018 .proj-overview-tool-name {
9019 font-weight: bold;
9020 font-size: 0.95rem;
9021 margin-bottom: var(--space-1);
9022 }
9023 .proj-overview-tool-desc {
9024 font-size: 0.85rem;
9025 opacity: 0.7;
9026 margin: 0;
9027 }
9028
9029 /* ===========================================
9030 PROJECT SYNCKIT TAB (replaces inline styles in partials/tabs/project_synckit.html)
9031 =========================================== */
9032
9033 .proj-synckit-intro { margin-bottom: 0.75rem; }
9034 .proj-synckit-intro-secondary { margin-bottom: 1.5rem; }
9035 .proj-synckit-create { margin-bottom: 1.5rem; }
9036 .proj-synckit-create-body {
9037 padding: var(--space-3); background: var(--surface-overlay); border: 1px solid var(--border);
9038 }
9039 .proj-synckit-create-form {
9040 display: flex; flex-direction: row; gap: 0.75rem; align-items: flex-end;
9041 }
9042 .proj-synckit-label {
9043 display: block; font-size: 0.85rem; margin-bottom: var(--space-1);
9044 }
9045 .proj-synckit-code { font-size: 0.8rem; }
9046 .proj-synckit-code--wrap { font-size: 0.8rem; word-break: break-all; }
9047 .proj-synckit-code--selectable { font-size: 0.85rem; word-break: break-all; user-select: all; }
9048 .proj-synckit-btn-tight {
9049 margin-left: var(--space-2); padding: 0.15rem 0.4rem; font-size: 0.75rem;
9050 }
9051 .proj-synckit-btn-row {
9052 padding: 0.15rem 0.4rem; font-size: 0.75rem;
9053 }
9054 .proj-synckit-btn-row + .proj-synckit-btn-row { margin-left: var(--space-1); }
9055 .proj-synckit-hint-inline {
9056 font-size: 0.7rem; margin-left: var(--space-1);
9057 }
9058 .proj-synckit-hint-warn {
9059 font-size: 0.7rem; color: var(--danger);
9060 }
9061 .proj-synckit-status-active { color: var(--success); }
9062 .proj-synckit-status-inactive { color: var(--danger); }
9063 .proj-synckit-new-key {
9064 padding: 0.75rem; background: var(--surface-overlay);
9065 border: 1px solid var(--border); margin-top: var(--space-2);
9066 }
9067 .proj-synckit-new-key-heading {
9068 margin: 0 0 var(--space-2) 0; font-weight: 500; color: var(--danger);
9069 }
9070 .proj-synckit-create-status--error { color: var(--danger); margin-top: var(--space-2); }
9071 .proj-synckit-create-status--reset { margin-top: var(--space-2); }
9072
9073 /* ===========================================
9074 ITEM PAGE (replaces inline styles in pages/item.html)
9075 =========================================== */
9076
9077 .item-page .breadcrumb {
9078 display: flex;
9079 justify-content: space-between;
9080 align-items: center;
9081 }
9082
9083 .item-page .breadcrumb-edit-link {
9084 font-size: 0.85rem;
9085 color: var(--content);
9086 }
9087
9088 .item-page .video-player {
9089 width: 100%;
9090 max-height: 600px;
9091 background: var(--primary-dark);
9092 }
9093
9094 .item-page .item-cover-img {
9095 width: 100%;
9096 aspect-ratio: 1 / 1;
9097 object-fit: cover;
9098 display: block;
9099 }
9100
9101 .item-page .tag-link {
9102 text-decoration: none;
9103 color: inherit;
9104 }
9105
9106 .item-page .bundle-notice-inline {
9107 background: var(--surface-sunken);
9108 padding: 1.25rem;
9109 }
9110
9111 .item-page .bundle-notice-title {
9112 font-weight: bold;
9113 margin-bottom: 0.5rem;
9114 }
9115
9116 .item-page .bundle-notice-desc {
9117 opacity: 0.8;
9118 font-size: 0.9rem;
9119 }
9120
9121 .item-page .bundle-notice-entry {
9122 margin-top: 0.75rem;
9123 }
9124
9125 .item-page .bundle-notice-entry a {
9126 font-weight: bold;
9127 }
9128
9129 .item-page .bundle-notice-price {
9130 opacity: 0.7;
9131 }
9132
9133 .item-page .bundle-notice-empty {
9134 margin-top: 0.5rem;
9135 opacity: 0.7;
9136 font-size: 0.9rem;
9137 }
9138
9139 .item-page .promo-details {
9140 margin-bottom: 1rem;
9141 font-size: 0.9rem;
9142 }
9143
9144 .item-page .promo-summary {
9145 cursor: pointer;
9146 opacity: 0.7;
9147 }
9148
9149 .item-page .promo-form {
9150 display: flex;
9151 gap: 0.5rem;
9152 align-items: center;
9153 margin-top: 0.5rem;
9154 }
9155
9156 .item-page .promo-input {
9157 flex: 1;
9158 padding: 0.4rem 0.6rem;
9159 font-size: 0.85rem;
9160 }
9161
9162 .item-page .action-row {
9163 margin-top: 1rem;
9164 }
9165
9166 .item-page .action-row-tight {
9167 margin-top: 0.5rem;
9168 }
9169
9170 .item-page .full-width-btn {
9171 width: 100%;
9172 font-size: 0.9rem;
9173 }
9174
9175 .item-page .license-preset-name {
9176 margin-bottom: 0.75rem;
9177 }
9178
9179 .item-page .license-summary {
9180 cursor: pointer;
9181 opacity: 0.7;
9182 font-size: 0.9rem;
9183 }
9184
9185 .item-page .license-text {
9186 white-space: pre-wrap;
9187 font-family: var(--font-body);
9188 font-size: 0.85rem;
9189 margin-top: 0.75rem;
9190 padding: 1rem;
9191 background: var(--surface-sunken);
9192 }
9193
9194 .item-page .license-download {
9195 margin-top: 0.75rem;
9196 }
9197
9198 .item-page .license-download a {
9199 font-size: 0.9rem;
9200 color: var(--content);
9201 }
9202
9203 .item-page .bundle-list-entry {
9204 margin-top: 0.5rem;
9205 }
9206
9207 .item-page .footer-links {
9208 margin-top: 0.5rem;
9209 }
9210
9211 /* ===========================================
9212 JOIN COMPLETE STEP (replaces inline styles in wizards/steps/join/complete.html)
9213 =========================================== */
9214 .join-complete-intro { margin-bottom: var(--space-5); }
9215 .join-complete-choices {
9216 display: grid; grid-template-columns: 1fr 1fr;
9217 gap: var(--space-4); max-width: 500px;
9218 }
9219 .join-complete-choice { text-decoration: none; color: inherit; display: block; }
9220 .join-complete-card {
9221 background: var(--surface-sunken); padding: var(--space-4); text-align: center;
9222 border: 2px solid transparent; transition: border-color 0.15s;
9223 }
9224 .join-complete-choice:hover .join-complete-card,
9225 .join-complete-card--active { border-color: var(--content); }
9226 .join-complete-card-title {
9227 font-family: var(--font-heading); font-weight: bold;
9228 font-size: 1.1rem; margin-bottom: var(--space-2);
9229 }
9230 .join-complete-card-desc {
9231 font-size: 0.85rem; opacity: 0.7; margin: 0;
9232 }
9233 .join-complete-footnote {
9234 font-size: 0.85rem; opacity: 0.5;
9235 margin-top: var(--space-4); text-align: center;
9236 }
9237
9238 /* ===========================================
9239 PROMO CODES LIST (replaces inline styles in partials/promo_codes_list.html)
9240 =========================================== */
9241 .promo-codes-row--expired { opacity: 0.5; }
9242 .promo-codes-row--pending { opacity: 0.7; }
9243 .promo-codes-schedule { font-size: 0.85rem; }
9244 .promo-codes-schedule-pending { color: var(--warning); }
9245 .promo-codes-schedule-expired { color: var(--danger); }
9246 .promo-codes-schedule-none { opacity: 0.5; }
9247 .promo-codes-actions { white-space: nowrap; }
9248 .promo-codes-edit-btn { font-size: 0.8rem; }
9249 .promo-codes-edit-row { background: var(--surface-sunken); }
9250 .promo-codes-edit-cell { padding: var(--space-3); }
9251 .promo-codes-edit-form {
9252 display: flex; gap: var(--space-3); align-items: end; flex-wrap: wrap;
9253 }
9254 .promo-codes-edit-label {
9255 font-size: 0.8rem; display: block; margin-bottom: var(--space-1);
9256 }
9257 .promo-codes-edit-save { font-size: 0.85rem; }
9258 .promo-codes-bulk-row { margin-top: var(--space-3); }
9259 .promo-codes-bulk-btn { font-size: 0.85rem; opacity: 0.7; }
9260
9261 /* ===========================================
9262 USER MEDIA TAB (replaces inline styles in partials/tabs/user_media.html)
9263 =========================================== */
9264
9265 .user-media-intro {
9266 margin-bottom: 1rem;
9267 }
9268
9269 .user-media-upload {
9270 border: 2px dashed var(--border);
9271 padding: 1.5rem;
9272 margin-bottom: 1.5rem;
9273 text-align: center;
9274 background: var(--surface-overlay);
9275 }
9276
9277 .user-media-upload--dragover {
9278 border-color: var(--action);
9279 }
9280
9281 .user-media-upload-row {
9282 margin-bottom: 0.75rem;
9283 }
9284
9285 .user-media-upload-label {
9286 display: inline-block;
9287 font-size: 0.85rem;
9288 margin-right: 0.75rem;
9289 }
9290
9291 .user-media-upload-folder-input {
9292 padding: 0.3rem;
9293 font-size: 0.85rem;
9294 width: 140px;
9295 margin-left: 0.25rem;
9296 }
9297
9298 .user-media-upload-progress {
9299 margin-top: 0.75rem;
9300 }
9301
9302 .user-media-upload-status {
9303 font-size: 0.85rem;
9304 margin-bottom: 0.25rem;
9305 }
9306
9307 .user-media-upload-status--ok {
9308 color: var(--success);
9309 }
9310
9311 .user-media-upload-status--err {
9312 color: var(--danger);
9313 }
9314
9315 .user-media-folders {
9316 margin-bottom: 1rem;
9317 display: flex;
9318 gap: 0.5rem;
9319 flex-wrap: wrap;
9320 align-items: center;
9321 }
9322
9323 .user-media-folders-label {
9324 font-size: 0.85rem;
9325 opacity: 0.7;
9326 }
9327
9328 .user-media-folders-btn {
9329 font-size: 0.8rem;
9330 }
9331
9332 .user-media-grid {
9333 display: grid;
9334 grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
9335 gap: 1rem;
9336 }
9337
9338 .user-media-card {
9339 background: var(--surface-overlay);
9340 border: 1px solid var(--border);
9341 padding: 0.75rem;
9342 position: relative;
9343 }
9344
9345 .user-media-card-thumb {
9346 width: 100%;
9347 height: 120px;
9348 overflow: hidden;
9349 margin-bottom: 0.5rem;
9350 display: flex;
9351 align-items: center;
9352 justify-content: center;
9353 background: var(--surface-sunken);
9354 }
9355
9356 .user-media-card-thumb--video {
9357 font-size: 2rem;
9358 opacity: 0.4;
9359 }
9360
9361 .user-media-card-img {
9362 max-width: 100%;
9363 max-height: 120px;
9364 object-fit: contain;
9365 }
9366
9367 .user-media-card-name {
9368 font-size: 0.8rem;
9369 word-break: break-all;
9370 margin-bottom: 0.25rem;
9371 }
9372
9373 .user-media-card-meta {
9374 font-size: 0.75rem;
9375 opacity: 0.6;
9376 margin-bottom: 0.5rem;
9377 }
9378
9379 .user-media-card-actions {
9380 display: flex;
9381 gap: 0.25rem;
9382 }
9383
9384 .user-media-card-btn {
9385 font-size: 0.7rem;
9386 padding: 0.15rem 0.4rem;
9387 }
9388
9389 /* ===========================================
9390 ITEM VERSION UPLOAD (replaces inline styles in partials/item_version_upload.html)
9391 =========================================== */
9392
9393 .item-version-upload-cell-sm {
9394 font-size: 0.85rem;
9395 }
9396
9397 .item-version-upload-no-file {
9398 opacity: 0.5;
9399 }
9400
9401 .item-version-upload-btn {
9402 padding: 0.4rem 0.8rem;
9403 font-size: 0.85rem;
9404 }
9405
9406 .item-version-upload-add-btn {
9407 padding: 0.4rem 0.8rem;
9408 }
9409
9410 .item-version-upload-grid {
9411 display: grid;
9412 grid-template-columns: 1fr 1fr;
9413 gap: var(--space-3);
9414 }
9415
9416 .item-version-upload-hint {
9417 margin-bottom: var(--space-2);
9418 }
9419
9420 .item-version-upload-file-table {
9421 width: 100%;
9422 border-collapse: collapse;
9423 }
9424
9425 .item-version-upload-file-table thead tr {
9426 text-align: left;
9427 font-size: 0.8rem;
9428 opacity: 0.7;
9429 text-transform: uppercase;
9430 letter-spacing: 0.03em;
9431 }
9432
9433 .item-version-upload-file-table th:first-child {
9434 padding: 0.4rem 0.5rem 0.4rem 0;
9435 }
9436
9437 .item-version-upload-file-table th + th {
9438 padding: 0.4rem 0.5rem;
9439 }
9440
9441 .item-version-upload-file-table th:last-child {
9442 width: 40px;
9443 }
9444
9445 .item-version-upload-add-row {
9446 margin-top: var(--space-2);
9447 }
9448
9449 .item-version-upload-queue {
9450 margin-bottom: 0.75rem;
9451 }
9452
9453 .item-version-upload-speed {
9454 font-size: 0.8rem;
9455 opacity: 0.6;
9456 margin-top: 0.25rem;
9457 }
9458
9459 /* ===========================================
9460 PROJECT PAGE (replaces inline styles in pages/project.html)
9461 =========================================== */
9462
9463 .project-page .store-cover {
9464 width: 120px;
9465 height: 120px;
9466 border-radius: 8px;
9467 object-fit: cover;
9468 margin-bottom: var(--space-5);
9469 }
9470 .project-page .store-actions .secondary {
9471 display: inline-block;
9472 padding: 0.5rem 1rem;
9473 text-decoration: none;
9474 }
9475 .project-page .follow-btn.is-selected {
9476 opacity: 0.7;
9477 }
9478 .project-page .follower-count-muted {
9479 font-size: 0.85rem;
9480 opacity: 0.7;
9481 padding: 0.5rem 0;
9482 }
9483 .project-page .item-tags .tag {
9484 text-decoration: none;
9485 color: inherit;
9486 }
9487 .project-page .promo-details {
9488 font-size: 0.85rem;
9489 margin-bottom: var(--space-2);
9490 }
9491 .project-page .promo-details summary {
9492 cursor: pointer;
9493 opacity: 0.7;
9494 }
9495 .project-page .promo-input {
9496 width: 100%;
9497 margin-top: 0.4rem;
9498 padding: 0.3rem 0.5rem;
9499 font-size: 0.85rem;
9500 text-transform: uppercase;
9501 }
9502 .project-page .store-footer-links {
9503 margin-top: var(--space-2);
9504 }
9505
9506 /* ===========================================
9507 INSERTION LIST (replaces inline styles in partials/insertion_list.html)
9508 =========================================== */
9509
9510 .insertion-list-heading {
9511 font-family: var(--font-mono);
9512 font-size: 1rem;
9513 margin-bottom: var(--space-4);
9514 }
9515 .insertion-list-toolbar {
9516 margin-bottom: var(--space-4);
9517 }
9518 .insertion-list-upload {
9519 font-family: var(--font-mono);
9520 }
9521 .insertion-list-table {
9522 width: 100%;
9523 font-family: var(--font-body);
9524 }
9525 .insertion-list-table th {
9526 text-align: left;
9527 font-family: var(--font-mono);
9528 font-size: 0.875rem;
9529 }
9530 .insertion-list-table th.insertion-list-th-actions {
9531 text-align: right;
9532 }
9533 .insertion-list-table .insertion-list-actions {
9534 text-align: right;
9535 }
9536 .insertion-list-table .insertion-list-action-btn {
9537 font-family: var(--font-mono);
9538 }
9539
9540 /* ===========================================
9541 PROJECT MEMBERS TAB (replaces inline styles in partials/tabs/project_members.html)
9542 =========================================== */
9543
9544 .proj-members-summary {
9545 background: var(--surface-sunken);
9546 padding: 1.25rem;
9547 margin-bottom: var(--space-4);
9548 }
9549
9550 .proj-members-summary-row {
9551 display: flex;
9552 justify-content: space-between;
9553 align-items: center;
9554 }
9555
9556 .proj-members-stat {
9557 font-size: 1.5rem;
9558 font-weight: bold;
9559 }
9560
9561 .proj-members-add {
9562 margin-bottom: var(--space-6);
9563 }
9564
9565 .proj-members-add-grid {
9566 display: grid;
9567 grid-template-columns: 1fr auto auto;
9568 gap: var(--space-3);
9569 align-items: end;
9570 }
9571
9572 .proj-members-field-label {
9573 font-size: 0.85rem;
9574 display: block;
9575 margin-bottom: var(--space-1);
9576 }
9577
9578 .proj-members-field-label--spaced {
9579 margin-top: 0.75rem;
9580 }
9581
9582 .proj-members-add-result {
9583 margin-top: var(--space-2);
9584 }
9585
9586 .proj-members-name-link {
9587 color: inherit;
9588 }
9589
9590 .proj-members-split-cell {
9591 font-weight: bold;
9592 }
9593
9594 /* ===========================================
9595 PLACEMENT LIST (replaces inline styles in partials/placement_list.html)
9596 =========================================== */
9597
9598 .placement-list-heading {
9599 font-family: var(--font-mono);
9600 font-size: 1rem;
9601 margin-bottom: var(--space-3);
9602 }
9603 .placement-list-table {
9604 width: 100%;
9605 font-family: var(--font-body);
9606 margin-bottom: var(--space-4);
9607 }
9608 .placement-list-table th {
9609 text-align: left;
9610 font-family: var(--font-mono);
9611 font-size: 0.875rem;
9612 }
9613 .placement-list-table th.placement-list-th-actions {
9614 text-align: right;
9615 }
9616 .placement-list-table .placement-list-actions {
9617 text-align: right;
9618 }
9619 .placement-list-table .placement-list-remove {
9620 font-family: var(--font-mono);
9621 }
9622 .placement-list-form {
9623 display: flex;
9624 gap: var(--space-2);
9625 align-items: flex-end;
9626 flex-wrap: wrap;
9627 }
9628 .placement-list-label {
9629 display: block;
9630 font-family: var(--font-mono);
9631 font-size: 0.8125rem;
9632 margin-bottom: var(--space-1);
9633 }
9634 .placement-list-add {
9635 font-family: var(--font-mono);
9636 }
9637
9638 /* ===========================================
9639 USER SYNCKIT TAB (replaces inline styles in partials/tabs/user_synckit.html)
9640 =========================================== */
9641
9642 .user-synckit-create { margin-bottom: var(--space-5); }
9643 .user-synckit-create-body {
9644 padding: var(--space-4);
9645 background: var(--surface-overlay);
9646 border: 1px solid var(--border);
9647 }
9648 .user-synckit-create-form {
9649 display: flex;
9650 flex-direction: row;
9651 gap: var(--space-3);
9652 align-items: flex-end;
9653 }
9654 .user-synckit-create-form label {
9655 display: block;
9656 font-size: 0.85rem;
9657 margin-bottom: var(--space-1);
9658 }
9659 .user-synckit-create-form input[type="text"],
9660 .user-synckit-create-form select {
9661 padding: var(--space-2);
9662 font-size: 0.9rem;
9663 }
9664 .user-synckit-create-form input[type="text"] { width: 220px; }
9665 .user-synckit-create-form select { width: 180px; }
9666
9667 .user-synckit-code { font-size: 0.8rem; }
9668 .user-synckit-hint {
9669 font-size: 0.7rem;
9670 margin-left: var(--space-1);
9671 }
9672
9673 .user-synckit-inline-btn {
9674 margin-left: var(--space-2);
9675 padding: 0.15rem 0.4rem;
9676 font-size: 0.75rem;
9677 }
9678 .user-synckit-row-btn {
9679 padding: 0.15rem 0.4rem;
9680 font-size: 0.75rem;
9681 }
9682 .user-synckit-row-btn + .user-synckit-row-btn {
9683 margin-left: var(--space-1);
9684 }
9685
9686 .user-synckit-status-active { color: var(--success); }
9687 .user-synckit-status-inactive { color: var(--danger); }
9688
9689 .user-synckit-edit-btn {
9690 padding: 0.15rem 0.4rem;
9691 font-size: 0.75rem;
9692 }
9693
9694 .user-synckit-create-error {
9695 color: var(--danger);
9696 margin-top: var(--space-2);
9697 }
9698
9699 /* ===========================================
9700 TOTP (replaces inline styles in partials/totp_setup.html and totp_status.html)
9701 =========================================== */
9702
9703 /* Section wrapper between TOTP subsections (QR + backup codes + confirm,
9704 or regenerate + disable). */
9705 .totp-section { margin-bottom: var(--space-5); }
9706
9707 /* Confirm-setup section is separated from the backup codes by a top border. */
9708 .totp-confirm {
9709 border-top: 1px solid var(--border);
9710 padding-top: var(--space-4);
9711 }
9712
9713 /* QR code container, centered above the manual-entry details. */
9714 .totp-qr {
9715 text-align: center;
9716 margin-bottom: var(--space-4);
9717 }
9718 .totp-qr img {
9719 max-width: 200px;
9720 image-rendering: pixelated;
9721 }
9722
9723 /* Collapsible "Manual entry key" group. */
9724 .totp-manual { margin-bottom: var(--space-4); }
9725 .totp-manual summary {
9726 cursor: pointer;
9727 opacity: 0.7;
9728 font-size: 0.85rem;
9729 }
9730 .totp-manual-secret {
9731 display: block;
9732 margin-top: var(--space-2);
9733 word-break: break-all;
9734 font-size: 0.85rem;
9735 padding: var(--space-2);
9736 background: var(--surface-sunken);
9737 }
9738
9739 /* Backup codes grid (rendered list of one-time codes). */
9740 .backup-codes-grid {
9741 display: grid;
9742 grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
9743 gap: var(--space-2);
9744 }
9745 .backup-codes-grid code {
9746 padding: var(--space-2);
9747 background: var(--surface-sunken);
9748 text-align: center;
9749 font-size: 0.9rem;
9750 }
9751
9752 /* Status row for the "Enabled" badge above the management forms. */
9753 .totp-status-row {
9754 display: flex;
9755 align-items: center;
9756 gap: var(--space-2);
9757 margin-bottom: var(--space-4);
9758 }
9759
9760 /* Container where regenerated backup codes are swapped in via HTMX. */
9761 .totp-regen-output { margin-top: var(--space-3); }
9762
9763 /* ===========================================
9764 DASHBOARD-USER SHELL (replaces inline styles in dashboards/dashboard-user.html)
9765 =========================================== */
9766
9767 .sandbox-banner {
9768 background: var(--action);
9769 color: var(--primary-light);
9770 padding: 0.75rem 1.5rem;
9771 text-align: center;
9772 font-family: var(--font-mono);
9773 font-size: 0.9rem;
9774 }
9775
9776 .sandbox-banner-link {
9777 color: var(--primary-light);
9778 text-decoration: underline;
9779 margin-left: 0.5rem;
9780 }
9781 .account-status-actions {
9782 display: flex;
9783 gap: 0.75rem;
9784 flex-wrap: wrap;
9785 margin-top: 1rem;
9786 }
9787
9788 .suspension-wrap {
9789 margin-bottom: 1rem;
9790 }
9791
9792 .password-warning-banner {
9793 margin-bottom: 1rem;
9794 padding: 1rem;
9795 background: color-mix(in oklch, var(--warning) 14%, var(--surface-page));
9796 border: 1px solid var(--warning);
9797 font-size: 0.95rem;
9798 }
9799
9800 .dash-user-header-links {
9801 margin-bottom: 0.5rem;
9802 display: flex;
9803 gap: 1.5rem;
9804 }
9805
9806 .dash-user-header-link {
9807 font-size: 0.9rem;
9808 opacity: 0.7;
9809 }
9810
9811 .checklist-recovery {
9812 padding: 0.75rem 0;
9813 text-align: right;
9814 }
9815
9816 .checklist-recovery-link {
9817 font-size: 0.85rem;
9818 opacity: 0.7;
9819 }
9820
9821 .tab-spinner {
9822 margin-left: 1rem;
9823 }
9824
9825 /* ===========================================
9826 USER PROFILE PAGE (replaces inline styles in pages/user.html)
9827 =========================================== */
9828
9829 .user-page .creator-paused-notice {
9830 margin-bottom: 1.5rem;
9831 padding: 1rem;
9832 background: var(--surface-sunken);
9833 border: 1px solid var(--border);
9834 text-align: center;
9835 font-size: 0.95rem;
9836 }
9837
9838 .user-page .profile-action-row {
9839 margin-top: 1rem;
9840 }
9841
9842 .user-page .profile-edit-btn {
9843 display: inline-block;
9844 padding: 0.5rem 1rem;
9845 text-decoration: none;
9846 font-size: 0.9rem;
9847 }
9848
9849 .user-page .follow-btn.is-selected {
9850 opacity: 0.7;
9851 }
9852
9853 .user-page .follower-count {
9854 margin-top: 1rem;
9855 font-size: 0.85rem;
9856 opacity: 0.7;
9857 }
9858
9859 .user-page .profile-share-row {
9860 margin-top: 0.75rem;
9861 display: flex;
9862 gap: 1rem;
9863 justify-content: center;
9864 font-size: 0.9rem;
9865 }
9866
9867 .user-page .profile-share-link {
9868 opacity: 0.7;
9869 }
9870
9871 .user-page .collections-section {
9872 margin-bottom: 2rem;
9873 }
9874
9875 /* ===========================================
9876 SUSPENSION BANNER (replaces inline styles in partials/suspension_banner.html)
9877 =========================================== */
9878
9879 .suspension-banner {
9880 background: color-mix(in oklch, var(--danger) 10%, var(--surface-page));
9881 border: 1px solid var(--danger);
9882 padding: var(--space-5);
9883 margin-bottom: var(--space-5);
9884 }
9885
9886 .suspension-banner-title {
9887 margin: 0 0 var(--space-2) 0;
9888 color: var(--danger);
9889 }
9890
9891 .suspension-banner-reason {
9892 font-size: 0.9rem;
9893 margin: 0 0 var(--space-3) 0;
9894 }
9895
9896 .suspension-banner-denial {
9897 background: var(--surface-overlay);
9898 padding: var(--space-3);
9899 margin-bottom: var(--space-3);
9900 font-size: 0.9rem;
9901 }
9902
9903 .suspension-banner-denial-response {
9904 margin: var(--space-1) 0 0 0;
9905 }
9906
9907 .suspension-banner-denial-hint {
9908 margin: var(--space-2) 0 0 0;
9909 opacity: 0.7;
9910 }
9911
9912 .suspension-banner-pending {
9913 font-size: 0.9rem;
9914 opacity: 0.7;
9915 margin: 0;
9916 }
9917
9918 .suspension-banner-appeal {
9919 margin-top: var(--space-2);
9920 }
9921
9922 .suspension-banner-appeal-summary {
9923 cursor: pointer;
9924 font-size: 0.9rem;
9925 }
9926
9927 .suspension-banner-appeal-form {
9928 margin-top: var(--space-3);
9929 }
9930
9931 .suspension-banner-appeal-text {
9932 width: 100%;
9933 margin-bottom: var(--space-2);
9934 font-size: 0.9rem;
9935 }
9936
9937 .suspension-banner-appeal-submit {
9938 font-size: 0.85rem;
9939 }
9940
9941 .suspension-banner-export {
9942 margin-top: var(--space-3);
9943 }
9944
9945 .suspension-banner-export-link {
9946 font-size: 0.9rem;
9947 }
9948
9949 /* ===========================================
9950 REPORT MODAL (replaces inline styles in partials/report_modal.html)
9951 =========================================== */
9952
9953 .report-modal-content {
9954 background: var(--surface-page);
9955 padding: var(--space-6);
9956 width: 90%;
9957 max-width: 480px;
9958 max-height: 90vh;
9959 overflow-y: auto;
9960 }
9961
9962 .report-modal-title {
9963 font-size: 1.2rem;
9964 margin: 0;
9965 }
9966
9967 .report-modal-fieldset {
9968 border: none;
9969 padding: 0;
9970 margin: 0 0 var(--space-4) 0;
9971 }
9972
9973 .report-modal-legend {
9974 font-size: 0.9rem;
9975 font-weight: 600;
9976 margin-bottom: var(--space-2);
9977 }
9978
9979 .report-modal-option {
9980 display: block;
9981 margin-bottom: 0.4rem;
9982 cursor: pointer;
9983 }
9984
9985 .report-modal-details {
9986 margin-bottom: var(--space-4);
9987 }
9988
9989 .report-modal-details-label {
9990 display: block;
9991 font-size: 0.85rem;
9992 margin-bottom: var(--space-1);
9993 }
9994
9995 .report-modal-textarea {
9996 width: 100%;
9997 font-size: 0.85rem;
9998 }
9999
10000 .report-modal-actions {
10001 display: flex;
10002 gap: var(--space-2);
10003 justify-content: flex-end;
10004 }
10005
10006 /* ===========================================
10007 LIBRARY COLLECTIONS TAB (partials/tabs/library_collections.html)
10008 =========================================== */
10009
10010 .badge.is-faded { opacity: 0.5; }
10011 .lib-coll-new { margin-top: var(--space-5); }
10012 .lib-coll-new-summary { cursor: pointer; font-weight: bold; }
10013 .lib-coll-new-form { margin-top: var(--space-4); }
10014 .lib-coll-wishlist-heading {
10015 font-size: 1.1rem;
10016 margin-top: 2.5rem;
10017 margin-bottom: var(--space-4);
10018 opacity: 0.8;
10019 }
10020 .lib-coll-wishlist-wrap {
10021 overflow-x: auto;
10022 -webkit-overflow-scrolling: touch;
10023 }
10024 .lib-coll-wishlist-table { min-width: 500px; }
10025 .lib-coll-row-actions { white-space: nowrap; }
10026 .lib-coll-row-actions .lib-coll-cart-btn { margin-right: 0.25rem; }
10027
10028 /* ===========================================
10029 USER ANALYTICS TAB (partials/tabs/user_analytics.html)
10030 =========================================== */
10031
10032 .analytics-export-link { margin-left: var(--space-4); }
10033 .analytics-range-heading {
10034 font-size: 1.1rem;
10035 margin: 0;
10036 }
10037 .analytics-section--comparison { margin-bottom: 2rem; }
10038 .analytics-section--comparison h2 { margin-bottom: var(--space-4); }
10039 .analytics-table-wrap {
10040 overflow-x: auto;
10041 -webkit-overflow-scrolling: touch;
10042 }
10043 .analytics-table { min-width: 500px; }
10044 .analytics-revenue-cell {
10045 display: flex;
10046 align-items: center;
10047 gap: var(--space-2);
10048 }
10049 .analytics-revenue-bar {
10050 height: 10px;
10051 min-width: 2px;
10052 max-width: 80px;
10053 background: var(--action);
10054 }
10055
10056 /* ===========================================
10057 ITEM EMBED TAB (templates/partials/tabs/item_embed.html)
10058 =========================================== */
10059 .embed-intro {
10060 opacity: 0.7;
10061 font-size: 0.9rem;
10062 margin-bottom: var(--space-5);
10063 }
10064 .embed-option {
10065 margin-bottom: var(--space-5);
10066 padding: var(--space-4);
10067 border: 1px solid var(--border);
10068 border-radius: 6px;
10069 }
10070 .embed-option h4 {
10071 margin-bottom: 0.25rem;
10072 font-size: 0.95rem;
10073 }
10074 .embed-option-desc {
10075 font-size: 0.85rem;
10076 opacity: 0.7;
10077 margin-bottom: var(--space-2);
10078 }
10079 .embed-preview {
10080 margin: var(--space-3) 0;
10081 overflow: hidden;
10082 }
10083 .embed-iframe {
10084 border: none;
10085 border-radius: 4px;
10086 }
10087 .embed-layout-toggle {
10088 font-size: 0.85rem;
10089 margin-bottom: var(--space-2);
10090 display: flex;
10091 gap: var(--space-4);
10092 }
10093 .embed-layout-toggle label {
10094 cursor: pointer;
10095 display: flex;
10096 align-items: center;
10097 gap: 0.3rem;
10098 }
10099 .embed-code-row {
10100 display: flex;
10101 align-items: center;
10102 gap: var(--space-2);
10103 }
10104 .embed-snippet {
10105 flex: 1;
10106 padding: var(--space-2) var(--space-3);
10107 background: var(--surface-overlay);
10108 border-radius: 4px;
10109 font-size: 11px;
10110 overflow-x: auto;
10111 white-space: nowrap;
10112 font-family: var(--font-mono);
10113 border: 1px solid var(--border);
10114 }
10115 .copy-btn {
10116 padding: 6px 12px;
10117 font-size: 12px;
10118 background: var(--action);
10119 color: var(--primary-light);
10120 border: none;
10121 border-radius: var(--radius-md);
10122 cursor: pointer;
10123 white-space: nowrap;
10124 }
10125 .copy-btn:hover {
10126 opacity: 0.9;
10127 }
10128
10129 /* ===========================================
10130 ADMIN NAV (templates/partials/admin_nav.html)
10131 =========================================== */
10132 .admin-nav {
10133 display: flex;
10134 gap: var(--space-2);
10135 margin-bottom: var(--space-5);
10136 flex-wrap: wrap;
10137 font-family: var(--font-mono);
10138 font-size: 0.85rem;
10139 }
10140 .admin-nav a {
10141 padding: 0.3rem 0.8rem;
10142 text-decoration: none;
10143 }
10144
10145 /* Active / inactive state for admin nav items and filter-bar toggles.
10146 The admin templates toggle `.primary` (current page / active filter) and
10147 `.secondary` (inactive) on these elements; style them to match the
10148 monospace admin surface using the existing tokens. */
10149 .admin-nav a.primary,
10150 .filter-bar button.primary {
10151 background: var(--primary-dark);
10152 color: var(--primary-light);
10153 font-weight: 700;
10154 }
10155 .admin-nav a.secondary,
10156 .filter-bar button.secondary {
10157 background: var(--surface-sunken);
10158 color: var(--content-secondary);
10159 cursor: pointer;
10160 }
10161 .admin-nav a.secondary:hover,
10162 .filter-bar button.secondary:hover {
10163 color: var(--content);
10164 }
10165
10166 /* ===========================================
10167 VIDEO PLAYER PAGE (templates/pages/video_player.html)
10168 =========================================== */
10169 .video-cover-img {
10170 width: 100%;
10171 display: block;
10172 background: var(--primary-dark);
10173 }
10174 .video-cover-placeholder {
10175 width: 100%;
10176 aspect-ratio: 16 / 9;
10177 background: var(--primary-dark);
10178 display: flex;
10179 align-items: center;
10180 justify-content: center;
10181 color: var(--content-muted);
10182 }
10183 .video-store-cta {
10184 margin: var(--space-6) 0;
10185 padding: var(--space-5);
10186 background: var(--surface-sunken);
10187 text-align: center;
10188 }
10189 .video-cta-lead {
10190 font-size: 1.1rem;
10191 margin-bottom: var(--space-4);
10192 }
10193 .video-cta-price {
10194 font-size: 1.5rem;
10195 margin-bottom: var(--space-4);
10196 }
10197 .video-cta-fineprint {
10198 font-size: 0.85rem;
10199 opacity: 0.7;
10200 margin-top: 0.75rem;
10201 }
10202 .video-library-status {
10203 font-family: var(--font-mono);
10204 color: var(--content-muted);
10205 }
10206 .video-tag-link {
10207 text-decoration: none;
10208 color: inherit;
10209 }
10210
10211 /* ===========================================
10212 LIBRARY LOCKED PAGE (templates/pages/library_locked.html)
10213 =========================================== */
10214 .library-locked-byline {
10215 opacity: 0.7;
10216 }
10217 .library-locked-cover {
10218 max-width: 320px;
10219 margin: var(--space-4) 0;
10220 }
10221 .library-locked-purchase {
10222 margin-top: var(--space-6);
10223 }
10224 .library-locked-lead {
10225 opacity: 0.85;
10226 }
10227 .library-locked-actions {
10228 margin-top: var(--space-5);
10229 display: flex;
10230 gap: 0.75rem;
10231 flex-wrap: wrap;
10232 }
10233 .library-locked-bundles {
10234 margin-top: var(--space-5);
10235 }
10236 .library-locked-bundles-title {
10237 font-weight: bold;
10238 }
10239 .library-locked-bundle {
10240 margin-top: var(--space-2);
10241 }
10242 .library-locked-bundle-price {
10243 opacity: 0.7;
10244 }
10245
10246 /* ===========================================
10247 BLOG (replaces inline styles in project_blog.html
10248 and dashboard-blog-editor.html)
10249 =========================================== */
10250
10251 .blog-empty-state { padding: var(--space-6) 0; }
10252 .blog-empty-hint {
10253 opacity: 0.7;
10254 font-size: 0.9rem;
10255 margin-top: var(--space-2);
10256 }
10257 .blog-post-title-link { font-weight: bold; }
10258 .blog-post-actions {
10259 display: flex;
10260 gap: var(--space-2);
10261 }
10262
10263 /* Blog editor */
10264 .blog-editor h1 {
10265 font-size: 2rem;
10266 margin-bottom: var(--space-4);
10267 text-align: left;
10268 }
10269 .blog-editor .editor-form { max-width: 800px; }
10270 .blog-editor .editor-form .form-group { margin-bottom: 1.25rem; }
10271 .blog-editor .editor-form textarea {
10272 font-family: var(--font-mono);
10273 font-size: 0.9rem;
10274 min-height: 400px;
10275 resize: vertical;
10276 }
10277 .blog-editor-slug-spinner { font-size: 0.85rem; }
10278 .blog-editor-media-btn {
10279 margin-top: var(--space-2);
10280 font-size: 0.85rem;
10281 }
10282 .blog-editor-actions {
10283 display: flex;
10284 gap: var(--space-4);
10285 align-items: center;
10286 }
10287 .blog-editor-status { margin-top: var(--space-2); }
10288
10289 /* ===========================================
10290 AUDIO PLAYER (replaces inline styles in pages/audio_player.html)
10291 =========================================== */
10292
10293 .audio-store-cta {
10294 margin: 2rem 0;
10295 padding: var(--space-5);
10296 background: var(--surface-sunken);
10297 text-align: center;
10298 }
10299 .audio-store-cta .audio-access-msg {
10300 font-size: 1.1rem;
10301 margin-bottom: var(--space-4);
10302 }
10303 .audio-store-cta .audio-price {
10304 font-size: 1.5rem;
10305 margin-bottom: var(--space-4);
10306 }
10307 .audio-store-cta .audio-fee-note {
10308 font-size: 0.85rem;
10309 opacity: 0.7;
10310 margin-top: 0.75rem;
10311 }
10312 .audio-library-status {
10313 font-family: var(--font-mono);
10314 color: var(--content-muted);
10315 }
10316 .audio-tag-link {
10317 text-decoration: none;
10318 color: inherit;
10319 }
10320
10321 /* ===========================================
10322 SECTIONS WIZARD STEP (templates/wizards/steps/item/sections.html)
10323 Parallels .psection-row used by item_details + project-sections.js,
10324 but isolated so wizard markup can evolve independently.
10325 =========================================== */
10326
10327 .section-row {
10328 display: flex;
10329 align-items: center;
10330 gap: var(--space-3);
10331 padding: 0.6rem 0;
10332 border-bottom: 1px solid var(--border);
10333 }
10334 .section-row-title { flex: 1; font-weight: bold; }
10335 .section-row-length { font-size: 0.8rem; opacity: 0.6; }
10336 .section-row .section-delete-btn {
10337 padding: 0.25rem 0.6rem;
10338 font-size: 0.8rem;
10339 }
10340
10341 .section-add-body { margin-top: var(--space-3); }
10342
10343 .wizard-actions { margin-top: var(--space-5); }
10344
10345 /* ===========================================
10346 PROJECT SUBSCRIPTIONS TAB (templates/partials/tabs/project_subscriptions.html)
10347 =========================================== */
10348
10349 .subs-connect-info {
10350 margin-bottom: var(--space-5);
10351 padding: 1.25rem;
10352 }
10353 .subs-new-tier { margin-bottom: var(--space-6); }
10354
10355 .tier-row-desc {
10356 font-size: 0.85rem;
10357 opacity: 0.7;
10358 margin-top: 0.25rem;
10359 }
10360 .tier-action-btn {
10361 font-size: 0.85rem;
10362 padding: 0.3rem 0.6rem;
10363 }
10364
10365 .subs-members-bar {
10366 margin-top: var(--space-6);
10367 display: flex;
10368 justify-content: space-between;
10369 align-items: center;
10370 }
10371
10372 /* ===========================================
10373 LIBRARY CONSUMPTION PAGES
10374 ===========================================
10375 Shared styles for the library-side consumption surfaces:
10376 text_reader.html, library_text.html (.article-page),
10377 library_downloads.html (.library-page),
10378 library_audio.html / library_video.html (.media-container + helpers).
10379 The .article-page and .library-page sections higher up in this file
10380 are activated by body classes set in the templates. */
10381
10382 /* Faded excerpt text on the public store-page text reader. */
10383 .article-page .article-body--excerpt { opacity: 0.85; }
10384
10385 /* Store-page call-to-action block (text_reader.html). */
10386 .article-page .store-cta {
10387 margin: 2.5rem 0;
10388 padding: var(--space-5);
10389 background: var(--surface-sunken);
10390 text-align: center;
10391 }
10392 .article-page .store-cta-lead {
10393 font-size: 1.1rem;
10394 margin-bottom: var(--space-4);
10395 }
10396 .article-page .store-cta-price {
10397 font-size: 1.5rem;
10398 margin-bottom: var(--space-4);
10399 }
10400 .article-page .store-cta-note {
10401 font-size: 0.85rem;
10402 opacity: 0.7;
10403 margin-top: 0.75rem;
10404 }
10405 .article-page .store-cta .library-status {
10406 font-family: var(--font-mono);
10407 color: var(--content-muted);
10408 }
10409
10410 /* Plain (text-decoration-free, inherit-colored) tag link on text_reader.
10411 Distinguishes from the default linked .article-tag in library_text. */
10412 .article-page .article-tag--plain {
10413 text-decoration: none;
10414 color: inherit;
10415 }
10416
10417 /* Library back-link breadcrumb shared by the media library pages. */
10418 .media-container .library-back {
10419 font-size: 0.85rem;
10420 opacity: 0.7;
10421 margin: var(--space-4) 0;
10422 }
10423 .media-container .library-back a { color: var(--content); }
10424
10425 /* Source-files download list under audio/video library pages.
10426 The .library-page version exists higher up; this block scopes the
10427 same look under .media-container for audio/video. */
10428 .media-container .library-downloads {
10429 background: var(--surface-overlay);
10430 padding: 1.5rem;
10431 margin-top: var(--space-6);
10432 }
10433 .media-container .library-downloads h3 {
10434 font-size: 1.1rem;
10435 margin-bottom: var(--space-4);
10436 }
10437 .media-container .download-row {
10438 display: flex;
10439 align-items: center;
10440 gap: var(--space-4);
10441 padding: var(--space-2) 0;
10442 border-bottom: 1px solid var(--border);
10443 }
10444 .media-container .download-row:last-child { border-bottom: none; }
10445 .media-container .download-version {
10446 min-width: 4em;
10447 font-family: var(--font-mono);
10448 font-size: 0.9rem;
10449 }
10450 .media-container .download-label { flex: 1; }
10451 .media-container .download-label--empty { flex: 1; opacity: 0.5; }
10452 .media-container .download-size {
10453 font-size: 0.85rem;
10454 opacity: 0.6;
10455 min-width: 5em;
10456 text-align: right;
10457 }
10458
10459 /* Compact download button used in both library_downloads.html and
10460 media library pages. */
10461 .btn-download-compact {
10462 padding: 0.4rem 0.8rem;
10463 font-size: 0.85rem;
10464 }
10465
10466 /* Faded "no label" placeholder on library_downloads.html download rows. */
10467 .library-page .download-label--empty { opacity: 0.5; }
10468
10469 /* Library-downloads description <details> summary + body. */
10470 .library-page .lib-summary {
10471 cursor: pointer;
10472 font-family: var(--font-heading);
10473 font-size: 1.3rem;
10474 }
10475 .library-page .lib-summary-body { margin-top: var(--space-4); }
10476
10477 /* License section on library_downloads.html. */
10478 .library-page .lib-license-name { margin-bottom: 0.75rem; }
10479 .library-page .lib-license-download {
10480 font-size: 0.9rem;
10481 color: var(--content);
10482 }
10483
10484 /* Footer below the item-footer (was inline on library_downloads.html). */
10485 .library-page .item-footer-sub { margin-top: var(--space-2); }
10486
10487 /* library_text.html footer (terse text-page footer, distinct from the
10488 text_reader.html .text-reader-footer that has its own classed style). */
10489 .article-page .lib-text-footer {
10490 text-align: center;
10491 padding: var(--space-6);
10492 font-size: 0.85rem;
10493 opacity: 0.6;
10494 border-top: 1px solid var(--border);
10495 }
10496 .article-page .lib-text-footer a { color: var(--content); }
10497
10498 /* Media player play/pause icon initial state. The JS in media-player.js
10499 toggles via element.style.display directly, so we must NOT use
10500 !important here, element.style would still beat a normal-priority
10501 declaration, but !important in the stylesheet would defeat that. */
10502 .media-icon-hidden { display: none; }
10503
10504 /* Video element fills its .video-display parent. .video-display already
10505 provides a black background. */
10506 .video-display video { width: 100%; }
10507
10508 /* Cover image inside .cover-art on library_audio.html, the parent
10509 .cover-art already sets aspect ratio and centering; the inline
10510 width/aspect-ratio/object-fit was redundant with .cover-art img. */
10511
10512 /* ===========================================
10513 USER DASHBOARD TABS (support / sessions / buyer contacts)
10514 =========================================== */
10515
10516 /* Support tab (templates/partials/tabs/user_support.html). */
10517 .support-tab .support-intro-meta {
10518 margin-bottom: var(--space-5);
10519 font-size: 0.9rem;
10520 opacity: 0.8;
10521 }
10522 .support-tab .support-form { max-width: 600px; }
10523 .support-tab .response-times {
10524 margin-top: var(--space-6);
10525 font-size: 0.85rem;
10526 opacity: 0.7;
10527 }
10528 .support-tab .response-times ul {
10529 margin: var(--space-1) 0 0 var(--space-5);
10530 }
10531
10532 /* Sessions tab (templates/partials/tabs/user_sessions.html). */
10533 .sessions-tab .sessions-table { width: 100%; }
10534 .sessions-tab .device-cell {
10535 max-width: 300px;
10536 overflow: hidden;
10537 text-overflow: ellipsis;
10538 white-space: nowrap;
10539 }
10540
10541 /* Buyer contacts tab (templates/partials/tabs/buyer_contacts.html). */
10542 .buyer-contacts .contacts-table { min-width: 500px; }
10543
10544 /* Creators page extras (templates/pages/creators.html). */
10545 .creators-page .pricing-fineprint {
10546 font-size: 0.9rem;
10547 opacity: 0.8;
10548 margin-top: var(--space-2);
10549 }
10550 .creators-page .trial-callout {
10551 font-size: 0.9rem;
10552 margin-top: var(--space-5);
10553 }
10554
10555 /* ===========================================
10556 LIBRARY TABS
10557 Shared classes for the library-dashboard tab partials:
10558 library_wishlists, library_contacts, library_purchases,
10559 library_subscriptions. Migrated from inline styles.
10560 =========================================== */
10561
10562 /* Tables in library tabs need a minimum width so columns stay readable
10563 while the outer container scrolls horizontally on narrow viewports. */
10564
10565 /* Empty-state hint paragraph (smaller, slightly faded). */
10566 .library-tab-empty-hint {
10567 font-size: 0.9rem;
10568 opacity: 0.7;
10569 margin-bottom: var(--space-4);
10570 }
10571
10572 /* Compact row-action button (wishlist Add to Cart / Remove, etc.). */
10573
10574 .library-filter-wrap { margin-bottom: var(--space-4); }
10575
10576 /* Purchases table "Open" action link + context menu trigger group. */
10577 .library-row-actions {
10578 display: flex;
10579 align-items: center;
10580 gap: var(--space-2);
10581 }
10582 .library-row-open {
10583 font-size: 0.8rem;
10584 padding: var(--space-1) var(--space-3);
10585 text-decoration: none;
10586 white-space: nowrap;
10587 }
10588
10589 /* Section sub-heading inside purchases tab (e.g. "Subscriptions"). */
10590 .library-tab-subheading {
10591 font-size: 1.1rem;
10592 margin-top: var(--space-6);
10593 margin-bottom: var(--space-4);
10594 opacity: 0.8;
10595 }
10596
10597 /* Inline-block button styled as a link target on empty-state CTAs. */
10598 .library-tab-cta {
10599 display: inline-block;
10600 text-decoration: none;
10601 }
10602
10603 /* Context menu (dropdown) on each purchase row. */
10604 .context-menu-wrapper { position: relative; }
10605 .context-menu-btn {
10606 background: none;
10607 border: none;
10608 cursor: pointer;
10609 padding: var(--space-2);
10610 font-size: 1.25rem;
10611 line-height: 1;
10612 color: var(--content-muted);
10613 border-radius: 4px;
10614 }
10615 .context-menu-btn:hover {
10616 background: var(--surface-sunken);
10617 color: var(--content);
10618 }
10619 .context-menu {
10620 display: none;
10621 position: absolute;
10622 right: 0;
10623 top: 100%;
10624 background: var(--surface-overlay);
10625 border: 1px solid var(--border);
10626 box-shadow: var(--shadow-2);
10627 min-width: 160px;
10628 z-index: 100;
10629 }
10630 .context-menu.open { display: block; }
10631 .context-menu-item {
10632 display: block;
10633 width: 100%;
10634 padding: var(--space-3) var(--space-4);
10635 text-align: left;
10636 background: none;
10637 border: none;
10638 font-family: var(--font-body);
10639 font-size: 0.9rem;
10640 color: var(--content);
10641 cursor: pointer;
10642 text-decoration: none;
10643 }
10644 .context-menu-item:hover { background: var(--surface-sunken); }
10645 .context-menu-item.danger { color: var(--danger); }
10646
10647 /* Inline license-key code chip shown beneath a purchase date. */
10648 .license-key-inline { margin-top: var(--space-1); }
10649 .key-code-small {
10650 font-size: 0.8rem;
10651 padding: 0.15rem 0.4rem;
10652 background: var(--surface-sunken);
10653 border-radius: 3px;
10654 cursor: pointer;
10655 user-select: all;
10656 }
10657 .key-code-small:hover { background: var(--border); }
10658
10659 /* Library row title link reads as plain text until hovered. */
10660 .library-title-link { color: inherit; text-decoration: none; }
10661 .library-title-link:hover { text-decoration: underline; }
10662 /* ===========================================
10663 ADMIN ENTRIES (replaces inline styles in partials/admin_user_entries.html,
10664 partials/admin_waitlist_entries.html,
10665 partials/admin_appeal_entries.html)
10666 =========================================== */
10667
10668 /* Status badges built ad hoc (Active / Trusted). */
10669 .badge-active,
10670 .badge-trusted {
10671 background: color-mix(in oklch, var(--success) 12%, var(--surface-page));
10672 color: var(--success);
10673 }
10674
10675 /* "Trust" toggle button sits next to a Trusted badge. */
10676 .admin-entries-trust-btn {
10677 margin-left: var(--space-1);
10678 }
10679
10680 /* Waitlist pitch cell, narrow body text. */
10681 .admin-entries-pitch {
10682 font-size: 0.9rem;
10683 max-width: 300px;
10684 }
10685 .admin-entries-pitch-empty {
10686 opacity: 0.5;
10687 font-style: italic;
10688 }
10689 .admin-entries-pitch-inviter {
10690 margin-top: var(--space-1);
10691 }
10692
10693 /* Appeal text columns. */
10694 .admin-entries-reason {
10695 font-size: 0.9rem;
10696 max-width: 200px;
10697 }
10698 .admin-entries-appeal {
10699 font-size: 0.9rem;
10700 max-width: 300px;
10701 }
10702
10703 /* Decide form textarea + stacked action buttons. */
10704 .admin-entries-decide-textarea {
10705 width: 200px;
10706 }
10707 .admin-entries-decide-actions {
10708 display: flex;
10709 flex-direction: column;
10710 gap: var(--space-1);
10711 }
10712
10713 /* Pagination row at the bottom of admin entry tables. */
10714 .admin-entries-pagination {
10715 display: flex;
10716 justify-content: center;
10717 align-items: center;
10718 gap: var(--space-4);
10719 padding: var(--space-4) 0;
10720 }
10721
10722 /* ===========================================
10723 ITEM TABS (item_settings, item_sales, item_overview partials)
10724 =========================================== */
10725
10726 /* Schedule form is hidden until "Schedule" button is clicked. JS toggles
10727 the `.hidden` utility class. */
10728 .item-settings-schedule-form {
10729 margin-top: var(--space-4);
10730 }
10731
10732 .item-sales-tab-header {
10733 display: flex;
10734 justify-content: space-between;
10735 align-items: center;
10736 margin-bottom: var(--space-4);
10737 }
10738 .item-sales-tab-header h2 { margin: 0; }
10739 .item-overview-embed {
10740 margin-top: var(--space-5);
10741 }
10742 .item-overview-embed > summary {
10743 cursor: pointer;
10744 font-weight: bold;
10745 font-size: 1.1rem;
10746 }
10747
10748 /* ===========================================
10749 ITEM TEXT EDITOR (partials/item_text_editor.html)
10750 =========================================== */
10751
10752 .text-editor-insert-btn {
10753 margin-top: var(--space-2);
10754 font-size: 0.85rem;
10755 }
10756
10757 .text-editor-placeholder {
10758 opacity: 0.6;
10759 }
10760
10761 .text-editor-actions {
10762 margin-top: var(--space-4);
10763 }
10764
10765 /* ===========================================
10766 PROJECT ANALYTICS TAB (partials/tabs/project_analytics.html)
10767 =========================================== */
10768
10769 .tab-docs-extra {
10770 margin-left: var(--space-4);
10771 }
10772
10773 .analytics-tab-header {
10774 display: flex;
10775 justify-content: space-between;
10776 align-items: center;
10777 margin-bottom: var(--space-4);
10778 }
10779 .analytics-tab-header h2 {
10780 font-size: 1.1rem;
10781 margin: 0;
10782 }
10783
10784 .analytics-empty-block {
10785 text-align: center;
10786 padding: var(--space-6) var(--space-4);
10787 opacity: 0.6;
10788 }
10789
10790 /* ===========================================
10791 RECEIPT PAGE INLINE FRAGMENTS (pages/receipt.html)
10792 =========================================== */
10793
10794 .receipt-page .receipt-brand {
10795 opacity: 0.6;
10796 font-size: 0.9rem;
10797 }
10798 .receipt-page .receipt-meta {
10799 text-align: right;
10800 }
10801 .receipt-page .receipt-meta-line {
10802 font-family: var(--font-mono);
10803 font-size: 0.85rem;
10804 opacity: 0.6;
10805 }
10806 .receipt-page .receipt-meta-sub {
10807 font-family: var(--font-mono);
10808 font-size: 0.75rem;
10809 opacity: 0.4;
10810 margin-top: 0.25rem;
10811 }
10812 .receipt-page .print-btn {
10813 margin-top: var(--space-4);
10814 font-size: 0.85rem;
10815 }
10816
10817 /* ===========================================
10818 IMPORT PAGE INLINE FRAGMENTS (dashboards/dashboard-import.html)
10819 =========================================== */
10820
10821 .import-page .import-preview-label,
10822 .import-page .import-mapping-label,
10823 .import-page .import-progress-label {
10824 font-family: var(--font-mono);
10825 font-size: 0.85rem;
10826 margin-bottom: var(--space-2);
10827 }
10828 .import-page .import-mapping-label {
10829 margin-bottom: 0.75rem;
10830 }
10831 .import-page .import-progress-label {
10832 font-size: 0.9rem;
10833 }
10834 .import-page .import-start-btn {
10835 margin-top: var(--space-4);
10836 }
10837 .import-page .import-history-heading {
10838 font-size: 1.3rem;
10839 margin-bottom: var(--space-4);
10840 }
10841
10842 /* ===========================================
10843 SLUG STATUS PARTIAL (partials/slug_status.html)
10844 =========================================== */
10845
10846 .slug-status {
10847 font-size: 0.85rem;
10848 }
10849 .slug-status.available { color: var(--success); }
10850 .slug-status.taken { color: var(--danger); }
10851
10852 .slug-suggestions {
10853 font-size: 0.85rem;
10854 display: block;
10855 margin-top: 0.25rem;
10856 }
10857 .slug-suggestion-link {
10858 margin-right: var(--space-2);
10859 }
10860
10861 /* ===========================================
10862 STRIPE DISCLAIMER PAGE (pages/stripe_disclaimer.html)
10863 =========================================== */
10864
10865 .stripe-disclaimer-page .container {
10866 max-width: 700px;
10867 margin: var(--space-5) auto;
10868 padding: 0 var(--space-6);
10869 }
10870 .stripe-disclaimer-page .stripe-disclaimer-title {
10871 text-align: center;
10872 }
10873 .stripe-disclaimer-page .tagline {
10874 font-size: 0.85rem;
10875 opacity: 0.7;
10876 margin-bottom: var(--space-6);
10877 text-align: center;
10878 }
10879 .stripe-disclaimer-page h2 {
10880 font-size: 1.5rem;
10881 margin-bottom: var(--space-5);
10882 }
10883 .stripe-disclaimer-page .stripe-disclaimer-lead {
10884 margin-bottom: var(--space-5);
10885 opacity: 0.8;
10886 }
10887 .stripe-disclaimer-page .section { margin-bottom: var(--space-6); }
10888 .stripe-disclaimer-page .section h3 {
10889 font-size: 1.1rem;
10890 margin-bottom: 0.75rem;
10891 font-family: var(--font-mono);
10892 }
10893 .stripe-disclaimer-page .section ul {
10894 margin: 0;
10895 padding-left: 1.25rem;
10896 }
10897 .stripe-disclaimer-page .section li {
10898 margin-bottom: var(--space-2);
10899 line-height: 1.5;
10900 }
10901 .stripe-disclaimer-page .stripe-disclaimer-fee-lead {
10902 margin-bottom: 0.75rem;
10903 }
10904 .stripe-disclaimer-page .fee-example {
10905 background: var(--surface-page);
10906 padding: var(--space-4) 1.25rem;
10907 margin: var(--space-4) 0;
10908 font-family: var(--font-mono);
10909 font-size: 0.9rem;
10910 }
10911 .stripe-disclaimer-page .fee-row {
10912 display: flex;
10913 justify-content: space-between;
10914 padding: 0.25rem 0;
10915 }
10916 .stripe-disclaimer-page .fee-row.highlight {
10917 font-weight: bold;
10918 border-top: 1px solid var(--border);
10919 margin-top: var(--space-2);
10920 padding-top: var(--space-2);
10921 }
10922 .stripe-disclaimer-page .fee-row .zero { color: var(--content); }
10923 .stripe-disclaimer-page .stripe-disclaimer-note {
10924 font-size: 0.9rem;
10925 opacity: 0.8;
10926 }
10927 .stripe-disclaimer-page .acceptance {
10928 background: var(--surface-page);
10929 padding: 1.25rem;
10930 margin: var(--space-5) 0;
10931 }
10932 .stripe-disclaimer-page .checkbox-group {
10933 display: flex;
10934 align-items: flex-start;
10935 gap: 0.75rem;
10936 }
10937 .stripe-disclaimer-page .checkbox-group input[type="checkbox"] {
10938 margin-top: 0.25rem;
10939 flex-shrink: 0;
10940 }
10941 .stripe-disclaimer-page .checkbox-group label {
10942 line-height: 1.5;
10943 cursor: pointer;
10944 }
10945 .stripe-disclaimer-page .button-row {
10946 display: flex;
10947 gap: var(--space-4);
10948 margin-top: var(--space-5);
10949 }
10950 .stripe-disclaimer-page .button-row button { flex: 1; }
10951 .stripe-disclaimer-page button:disabled {
10952 opacity: 0.5;
10953 cursor: not-allowed;
10954 }
10955 .stripe-disclaimer-page .note {
10956 font-size: 0.85rem;
10957 opacity: 0.6;
10958 margin-top: var(--space-4);
10959 text-align: center;
10960 }
10961
10962 /* ===========================================
10963 LONG-TAIL CLEANUP, shared utilities promoted from the final inline-style sweep.
10964 Each rule replaces ≥2 inline-style instances across templates.
10965 =========================================== */
10966
10967 /* Tab-spinner loading indicator (used by 3+ dashboards). */
10968 .tab-spinner-indicator { margin-left: var(--space-4); }
10969
10970 /* Inline-block secondary action link styled as a button. */
10971 .btn-link {
10972 display: inline-block;
10973 padding: var(--space-2) var(--space-4);
10974 text-decoration: none;
10975 }
10976 .btn-link--sm { padding: var(--space-2) var(--space-4); }
10977
10978 /* Username-availability spinner (wizards + standalone account form). */
10979 .username-spinner { font-size: 0.85rem; }
10980
10981 /* Centered foot-link beneath wizard cards. */
10982 .foot-link--centered { margin-top: var(--space-4); text-align: center; }
10983
10984 /* Health-page status dots. */
10985 .health-indicator-dot { width: 8px; height: 8px; margin-right: 0.4rem; }
10986 .health-error-text { color: var(--danger); }
10987
10988 /* Inline error fragments (login_error, error_fragment) toggle this on. */
10989 .error-message.is-active { display: block; }
10990
10991 /* Cart count badge in nav. */
10992 .cart-badge-count { font-size: 0.8em; }
10993
10994 /* Empty-row inside a data table. */
10995 .table-empty-row { text-align: center; opacity: 0.6; }
10996
10997 /* Discover grid: card wrapper + body anchor. */
10998 .discover-grid-card { position: relative; }
10999 .discover-card-link {
11000 text-decoration: none;
11001 color: inherit;
11002 display: flex;
11003 flex-direction: column;
11004 flex: 1;
11005 }
11006 .discover-filter-checkbox {
11007 display: flex;
11008 align-items: center;
11009 gap: var(--space-2);
11010 cursor: pointer;
11011 font-size: 0.9rem;
11012 }
11013
11014 /* Tag suggestion list. */
11015 .tag-suggest-label {
11016 font-size: 0.8rem;
11017 opacity: 0.7;
11018 margin-bottom: var(--space-2);
11019 }
11020 .tag-suggest-pill {
11021 background: var(--surface-sunken);
11022 border: 1px solid var(--border);
11023 padding: 0.15rem 0.4rem;
11024 font-size: 0.8rem;
11025 cursor: pointer;
11026 margin: 0.1rem;
11027 }
11028
11029 /* Dashboard-export header layout + Export-all CTA. */
11030 .dashboard-export-header {
11031 display: flex;
11032 justify-content: space-between;
11033 align-items: flex-start;
11034 }
11035 .export-all-btn {
11036 white-space: nowrap;
11037 margin-top: var(--space-2);
11038 }
11039
11040 /* Tiny inline action button (admin-metrics, dashboard-item share). */
11041 .dashboard-item-share-btn {
11042 font-size: 0.8rem;
11043 padding: 0.15rem 0.5rem;
11044 opacity: 0.6;
11045 }
11046
11047 /* Monospaced page sub-headers. */
11048 .section-mono-meta {
11049 font-family: var(--font-mono);
11050 font-size: 0.85rem;
11051 opacity: 0.6;
11052 margin-bottom: var(--space-5);
11053 }
11054 .section-mono-hint {
11055 font-family: var(--font-mono);
11056 font-size: 0.9rem;
11057 margin-top: var(--space-2);
11058 }
11059
11060 /* Email-result single-card page. */
11061 .email-result-wrap {
11062 max-width: 600px;
11063 margin: 50px auto;
11064 padding: 20px;
11065 }
11066
11067 /* Admin lottery form (admin-waitlist). */
11068 .lottery-form {
11069 display: flex;
11070 gap: var(--space-4);
11071 align-items: flex-end;
11072 }
11073
11074 /* Login screen: "or" divider + passkey button + error slot. */
11075 .login-divider {
11076 text-align: center;
11077 margin: var(--space-5) 0 var(--space-4);
11078 opacity: 0.5;
11079 font-size: 0.85rem;
11080 }
11081 .login-passkey-btn { width: 100%; }
11082 .login-passkey-error { margin-top: var(--space-2); }
11083
11084 /* Upload-progress sibling text (item_audio_upload). */
11085 .upload-speed-text {
11086 font-size: 0.8rem;
11087 opacity: 0.6;
11088 margin-top: 0.25rem;
11089 }
11090
11091 /* Faded "Following" follow-button state. */
11092 .follow-btn.is-selected { opacity: 0.7; }
11093
11094 /* Project blog footer. */
11095 .project-blog-footer {
11096 margin-top: 4rem;
11097 padding-top: 2rem;
11098 border-top: 1px solid var(--border);
11099 opacity: 0.6;
11100 }
11101 .project-blog-footer a { color: var(--content); }
11102
11103 /* Compact alert / paragraph margin variants used 2+ times. */
11104 .alert.mb-4 { margin-bottom: var(--space-4); }
11105
11106 /* Paywall trust line. */
11107 .paywall-trust {
11108 font-size: 0.85rem;
11109 opacity: 0.7;
11110 margin-top: var(--space-4);
11111 line-height: 1.4;
11112 }
11113
11114 /* Confirm-delete: button background already covered by .danger class.
11115 The wizard step uses `.primary` and inlines the danger background; we just
11116 change the class instead. No CSS rule needed here. */
11117
11118 /* Paywall-style centered narrow form-group used inside project_paywall. */
11119 .form-group--centered-narrow {
11120 max-width: 240px;
11121 margin: var(--space-4) auto;
11122 }
11123
11124 /* Inline-form margin-left for adjacent pills (collection.html private badge). */
11125 .badge--inline-l { margin-left: var(--space-2); }
11126
11127 /* ===== Team page ===== */
11128
11129 .team-page { max-width: 56rem; margin: 0 auto; }
11130 .team-intro {
11131 font-size: 1.05rem;
11132 line-height: 1.55;
11133 margin: 0 0 var(--space-6);
11134 opacity: 0.85;
11135 }
11136 .team-section { margin-top: var(--space-8); }
11137 .team-section + .team-section { margin-top: var(--space-7); }
11138 .team-empty {
11139 font-size: 0.95rem;
11140 opacity: 0.65;
11141 font-style: italic;
11142 }
11143 .team-card-experience {
11144 margin: var(--space-3) 0 var(--space-2);
11145 line-height: 1.5;
11146 }
11147 .team-card-links {
11148 margin: var(--space-2) 0;
11149 font-size: 0.95rem;
11150 }
11151 .team-card-link { font-weight: 500; }
11152 .team-card-bio {
11153 margin-top: var(--space-3);
11154 border-top: 1px solid var(--border);
11155 padding-top: var(--space-3);
11156 }
11157 .team-card-bio > summary {
11158 cursor: pointer;
11159 font-weight: 500;
11160 font-size: 0.95rem;
11161 list-style: none;
11162 }
11163 .team-card-bio > summary::-webkit-details-marker { display: none; }
11164 .team-card-bio > summary::before {
11165 content: "+ ";
11166 display: inline-block;
11167 width: 1.2em;
11168 opacity: 0.6;
11169 }
11170 .team-card-bio[open] > summary::before { content: "− "; }
11171 .team-card-bio > p {
11172 margin-top: var(--space-3);
11173 line-height: 1.6;
11174 }
11175
11176 /* ── SyncKit billing panel ──
11177 Per-app accordion shown inside the SyncKit dashboard tab (both user and
11178 project levels). The .synckit-billing root carries pricing constants as
11179 data-attrs that static/synckit-billing.js reads to mirror monthly_price_cents.
11180 */
11181 .synckit-billing {
11182 background: var(--surface-raised);
11183 border: 1px solid var(--border);
11184 border-radius: 3px;
11185 padding: var(--space-2) var(--space-3);
11186 min-width: 220px;
11187 }
11188 .synckit-billing-summary {
11189 cursor: pointer;
11190 display: flex;
11191 align-items: center;
11192 gap: var(--space-3);
11193 font-size: 0.875rem;
11194 }
11195 .synckit-billing-toggle { margin-left: auto; color: var(--content-muted); }
11196 .synckit-billing-status {
11197 display: inline-block;
11198 padding: 2px var(--space-2);
11199 border-radius: 2px;
11200 font-size: 0.75rem;
11201 font-weight: 600;
11202 }
11203 .synckit-billing-status--draft { background: var(--surface-sunken); }
11204 .synckit-billing-status--active { background: color-mix(in oklch, var(--success) 12%, var(--surface-page)); color: var(--success); }
11205 .synckit-billing-status--suspended_unpaid { background: color-mix(in oklch, var(--warning) 14%, var(--surface-page)); color: var(--warning); }
11206 .synckit-billing-status--canceled { background: color-mix(in oklch, var(--danger) 10%, var(--surface-page)); color: var(--danger); }
11207 .synckit-billing-price { font-weight: 600; }
11208 .synckit-billing-body {
11209 padding-top: var(--space-3);
11210 display: flex;
11211 flex-direction: column;
11212 gap: var(--space-4);
11213 }
11214 .synckit-billing-section { display: flex; flex-direction: column; gap: var(--space-2); }
11215 .synckit-billing-subheading { font-size: 0.875rem; margin: 0; font-weight: 600; }
11216 .synckit-knob-row {
11217 display: flex;
11218 align-items: center;
11219 gap: var(--space-2);
11220 flex-wrap: wrap;
11221 }
11222 .synckit-knob-row label { min-width: 110px; }
11223 .synckit-knob-row input[type="range"] { flex: 1 1 160px; min-width: 120px; }
11224 .synckit-radio { display: inline-flex; align-items: center; gap: var(--space-1); min-width: 0; }
11225 .synckit-billing-summary-line {
11226 display: flex;
11227 align-items: baseline;
11228 gap: var(--space-2);
11229 padding-top: var(--space-2);
11230 border-top: 1px solid var(--border);
11231 }
11232 .synckit-price-preview { font-size: 1.125rem; font-weight: 600; }
11233 .synckit-billing-actions { display: flex; gap: var(--space-2); }
11234 .synckit-billing-manage { flex-direction: row; gap: var(--space-2); }
11235 .synckit-billing-status-msg { font-size: 0.875rem; min-height: 1.25em; }
11236 .synckit-billing-status-msg--info { color: var(--content-muted); }
11237 .synckit-billing-status-msg--error { color: var(--danger); }
11238 .synckit-billing-period { margin: 0; }
11239 .synckit-gauge { display: flex; flex-direction: column; gap: 2px; }
11240 .synckit-gauge-label {
11241 display: flex;
11242 justify-content: space-between;
11243 font-size: 0.8125rem;
11244 }
11245 .synckit-gauge-value { color: var(--content-muted); }
11246 .synckit-gauge-fill--warn { background: var(--warning); }
11247 .synckit-gauge-fill--danger { background: var(--danger); }
11248
11249 /* ============================================================================
11250 Carousel: composable click-through widget (partials/carousel.html).
11251 One frame visible at a time; viewer-driven (prev/next, dots, arrow keys).
11252 No autoplay, no slide animation; frames swap instantly.
11253 ========================================================================= */
11254
11255 /* Public gallery carousel sections (item + project pages). */
11256 .item-gallery,
11257 .project-gallery {
11258 margin: 1.5rem 0;
11259 }
11260
11261 /* Wizard gallery manager: thumbnail tiles with reorder + delete controls. */
11262 .gallery-manager-list {
11263 display: flex;
11264 flex-wrap: wrap;
11265 gap: 0.5rem;
11266 margin-bottom: 0.5rem;
11267 }
11268
11269 .gallery-tile {
11270 position: relative;
11271 width: 96px;
11272 height: 96px;
11273 border: 1px solid var(--border);
11274 border-radius: 4px;
11275 overflow: hidden;
11276 }
11277
11278 .gallery-tile-img {
11279 width: 100%;
11280 height: 100%;
11281 object-fit: cover;
11282 display: block;
11283 }
11284
11285 .gallery-tile-controls {
11286 position: absolute;
11287 inset: auto 0 0 0;
11288 display: flex;
11289 justify-content: space-between;
11290 background: rgba(0, 0, 0, 0.55);
11291 }
11292
11293 .gallery-tile-btn {
11294 flex: 1;
11295 border: none;
11296 background: transparent;
11297 color: #fff;
11298 cursor: pointer;
11299 font-size: 0.9rem;
11300 line-height: 1.4;
11301 padding: 2px 0;
11302 }
11303
11304 .gallery-tile-btn:disabled {
11305 opacity: 0.35;
11306 cursor: default;
11307 }
11308
11309 .gallery-tile-delete {
11310 color: var(--danger);
11311 font-weight: bold;
11312 }
11313
11314 /* <mnw-carousel> is a custom element (default display:inline); make it lay out
11315 like the block container it replaced. */
11316 mnw-carousel {
11317 display: block;
11318 }
11319
11320 .carousel {
11321 position: relative;
11322 margin: 0 auto;
11323 }
11324
11325 .carousel:focus-visible {
11326 outline: 2px solid var(--focus-ring);
11327 outline-offset: 3px;
11328 }
11329
11330 .carousel-viewport {
11331 display: grid; /* all frames share one cell; only the active one renders */
11332 }
11333
11334 .carousel-frame {
11335 grid-area: 1 / 1;
11336 margin: 0;
11337 display: none;
11338 }
11339
11340 .carousel-frame.is-active {
11341 display: block;
11342 }
11343
11344 /* JS-off fallback: no [data-ready] means stack every frame so all
11345 screenshots are still visible rather than stranded behind dead controls. */
11346 .carousel:not([data-ready]) .carousel-frame {
11347 display: block;
11348 }
11349
11350 .carousel-img {
11351 display: block;
11352 width: 100%;
11353 height: auto;
11354 border: 1px solid var(--border);
11355 border-radius: 4px;
11356 background: var(--surface-raised);
11357 }
11358
11359 .carousel-caption {
11360 margin-top: 0.6rem;
11361 font-family: var(--font-mono);
11362 font-size: 0.82rem;
11363 color: var(--content-muted);
11364 text-align: center;
11365 }
11366
11367 /* Prev / next: brutalist offset buttons, vertically centered over the frame. */
11368 .carousel-nav {
11369 position: absolute;
11370 top: 50%;
11371 transform: translateY(-50%);
11372 display: flex;
11373 align-items: center;
11374 justify-content: center;
11375 width: 2.4rem;
11376 height: 2.4rem;
11377 /* Bias the flex-centered glyph up ~2px: the chevron characters sit low in
11378 their line box, so geometric centering reads as a few pixels too low. */
11379 padding: 0 0 4px;
11380 font-size: 1.5rem;
11381 line-height: 1;
11382 color: var(--content);
11383 background: var(--surface-raised);
11384 border: 1px solid var(--content);
11385 border-radius: 4px;
11386 box-shadow: 2px 2px var(--shadow-edge);
11387 cursor: pointer;
11388 }
11389
11390 .carousel-nav:hover {
11391 background: var(--surface-page);
11392 }
11393
11394 .carousel-nav:active {
11395 transform: translateY(-50%) translate(2px, 2px);
11396 box-shadow: none;
11397 }
11398
11399 .carousel-nav:focus-visible {
11400 outline: 2px solid var(--focus-ring);
11401 outline-offset: 2px;
11402 }
11403
11404 .carousel-prev { left: 0.6rem; }
11405 .carousel-next { right: 0.6rem; }
11406
11407 /* Hide the prev/next chrome entirely when JS hasn't taken over. */
11408 .carousel:not([data-ready]) .carousel-nav,
11409 .carousel:not([data-ready]) .carousel-dots {
11410 display: none;
11411 }
11412
11413 .carousel-dots {
11414 display: flex;
11415 justify-content: center;
11416 gap: 0.5rem;
11417 margin-top: 0.8rem;
11418 }
11419
11420 .carousel-dot {
11421 width: 0.7rem;
11422 height: 0.7rem;
11423 padding: 0;
11424 border: 1px solid var(--content);
11425 border-radius: 50%;
11426 background: transparent;
11427 cursor: pointer;
11428 }
11429
11430 .carousel-dot.is-active {
11431 background: var(--action);
11432 border-color: var(--action);
11433 }
11434
11435 .carousel-dot:focus-visible {
11436 outline: 2px solid var(--focus-ring);
11437 outline-offset: 2px;
11438 }
11439
11440 @media (max-width: 640px) {
11441 .carousel-nav { width: 2rem; height: 2rem; font-size: 1.2rem; }
11442 }
11443
11444 /* ---------------------------------------------------------------------------
11445 Custom page editor (dashboard/custom_page_editor.html)
11446 Moved out of an inline <style> block per the extract-shared-CSS rule.
11447 --------------------------------------------------------------------------- */
11448 .cp-editor { max-width: 1200px; margin: 0 auto; padding: 1rem; }
11449 .cp-editor-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
11450 .cp-editor-actions { display: flex; gap: 1rem; }
11451 .cp-intro { color: var(--muted, #666); margin: .25rem 0 1rem; }
11452 .cp-editor-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
11453 .cp-editor-form { display: flex; flex-direction: column; gap: .35rem; }
11454 .cp-code { width: 100%; min-height: 220px; font-family: var(--font-mono, ui-monospace, monospace); font-size: .85rem; line-height: 1.4; resize: vertical; }
11455 .cp-editor-buttons { display: flex; align-items: center; gap: 1rem; margin-top: .5rem; }
11456 .cp-preview-pane { border: 1px solid var(--detail, #ccc); border-radius: 4px; overflow: hidden; }
11457 .cp-preview-bar { font-size: .8rem; padding: .3rem .6rem; background: var(--light-background, #f2f2f2); border-bottom: 1px solid var(--detail, #ccc); }
11458 .cp-preview { width: 100%; height: 520px; border: 0; background: #fff; display: block; }
11459 .cp-blocked { margin-top: 1.25rem; }
11460 .cp-blocked-title { font-weight: 600; margin-bottom: .5rem; }
11461 .cp-blocked-empty { color: var(--muted, #666); }
11462 .cp-blocked-list { list-style: none; padding: 0; margin: 0; }
11463 .cp-blocked-list li { padding: .4rem 0; border-bottom: 1px solid var(--detail, #eee); font-size: .85rem; display: flex; gap: .5rem; flex-wrap: wrap; align-items: baseline; }
11464 .cp-blocked-kind { font-weight: 600; }
11465 .cp-blocked-loc { color: var(--muted, #666); }
11466 .cp-blocked-val { background: var(--light-background, #f2f2f2); padding: 0 .25rem; }
11467 .cp-status.cp-ok { color: var(--success, #2a7); }
11468 .cp-status.cp-err { color: var(--warning, #b00); }
11469 .cp-reset { margin-top: 1.5rem; }
11470 .cp-locked-banner { margin: .5rem 0 1rem; padding: .75rem 1rem; border: 1px solid var(--warning, #b00); border-radius: 4px; background: var(--light-background, #fbeaea); }
11471 @media (max-width: 800px) { .cp-editor-grid { grid-template-columns: 1fr; } }
11472
11473 /* Layout-shift fixes (audit Run 17 Frontend): reserve space for cover images
11474 whose class didn't already set an aspect-ratio / fixed size. */
11475 .library-locked-cover { aspect-ratio: 1 / 1; object-fit: cover; }
11476 .proj-image-preview img { width: 120px; height: 120px; object-fit: cover; }
11477
11478 /* ---- Discover search: how well a result matched -------------------------
11479 Two surfaces, doing two different jobs (db/discover.rs, migration 179).
11480
11481 .results-tier-break is the single heading, and it sits exactly where the
11482 claim it makes turns true: above it every row holds at least one word the
11483 searcher typed, below it none of them do. .row-match-note is the per-row
11484 half, "Matched 3 of 5 words", because coverage varies row to row and one
11485 page can hold a 4-of-5 beside a 1-of-5.
11486
11487 Both are deliberately quiet. They explain a result the reader is already
11488 looking at; competing with the title would make search feel like it is
11489 apologising. Muted colour and small type, no accent, no border of their own
11490 beyond the rule that separates the tiers. */
11491 .results-tier-break {
11492 display: flex;
11493 align-items: baseline;
11494 gap: var(--space-2);
11495 flex-wrap: wrap;
11496 padding: var(--space-3) 0.75rem var(--space-2);
11497 border-top: 1px solid var(--border);
11498 background: var(--surface-page);
11499 }
11500
11501 /* .results-table sets border-top: none and lets .table-row draw the rules, so
11502 the break supplies its own top border. Mid-list that sits against the
11503 preceding row's border-bottom and reads as one heavier 2px rule, which is
11504 wanted here: it is a section change, not another row. At the top of an
11505 all-fuzzy page there is no preceding row, and the same border supplies the
11506 table's missing top edge. */
11507 .results-tier-label {
11508 font-family: var(--font-heading);
11509 font-weight: bold;
11510 font-size: 0.8rem;
11511 text-transform: uppercase;
11512 letter-spacing: 0.03em;
11513 color: var(--content);
11514 }
11515
11516 .results-tier-hint {
11517 font-size: 0.75rem;
11518 color: var(--content-muted);
11519 }
11520
11521 /* The grid is `repeat(auto-fill, minmax(280px, 1fr))`, so without this the
11522 heading takes one card's slot and the tiers interleave visually. */
11523 .results-container.results-grid .results-tier-break {
11524 grid-column: 1 / -1;
11525 padding-left: 0;
11526 padding-right: 0;
11527 background: none;
11528 }
11529
11530 /* In list view this rides inside .row-info, under the creator line, not as
11531 another child of .table-row-link: that is a fixed five-column grid and a
11532 sixth child would invent a column and shift every row that carried one. */
11533 .row-match-note {
11534 font-family: var(--font-mono);
11535 font-size: 0.7rem;
11536 color: var(--content-muted);
11537 white-space: nowrap;
11538 overflow: hidden;
11539 text-overflow: ellipsis;
11540 }
11541
11542 /* Grid cards have room to breathe; give the note its own line under the meta. */
11543 .grid-card .row-match-note {
11544 display: block;
11545 margin-top: var(--space-1);
11546 }
11547
11548 /* The narrow list layouts drop columns rather than wrap, and .row-info is the
11549 column that survives. Keeping the note there would crowd the title on a
11550 phone, where the tier heading above still carries the important half. */
11551 @media (max-width: 700px) {
11552 .table-row .row-match-note { display: none; }
11553 }
11554