gabriel / musehub public
_layout.scss
1,389 lines 35.0 KB
Raw
sha256:0521dce9aca20da6ab4d9ebee6de75ab876bd82cddbc6bd4897d1ac6ecd11d3d docs(musehub#129): freeze Phase 1 OG repo card design Human 14 days ago
1 // ── Icon base ─────────────────────────────────────────────────────────────────
2 // Applied by the icon() Jinja2 global to every <svg><use> icon.
3 .icon {
4 display: inline-block;
5 vertical-align: middle;
6 flex-shrink: 0;
7 }
8
9 // Meta row icons (author, timestamp, branch) are intentionally muted.
10 .commit-meta-item .icon { opacity: .6; }
11
12 // Decorative empty-state icons use a lighter stroke weight.
13 .icon--light-stroke { stroke-width: 1.2; }
14
15 /*
16 * MuseHub Layout System
17 *
18 * Global structural layout: page container, header/nav chrome, responsive
19 * breakpoints, and utility spacing helpers.
20 *
21 * Breakpoints (mobile-first):
22 * xs < 480px — compact phones
23 * sm 480-767px — large phones / small tablets (portrait)
24 * md 768-1023px— tablets and small laptops
25 * lg 1024-1279px— laptops
26 * xl >= 1280px — desktops / wide monitors
27 *
28 * Minimum supported width: 375px (iPhone SE / most modern phones).
29 * Maximum design width: 1280px (content column; wider screens add side whitespace).
30 */
31
32 /* -------------------------------------------------------------------------
33 * Base scaling
34 *
35 * FOUC prevention is handled by setting background:#0d1117 directly on the
36 * <html> element as an inline style in base.html — no opacity tricks needed.
37 * -------------------------------------------------------------------------*/
38
39 :root {
40 --zoom-factor: 1.25;
41 }
42
43 body {
44 zoom: var(--zoom-factor);
45 }
46
47 @media (max-width: 768px) {
48 :root { --zoom-factor: 1; }
49 }
50
51 /* -------------------------------------------------------------------------
52 * Global navigation bar (.musehub-navbar)
53 *
54 * Replaces the plain <header> element with a structured nav bar that includes
55 * logo, search form, site links, and a mobile hamburger toggle.
56 * ------------------------------------------------------------------------- */
57
58 /* Hidden checkbox drives the CSS-only mobile collapse — no JS required. */
59 .navbar-toggle-input {
60 display: none;
61 }
62
63 .musehub-navbar {
64 background: var(--bg-surface);
65 border-bottom: 1px solid var(--border-default);
66 position: sticky;
67 top: 0;
68 z-index: var(--z-raised);
69 height: 42px;
70 }
71
72 .navbar-inner {
73 display: flex;
74 align-items: center;
75 gap: var(--space-3);
76 padding: 0 var(--space-4);
77 height: 100%;
78 width: 100%;
79 }
80
81 .navbar-logo {
82 display: inline-flex;
83 align-items: center;
84 gap: var(--space-2);
85 font-size: var(--text-base);
86 font-weight: var(--weight-semibold);
87 color: var(--text-primary);
88 white-space: nowrap;
89 text-decoration: none;
90 flex-shrink: 0;
91 letter-spacing: -0.01em;
92 }
93
94 .navbar-logo:hover {
95 text-decoration: none;
96 color: var(--text-primary);
97 opacity: 0.85;
98
99 .gradient-text {
100 opacity: 1; /* gradient handles its own visual feedback via parent opacity */
101 }
102 }
103
104 .navbar-logo-icon {
105 color: var(--color-accent);
106 flex-shrink: 0;
107 }
108
109 .navbar-logo-text {
110 font-family: var(--font-mono);
111 font-weight: var(--weight-bold);
112 font-size: 16px;
113 }
114
115 /* Search form */
116 .navbar-search-form {
117 display: flex;
118 align-items: center;
119 gap: var(--space-2);
120 flex: 1;
121 max-width: 400px;
122 background: var(--bg-base);
123 border: 1px solid var(--border-default);
124 border-radius: var(--radius-base);
125 padding: 0 var(--space-3);
126 transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
127
128 /* Override the global input[type="search"] rule which has higher specificity
129 (0-1-1) than .navbar-search-input (0-1-0) and would otherwise show its
130 own border, padding, and width as an inner stroke. */
131 input[type="search"],
132 .navbar-search-input {
133 flex: 1;
134 background: transparent;
135 border: none;
136 border-radius: 0;
137 outline: none;
138 box-shadow: none;
139 padding: 6px 0;
140 font-size: var(--text-sm);
141 font-family: var(--font-sans);
142 color: var(--text-primary);
143 min-width: 0;
144 width: auto;
145 }
146
147 input[type="search"]::placeholder,
148 .navbar-search-input::placeholder {
149 color: var(--text-muted);
150 }
151 }
152
153 .navbar-search-form:focus-within {
154 border-color: var(--color-accent);
155 box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 12%, transparent);
156 }
157
158 .navbar-search-icon {
159 color: var(--text-muted);
160 flex-shrink: 0;
161 }
162
163 /* Action links */
164 .navbar-actions {
165 display: flex;
166 align-items: center;
167 gap: var(--space-2);
168 flex-shrink: 0;
169 margin-left: auto;
170 }
171
172 .navbar-link {
173 font-size: var(--text-sm);
174 color: var(--text-secondary);
175 text-decoration: none;
176 white-space: nowrap;
177 padding: var(--space-1) var(--space-2);
178 border-radius: var(--radius-sm);
179 transition: background var(--transition-fast), color var(--transition-fast);
180 }
181
182 .navbar-link:hover {
183 background: var(--bg-hover);
184 color: var(--text-primary);
185 text-decoration: none;
186 }
187
188 /* Icon-only nav button (bell, etc.) */
189 .navbar-icon-btn {
190 position: relative;
191 display: inline-flex;
192 align-items: center;
193 justify-content: center;
194 width: 32px;
195 height: 32px;
196 padding: 0;
197 border-radius: var(--radius-base);
198 color: var(--text-muted);
199 text-decoration: none;
200 transition: background var(--transition-fast), color var(--transition-fast);
201 }
202
203 .navbar-icon-btn:hover {
204 background: var(--bg-hover);
205 color: var(--text-primary);
206 text-decoration: none;
207 }
208
209 .nav-notif-badge {
210 position: absolute;
211 top: 2px;
212 right: 2px;
213 background: var(--color-danger);
214 color: #fff;
215 border-radius: var(--radius-full);
216 font-size: 9px;
217 font-weight: var(--weight-bold);
218 min-width: 14px;
219 height: 14px;
220 display: none;
221 align-items: center;
222 justify-content: center;
223 padding: 0 3px;
224 line-height: 1;
225 pointer-events: none;
226 }
227
228 .navbar-signout {
229 flex-shrink: 0;
230 }
231
232 /* Theme toggle — swap sun/moon icon based on [data-theme] on <html> */
233 .navbar-theme-btn {
234 border: none;
235 background: none;
236 cursor: pointer;
237 }
238
239 .navbar-theme-icon { display: none; }
240
241 /* Dark mode (default): show sun so user can switch to light */
242 .navbar-theme-icon--sun { display: block; }
243
244 /* Light mode: show moon so user can switch back to dark */
245 [data-theme="light"] .navbar-theme-icon--sun { display: none; }
246 [data-theme="light"] .navbar-theme-icon--moon { display: block; }
247
248 /* Hamburger button (hidden on desktop) */
249 .navbar-hamburger {
250 display: none;
251 flex-direction: column;
252 gap: 5px;
253 background: none;
254 border: none;
255 cursor: pointer;
256 padding: var(--space-2);
257 border-radius: var(--radius-sm);
258 flex-shrink: 0;
259 }
260
261 .navbar-hamburger span {
262 display: block;
263 width: 20px;
264 height: 2px;
265 background: var(--text-secondary);
266 border-radius: 1px;
267 transition: background var(--transition-fast);
268 }
269
270 .navbar-hamburger:hover span {
271 background: var(--text-primary);
272 }
273
274 /* Breadcrumb bar below navbar */
275 .breadcrumb-bar {
276 background: var(--bg-surface);
277 border-bottom: 1px solid var(--border-subtle);
278 padding: 4px var(--space-4);
279 display: flex;
280 align-items: center;
281 gap: var(--space-2);
282 min-height: 0;
283 }
284
285 .breadcrumb-bar:empty,
286 .breadcrumb-bar .breadcrumb:empty + * {
287 display: none;
288 }
289
290 .breadcrumb-bar .breadcrumb {
291 color: var(--text-muted);
292 font-size: var(--text-sm);
293 overflow: hidden;
294 text-overflow: ellipsis;
295 white-space: nowrap;
296 }
297
298 .breadcrumb-bar .breadcrumb a,
299 .breadcrumb-link {
300 color: var(--color-accent);
301 text-decoration: none;
302 }
303
304 .breadcrumb-bar .breadcrumb a:hover,
305 .breadcrumb-link:hover {
306 text-decoration: none;
307 }
308
309 .breadcrumb-sep {
310 color: var(--text-muted);
311 padding: 0 var(--space-1);
312 }
313
314 .breadcrumb-current {
315 color: var(--text-muted);
316 font-size: var(--text-sm);
317 }
318
319 /* breadcrumb_data nav rendered by breadcrumbs.html */
320 .breadcrumb-data-nav {
321 display: inline-flex;
322 align-items: center;
323 flex-wrap: wrap;
324 gap: 0;
325 font-size: var(--text-sm);
326 color: var(--text-muted);
327 }
328
329 /* -------------------------------------------------------------------------
330 * Page header / navigation bar (legacy — kept for embed and non-base pages)
331 * ------------------------------------------------------------------------- */
332 header {
333 background: var(--bg-surface);
334 border-bottom: 1px solid var(--border-default);
335 padding: var(--space-3) var(--space-6);
336 display: flex;
337 align-items: center;
338 gap: var(--space-4);
339 position: sticky;
340 top: 0;
341 z-index: var(--z-raised);
342 }
343
344 header .logo {
345 font-size: var(--text-lg);
346 font-weight: var(--weight-bold);
347 color: var(--text-primary);
348 white-space: nowrap;
349 }
350
351 header .breadcrumb {
352 color: var(--text-muted);
353 font-size: var(--text-base);
354 overflow: hidden;
355 text-overflow: ellipsis;
356 white-space: nowrap;
357 }
358
359 header .breadcrumb a {
360 color: var(--color-accent);
361 }
362
363 header .spacer {
364 flex: 1;
365 }
366
367 header .header-actions {
368 display: flex;
369 align-items: center;
370 gap: var(--space-2);
371 flex-shrink: 0;
372 }
373
374 /* -------------------------------------------------------------------------
375 * Repo header card (shown on all repo-scoped pages)
376 * ------------------------------------------------------------------------- */
377 .repo-header {
378 background: var(--bg-surface);
379 border-bottom: 1px solid var(--border-default);
380 padding: 10px 0;
381 }
382
383 .repo-header-inner {
384 padding: 0 var(--space-4);
385 display: flex;
386 align-items: center;
387 gap: var(--space-3);
388 flex-wrap: wrap;
389 width: 100%;
390 }
391
392 .repo-header-identity {
393 display: flex;
394 align-items: center;
395 gap: var(--space-2);
396 font-size: var(--text-lg);
397 font-weight: var(--weight-semibold);
398 flex-shrink: 0;
399 }
400
401 .repo-header-owner {
402 color: var(--color-accent);
403 }
404
405 .repo-header-sep {
406 color: var(--text-muted);
407 font-weight: var(--weight-normal);
408 }
409
410 .repo-header-name {
411 color: var(--text-primary);
412 }
413
414 .repo-visibility-badge {
415 font-size: var(--text-xs);
416 border: 1px solid var(--border-default);
417 background: transparent;
418 color: var(--text-muted);
419 border-radius: var(--radius-full);
420 padding: 1px var(--space-2);
421 }
422
423 .repo-header-meta {
424 display: flex;
425 align-items: center;
426 gap: var(--space-2);
427 flex-wrap: wrap;
428 flex: 1;
429 }
430
431 .nav-meta-pill {
432 display: inline-flex;
433 align-items: center;
434 gap: var(--space-1);
435 background: var(--bg-overlay);
436 color: var(--text-muted);
437 font-family: var(--font-mono);
438 font-size: var(--text-xs);
439 padding: 2px var(--space-2);
440 border-radius: var(--radius-full);
441 border: 1px solid var(--border-subtle);
442 white-space: nowrap;
443
444 svg { flex-shrink: 0; }
445 }
446
447 .nav-meta-tags {
448 display: flex;
449 gap: var(--space-1);
450 flex-wrap: wrap;
451 }
452
453 .nav-meta-tag,
454 .nav-tag-chip {
455 background: var(--bg-overlay);
456 color: var(--color-accent);
457 font-size: var(--text-xs);
458 padding: 2px var(--space-2);
459 border-radius: var(--radius-full);
460 border: 1px solid var(--border-subtle);
461 }
462
463 .repo-visibility-public { color: var(--color-success, #3fb950); border-color: var(--color-success, #3fb950); }
464 .repo-visibility-private { color: var(--text-muted); }
465 .repo-visibility-unlisted { color: var(--color-warning); border-color: var(--color-warning); }
466
467 .repo-header-actions {
468 display: flex;
469 align-items: center;
470 gap: var(--space-2);
471 flex-shrink: 0;
472 }
473
474 /* -------------------------------------------------------------------------
475 * Repo tab strip (sticky below global header)
476 * ------------------------------------------------------------------------- */
477 :root {
478 --header-height: 42px; /* global header height — matches .musehub-navbar height */
479 --repo-tabs-height: 38px; /* repo tab strip height — sticky below global header */
480 }
481
482 /* Repo tab strip present — account for header + tabs in sticky sidebar offset. */
483 body:has(.repo-tabs) {
484 --sticky-offset: calc(var(--header-height) + var(--repo-tabs-height));
485 }
486
487 /* -------------------------------------------------------------------------
488 * App shell — viewport-locked flex column (issue #139)
489 *
490 * Opt-in via `{% block body_class %}app-shell{% endblock %}` on pages that
491 * use a two-column, independently-scrolling layout (issues, proposals,
492 * docs, blame, etc.) — the same pattern Gmail/Slack/VS Code/Notion use for
493 * sibling panes. Every fixed-height element above the scrollable region is
494 * `flex-shrink: 0`; the scrollable region is `flex: 1; min-height: 0`. The
495 * browser computes "whatever's left" — no calc(), no magic numbers, no
496 * per-page height budget to get wrong.
497 *
498 * This replaces `--sticky-offset`/`max-height: calc(...)` for pages that
499 * adopt it. Pages that don't opt in keep normal document scroll + footer,
500 * unchanged. See docs/issues/two-column-app-shell-refactor.md.
501 * ------------------------------------------------------------------------- */
502 body.app-shell {
503 // zoom scales the element's own rendered box, not just its descendants —
504 // a 100dvh body zoomed 1.25x paints ~125dvh tall, and the 25% below the
505 // real viewport gets silently eaten by overflow:hidden below, no matter
506 // how much a descendant scrolls internally. Divide by the same
507 // --zoom-factor used by body's own zoom so the rendered height always
508 // matches the real viewport exactly, at any zoom level.
509 height: calc(100dvh / var(--zoom-factor));
510 // _components.scss's general `body { min-height: 100dvh; }` otherwise
511 // clamps the box back up to the uncompensated 100dvh — min-height wins
512 // over a smaller height. Must override it here too.
513 min-height: 0;
514 overflow: hidden;
515 display: flex;
516 flex-direction: column;
517
518 > .musehub-navbar,
519 > #repo-header,
520 > .repo-tabs,
521 > #htmx-loading {
522 flex-shrink: 0;
523 }
524
525 > .container-wide {
526 flex: 1;
527 min-height: 0;
528 overflow: hidden;
529 display: flex;
530 flex-direction: column;
531 }
532
533 #content {
534 flex: 1;
535 min-height: 0;
536 overflow: hidden;
537 display: flex;
538 flex-direction: column;
539 }
540
541 .site-footer {
542 display: none;
543 }
544
545 @media (max-width: 900px) {
546 height: auto;
547 overflow: visible;
548 display: block;
549
550 > .container-wide,
551 #content {
552 display: block;
553 overflow: visible;
554 }
555
556 .site-footer {
557 display: flex;
558 }
559 }
560 }
561
562 .repo-tabs {
563 background: var(--bg-surface);
564 border-bottom: 1px solid var(--border-default);
565 padding: 0;
566 overflow-x: auto;
567 scrollbar-width: none;
568 position: sticky;
569 top: var(--header-height);
570 z-index: calc(var(--z-raised) - 1);
571 /* Right-only fade for overflow scroll indicator; left is flush with content */
572 -webkit-mask-image: linear-gradient(to right, black calc(100% - 32px), transparent 100%);
573 mask-image: linear-gradient(to right, black calc(100% - 32px), transparent 100%);
574 }
575
576 /* Inner wrapper aligns tabs with the page container */
577 .repo-tabs-inner {
578 display: flex;
579 align-items: stretch;
580 padding: 0 var(--space-4);
581 width: 100%;
582 }
583
584 .repo-tabs::-webkit-scrollbar { display: none; }
585
586 .repo-tab {
587 display: inline-flex;
588 align-items: center;
589 gap: var(--space-2);
590 padding: var(--space-2) var(--space-3);
591 font-size: var(--text-sm);
592 color: var(--text-muted);
593 border-bottom: 2px solid transparent;
594 white-space: nowrap;
595 text-decoration: none;
596 transition: color var(--transition-fast), border-color var(--transition-fast);
597 flex-shrink: 0;
598
599 svg {
600 opacity: 0.6;
601 transition: opacity var(--transition-fast);
602 }
603 }
604
605 .repo-tab:hover {
606 color: var(--text-primary);
607 text-decoration: none;
608 background: var(--bg-hover);
609
610 svg { opacity: 1; }
611 }
612
613 .repo-tab.active {
614 color: var(--text-primary);
615 border-bottom-color: var(--color-accent);
616
617 svg { opacity: 1; }
618 }
619
620 .tab-count {
621 background: var(--bg-overlay);
622 color: var(--text-muted);
623 border-radius: var(--radius-full);
624 padding: 0 var(--space-2);
625 font-size: var(--text-xs);
626 font-weight: var(--weight-medium);
627 min-width: 18px;
628 text-align: center;
629 }
630
631 .repo-tab.active .tab-count {
632 background: var(--color-accent);
633 color: white;
634 }
635
636 /* -------------------------------------------------------------------------
637 * Page container
638 * ------------------------------------------------------------------------- */
639 .container {
640 max-width: 960px;
641 margin: var(--space-6) auto;
642 padding: 0 var(--space-6);
643 }
644
645 .container-wide {
646 margin: var(--space-3) 0;
647 padding: 0 var(--space-4);
648 }
649
650 .container-narrow {
651 max-width: 720px;
652 margin: var(--space-6) auto;
653 padding: 0 var(--space-6);
654 }
655
656 /* -------------------------------------------------------------------------
657 * Shared full-bleed page layout (.ph-* = page hero/layout primitives)
658 *
659 * Used by MCP docs, Domain detail, and any future full-page layout.
660 * Pages using this system add:
661 * {% block container_extra_class %} page-container{% endblock %}
662 * to strip the default container padding, then manage their own padding
663 * internally so hero backgrounds can be truly full-bleed.
664 * ------------------------------------------------------------------------- */
665
666 /* Strips container padding so child sections can be full-bleed.
667 .container-wide.page-container wins over .container-wide by specificity. */
668 .container-wide.page-container,
669 .page-container {
670 padding: 0;
671 margin-top: 0;
672 }
673
674 /* ── Hero ─────────────────────────────────────────────────────────────────── */
675 .ph-hero {
676 position: relative;
677 border-bottom: 1px solid var(--border-subtle);
678 overflow: hidden;
679 padding: 0 var(--space-4);
680 }
681
682 .ph-hero-inner {
683 display: flex;
684 align-items: flex-start;
685 justify-content: space-between;
686 gap: var(--space-6);
687 padding: var(--space-6) 0 var(--space-4);
688
689 @media (max-width: 768px) { flex-direction: column; }
690 }
691
692 .ph-hero-eyebrow {
693 display: flex;
694 align-items: center;
695 gap: var(--space-2);
696 margin-bottom: var(--space-3);
697 flex-wrap: wrap;
698 }
699
700 .ph-hero-title {
701 font-size: clamp(24px, 3.5vw, 40px);
702 font-weight: 700;
703 line-height: 1.1;
704 letter-spacing: -0.02em;
705 margin: 0 0 var(--space-2);
706 color: var(--text-primary);
707 }
708
709 .ph-hero-sub {
710 font-size: 14px;
711 line-height: 1.6;
712 color: var(--text-secondary);
713 max-width: 520px;
714 margin-bottom: var(--space-3);
715 }
716
717 .ph-hero-actions {
718 display: flex;
719 gap: var(--space-2);
720 flex-wrap: wrap;
721 align-items: center;
722 }
723
724 /* ── Stats strip — flat separator bar ────────────────────────────────────── */
725 .ph-stats-strip {
726 display: flex;
727 background: transparent;
728 border-top: 1px solid var(--border-subtle);
729 border-bottom: 1px solid var(--border-subtle);
730 overflow-x: auto;
731 scrollbar-width: none;
732 &::-webkit-scrollbar { display: none; }
733 }
734
735 .ph-stat {
736 flex: 1;
737 min-width: 70px;
738 display: flex;
739 flex-direction: column;
740 align-items: center;
741 justify-content: center;
742 padding: 10px 12px;
743 gap: 2px;
744 text-align: center;
745 border-right: 1px solid var(--border-subtle);
746 &:last-child { border-right: none; }
747 }
748
749 .ph-stat-value {
750 font-size: 15px;
751 font-weight: 700;
752 color: var(--text-primary);
753 line-height: 1;
754 font-family: var(--font-mono);
755 }
756
757 .ph-stat-label {
758 font-size: 9px;
759 color: var(--text-muted);
760 text-transform: uppercase;
761 letter-spacing: 0.06em;
762 white-space: nowrap;
763 }
764
765 // Color modifiers for ph-stat-value — used by insights page
766 .ins-val--add { color: var(--color-success); }
767 .ins-val--del { color: var(--color-danger); }
768 .ins-val--agent { color: var(--color-purple); }
769
770 /* ── Page body: sidebar + main content ───────────────────────────────────── */
771 .ph-body {
772 display: grid;
773 grid-template-columns: 240px 1fr; // narrow content left | wide sidebar right
774 align-items: start;
775 gap: 0;
776 min-height: 0;
777
778 @media (max-width: 900px) { grid-template-columns: 1fr; }
779 }
780
781 /* ── Sidebar (right column) ───────────────────────────────────────────────── */
782 .ph-sidebar {
783 padding: var(--space-4) var(--space-4) var(--space-4) var(--space-3);
784 border-left: 1px solid var(--border-subtle);
785 min-width: 0;
786 position: sticky;
787 top: var(--sticky-offset, var(--header-height));
788 max-height: calc(100dvh - var(--sticky-offset, var(--header-height)) - var(--space-4));
789 overflow-y: auto;
790 scrollbar-width: thin;
791 scrollbar-color: var(--border-default) transparent;
792
793 @media (max-width: 900px) {
794 position: static;
795 max-height: none;
796 overflow-y: visible;
797 display: none;
798 }
799 }
800
801 .ph-sidebar-section {
802 padding: var(--space-4) 0;
803 border-bottom: 1px solid var(--border-subtle);
804 &:last-child { border-bottom: none; }
805 }
806
807 .ph-sidebar-heading {
808 display: flex; align-items: center; gap: 6px;
809 font-size: 10px;
810 font-weight: 700;
811 letter-spacing: 0.08em;
812 text-transform: uppercase;
813 color: var(--text-muted);
814 margin: 0 0 var(--space-2);
815 }
816
817 .ph-sidebar-link {
818 display: flex;
819 align-items: center;
820 gap: 6px;
821 padding: 3px var(--space-2);
822 border-radius: 3px;
823 font-size: 12px;
824 color: var(--text-secondary);
825 text-decoration: none;
826 transition: color 0.1s, background 0.1s;
827
828 &:hover { color: var(--text-primary); background: var(--bg-hover); text-decoration: none; }
829 &.is-active { color: var(--color-accent); }
830 }
831
832 /* ── Main content area ────────────────────────────────────────────────────── */
833 .ph-content {
834 padding: 0 var(--space-4);
835 min-width: 0;
836 }
837
838 /* ── Section: divider-based, no card box ─────────────────────────────────── */
839 .ph-section {
840 padding: var(--space-4) 0;
841 border-bottom: 1px solid var(--border-subtle);
842
843 &:last-child { border-bottom: none; }
844 }
845
846 .ph-section-title {
847 font-size: 13px;
848 font-weight: 700;
849 color: var(--text-primary);
850 margin: 0 0 var(--space-2);
851 display: flex;
852 align-items: center;
853 gap: var(--space-2);
854 }
855
856 .ph-section-desc {
857 font-size: 13px;
858 color: var(--text-muted);
859 margin: 0 0 var(--space-3);
860 line-height: 1.55;
861 }
862
863 /* ── Count badge (section title inline pill) ─────────────────────────────── */
864 .ph-count {
865 font-size: 11px;
866 font-weight: 600;
867 font-family: var(--font-mono);
868 padding: 1px 6px;
869 border-radius: var(--radius-full);
870 background: var(--bg-overlay);
871 color: var(--text-muted);
872 border: 1px solid var(--border-subtle);
873 }
874
875 /* -------------------------------------------------------------------------
876 * Section divider
877 * ------------------------------------------------------------------------- */
878 .section-title {
879 font-family: var(--font-mono);
880 font-size: var(--text-xs);
881 font-weight: var(--weight-semibold);
882 color: var(--color-accent);
883 text-transform: uppercase;
884 letter-spacing: 1.5px;
885 margin-bottom: var(--space-3);
886 padding-bottom: var(--space-2);
887 border-bottom: 1px solid var(--border-subtle);
888 }
889
890 /* -------------------------------------------------------------------------
891 * Flex utilities
892 * ------------------------------------------------------------------------- */
893 .flex { display: flex; }
894 .flex-col { display: flex; flex-direction: column; }
895 .items-center { align-items: center; }
896 .items-start { align-items: flex-start; }
897 .justify-between { justify-content: space-between; }
898 .gap-1 { gap: var(--space-1); }
899 .gap-2 { gap: var(--space-2); }
900 .gap-3 { gap: var(--space-3); }
901 .gap-4 { gap: var(--space-4); }
902 .flex-1 { flex: 1; }
903 .flex-wrap { flex-wrap: wrap; }
904 .flex-shrink-0 { flex-shrink: 0; }
905
906 /* -------------------------------------------------------------------------
907 * Spacing utilities
908 * ------------------------------------------------------------------------- */
909 .mb-2 { margin-bottom: var(--space-2); }
910 .mb-3 { margin-bottom: var(--space-3); }
911 .mb-4 { margin-bottom: var(--space-4); }
912 .mb-6 { margin-bottom: var(--space-6); }
913 .mt-2 { margin-top: var(--space-2); }
914 .mt-3 { margin-top: var(--space-3); }
915 .mt-4 { margin-top: var(--space-4); }
916
917 /* -------------------------------------------------------------------------
918 * Text utilities
919 * ------------------------------------------------------------------------- */
920 .text-muted { color: var(--text-muted); }
921 .text-primary { color: var(--text-primary); }
922 .text-accent { color: var(--color-accent); }
923 .text-danger { color: var(--color-danger); }
924 .text-success { color: var(--color-success); }
925 .text-sm { font-size: var(--text-sm); }
926 .text-xs { font-size: var(--text-xs); }
927 .text-mono { font-family: var(--font-mono); }
928 .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
929
930 /* -------------------------------------------------------------------------
931 * Repo landing page — two-column layout (GitHub-style)
932 * Main content (~68%) + sidebar (~30%), collapses to single column on mobile.
933 * ------------------------------------------------------------------------- */
934 .repo-layout {
935 display: grid;
936 grid-template-columns: minmax(0, 1fr) 296px;
937 gap: var(--space-6);
938 align-items: start;
939 margin-top: var(--space-6);
940 }
941
942 .repo-main { min-width: 0; }
943 .repo-sidebar { min-width: 0; }
944
945 @media (max-width: 1023px) {
946 .repo-layout {
947 grid-template-columns: 1fr;
948 }
949 /* On mobile, sidebar collapses above main (like GitHub mobile) */
950 .repo-sidebar { order: -1; }
951 }
952
953 /* Latest commit banner — sits flush above the commit card */
954 .latest-commit-banner {
955 background: var(--bg-overlay);
956 border: 1px solid var(--border-default);
957 border-radius: var(--radius-base) var(--radius-base) 0 0;
958 border-bottom: none;
959 padding: var(--space-3) var(--space-4);
960 display: flex;
961 align-items: center;
962 gap: var(--space-2);
963 font-size: var(--text-sm);
964 color: var(--text-secondary);
965 }
966
967 /* Small inline avatar (author initials) in commit rows and banner */
968 .commit-avatar {
969 width: 20px;
970 height: 20px;
971 border-radius: var(--radius-full);
972 display: inline-flex;
973 align-items: center;
974 justify-content: center;
975 font-size: 9px;
976 font-weight: var(--weight-bold);
977 color: #fff;
978 flex-shrink: 0;
979 vertical-align: middle;
980 }
981
982 /* ── Sidebar ── */
983
984 /* Star / Watch / Fork action strip */
985 .repo-action-strip {
986 display: flex;
987 gap: var(--space-2);
988 margin-bottom: var(--space-5);
989 }
990
991 .repo-action-btn {
992 display: flex;
993 align-items: center;
994 justify-content: center;
995 gap: 4px;
996 padding: 5px var(--space-3);
997 font-size: var(--text-sm);
998 border: 1px solid var(--border-default);
999 border-radius: var(--radius-base);
1000 background: var(--bg-overlay);
1001 color: var(--text-secondary);
1002 cursor: pointer;
1003 text-decoration: none;
1004 flex: 1;
1005 line-height: 1.4;
1006 transition: background var(--transition-fast), color var(--transition-fast);
1007 }
1008
1009 .repo-action-btn:hover {
1010 background: var(--bg-hover);
1011 color: var(--text-primary);
1012 text-decoration: none;
1013 }
1014
1015 .repo-action-btn.active {
1016 background: var(--color-accent-muted);
1017 border-color: var(--color-accent);
1018 color: var(--text-primary);
1019 }
1020
1021 .repo-action-count {
1022 font-weight: var(--weight-semibold);
1023 color: var(--text-primary);
1024 font-size: var(--text-xs);
1025 }
1026
1027 /* Sidebar sections — each separated by a subtle rule */
1028 .sidebar-section {
1029 padding-bottom: var(--space-5);
1030 margin-bottom: var(--space-5);
1031 border-bottom: 1px solid var(--border-subtle);
1032 }
1033
1034 .sidebar-section:last-child {
1035 border-bottom: none;
1036 margin-bottom: 0;
1037 padding-bottom: 0;
1038 }
1039
1040 .sidebar-section h3 {
1041 font-size: var(--text-sm);
1042 font-weight: var(--weight-semibold);
1043 color: var(--text-primary);
1044 margin-bottom: var(--space-3);
1045 display: flex;
1046 align-items: center;
1047 gap: var(--space-2);
1048 }
1049
1050 /* About section prose */
1051 .about-description {
1052 font-size: var(--text-sm);
1053 color: var(--text-secondary);
1054 line-height: 1.6;
1055 margin-bottom: var(--space-3);
1056 }
1057
1058 .about-stat-row {
1059 display: flex;
1060 align-items: center;
1061 gap: var(--space-2);
1062 font-size: var(--text-sm);
1063 color: var(--text-secondary);
1064 padding: 3px 0;
1065 }
1066
1067 .about-stat-row strong {
1068 color: var(--text-primary);
1069 font-weight: var(--weight-semibold);
1070 }
1071
1072 /* Contributor avatar grid */
1073 .contributor-grid {
1074 display: flex;
1075 flex-wrap: wrap;
1076 gap: var(--space-1);
1077 margin-bottom: var(--space-2);
1078 }
1079
1080 .contributor-avatar {
1081 width: 32px;
1082 height: 32px;
1083 border-radius: var(--radius-full);
1084 background: var(--bg-overlay);
1085 border: 2px solid var(--border-default);
1086 display: inline-flex;
1087 align-items: center;
1088 justify-content: center;
1089 font-size: 11px;
1090 font-weight: var(--weight-bold);
1091 color: #fff;
1092 text-decoration: none;
1093 cursor: pointer;
1094 transition: border-color var(--transition-fast), transform var(--transition-fast);
1095 position: relative;
1096 flex-shrink: 0;
1097 }
1098
1099 .contributor-avatar:hover {
1100 border-color: var(--color-accent);
1101 transform: scale(1.15);
1102 text-decoration: none;
1103 z-index: 1;
1104 }
1105
1106 /* Instrument / track breakdown bar (like GitHub's language bar) */
1107 .instrument-bar {
1108 height: 8px;
1109 border-radius: var(--radius-full);
1110 overflow: hidden;
1111 display: flex;
1112 gap: 2px;
1113 margin-bottom: var(--space-3);
1114 }
1115
1116 .instrument-segment {
1117 height: 100%;
1118 transition: opacity var(--transition-fast);
1119 }
1120
1121 .instrument-segment:hover { opacity: 0.7; }
1122
1123 .instrument-legend {
1124 display: flex;
1125 flex-wrap: wrap;
1126 gap: var(--space-1) var(--space-4);
1127 }
1128
1129 .instrument-legend-item {
1130 display: flex;
1131 align-items: center;
1132 gap: var(--space-1);
1133 font-size: var(--text-xs);
1134 color: var(--text-secondary);
1135 }
1136
1137 .instrument-dot {
1138 width: 10px;
1139 height: 10px;
1140 border-radius: 50%;
1141 flex-shrink: 0;
1142 }
1143
1144 /* -------------------------------------------------------------------------
1145 * Responsive breakpoints — mobile-first overrides
1146 * ------------------------------------------------------------------------- */
1147
1148 /* xs — phones < 480px */
1149 @media (max-width: 479px) {
1150 header {
1151 padding: var(--space-2) var(--space-3);
1152 gap: var(--space-2);
1153 }
1154
1155 header .breadcrumb {
1156 display: none;
1157 }
1158
1159 /* Mobile navbar: hamburger visible, search and actions collapse */
1160 .navbar-hamburger {
1161 display: flex;
1162 }
1163
1164 .navbar-search-form {
1165 display: none;
1166 max-width: 100%;
1167 }
1168
1169 .navbar-actions {
1170 display: none;
1171 position: absolute;
1172 top: 100%;
1173 left: 0;
1174 right: 0;
1175 background: var(--bg-surface);
1176 border-bottom: 1px solid var(--border-default);
1177 flex-direction: column;
1178 align-items: flex-start;
1179 padding: var(--space-3) var(--space-4);
1180 gap: var(--space-2);
1181 z-index: calc(var(--z-raised) + 1);
1182 }
1183
1184 /* Show when hamburger checkbox is checked */
1185 .navbar-toggle-input:checked ~ * .navbar-search-form,
1186 .navbar-toggle-input:checked + .navbar-inner .navbar-search-form {
1187 display: flex;
1188 }
1189
1190 .navbar-toggle-input:checked ~ .navbar-inner .navbar-actions {
1191 display: flex;
1192 }
1193
1194 .musehub-navbar {
1195 position: relative;
1196 }
1197
1198 .container,
1199 .container-wide,
1200 .container-narrow {
1201 padding: 0 var(--space-3);
1202 margin-top: var(--space-4);
1203 }
1204
1205 .grid-2,
1206 .grid-3 {
1207 grid-template-columns: 1fr;
1208 }
1209
1210 h1 { font-size: var(--text-md); }
1211 h2 { font-size: var(--text-base); }
1212 }
1213
1214 /* sm — large phones 480-767px */
1215 @media (min-width: 480px) and (max-width: 767px) {
1216 header {
1217 padding: var(--space-2) var(--space-4);
1218 }
1219
1220 .container,
1221 .container-wide,
1222 .container-narrow {
1223 padding: 0 var(--space-4);
1224 }
1225
1226 .grid-3 {
1227 grid-template-columns: 1fr 1fr;
1228 }
1229 }
1230
1231 /* md — tablets 768-1023px */
1232 @media (min-width: 768px) and (max-width: 1023px) {
1233 .container {
1234 max-width: 100%;
1235 padding: 0 var(--space-6);
1236 }
1237
1238 }
1239
1240 /* lg — laptops 1024px+ */
1241 @media (min-width: 1024px) {
1242 /* Full layout — no overrides needed; base styles apply */
1243 }
1244
1245 /* xl — desktops 1280px+ */
1246 @media (min-width: 1280px) {
1247 /* No overrides needed — content is full-width at all viewport sizes */
1248 }
1249
1250 /* -------------------------------------------------------------------------
1251 * Print styles (minimal — MuseHub is primarily a screen UI)
1252 * ------------------------------------------------------------------------- */
1253 @media print {
1254 header { display: none; }
1255 .btn { display: none; }
1256 .token-form { display: none; }
1257 pre { white-space: pre-wrap; border: 1px solid var(--border-default); }
1258 }
1259
1260 /* =========================================================================
1261 * Muse protocol design language utilities
1262 * ========================================================================= */
1263
1264 /* -------------------------------------------------------------------------
1265 * Section eyebrow
1266 * Monospace uppercase label placed above section headings, identical in
1267 * style to the section labels used on cgcardona.github.io/muse/.
1268 * Usage: <p class="eyebrow">Protocol</p><h2>…</h2>
1269 * ------------------------------------------------------------------------- */
1270 .eyebrow {
1271 font-family: var(--font-mono);
1272 font-size: 11px;
1273 color: var(--color-accent);
1274 letter-spacing: 2px;
1275 text-transform: uppercase;
1276 margin-bottom: var(--space-2);
1277 font-weight: var(--weight-medium);
1278 }
1279
1280 /* -------------------------------------------------------------------------
1281 * Page sections — full-bleed horizontal bands with border separator,
1282 * mirroring the section rhythm on the Muse protocol site.
1283 * .page-section — default (--bg-base background)
1284 * .page-section-alt — elevated surface (--bg-surface background)
1285 * .page-section-hero — gradient glow overlay for landing/hero areas
1286 * ------------------------------------------------------------------------- */
1287 .page-section {
1288 padding: var(--space-12) var(--space-6);
1289 border-top: 1px solid var(--border-subtle);
1290 }
1291
1292 .page-section-alt {
1293 background: var(--bg-surface);
1294 }
1295
1296 .page-section-hero {
1297 background:
1298 var(--gradient-hero),
1299 linear-gradient(160deg, var(--bg-base) 0%, var(--bg-surface) 50%, var(--bg-base) 100%);
1300 border-bottom: 1px solid var(--border-default);
1301 }
1302
1303 /* Section lead text — descriptive subtitle beneath a section heading */
1304 .section-lead {
1305 font-size: var(--text-md);
1306 color: var(--text-muted);
1307 max-width: 620px;
1308 margin-bottom: var(--space-10);
1309 line-height: 1.7;
1310
1311 strong { color: var(--text-primary); }
1312 }
1313
1314 /* -------------------------------------------------------------------------
1315 * Accent text — solid brand blue for headings and wordmarks.
1316 * ------------------------------------------------------------------------- */
1317 .gradient-text {
1318 color: var(--color-accent);
1319 }
1320
1321 /* -------------------------------------------------------------------------
1322 * Radial glow overlay — decorative background for hero / banner cards.
1323 * Apply to a position:relative container; the pseudo-element renders the
1324 * radial gradients as a non-interactive overlay.
1325 * ------------------------------------------------------------------------- */
1326 .glow-overlay {
1327 position: relative;
1328 overflow: hidden;
1329
1330 &::before {
1331 content: '';
1332 position: absolute;
1333 inset: 0;
1334 background: var(--gradient-hero);
1335 pointer-events: none;
1336 z-index: 0;
1337 }
1338
1339 > * { position: relative; z-index: 1; }
1340 }
1341
1342 /* -------------------------------------------------------------------------
1343 * Site footer
1344 * ------------------------------------------------------------------------- */
1345
1346 .site-footer {
1347 margin-top: var(--space-12);
1348 border-top: 1px solid var(--border-subtle);
1349 background: var(--bg-base);
1350
1351 &__inner {
1352 display: flex;
1353 align-items: center;
1354 gap: var(--space-6);
1355 max-width: 1280px;
1356 margin: 0 auto;
1357 padding: var(--space-4) var(--space-6);
1358 flex-wrap: wrap;
1359 }
1360
1361 &__brand {
1362 font-size: var(--text-sm);
1363 font-weight: 700;
1364 color: var(--text-primary);
1365 letter-spacing: 0.02em;
1366 }
1367
1368 &__copy {
1369 font-size: var(--text-xs);
1370 color: var(--text-muted);
1371 flex: 1;
1372 }
1373
1374 &__legal {
1375 display: flex;
1376 gap: var(--space-4);
1377
1378 a {
1379 font-size: var(--text-xs);
1380 color: var(--text-muted);
1381 text-decoration: none;
1382 transition: color 0.15s ease;
1383
1384 &:hover {
1385 color: var(--color-accent-link);
1386 }
1387 }
1388 }
1389 }
File History 1 commit
sha256:6ad6d62107bbd6940c52d63327966b8a65c6391f4a3da6cd9e7548ba4b38bc48 feat(musehub#129): OG repo preview cards — endpoint, cache,… Human minor 14 days ago