1/*
2 * impeccable.style — shared styles for sub-pages and the site-wide header
3 *
4 * Imported by all generated pages under /skills, /anti-patterns, /tutorials,
5 * and by the hand-authored pages (index, cheatsheet, gallery, privacy) via
6 * a direct <link> tag so they all share the same header + prose typography.
7 */
8
9@import "./tokens.css";
10@import "./docs-visuals.css";
11
12/* ============================================
13 SKIP LINK (a11y)
14 ============================================ */
15
16.skip-link {
17 position: absolute;
18 top: -100%;
19 left: 50%;
20 transform: translateX(-50%);
21 z-index: 10000;
22 padding: var(--spacing-sm) var(--spacing-lg);
23 background: var(--color-ink);
24 color: var(--color-paper);
25 font-weight: 600;
26 text-decoration: none;
27 border-radius: 0 0 8px 8px;
28 transition: top 0.2s ease;
29}
30
31.skip-link:focus {
32 top: 0;
33 outline: 2px solid var(--color-accent);
34 outline-offset: 2px;
35}
36
37/* ============================================
38 BASE
39 ============================================ */
40
41/* No smooth scroll — long editorial pages feel slow on anchor jumps, and
42 a secretly-smooth CSS rule also overrides JS `behavior: 'auto'` calls. */
43
44body {
45 font-family: var(--font-body);
46 color: var(--color-ink);
47 background: var(--color-paper);
48 line-height: 1.6;
49 -webkit-font-smoothing: antialiased;
50 -moz-osx-font-smoothing: grayscale;
51 text-rendering: optimizeLegibility;
52}
53
54a {
55 color: inherit;
56 text-decoration: none;
57}
58
59/* ============================================
60 SHARED SITE HEADER
61 ============================================ */
62
63.site-header {
64 position: sticky;
65 top: 0;
66 z-index: 100;
67 display: flex;
68 align-items: center;
69 justify-content: space-between;
70 gap: var(--spacing-md);
71 padding: 14px clamp(var(--spacing-md), 4vw, var(--spacing-2xl));
72 background: color-mix(in oklch, var(--color-paper) 94%, transparent);
73 -webkit-backdrop-filter: saturate(1.4) blur(16px);
74 backdrop-filter: saturate(1.4) blur(16px);
75 border-bottom: 1px solid var(--color-mist);
76}
77
78/* Kill any inherited text-decoration from page-level `a` rules. */
79.site-header a,
80.site-header a:hover {
81 text-decoration: none;
82 text-decoration-thickness: 0;
83}
84
85.site-header-brand {
86 display: inline-flex;
87 align-items: center;
88 gap: 10px;
89 font-family: var(--font-display);
90 font-size: 1.25rem;
91 font-weight: 600;
92 letter-spacing: -0.01em;
93 color: var(--color-ink);
94 flex-shrink: 0;
95 transition: color var(--duration-fast) var(--ease-out);
96}
97
98.site-header-brand:hover {
99 color: var(--color-accent);
100}
101
102.site-header-brand-logo {
103 width: 26px;
104 height: 26px;
105 border-radius: 6px;
106 flex-shrink: 0;
107}
108
109.site-header-brand-name {
110 display: inline-block;
111}
112
113.site-header-right {
114 display: flex;
115 align-items: center;
116 gap: clamp(var(--spacing-sm), 2vw, var(--spacing-md));
117 min-width: 0;
118}
119
120.site-header-nav {
121 display: flex;
122 align-items: center;
123 gap: clamp(var(--spacing-sm), 2vw, var(--spacing-md));
124 font-family: var(--font-body);
125 font-size: 0.9375rem;
126 font-weight: 500;
127 min-width: 0;
128}
129
130.site-header-nav a {
131 position: relative;
132 display: inline-block;
133 white-space: nowrap;
134 color: var(--color-charcoal);
135 padding: 4px 0;
136 transition: color var(--duration-fast) var(--ease-out);
137}
138
139.site-header-nav a:hover {
140 color: var(--color-accent);
141}
142
143.site-header-nav a[aria-current="page"] {
144 color: var(--color-ink);
145 font-weight: 600;
146}
147
148.site-header-nav a[aria-current="page"]::after {
149 content: "";
150 position: absolute;
151 left: 0;
152 right: 0;
153 bottom: -4px;
154 height: 2px;
155 background: var(--color-accent);
156 border-radius: 2px;
157}
158
159/* GitHub star pill — subtle, inviting nudge without shouting */
160.site-header-github {
161 display: inline-flex;
162 align-items: center;
163 gap: 6px;
164 padding: 4px 10px 4px 8px;
165 border-radius: 99px;
166 background: var(--color-cream);
167 border: 1px solid var(--color-mist);
168 font-family: var(--font-mono);
169 font-size: 0.8125rem;
170 font-weight: 500;
171 color: var(--color-charcoal);
172 flex-shrink: 0;
173 transition:
174 background var(--duration-fast) var(--ease-out),
175 border-color var(--duration-fast) var(--ease-out),
176 color var(--duration-fast) var(--ease-out);
177}
178
179.site-header-github svg {
180 width: 14px;
181 height: 14px;
182 flex-shrink: 0;
183}
184
185.site-header-github:hover {
186 background: var(--color-paper);
187 border-color: var(--color-ink);
188 color: var(--color-ink);
189}
190
191.site-header-github-star {
192 color: #f59e0b;
193 width: 12px;
194 height: 12px;
195 flex-shrink: 0;
196}
197
198@media (max-width: 820px) {
199 .site-header {
200 padding: 12px var(--spacing-md);
201 gap: var(--spacing-sm);
202 }
203
204 .site-header-brand {
205 font-size: 1.0625rem;
206 }
207
208 .site-header-brand-logo {
209 width: 22px;
210 height: 22px;
211 }
212
213 .site-header-right {
214 gap: var(--spacing-sm);
215 }
216
217 .site-header-nav {
218 font-size: 0.8125rem;
219 gap: var(--spacing-sm);
220 overflow-x: auto;
221 scrollbar-width: none;
222 -webkit-overflow-scrolling: touch;
223 /* fade the right edge so users see there's more to scroll */
224 mask-image: linear-gradient(to right, black 0%, black calc(100% - 24px), transparent 100%);
225 -webkit-mask-image: linear-gradient(to right, black 0%, black calc(100% - 24px), transparent 100%);
226 }
227
228 .site-header-nav::-webkit-scrollbar {
229 display: none;
230 }
231
232 .site-header-nav a[data-nav="home"] {
233 /* Brand already acts as home link on mobile */
234 display: none;
235 }
236
237 .site-header-github {
238 padding: 4px 8px;
239 }
240
241 .site-header-github-label {
242 display: none;
243 }
244}
245
246@media (max-width: 480px) {
247 .site-header-brand-name {
248 /* Logo alone on narrow screens */
249 display: none;
250 }
251}
252
253/* ============================================
254 SUB-PAGE LAYOUT SHELL
255 ============================================ */
256
257main#main {
258 display: block;
259}
260
261.sub-page-content {
262 max-width: 820px;
263 margin: 0 auto;
264 padding: clamp(2rem, 5vw, 4rem) clamp(1.25rem, 4vw, 2.5rem) 6rem;
265}
266
267.skill-detail {
268 /* No max-width on the article itself. The editorial body sections
269 (header, editorial wrapper, skill source, references) each cap
270 themselves at 720px for readable line length, while the hero is
271 allowed to break out on wide viewports. */
272 width: 100%;
273}
274
275.sub-page-header {
276 margin-bottom: clamp(2.5rem, 6vw, 4rem);
277}
278
279.sub-page-eyebrow {
280 font-family: var(--font-mono);
281 font-size: 0.75rem;
282 font-weight: 600;
283 text-transform: uppercase;
284 letter-spacing: 0.14em;
285 color: var(--color-accent);
286 margin-bottom: var(--spacing-sm);
287}
288
289.sub-page-title {
290 font-family: var(--font-display);
291 font-size: clamp(2.5rem, 6vw, 4.5rem);
292 font-weight: 400;
293 line-height: 1.05;
294 letter-spacing: -0.02em;
295 color: var(--color-ink);
296 margin-bottom: var(--spacing-md);
297}
298
299.sub-page-lede {
300 font-size: clamp(1rem, 1.4vw, 1.125rem);
301 line-height: 1.55;
302 color: var(--color-charcoal);
303 max-width: 62ch;
304}
305
306/* ============================================
307 DOCS-BROWSER LAYOUT (used by /skills)
308 ============================================ */
309
310:root {
311 --site-header-height: 62px;
312 --skills-sidebar-width: 200px;
313}
314
315.skills-layout-page main#main {
316 /* Reset: the docs layout provides its own max-width container. */
317 max-width: none;
318 margin: 0;
319 padding: 0;
320}
321
322.skills-layout {
323 display: grid;
324 grid-template-columns: var(--skills-sidebar-width) minmax(0, 1fr);
325 gap: clamp(var(--spacing-lg), 4vw, var(--spacing-2xl));
326 /*
327 * Match horizontal padding to .site-header so the sidebar content lines
328 * up with the brand logo in the nav bar above. Intentionally no max-width
329 * so the docs-browser feels wall-to-wall on wide screens.
330 */
331 padding: 0 clamp(var(--spacing-md), 4vw, var(--spacing-2xl));
332 align-items: start;
333}
334
335/* ============================================
336 SIDEBAR
337 ============================================ */
338
339.skills-sidebar {
340 position: sticky;
341 top: var(--site-header-height);
342 align-self: start;
343 max-height: calc(100vh - var(--site-header-height));
344 overflow-y: auto;
345 padding: var(--spacing-lg) 0 var(--spacing-2xl);
346 border-right: 1px solid var(--color-mist);
347 scrollbar-width: thin;
348 scrollbar-color: var(--color-mist) transparent;
349}
350
351/* Desktop only: reserve full viewport height so the border-right
352 divider reaches the bottom of the viewport even on short pages.
353 On mobile this rule would leave a viewport-sized empty block
354 above the main content when the menu is collapsed. */
355@media (min-width: 921px) {
356 .skills-sidebar {
357 min-height: calc(100vh - var(--site-header-height));
358 }
359}
360
361.skills-sidebar::-webkit-scrollbar {
362 width: 6px;
363}
364
365.skills-sidebar::-webkit-scrollbar-thumb {
366 background: var(--color-mist);
367 border-radius: 3px;
368}
369
370.skills-sidebar-inner {
371 padding-right: var(--spacing-md);
372}
373
374/* Mobile menu toggle. Hidden on desktop. */
375.skills-sidebar-toggle {
376 display: none;
377}
378
379.skills-sidebar-toggle-chevron {
380 transition: transform var(--duration-base) var(--ease-out);
381 flex-shrink: 0;
382 color: var(--color-ash);
383}
384
385/* Label at the top of the sidebar — hidden visually, kept for a11y tree. */
386.skills-sidebar-label {
387 position: absolute;
388 width: 1px;
389 height: 1px;
390 padding: 0;
391 margin: -1px;
392 overflow: hidden;
393 clip: rect(0, 0, 0, 0);
394 border: 0;
395}
396
397.skills-sidebar-group {
398 margin-bottom: 1.5rem;
399}
400
401.skills-sidebar-group:last-child {
402 margin-bottom: 0;
403}
404
405.skills-sidebar-divider {
406 border: none;
407 height: 1px;
408 background: var(--color-mist);
409 margin: 0 0 1.5rem 0;
410 width: 100%;
411}
412
413.skills-sidebar-group-title {
414 font-family: var(--font-mono);
415 font-size: 0.625rem;
416 font-weight: 600;
417 text-transform: uppercase;
418 letter-spacing: 0.14em;
419 color: var(--color-ash);
420 margin-bottom: 6px;
421 /* Match the link text's 14px left inset (2 border + 12 padding) so
422 category titles and link labels start at the same x position. */
423 padding: 0 0 0 14px;
424}
425
426.skills-sidebar-list {
427 list-style: none;
428 padding: 0;
429 margin: 0;
430}
431
432.skills-sidebar-list li {
433 margin: 0;
434}
435
436.skills-sidebar-list a {
437 display: block;
438 /* Border sits inside the normal flow (no negative margin) because
439 the sidebar's `overflow-y: auto` coerces overflow-x to auto too
440 per CSS spec, which would clip any border hanging left of the
441 column. Text is inset 14px (2 border + 12 padding) from the column
442 edge; group titles above use the same 14px inset. Accepts a small
443 misalignment with the header logo in exchange for a visible
444 active-state accent. */
445 padding: 4px 0 4px 12px;
446 border-left: 2px solid transparent;
447 font-family: var(--font-mono);
448 font-size: 0.875rem;
449 font-weight: 500;
450 line-height: 1.5;
451 color: var(--color-charcoal);
452 text-decoration: none;
453 transition: color var(--duration-fast) var(--ease-out),
454 border-color var(--duration-fast) var(--ease-out),
455 background var(--duration-fast) var(--ease-out);
456}
457
458.skills-sidebar-list a:hover {
459 color: var(--color-accent);
460 background: color-mix(in oklch, var(--color-accent-dim) 30%, transparent);
461}
462
463.skills-sidebar-list a[aria-current="page"] {
464 color: var(--color-ink);
465 font-weight: 600;
466 border-left-color: var(--color-accent);
467}
468
469.skills-sidebar-list a[aria-current="page"]:hover {
470 color: var(--color-ink);
471 background: transparent;
472}
473
474.skills-sidebar-sub a {
475 padding-left: 24px;
476 font-size: 0.8125rem;
477 color: var(--color-ash);
478}
479
480/* ============================================
481 OVERVIEW MAIN CONTENT
482 ============================================ */
483
484.skills-main {
485 min-width: 0;
486 padding: clamp(2rem, 4vw, 3.5rem) 0 clamp(4rem, 8vw, 6rem);
487}
488
489/* ============================================
490 DOCS OVERVIEW — /skills page
491 ============================================ */
492
493.docs-overview {
494 max-width: 920px;
495}
496
497.docs-overview-header {
498 margin-bottom: clamp(2rem, 4vw, 3rem);
499}
500
501.docs-overview-header .sub-page-lede {
502 max-width: 60ch;
503}
504
505/* Home command hero — the /impeccable root card that sits above the
506 category sections. It gets special treatment because it's the entry
507 point, not just another command in a category. */
508.docs-home-card {
509 display: grid;
510 grid-template-columns: 1.1fr 1fr;
511 gap: clamp(1.5rem, 3vw, 2.5rem);
512 padding: clamp(1.5rem, 3vw, 2rem);
513 background: #ffffff;
514 border: 1px solid var(--color-mist);
515 border-radius: 12px;
516 margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
517}
518
519.docs-home-card-identity {
520 min-width: 0;
521}
522
523.docs-home-card-eyebrow {
524 display: inline-block;
525 font-family: var(--font-body);
526 font-size: 0.6875rem;
527 font-weight: 600;
528 text-transform: uppercase;
529 letter-spacing: 0.12em;
530 color: var(--color-accent);
531 margin-bottom: var(--spacing-sm);
532}
533
534.docs-home-card-title {
535 font-family: var(--font-display);
536 font-size: clamp(2rem, 4vw, 2.75rem);
537 font-weight: 500;
538 font-style: italic;
539 color: var(--color-ink);
540 letter-spacing: -0.02em;
541 line-height: 1;
542 margin: 0 0 var(--spacing-sm) 0;
543}
544
545.docs-home-card-tagline {
546 font-family: var(--font-body);
547 font-size: 1rem;
548 font-weight: 500;
549 color: var(--color-ink);
550 line-height: 1.5;
551 margin: 0 0 var(--spacing-md) 0;
552 max-width: 32ch;
553}
554
555.docs-home-card-desc {
556 font-size: 0.9375rem;
557 line-height: 1.6;
558 color: var(--color-ink);
559 max-width: 36ch;
560 margin: 0;
561}
562
563.docs-home-card-desc code {
564 font-family: var(--font-mono);
565 font-size: 0.8125rem;
566 font-weight: 500;
567 color: var(--color-ink);
568 background: var(--color-accent-dim);
569 padding: 1px 6px;
570 border-radius: 3px;
571}
572
573.docs-home-card-modes {
574 list-style: none;
575 padding: 0;
576 margin: 0;
577 display: flex;
578 flex-direction: column;
579 gap: var(--spacing-md);
580}
581
582.docs-home-card-modes a {
583 display: block;
584 text-decoration: none;
585 padding-left: 10px;
586 border-left: 2px solid transparent;
587 transition:
588 border-color var(--duration-fast) var(--ease-out, ease),
589 color var(--duration-fast) var(--ease-out, ease);
590}
591
592.docs-home-card-modes a:hover {
593 border-left-color: var(--color-accent);
594}
595
596.docs-home-card-modes a:hover .docs-home-mode-label {
597 color: var(--color-accent);
598}
599
600.docs-home-mode-label {
601 display: block;
602 font-family: var(--font-mono);
603 font-size: 0.875rem;
604 font-weight: 600;
605 color: var(--color-ink);
606 margin-bottom: 2px;
607}
608
609.docs-home-mode-slash {
610 color: var(--color-accent);
611 font-weight: 400;
612}
613
614.docs-home-mode-hint {
615 display: block;
616 font-family: var(--font-body);
617 font-size: 0.8125rem;
618 color: var(--color-charcoal);
619 line-height: 1.4;
620}
621
622/* Category sections with rich command cards */
623.docs-categories {
624 display: flex;
625 flex-direction: column;
626 gap: clamp(2.5rem, 5vw, 3.5rem);
627}
628
629.docs-category-header {
630 display: flex;
631 align-items: baseline;
632 justify-content: space-between;
633 gap: var(--spacing-md);
634 margin-bottom: var(--spacing-md);
635 padding-bottom: var(--spacing-sm);
636 border-bottom: 1px solid var(--color-mist);
637}
638
639.docs-category-title {
640 font-family: var(--font-display);
641 font-size: clamp(1.5rem, 3vw, 2rem);
642 font-weight: 500;
643 font-style: italic;
644 color: var(--color-ink);
645 letter-spacing: -0.01em;
646 line-height: 1.1;
647 margin: 0 0 4px 0;
648}
649
650.docs-category-desc {
651 font-size: 0.875rem;
652 line-height: 1.5;
653 color: var(--color-charcoal);
654 max-width: 58ch;
655 margin: 0;
656}
657
658.docs-category-count {
659 font-family: var(--font-mono);
660 font-size: 0.6875rem;
661 font-weight: 600;
662 text-transform: uppercase;
663 letter-spacing: 0.12em;
664 color: var(--color-ash);
665 white-space: nowrap;
666 flex-shrink: 0;
667}
668
669/* Dense two-column rows for each command: name on the left, description +
670 relationship on the right. Mirrors the original cheatsheet density. */
671.docs-category-rows {
672 display: flex;
673 flex-direction: column;
674}
675
676.command-row {
677 display: grid;
678 grid-template-columns: minmax(11rem, 13rem) 1fr;
679 gap: var(--spacing-lg);
680 padding: var(--spacing-md) 0;
681 border-bottom: 1px solid var(--color-mist);
682 align-items: baseline;
683}
684
685.command-row:last-child {
686 border-bottom: none;
687}
688
689.command-row-name {
690 font-family: var(--font-mono);
691 font-size: 0.875rem;
692 font-weight: 600;
693 color: var(--color-ink);
694 line-height: 1.4;
695 min-width: 0;
696}
697
698.command-row-name a {
699 color: inherit;
700 text-decoration: none;
701 border-bottom: 1px solid transparent;
702 transition: border-color var(--duration-fast) var(--ease-out, ease);
703}
704
705.command-row-name a:hover {
706 border-bottom-color: var(--color-accent);
707}
708
709.command-row-namespace {
710 color: var(--color-ash);
711 font-weight: 400;
712}
713
714.command-row-beta {
715 display: inline-block;
716 font-family: var(--font-mono);
717 font-size: 0.5625rem;
718 font-weight: 600;
719 letter-spacing: 0.08em;
720 text-transform: uppercase;
721 color: var(--color-accent);
722 border: 1px solid var(--color-accent);
723 border-radius: 3px;
724 padding: 1px 5px;
725 vertical-align: 1px;
726 margin-left: 4px;
727}
728
729.command-row-info {
730 min-width: 0;
731}
732
733.command-row-desc {
734 font-family: var(--font-body);
735 font-size: 0.875rem;
736 line-height: 1.55;
737 color: var(--color-ink);
738 margin: 0;
739}
740
741.command-row-rel {
742 font-family: var(--font-body);
743 font-size: 0.75rem;
744 line-height: 1.5;
745 color: var(--color-ash);
746 margin-top: 4px;
747}
748
749.command-row-rel a {
750 font-family: var(--font-mono);
751 font-size: 0.75rem;
752 color: var(--color-charcoal);
753 text-decoration: none;
754 border-bottom: 1px solid var(--color-mist);
755 transition: color var(--duration-fast) var(--ease-out, ease),
756 border-color var(--duration-fast) var(--ease-out, ease);
757}
758
759.command-row-rel a:hover {
760 color: var(--color-accent);
761 border-color: var(--color-accent);
762}
763
764/* Narrow viewport: stack name above info */
765@media (max-width: 820px) {
766 .docs-home-card {
767 grid-template-columns: 1fr;
768 }
769
770 .command-row {
771 grid-template-columns: 1fr;
772 gap: 4px;
773 }
774}
775
776/* ============================================
777 ANTI-PATTERNS INDEX
778 ============================================ */
779
780.anti-patterns-sidebar-list a {
781 display: flex !important;
782 align-items: baseline;
783 justify-content: space-between;
784 gap: var(--spacing-sm);
785}
786
787.anti-patterns-sidebar-count {
788 font-size: 0.6875rem;
789 font-weight: 500;
790 color: var(--color-ash);
791 font-variant-numeric: tabular-nums;
792}
793
794/* The anti-patterns page lets the grid of rule cards use the full
795 column width. Header, lede, and legend stay capped for line length. */
796.anti-patterns-content {
797 width: 100%;
798}
799
800.anti-patterns-header {
801 max-width: 720px;
802 margin-bottom: clamp(2rem, 4vw, 3rem);
803}
804
805.anti-patterns-header .sub-page-lede code {
806 font-family: var(--font-mono);
807 font-size: 0.875em;
808 color: var(--color-ink);
809 background: var(--color-cream);
810 padding: 2px 6px;
811 border-radius: 4px;
812 border: 1px solid var(--color-mist);
813}
814
815.anti-patterns-header .sub-page-lede a {
816 color: var(--color-ink);
817 text-decoration: underline;
818 text-decoration-color: var(--color-accent);
819 text-decoration-thickness: 1px;
820 text-underline-offset: 4px;
821 font-family: var(--font-mono);
822 font-weight: 500;
823 font-size: 0.9375em;
824}
825
826.anti-patterns-legend {
827 background: var(--color-cream);
828 border: 1px solid var(--color-mist);
829 border-radius: 10px;
830 margin-bottom: clamp(2rem, 4vw, 3rem);
831 max-width: 720px;
832}
833
834.anti-patterns-legend-summary {
835 list-style: none;
836 cursor: pointer;
837 display: flex;
838 align-items: center;
839 justify-content: space-between;
840 gap: var(--spacing-sm);
841 padding: 14px var(--spacing-lg);
842 transition: background var(--duration-fast) var(--ease-out);
843}
844
845.anti-patterns-legend-summary::-webkit-details-marker {
846 display: none;
847}
848
849.anti-patterns-legend-summary:hover {
850 background: color-mix(in oklch, var(--color-mist) 40%, transparent);
851}
852
853.anti-patterns-legend-title {
854 font-family: var(--font-body);
855 font-size: 0.875rem;
856 font-weight: 600;
857 color: var(--color-ink);
858}
859
860.anti-patterns-legend-chevron {
861 color: var(--color-ash);
862 transition: transform var(--duration-base) var(--ease-out);
863 flex-shrink: 0;
864}
865
866.anti-patterns-legend[open] .anti-patterns-legend-chevron {
867 transform: rotate(180deg);
868}
869
870.anti-patterns-legend-body {
871 padding: 0 var(--spacing-lg) var(--spacing-lg);
872 border-top: 1px solid var(--color-mist);
873 margin-top: 4px;
874 padding-top: var(--spacing-md);
875}
876
877.anti-patterns-legend-body p {
878 font-size: 0.9375rem;
879 line-height: 1.7;
880 color: var(--color-charcoal);
881}
882
883.anti-patterns-legend-body a {
884 color: var(--color-ink);
885 text-decoration: none;
886 border-bottom: 1px solid var(--color-accent);
887 font-family: var(--font-mono);
888 font-size: 0.875em;
889 font-weight: 500;
890}
891
892.anti-patterns-legend-body a:hover {
893 color: var(--color-accent);
894}
895
896.anti-patterns-sections {
897 display: flex;
898 flex-direction: column;
899 gap: clamp(3rem, 6vw, 4.5rem);
900}
901
902.anti-patterns-section-header {
903 display: flex;
904 align-items: baseline;
905 justify-content: space-between;
906 gap: var(--spacing-md);
907 padding-bottom: 10px;
908 border-bottom: 1px solid var(--color-mist);
909 margin-bottom: var(--spacing-md);
910}
911
912/* Catalog subsections sit under the "The catalog" h2 on /slop, so they
913 must read clearly as h3 — smaller, uppercase mono label instead of
914 display italic, to avoid competing with the parent section heading. */
915.anti-patterns-section-title {
916 font-family: var(--font-mono);
917 font-size: 0.8125rem;
918 font-weight: 600;
919 text-transform: uppercase;
920 letter-spacing: 0.12em;
921 color: var(--color-ink);
922}
923
924.anti-patterns-section-count {
925 font-family: var(--font-mono);
926 font-size: 0.6875rem;
927 font-weight: 500;
928 letter-spacing: 0.08em;
929 color: var(--color-ash);
930}
931
932/* ============================================
933 SLOP PAGE (/slop)
934 Merger of the former /anti-patterns + /visual-mode.
935 Reuses .anti-patterns-* for the catalog and .visual-mode-*
936 for the demo / gallery / methods blocks; the rules below wire
937 the four numbered top-level sections and the nested sidebar.
938 ============================================ */
939
940.slop-content { width: 100%; }
941
942.slop-header {
943 max-width: 720px;
944}
945
946.slop-section {
947 margin-top: clamp(3rem, 6vw, 4.5rem);
948 scroll-margin-top: 80px;
949}
950
951.slop-section-heading {
952 font-family: var(--font-display);
953 font-size: clamp(2rem, 3.5vw, 2.75rem);
954 font-weight: 500;
955 font-style: italic;
956 color: var(--color-ink);
957 letter-spacing: -0.015em;
958 line-height: 1.15;
959 margin-bottom: var(--spacing-lg);
960 padding-bottom: var(--spacing-sm);
961 border-bottom: 1px solid var(--color-mist);
962 display: flex;
963 align-items: baseline;
964 gap: var(--spacing-md);
965}
966
967.slop-section-num {
968 font-family: var(--font-mono);
969 font-size: 0.75rem;
970 font-weight: 600;
971 font-style: normal;
972 letter-spacing: 0.12em;
973 color: var(--color-ash);
974 text-transform: uppercase;
975 flex-shrink: 0;
976}
977
978.slop-catalog-header {
979 margin-bottom: var(--spacing-lg);
980}
981
982.slop-catalog-lede {
983 font-size: 0.9375rem;
984 line-height: 1.7;
985 color: var(--color-charcoal);
986 max-width: 72ch;
987 margin-top: var(--spacing-sm);
988}
989
990.slop-catalog-lede strong {
991 color: var(--color-ink);
992 font-weight: 600;
993}
994
995.slop-catalog-lede a {
996 color: var(--color-ink);
997 text-decoration: none;
998 border-bottom: 1px solid var(--color-accent);
999 font-family: var(--font-mono);
1000 font-size: 0.875em;
1001 font-weight: 500;
1002}
1003
1004.slop-catalog-lede a:hover {
1005 color: var(--color-accent);
1006}
1007
1008/* Sidebar: nested catalog-section list under "The catalog". */
1009.slop-sidebar-sublist {
1010 list-style: none;
1011 margin: 6px 0 4px 0;
1012 padding: 0 0 0 var(--spacing-md);
1013 border-left: 1px solid var(--color-mist);
1014}
1015
1016.slop-sidebar-sublist li {
1017 margin: 0;
1018}
1019
1020.slop-sidebar-sublist a {
1021 display: flex !important;
1022 align-items: baseline;
1023 justify-content: space-between;
1024 gap: var(--spacing-sm);
1025 font-size: 0.8125rem;
1026 color: var(--color-ash);
1027 padding: 4px 0;
1028}
1029
1030.slop-sidebar-sublist a:hover {
1031 color: var(--color-ink);
1032}
1033
1034.slop-sidebar-sublist .anti-patterns-sidebar-count {
1035 font-size: 0.625rem;
1036}
1037
1038.rule-card-grid {
1039 display: grid;
1040 grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
1041 gap: var(--spacing-md);
1042}
1043
1044.rule-card {
1045 background: var(--color-paper);
1046 border: 1px solid var(--color-mist);
1047 border-radius: 10px;
1048 display: flex;
1049 flex-direction: column;
1050 overflow: hidden;
1051 transition: border-color var(--duration-fast) var(--ease-out);
1052}
1053
1054.rule-card:hover {
1055 border-color: var(--color-ash);
1056}
1057
1058/* Visual example preview at the top of each card. */
1059.rule-card-visual {
1060 position: relative;
1061 height: 160px;
1062 background: var(--color-cream);
1063 border-bottom: 1px solid var(--color-mist);
1064 overflow: hidden;
1065}
1066
1067.rule-card-visual-inner {
1068 position: absolute;
1069 inset: 0;
1070 display: flex;
1071 align-items: center;
1072 justify-content: center;
1073 padding: var(--spacing-md);
1074 /* Prevent the inline snippet's styles from bleeding outside the box. */
1075 overflow: hidden;
1076}
1077
1078.rule-card-body {
1079 padding: var(--spacing-md);
1080 display: flex;
1081 flex-direction: column;
1082 gap: 8px;
1083 flex: 1;
1084}
1085
1086.rule-card-head {
1087 display: flex;
1088 align-items: center;
1089 gap: 6px;
1090 margin-bottom: 2px;
1091 flex-wrap: wrap;
1092}
1093
1094.rule-card-category {
1095 font-family: var(--font-mono);
1096 font-size: 0.625rem;
1097 font-weight: 600;
1098 text-transform: uppercase;
1099 letter-spacing: 0.1em;
1100 padding: 3px 8px;
1101 border-radius: 99px;
1102}
1103
1104.rule-card-category[data-category="slop"] {
1105 color: var(--color-accent);
1106 background: var(--color-accent-dim);
1107}
1108
1109.rule-card-category[data-category="quality"] {
1110 color: var(--color-charcoal);
1111 background: var(--color-mist);
1112}
1113
1114/* Detection layer badge: CLI, Browser, or LLM only. */
1115.rule-card-layer {
1116 font-family: var(--font-mono);
1117 font-size: 0.625rem;
1118 font-weight: 600;
1119 text-transform: uppercase;
1120 letter-spacing: 0.1em;
1121 padding: 3px 8px;
1122 border-radius: 99px;
1123 border: 1px solid var(--color-mist);
1124}
1125
1126.rule-card-layer[data-layer="cli"] {
1127 color: var(--color-charcoal);
1128 border-color: var(--color-mist);
1129 background: var(--color-paper);
1130}
1131
1132.rule-card-layer[data-layer="browser"] {
1133 color: oklch(40% 0.12 230);
1134 border-color: oklch(90% 0.05 230);
1135 background: oklch(97% 0.02 230);
1136}
1137
1138.rule-card-layer[data-layer="llm"] {
1139 color: oklch(45% 0.15 45);
1140 border-color: oklch(92% 0.08 45);
1141 background: oklch(98% 0.03 45);
1142}
1143
1144/* Layer legend dl inside the How-to-read block. */
1145.anti-patterns-legend-layers {
1146 display: flex;
1147 flex-direction: column;
1148 gap: var(--spacing-sm);
1149 margin-top: var(--spacing-md);
1150}
1151
1152.anti-patterns-legend-layers > div {
1153 display: grid;
1154 grid-template-columns: 90px 1fr;
1155 gap: var(--spacing-md);
1156 align-items: baseline;
1157}
1158
1159.anti-patterns-legend-layers dt {
1160 margin: 0;
1161}
1162
1163.anti-patterns-legend-layers dd {
1164 margin: 0;
1165 font-size: 0.875rem;
1166 line-height: 1.55;
1167 color: var(--color-charcoal);
1168}
1169
1170.anti-patterns-legend-layers dd code {
1171 font-family: var(--font-mono);
1172 font-size: 0.8125rem;
1173 background: var(--color-cream);
1174 border: 1px solid var(--color-mist);
1175 padding: 1px 6px;
1176 border-radius: 4px;
1177}
1178
1179.rule-card-name {
1180 font-family: var(--font-body);
1181 font-size: 1rem;
1182 font-weight: 600;
1183 color: var(--color-ink);
1184 line-height: 1.35;
1185}
1186
1187.rule-card-desc {
1188 font-size: 0.875rem;
1189 line-height: 1.6;
1190 color: var(--color-charcoal);
1191 flex: 1;
1192}
1193
1194.rule-card-skill-link {
1195 font-family: var(--font-mono);
1196 font-size: 0.75rem;
1197 font-weight: 500;
1198 color: var(--color-charcoal);
1199 text-decoration: none;
1200 align-self: flex-start;
1201 padding-top: 4px;
1202 transition: color var(--duration-fast) var(--ease-out);
1203}
1204
1205.rule-card-skill-link:hover {
1206 color: var(--color-accent);
1207}
1208
1209.rule-card-skill-link::after {
1210 content: " →";
1211}
1212
1213/* ============================================
1214 TUTORIALS INDEX
1215 ============================================ */
1216
1217.tutorials-content {
1218 max-width: 720px;
1219}
1220
1221.tutorial-cards {
1222 display: flex;
1223 flex-direction: column;
1224 gap: var(--spacing-sm);
1225}
1226
1227.tutorial-card {
1228 display: grid;
1229 grid-template-columns: auto 1fr auto;
1230 gap: var(--spacing-md);
1231 align-items: center;
1232 padding: var(--spacing-md) var(--spacing-lg);
1233 background: var(--color-paper);
1234 border: 1px solid var(--color-mist);
1235 border-radius: 10px;
1236 color: var(--color-ink);
1237 text-decoration: none;
1238 transition: border-color var(--duration-fast) var(--ease-out),
1239 transform var(--duration-fast) var(--ease-out);
1240}
1241
1242.tutorial-card:hover {
1243 border-color: var(--color-ink);
1244}
1245
1246.tutorial-card-number {
1247 font-family: var(--font-mono);
1248 font-size: 1.5rem;
1249 font-weight: 500;
1250 color: var(--color-ash);
1251 line-height: 1;
1252 font-variant-numeric: tabular-nums;
1253}
1254
1255.tutorial-card:hover .tutorial-card-number {
1256 color: var(--color-accent);
1257}
1258
1259.tutorial-card-body {
1260 min-width: 0;
1261}
1262
1263.tutorial-card-title {
1264 font-family: var(--font-display);
1265 font-size: 1.375rem;
1266 font-style: italic;
1267 font-weight: 500;
1268 color: var(--color-ink);
1269 line-height: 1.2;
1270 margin-bottom: 4px;
1271}
1272
1273.tutorial-card-tagline {
1274 font-size: 0.9375rem;
1275 color: var(--color-charcoal);
1276 line-height: 1.5;
1277}
1278
1279.tutorial-card-arrow {
1280 font-family: var(--font-body);
1281 font-size: 1.25rem;
1282 color: var(--color-ash);
1283 transition: color var(--duration-fast) var(--ease-out),
1284 transform var(--duration-fast) var(--ease-out);
1285}
1286
1287.tutorial-card:hover .tutorial-card-arrow {
1288 color: var(--color-accent);
1289 transform: translateX(4px);
1290}
1291
1292/* ============================================
1293 TUTORIAL EMBEDS (live overlays, screenshots)
1294 ============================================ */
1295
1296.tutorial-embed {
1297 margin: var(--spacing-lg) 0 var(--spacing-xl);
1298 border-radius: 10px;
1299 overflow: hidden;
1300 border: 1px solid var(--color-mist);
1301 box-shadow: 0 8px 30px -6px rgba(0, 0, 0, 0.12);
1302 max-width: none;
1303}
1304
1305.tutorial-embed-header {
1306 display: flex;
1307 align-items: center;
1308 gap: 6px;
1309 padding: 10px 14px;
1310 background: var(--color-cream);
1311 border-bottom: 1px solid var(--color-mist);
1312}
1313
1314.tutorial-embed-dot {
1315 width: 10px;
1316 height: 10px;
1317 border-radius: 50%;
1318 flex-shrink: 0;
1319}
1320
1321.tutorial-embed-dot.red { background: #ff5f56; }
1322.tutorial-embed-dot.yellow { background: #ffbd2e; }
1323.tutorial-embed-dot.green { background: #27c93f; }
1324
1325.tutorial-embed-title {
1326 margin-left: auto;
1327 font-family: var(--font-mono);
1328 font-size: 0.75rem;
1329 color: var(--color-ash);
1330}
1331
1332.tutorial-embed-iframe {
1333 display: block;
1334 width: 100%;
1335 height: 520px;
1336 border: none;
1337 background: white;
1338}
1339
1340.tutorial-embed-caption {
1341 font-size: 0.8125rem;
1342 color: var(--color-ash);
1343 margin-top: var(--spacing-sm);
1344 font-style: italic;
1345 max-width: 60ch;
1346}
1347
1348/* ============================================
1349 TUTORIAL DETAIL
1350 ============================================ */
1351
1352.tutorial-detail {
1353 max-width: 680px;
1354}
1355
1356.tutorial-detail-header {
1357 margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
1358}
1359
1360.tutorial-detail-title {
1361 font-family: var(--font-display);
1362 font-size: clamp(2.5rem, 6vw, 4.5rem);
1363 font-weight: 400;
1364 line-height: 1.05;
1365 letter-spacing: -0.02em;
1366 color: var(--color-ink);
1367 margin-bottom: var(--spacing-md);
1368}
1369
1370.tutorial-detail-tagline {
1371 font-family: var(--font-body);
1372 font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
1373 line-height: 1.55;
1374 color: var(--color-charcoal);
1375 max-width: 60ch;
1376}
1377
1378.tutorial-detail-body {
1379 max-width: 65ch;
1380}
1381
1382/* ============================================
1383 VISUAL MODE PAGE
1384 ============================================ */
1385
1386.visual-mode-demo-wrap {
1387 margin-bottom: clamp(3rem, 6vw, 4.5rem);
1388}
1389
1390.visual-mode-demo-caption {
1391 font-size: 0.8125rem;
1392 color: var(--color-ash);
1393 font-style: italic;
1394 margin-top: var(--spacing-sm);
1395 text-align: center;
1396}
1397
1398/* Mac-window chrome around the iframe. Lives inside sub-pages.css, which
1399 is not loaded on the homepage — the homepage has its own copy in
1400 main.css. The max-width + auto margins would disable grid stretch on
1401 the homepage and collapse the preview to the iframe's intrinsic width. */
1402.visual-mode-preview {
1403 border-radius: 10px;
1404 overflow: hidden;
1405 border: 1px solid var(--color-mist);
1406 box-shadow: 0 12px 40px -8px rgba(0, 0, 0, 0.12);
1407 max-width: 1040px;
1408 margin: 0 auto;
1409}
1410
1411.visual-mode-preview-header {
1412 display: flex;
1413 align-items: center;
1414 gap: 6px;
1415 padding: 10px 14px;
1416 background: var(--color-cream);
1417 border-bottom: 1px solid var(--color-mist);
1418}
1419
1420.visual-mode-preview-dot {
1421 width: 10px;
1422 height: 10px;
1423 border-radius: 50%;
1424 flex-shrink: 0;
1425}
1426
1427.visual-mode-preview-dot.red { background: #ff5f56; }
1428.visual-mode-preview-dot.yellow { background: #ffbd2e; }
1429.visual-mode-preview-dot.green { background: #27c93f; }
1430
1431.visual-mode-preview-title {
1432 margin-left: auto;
1433 font-family: var(--font-mono);
1434 font-size: 0.75rem;
1435 color: var(--color-ash);
1436}
1437
1438.visual-mode-frame {
1439 display: block;
1440 width: 100%;
1441 height: 580px;
1442 border: none;
1443 background: white;
1444}
1445
1446/* Then vs Now: era toggle inline with lede */
1447.slop-then-now-intro {
1448 display: flex;
1449 align-items: flex-end;
1450 justify-content: space-between;
1451 gap: var(--spacing-md);
1452 margin-bottom: var(--spacing-md);
1453}
1454
1455.slop-then-now-lede {
1456 color: var(--color-charcoal);
1457 font-size: 1.0625rem;
1458 line-height: 1.6;
1459 max-width: 52ch;
1460 margin: 0;
1461}
1462
1463.slop-era-toggle {
1464 display: inline-flex;
1465 border: 1px solid var(--color-mist);
1466 border-radius: 8px;
1467 overflow: hidden;
1468 flex-shrink: 0;
1469}
1470
1471.slop-then-now .visual-mode-preview {
1472 max-width: none;
1473 margin: 0;
1474}
1475
1476.slop-then-now .visual-mode-demo-caption {
1477 text-align: left;
1478}
1479
1480@media (max-width: 600px) {
1481 .slop-then-now-intro {
1482 flex-direction: column;
1483 align-items: flex-start;
1484 }
1485}
1486
1487.slop-era-tab {
1488 font-family: var(--font-mono);
1489 font-size: 0.875rem;
1490 font-weight: 600;
1491 padding: 8px 20px;
1492 border: none;
1493 background: transparent;
1494 color: var(--color-ash);
1495 cursor: pointer;
1496 transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
1497}
1498
1499.slop-era-tab + .slop-era-tab {
1500 border-left: 1px solid var(--color-mist);
1501}
1502
1503.slop-era-tab.is-active {
1504 background: var(--color-ink);
1505 color: var(--color-paper);
1506}
1507
1508.slop-era-tab:not(.is-active):hover {
1509 background: var(--color-mist);
1510 color: var(--color-ink);
1511}
1512
1513/* Three invocation methods grid. Section wrapper margins come from
1514 .slop-section; this block only controls the grid of cards. */
1515.visual-mode-methods-grid {
1516 display: grid;
1517 grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
1518 gap: var(--spacing-md);
1519}
1520
1521.visual-mode-method {
1522 padding: var(--spacing-lg);
1523 background: var(--color-paper);
1524 border: 1px solid var(--color-mist);
1525 border-radius: 10px;
1526 display: flex;
1527 flex-direction: column;
1528 gap: 8px;
1529 transition: border-color var(--duration-fast) var(--ease-out);
1530}
1531
1532.visual-mode-method:hover {
1533 border-color: var(--color-ash);
1534}
1535
1536.visual-mode-method[data-coming-soon] {
1537 background: var(--color-cream);
1538}
1539
1540.visual-mode-method-label {
1541 font-family: var(--font-mono);
1542 font-size: 0.625rem;
1543 font-weight: 600;
1544 text-transform: uppercase;
1545 letter-spacing: 0.14em;
1546 color: var(--color-accent);
1547}
1548
1549.visual-mode-method-name {
1550 font-family: var(--font-display);
1551 font-size: 1.375rem;
1552 font-style: italic;
1553 font-weight: 500;
1554 color: var(--color-ink);
1555 line-height: 1.25;
1556}
1557
1558.visual-mode-method-name a {
1559 color: inherit;
1560 text-decoration: none;
1561 border-bottom: 1px solid var(--color-accent);
1562}
1563
1564.visual-mode-method-name a:hover {
1565 color: var(--color-accent);
1566}
1567
1568.visual-mode-method-name code {
1569 font-family: var(--font-mono);
1570 font-size: 0.875em;
1571 font-style: normal;
1572 background: var(--color-cream);
1573 border: 1px solid var(--color-mist);
1574 padding: 2px 8px;
1575 border-radius: 4px;
1576 color: var(--color-ink);
1577}
1578
1579.visual-mode-method-desc {
1580 font-size: 0.9375rem;
1581 line-height: 1.6;
1582 color: var(--color-charcoal);
1583 flex: 1;
1584}
1585
1586.visual-mode-method-desc a {
1587 color: var(--color-ink);
1588 text-decoration: none;
1589 border-bottom: 1px solid var(--color-accent);
1590 font-family: var(--font-mono);
1591 font-size: 0.875em;
1592 font-weight: 500;
1593}
1594
1595.visual-mode-method-desc a:hover {
1596 color: var(--color-accent);
1597}
1598
1599/* Gallery (specimens) section header. Title comes from .slop-section-heading;
1600 this block just scopes the lede + spacing under the heading. */
1601.visual-mode-gallery-header {
1602 margin-bottom: var(--spacing-lg);
1603}
1604
1605.visual-mode-gallery-lede {
1606 font-size: 0.9375rem;
1607 line-height: 1.6;
1608 color: var(--color-charcoal);
1609 max-width: 60ch;
1610 margin-top: var(--spacing-sm);
1611}
1612
1613/* ============================================
1614 ANTI-PATTERNS: IN THE WILD (merged gallery)
1615 ============================================ */
1616
1617.gallery-section {
1618 margin-top: clamp(3rem, 6vw, 4.5rem);
1619}
1620
1621.gallery-section-lede {
1622 font-size: 0.9375rem;
1623 line-height: 1.6;
1624 color: var(--color-charcoal);
1625 max-width: 60ch;
1626 margin-bottom: var(--spacing-lg);
1627}
1628
1629.gallery-grid {
1630 display: grid;
1631 grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
1632 gap: var(--spacing-md);
1633}
1634
1635.gallery-card {
1636 display: flex;
1637 flex-direction: column;
1638 background: var(--color-paper);
1639 border: 1px solid var(--color-mist);
1640 border-radius: 10px;
1641 overflow: hidden;
1642 text-decoration: none;
1643 color: inherit;
1644 transition: border-color var(--duration-fast) var(--ease-out),
1645 transform var(--duration-fast) var(--ease-out);
1646}
1647
1648.gallery-card:hover {
1649 border-color: var(--color-ink);
1650 transform: translateY(-2px);
1651}
1652
1653.gallery-card-thumb {
1654 aspect-ratio: 1;
1655 overflow: hidden;
1656 background: var(--color-cream);
1657 border-bottom: 1px solid var(--color-mist);
1658}
1659
1660.gallery-card-thumb img {
1661 width: 100%;
1662 height: 100%;
1663 object-fit: cover;
1664 object-position: top left;
1665 display: block;
1666}
1667
1668.gallery-card-body {
1669 padding: var(--spacing-md);
1670 display: flex;
1671 flex-direction: column;
1672 gap: 6px;
1673 flex: 1;
1674}
1675
1676.gallery-card-title {
1677 font-family: var(--font-display);
1678 font-size: 1.125rem;
1679 font-style: italic;
1680 font-weight: 500;
1681 color: var(--color-ink);
1682 line-height: 1.25;
1683}
1684
1685.gallery-card:hover .gallery-card-title {
1686 color: var(--color-accent);
1687}
1688
1689.gallery-card-desc {
1690 font-size: 0.8125rem;
1691 line-height: 1.55;
1692 color: var(--color-charcoal);
1693}
1694
1695/* ============================================
1696 MOBILE: collapsible sidebar behind a toggle
1697 ============================================ */
1698
1699@media (max-width: 920px) {
1700 .skills-layout {
1701 grid-template-columns: 1fr;
1702 gap: 0;
1703 }
1704
1705 .skills-sidebar {
1706 position: static;
1707 max-height: none;
1708 overflow: visible;
1709 border-right: none;
1710 padding: var(--spacing-md) 0;
1711 margin-bottom: var(--spacing-lg);
1712 }
1713
1714 /* Show the toggle button and collapse the menu by default. */
1715 .skills-sidebar-toggle {
1716 display: flex;
1717 align-items: center;
1718 justify-content: space-between;
1719 gap: var(--spacing-sm);
1720 width: 100%;
1721 padding: 12px 16px;
1722 background: var(--color-cream);
1723 border: 1px solid var(--color-mist);
1724 border-radius: 8px;
1725 cursor: pointer;
1726 font-family: var(--font-mono);
1727 font-size: 0.8125rem;
1728 font-weight: 600;
1729 color: var(--color-ink);
1730 text-align: left;
1731 transition: border-color var(--duration-fast) var(--ease-out);
1732 }
1733
1734 .skills-sidebar-toggle:hover {
1735 border-color: var(--color-ink);
1736 }
1737
1738 .skills-sidebar-toggle[aria-expanded="true"] .skills-sidebar-toggle-chevron {
1739 transform: rotate(180deg);
1740 }
1741
1742 .skills-sidebar-inner {
1743 display: none;
1744 padding-right: 0;
1745 padding-top: var(--spacing-md);
1746 border-top: 1px solid var(--color-mist);
1747 margin-top: var(--spacing-md);
1748 }
1749
1750 .skills-sidebar-toggle[aria-expanded="true"] + .skills-sidebar-inner {
1751 display: block;
1752 }
1753
1754 .skills-sidebar-group {
1755 margin-bottom: var(--spacing-md);
1756 }
1757}
1758
1759/* ============================================
1760 SKILL DETAIL — BEFORE/AFTER DEMO
1761 ============================================ */
1762
1763/* Ported from main.css for use on sub-pages. The split-compare effect
1764 is initialized by js/effects/split-compare.js loaded on demand. */
1765
1766.split-comparison {
1767 position: relative;
1768 width: 100%;
1769 /* 500px visible + 64px buffer (32px per side) = 564px total.
1770 box-sizing: border-box is inherited, so children sit in 500px. */
1771 max-width: 564px;
1772 /* 32px padding is an invisible hover buffer so the divider does not
1773 immediately snap back when the pointer grazes the visible box
1774 edge. Negative top/bottom margins collapse the padding out of
1775 layout flow so the demo keeps its rhythm in the page. */
1776 padding: 32px;
1777 margin: -32px 0 calc(clamp(2rem, 4vw, 3rem) - 32px);
1778}
1779
1780.split-container {
1781 position: relative;
1782 width: 100%;
1783 height: 360px;
1784 border-radius: 12px;
1785 overflow: hidden;
1786 /* Match the page background so the 32px padding area is invisible.
1787 The border + border-radius define the visible box; individual
1788 demo content provides its own colors on top. */
1789 background: var(--color-paper);
1790 border: 1px solid var(--color-mist);
1791 cursor: ew-resize;
1792 user-select: none;
1793}
1794
1795.split-before,
1796.split-after {
1797 position: absolute;
1798 inset: 0;
1799 display: flex;
1800 align-items: center;
1801 justify-content: center;
1802}
1803
1804.split-before {
1805 z-index: 1;
1806}
1807
1808.split-content {
1809 width: 100%;
1810 height: 100%;
1811 display: flex;
1812 align-items: center;
1813 justify-content: center;
1814 /* No padding: demos that fill the container (overdrive) need full
1815 bleed, and demos with smaller content (polish, bolder) already
1816 center themselves via flex. */
1817}
1818
1819.split-after {
1820 clip-path: polygon(58% 0%, 100% 0%, 100% 100%, 42% 100%);
1821 z-index: 2;
1822 background: var(--color-paper);
1823}
1824
1825.split-divider {
1826 position: absolute;
1827 top: 0;
1828 bottom: 0;
1829 left: 50%;
1830 width: 3px;
1831 background: var(--color-accent);
1832 transform: translateX(-50%) skewX(-10deg);
1833 pointer-events: none;
1834 z-index: 3;
1835 box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
1836}
1837
1838/* Before | caption | After all on one row. The caption lives in the
1839 middle column; if a skill has no caption we emit an empty <span> so
1840 the grid still has three cells and Before/After sit at the edges. */
1841.split-labels {
1842 display: grid;
1843 grid-template-columns: auto minmax(0, 1fr) auto;
1844 align-items: baseline;
1845 gap: var(--spacing-md);
1846 margin-top: 10px;
1847 font-family: var(--font-mono);
1848 font-size: 0.6875rem;
1849 font-weight: 600;
1850 text-transform: uppercase;
1851 letter-spacing: 0.12em;
1852 color: var(--color-ash);
1853}
1854
1855.split-label-item[data-point="before"] {
1856 color: var(--color-ash);
1857 justify-self: start;
1858}
1859
1860.split-label-item[data-point="after"] {
1861 color: var(--color-accent);
1862 justify-self: end;
1863}
1864
1865.skill-demo-caption {
1866 margin: 0;
1867 font-family: var(--font-body);
1868 font-size: 0.8125rem;
1869 font-weight: 400;
1870 text-transform: none;
1871 letter-spacing: 0;
1872 color: var(--color-ash);
1873 font-style: italic;
1874 text-align: center;
1875 justify-self: center;
1876 /* Allow wrapping inside the middle column if the text is long. */
1877 max-width: 100%;
1878}
1879
1880.skill-demo-eyebrow {
1881 font-family: var(--font-mono);
1882 font-size: 0.6875rem;
1883 font-weight: 600;
1884 text-transform: uppercase;
1885 letter-spacing: 0.14em;
1886 color: var(--color-ash);
1887 margin-bottom: var(--spacing-sm);
1888 /* Eyebrow now lives inside .split-comparison (which has 32px
1889 padding), so it aligns with the visible card edge automatically. */
1890}
1891
1892/* ============================================
1893 SKILL DETAIL
1894 ============================================ */
1895
1896/* Editorial hero: on wide viewports, text header on the left and the
1897 before/after demo floats to the right as a hero module and is allowed
1898 to break out of the 720px body cap. On narrow viewports everything
1899 stacks within the 720px column. */
1900.skill-detail-hero {
1901 max-width: 720px;
1902 margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
1903}
1904
1905/* Stacked spacing between header and demo on narrow viewports; cancelled
1906 when the hero switches to two columns at >=1280px. */
1907.skill-detail-hero--has-demo .skill-demo {
1908 margin-top: clamp(2rem, 4vw, 2.5rem);
1909}
1910
1911@media (min-width: 1280px) {
1912 .skill-detail-hero--has-demo {
1913 /* Wider editorial hero at large viewports. Fixed 564px demo column
1914 (500px visible + 64px hover buffer) keeps the split-container at
1915 its designed 500x360 landscape aspect ratio. Text column takes
1916 whatever's left, clamped by the hero's own max-width. */
1917 max-width: 1200px;
1918 display: grid;
1919 grid-template-columns: minmax(0, 1fr) 564px;
1920 gap: clamp(var(--spacing-xl), 4vw, var(--spacing-2xl));
1921 align-items: center;
1922 }
1923
1924 .skill-detail-hero--has-demo .skill-detail-header {
1925 margin-bottom: 0;
1926 }
1927
1928 .skill-detail-hero--has-demo .skill-demo {
1929 align-self: center;
1930 margin-top: 0;
1931 }
1932}
1933
1934/* Body sections stay at a readable line length regardless of the hero
1935 width above them. */
1936.skill-detail-editorial,
1937.skill-source-card,
1938.skill-references {
1939 max-width: 720px;
1940}
1941
1942.skill-detail-eyebrow {
1943 font-family: var(--font-mono);
1944 font-size: 0.75rem;
1945 font-weight: 500;
1946 text-transform: uppercase;
1947 letter-spacing: 0.12em;
1948 color: var(--color-ash);
1949 margin-bottom: var(--spacing-sm);
1950}
1951
1952.skill-detail-eyebrow a {
1953 color: inherit;
1954 text-decoration: none;
1955}
1956
1957.skill-detail-eyebrow a:hover {
1958 color: var(--color-accent);
1959}
1960
1961.skill-detail-title {
1962 font-family: var(--font-display);
1963 font-size: clamp(3rem, 5.5vw, 5rem);
1964 font-weight: 600;
1965 line-height: 0.95;
1966 letter-spacing: -0.02em;
1967 color: var(--color-ink);
1968 margin-bottom: var(--spacing-md);
1969 white-space: nowrap;
1970}
1971
1972.skill-detail-title-slash {
1973 color: var(--color-accent);
1974 font-weight: 300;
1975}
1976
1977/* Sub-commands: show "/impeccable" as a smaller label above the command name
1978 so it stacks and the command name stays at full display size. */
1979.skill-detail-title-namespace {
1980 display: block;
1981 font-family: var(--font-body);
1982 font-size: 0.9375rem;
1983 font-weight: 500;
1984 color: var(--color-ash);
1985 letter-spacing: 0.04em;
1986 margin-bottom: 0.4em;
1987 line-height: 1;
1988}
1989
1990.skill-detail-title-namespace .skill-detail-title-slash {
1991 color: var(--color-accent);
1992 font-weight: 400;
1993}
1994
1995.skill-detail-tagline {
1996 font-family: var(--font-body);
1997 font-size: clamp(1rem, 1.4vw, 1.125rem);
1998 font-weight: 400;
1999 color: var(--color-charcoal);
2000 line-height: 1.55;
2001 max-width: 60ch;
2002 margin-bottom: var(--spacing-md);
2003}
2004
2005.skill-meta-strip {
2006 display: flex;
2007 flex-wrap: wrap;
2008 gap: 8px;
2009 margin-top: var(--spacing-sm);
2010}
2011
2012.skill-meta-chip {
2013 display: inline-flex;
2014 align-items: center;
2015 font-family: var(--font-mono);
2016 font-size: 0.6875rem;
2017 font-weight: 600;
2018 text-transform: uppercase;
2019 letter-spacing: 0.08em;
2020 padding: 4px 10px;
2021 border-radius: 99px;
2022 background: var(--color-cream);
2023 border: 1px solid var(--color-mist);
2024 color: var(--color-charcoal);
2025}
2026
2027.skill-meta-category[data-category="create"] {
2028 background: var(--cat-create-bg);
2029 border-color: var(--cat-create-border);
2030 color: var(--cat-create-text);
2031}
2032
2033.skill-meta-category[data-category="evaluate"] {
2034 background: var(--cat-evaluate-bg);
2035 border-color: var(--cat-evaluate-border);
2036 color: var(--cat-evaluate-text);
2037}
2038
2039.skill-meta-category[data-category="refine"] {
2040 background: var(--cat-refine-bg);
2041 border-color: var(--cat-refine-border);
2042 color: var(--cat-refine-text);
2043}
2044
2045.skill-meta-category[data-category="simplify"] {
2046 background: var(--cat-simplify-bg);
2047 border-color: var(--cat-simplify-border);
2048 color: var(--cat-simplify-text);
2049}
2050
2051.skill-meta-category[data-category="harden"] {
2052 background: var(--cat-harden-bg);
2053 border-color: var(--cat-harden-border);
2054 color: var(--cat-harden-text);
2055}
2056
2057.skill-meta-category[data-category="system"] {
2058 background: var(--cat-system-bg);
2059 border-color: var(--cat-system-border);
2060 color: var(--cat-system-text);
2061}
2062
2063.skill-meta-args {
2064 font-family: var(--font-mono);
2065 text-transform: none;
2066 letter-spacing: 0;
2067 font-weight: 500;
2068}
2069
2070.skill-detail-editorial {
2071 margin-bottom: clamp(2rem, 4vw, 3rem);
2072}
2073
2074/* "The skill itself" card: visually contains the auto-rendered SKILL.md
2075 body so it reads as a distinct reference block, not a continuation of
2076 the editorial section above. */
2077.skill-source-card {
2078 background: var(--color-paper);
2079 border: 1px solid var(--color-mist);
2080 border-radius: 12px;
2081 padding: clamp(var(--spacing-md), 3vw, var(--spacing-xl));
2082 margin-top: clamp(2rem, 4vw, 3rem);
2083 box-shadow: 0 1px 0 oklch(90% 0 0);
2084}
2085
2086.skill-source-card-header {
2087 display: flex;
2088 align-items: baseline;
2089 flex-wrap: wrap;
2090 gap: var(--spacing-sm);
2091 padding-bottom: var(--spacing-md);
2092 margin-bottom: var(--spacing-md);
2093 border-bottom: 1px solid var(--color-mist);
2094}
2095
2096.skill-source-card-label {
2097 font-family: var(--font-mono);
2098 font-size: 0.75rem;
2099 font-weight: 600;
2100 text-transform: uppercase;
2101 letter-spacing: 0.1em;
2102 color: var(--color-accent);
2103 padding: 3px 8px;
2104 background: var(--color-accent-dim);
2105 border-radius: 4px;
2106 flex-shrink: 0;
2107}
2108
2109.skill-source-card-subtitle {
2110 font-size: 0.8125rem;
2111 color: var(--color-ash);
2112 font-style: italic;
2113}
2114
2115.skill-source-card-body {
2116 max-width: none;
2117}
2118
2119.skill-source-card-body > :first-child {
2120 margin-top: 0;
2121}
2122
2123.skill-source-card-body > :last-child {
2124 margin-bottom: 0;
2125}
2126
2127.skill-references {
2128 margin-top: clamp(3rem, 6vw, 4.5rem);
2129 padding-top: clamp(2rem, 4vw, 3rem);
2130 border-top: 1px solid var(--color-mist);
2131}
2132
2133.skill-references-heading {
2134 font-family: var(--font-display);
2135 font-size: 1.5rem;
2136 font-style: italic;
2137 font-weight: 500;
2138 color: var(--color-ink);
2139 margin-bottom: var(--spacing-md);
2140}
2141
2142.skill-reference {
2143 border-top: 1px solid var(--color-mist);
2144}
2145
2146.skill-reference:last-child {
2147 border-bottom: 1px solid var(--color-mist);
2148}
2149
2150.skill-reference > summary {
2151 list-style: none;
2152 cursor: pointer;
2153 padding: 16px 0;
2154 display: flex;
2155 align-items: center;
2156 gap: var(--spacing-md);
2157 transition: color var(--duration-fast) var(--ease-out);
2158}
2159
2160.skill-reference > summary::-webkit-details-marker {
2161 display: none;
2162}
2163
2164.skill-reference > summary::before {
2165 content: "+";
2166 flex-shrink: 0;
2167 width: 18px;
2168 font-family: var(--font-display);
2169 font-size: 1.5rem;
2170 color: var(--color-accent);
2171 line-height: 1;
2172 transition: transform var(--duration-base) var(--ease-out);
2173}
2174
2175.skill-reference[open] > summary::before {
2176 transform: rotate(45deg);
2177}
2178
2179.skill-reference > summary:hover {
2180 color: var(--color-accent);
2181}
2182
2183.skill-reference-label {
2184 font-family: var(--font-mono);
2185 font-size: 0.6875rem;
2186 font-weight: 600;
2187 text-transform: uppercase;
2188 letter-spacing: 0.12em;
2189 color: var(--color-ash);
2190 flex-shrink: 0;
2191}
2192
2193.skill-reference-title {
2194 font-family: var(--font-display);
2195 font-size: 1.125rem;
2196 font-style: italic;
2197 color: var(--color-ink);
2198}
2199
2200.skill-reference-body {
2201 padding: var(--spacing-sm) 0 var(--spacing-md) 34px;
2202 max-width: 62ch;
2203}
2204
2205/* ============================================
2206 PROSE — rendered markdown bodies
2207 ============================================ */
2208
2209.prose {
2210 font-size: 1rem;
2211 line-height: 1.7;
2212 color: var(--color-charcoal);
2213 max-width: 65ch;
2214}
2215
2216.prose h1,
2217.prose h2,
2218.prose h3,
2219.prose h4 {
2220 color: var(--color-ink);
2221 font-weight: 600;
2222 scroll-margin-top: 5rem;
2223 line-height: 1.25;
2224 margin-top: 2em;
2225 margin-bottom: 0.6em;
2226}
2227
2228.prose h1 { font-family: var(--font-display); font-size: 1.875rem; font-weight: 500; font-style: italic; }
2229.prose h2 { font-family: var(--font-display); font-size: 1.5rem; font-weight: 500; font-style: italic; margin-top: 2.2em; }
2230.prose h3 { font-size: 1.125rem; margin-top: 1.8em; }
2231.prose h4 { font-size: 1rem; }
2232
2233.prose h2:first-child,
2234.prose h3:first-child {
2235 margin-top: 0;
2236}
2237
2238.prose p {
2239 margin-top: 0;
2240 margin-bottom: 1.1em;
2241}
2242
2243.prose ul,
2244.prose ol {
2245 margin: 0 0 1.2em 0;
2246 padding-left: 1.25rem;
2247}
2248
2249.prose li {
2250 margin-bottom: 0.4em;
2251}
2252
2253.prose a {
2254 color: var(--color-accent);
2255 text-decoration: underline;
2256 text-decoration-thickness: 1px;
2257 text-underline-offset: 3px;
2258 text-decoration-color: var(--color-accent-dim);
2259 transition: text-decoration-color var(--duration-fast) var(--ease-out);
2260}
2261
2262.prose a:hover {
2263 text-decoration-color: var(--color-accent);
2264}
2265
2266.prose strong {
2267 color: var(--color-ink);
2268 font-weight: 600;
2269}
2270
2271.prose em {
2272 font-style: italic;
2273}
2274
2275.prose code {
2276 font-family: var(--font-mono);
2277 font-size: 0.875em;
2278 background: var(--color-cream);
2279 border: 1px solid var(--color-mist);
2280 padding: 2px 6px;
2281 border-radius: 4px;
2282 color: var(--color-ink);
2283}
2284
2285.prose .code-block-wrap {
2286 position: relative;
2287 margin: 1.25em 0;
2288}
2289
2290.prose .code-block-wrap .code-block {
2291 margin: 0;
2292}
2293
2294/* Fenced code blocks: covers Astro+Shiki's auto-generated <pre class="astro-code">
2295 in markdown bodies and the legacy hand-written <pre class="code-block"> still
2296 used by the case-study pages. Shiki sets background/color inline, so its theme
2297 wins on .astro-code; the CSS values here apply to .code-block. */
2298.prose pre,
2299.prose .code-block {
2300 margin: 1.25em 0;
2301 padding: var(--spacing-md);
2302 background: oklch(12% 0.005 350);
2303 color: oklch(92% 0.005 350);
2304 border-radius: 10px;
2305 overflow-x: auto;
2306 font-family: var(--font-mono);
2307 font-size: 0.8125rem;
2308 line-height: 1.55;
2309 border: 1px solid oklch(20% 0.005 350);
2310 max-width: 100%;
2311}
2312
2313.code-block-copy {
2314 position: absolute;
2315 top: 10px;
2316 right: 10px;
2317 padding: 4px 10px;
2318 background: oklch(20% 0.005 350);
2319 border: 1px solid oklch(30% 0.005 350);
2320 color: oklch(78% 0.005 350);
2321 border-radius: 4px;
2322 font-family: var(--font-mono);
2323 font-size: 0.6875rem;
2324 font-weight: 600;
2325 text-transform: uppercase;
2326 letter-spacing: 0.08em;
2327 cursor: pointer;
2328 opacity: 0;
2329 transition:
2330 opacity var(--duration-fast) var(--ease-out),
2331 background var(--duration-fast) var(--ease-out),
2332 color var(--duration-fast) var(--ease-out),
2333 border-color var(--duration-fast) var(--ease-out);
2334}
2335
2336.code-block-wrap:hover .code-block-copy,
2337.code-block-copy:focus-visible {
2338 opacity: 1;
2339}
2340
2341.code-block-copy::before {
2342 content: "Copy";
2343}
2344
2345.code-block-copy:hover {
2346 background: oklch(30% 0.005 350);
2347 color: oklch(92% 0.005 350);
2348 border-color: oklch(40% 0.005 350);
2349}
2350
2351.code-block-copy.is-copied {
2352 opacity: 1;
2353 background: var(--color-accent);
2354 color: var(--color-paper);
2355 border-color: var(--color-accent);
2356}
2357
2358.code-block-copy.is-copied::before {
2359 content: "Copied";
2360}
2361
2362.prose pre code,
2363.prose .code-block code {
2364 background: transparent;
2365 border: none;
2366 padding: 0;
2367 color: inherit;
2368 font-size: inherit;
2369 border-radius: 0;
2370}
2371
2372.prose blockquote {
2373 margin: 1.5em 0;
2374 padding: 0 0 0 var(--spacing-md);
2375 border-left: 3px solid var(--color-mist);
2376 color: var(--color-ash);
2377 font-style: italic;
2378}
2379
2380.prose hr {
2381 border: none;
2382 height: 1px;
2383 background: var(--color-mist);
2384 margin: 2.5em 0;
2385}