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