@stnd/styles 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1261 @@
1
+ @use "standard-00-variables" as *;
2
+
3
+ /* =========================== */
4
+ /* BUTTONS */
5
+ /* =========================== */
6
+
7
+ .loader {
8
+ width: var(--size-lg);
9
+ height: var(--size-lg);
10
+ border: var(--space-d3) solid transparent;
11
+ background: transparent;
12
+ border-radius: 50%;
13
+ display: inline-block;
14
+ box-sizing: border-box;
15
+ filter: blur(0.3px);
16
+ animation: rotation 0.25s linear infinite;
17
+
18
+ --color-loading-mix: color-mix(in oklch, var(--color-accent) 100%, black);
19
+ --color-loading: oklch(from var(--color-loading-mix) l c h / 0.25);
20
+ border-bottom-color: var(--color-loading);
21
+ box-shadow:
22
+ 0px 4px 6px -2px var(--color-loading),
23
+ inset 0px -4px 6px -2px var(--color-loading);
24
+ }
25
+
26
+ @keyframes rotation {
27
+ 0% {
28
+ transform: rotate(0deg);
29
+ }
30
+
31
+ 100% {
32
+ transform: rotate(360deg);
33
+ }
34
+ }
35
+
36
+ kbd {
37
+ background-color: var(--color-surface);
38
+ background-image: var(--effect-grain);
39
+ border: none;
40
+ border-radius: var(--radius);
41
+ /* Button-like raised effect */
42
+ box-shadow: var(--shadow-raised);
43
+ padding: var(--space-d6) var(--space-d3);
44
+ font-family: var(--font-monospace);
45
+ font-size: var(--size-xs);
46
+ pointer-events: none;
47
+ }
48
+
49
+ $types: "secondary", "outline", "destructive", "ghost", "icon";
50
+
51
+ :where(button),
52
+ a.btn {
53
+ @extend %surface;
54
+ @extend %padding-text;
55
+ padding: var(--space-d6) var(--space-d2);
56
+ display: inline-flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ font-family: var(--font-interface);
60
+ font-weight: var(--font-weight-bold);
61
+ line-height: var(--line-height);
62
+ font-size: 1em;
63
+ user-select: none;
64
+ background-color: var(--color-surface-high);
65
+ color: var(--color-foreground);
66
+ cursor: pointer;
67
+ gap: var(--space-d3);
68
+ text-align: center;
69
+ min-height: 1em;
70
+
71
+ /* shadcn-style raised effect */
72
+ box-shadow: var(--shadow-raised);
73
+ border: var(--border);
74
+
75
+ transition: all var(--transition-fast);
76
+
77
+ text-box-trim: trim-both;
78
+ text-box-edge: cap alphabetic;
79
+
80
+ text-decoration: none !important;
81
+
82
+ &:hover {
83
+ background-color: var(--color-surface-highest);
84
+ /* Lift shadow slightly on hover */
85
+ color: var(--color-foreground);
86
+ box-shadow: var(--shadow-raised), var(--shadow-lg);
87
+ }
88
+
89
+ &:active {
90
+ background-color: var(--color-surface-low);
91
+ /* Flatten shadow on press */
92
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
93
+ }
94
+
95
+ /* Loop through the list to create .badge-outline, .badge-ghost, etc. */
96
+ @each $type in $types {
97
+ &.#{$type} {
98
+ @extend .btn;
99
+ @extend button;
100
+ }
101
+ }
102
+ }
103
+
104
+ :where(button):focus-visible,
105
+ a.btn:focus-visible {
106
+ outline: 2px solid var(--color-accent);
107
+ outline-offset: 2px;
108
+ }
109
+
110
+ :where(button).destructive,
111
+ a.btn.destructive {
112
+ color: color-mix(in srgb, var(--color-error) 75%, transparent);
113
+
114
+ &:hover {
115
+ background-color: var(--color-error);
116
+ color: var(--color-on-accent);
117
+ }
118
+ }
119
+
120
+ :where(button).secondary,
121
+ a.btn.secondary {
122
+ background-color: var(--color-accent);
123
+ color: var(--color-on-accent);
124
+
125
+ &:hover {
126
+ color: var(--color-accent);
127
+ background-color: var(--color-surface-high);
128
+ box-shadow: var(--shadow-raised), var(--shadow-glow);
129
+ }
130
+
131
+ &:active {
132
+ background-color: var(--color-surface);
133
+ /* Flatten shadow on press */
134
+ box-shadow: var(--shadow-inset), var(--shadow-ring), var(--shadow-glow);
135
+ }
136
+ }
137
+
138
+ :where(button).link,
139
+ a.btn.link {
140
+ background-color: var(--color-surface);
141
+ color: var(--color-link);
142
+
143
+ &:hover {
144
+ background: color-mix(in srgb, currentColor 10%, var(--color-surface));
145
+ }
146
+
147
+ &:active {
148
+ background-color: var(--color-surface);
149
+ /* Flatten shadow on press */
150
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
151
+ }
152
+ }
153
+
154
+ :where(button).outline,
155
+ a.btn.outline {
156
+ background-color: transparent;
157
+ backdrop-filter: var(--filter-blur);
158
+ color: var(--color-subtle);
159
+
160
+ &:hover {
161
+ color: var(--color-foreground);
162
+ background-color: var(--color-surface-higher);
163
+ }
164
+
165
+ &:active {
166
+ color: var(--color-foreground);
167
+ background-color: var(--color-surface-lower);
168
+ /* Flatten shadow on press */
169
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
170
+ }
171
+ }
172
+
173
+ :where(button).ghost,
174
+ a.btn.ghost {
175
+ background: none;
176
+ border: none;
177
+ box-shadow: none;
178
+ color: var(--color-muted);
179
+
180
+ &:hover {
181
+ color: var(--color-foreground);
182
+ background-color: var(--color-surface-higher);
183
+ box-shadow: var(--shadow-raised), var(--shadow-lg);
184
+ }
185
+
186
+ &:active {
187
+ background-color: var(--color-surface);
188
+ /* Flatten shadow on press */
189
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
190
+ }
191
+ }
192
+
193
+ :where(button).large,
194
+ a.btn.large {
195
+ padding: var(--space) var(--space-2);
196
+ font-size: var(--size-base);
197
+ }
198
+
199
+ :where(button).small,
200
+ a.btn.small {
201
+ padding: var(--space-d6) var(--space-d2);
202
+ font-size: var(--size-xs);
203
+ }
204
+
205
+ :where(button).smaller,
206
+ a.btn.smaller {
207
+ padding: var(--space-d6) var(--space-d3);
208
+ font-size: var(--size-xs);
209
+ }
210
+
211
+ :where(button).icon,
212
+ a.btn.icon {
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: center;
216
+ padding: var(--leading);
217
+ margin: 0;
218
+ aspect-ratio: 1/1;
219
+ }
220
+
221
+ :where(button).disabled,
222
+ :where(button):disabled,
223
+ a.btn.disabled,
224
+ a.btn:disabled {
225
+ opacity: 0.5 !important;
226
+ color: var(--color-subtle) !important;
227
+ cursor: not-allowed !important;
228
+ pointer-events: none !important;
229
+ }
230
+ /*
231
+ :is(:where(button), .btn) svg {
232
+ height: 100%;
233
+ width: auto;
234
+ fill: currentColor;
235
+ }
236
+ */
237
+
238
+ .tag {
239
+ color: var(--color-muted);
240
+ }
241
+
242
+ .tag:hover {
243
+ color: var(--color-accent);
244
+ }
245
+
246
+ .badge {
247
+ padding: 0 var(--space-d3);
248
+ background-color: color-mix(in oklch, currentColor 15%, transparent);
249
+ color: var(--color-accent);
250
+ border-radius: 999px;
251
+ border: var(--stroke-width) solid
252
+ color-mix(in oklch, currentColor 30%, transparent);
253
+ font-size: var(--size-xs);
254
+ display: inline-flex;
255
+ align-items: center;
256
+ gap: var(--space-d3);
257
+ text-box-trim: trim-both;
258
+ text-box-edge: cap alphabetic;
259
+ text-decoration: none;
260
+ font-weight: 500;
261
+ font-family: var(--font-interface);
262
+ user-select: none;
263
+ transition: all var(--transition-fast);
264
+ box-shadow: var(--shadow-ring);
265
+ width: fit-content;
266
+
267
+ font-variation-settings: "wdth" 900;
268
+
269
+ &.small {
270
+ padding: 0 var(--space-d4) !important;
271
+ font-size: var(--size-xs);
272
+ }
273
+
274
+ &.smaller {
275
+ padding: 0 var(--space-d4) !important;
276
+ font-size: var(--size-2xs);
277
+ }
278
+
279
+ ::selection {
280
+ background: transparent;
281
+ color: currentColor;
282
+ }
283
+
284
+ a {
285
+ text-decoration-color: oklch(from currentColor l c h / 0.5);
286
+ text-decoration-thickness: 0.112em;
287
+ }
288
+
289
+ /* Loop through the list to create .badge-outline, .badge-ghost, etc. */
290
+ @each $type in $types {
291
+ &.#{$type} {
292
+ @extend .badge;
293
+ }
294
+ }
295
+ }
296
+
297
+ a.badge:hover,
298
+ .badge a:hover {
299
+ color: var(--color-on-accent);
300
+ background: color-mix(
301
+ in oklch,
302
+ var(--color-accent) 70%,
303
+ var(--color-surface)
304
+ );
305
+ }
306
+
307
+ .badge.secondary,
308
+ a.badge.secondary {
309
+ background-color: var(--color-surface);
310
+ color: var(--color-foreground);
311
+ }
312
+
313
+ a.badge.secondary:hover,
314
+ .badge.secondary a:hover {
315
+ color: var(--color-accent);
316
+ background: color-mix(in oklch, currentColor 5%, var(--color-surface));
317
+ }
318
+
319
+ .badge.outline {
320
+ background-color: transparent;
321
+ color: var(--color-muted);
322
+
323
+ &:hover,
324
+ a:hover {
325
+ color: var(--color-foreground);
326
+ background: var(--color-surface);
327
+ }
328
+ }
329
+
330
+ .badge.ghost {
331
+ background-color: transparent;
332
+ border-color: transparent;
333
+ color: var(--color-muted);
334
+
335
+ &:hover {
336
+ color: var(--color-foreground);
337
+ background: var(--color-surface);
338
+ }
339
+ }
340
+
341
+ .badge.destructive {
342
+ background-color: var(--color-surface);
343
+ border-color: color-mix(
344
+ in oklch,
345
+ var(--color-error) 10%,
346
+ var(--color-border)
347
+ );
348
+ color: var(--color-error);
349
+
350
+ &:hover,
351
+ a:hover {
352
+ background-color: var(--color-error);
353
+ color: var(--color-on-accent);
354
+ }
355
+ }
356
+
357
+ .alert {
358
+ font-family: var(--font-interface);
359
+ --color-alert: var(--color-accent);
360
+ padding: var(--space-d2);
361
+ color: color-mix(
362
+ in oklch,
363
+ var(--color-alert) 25%,
364
+ var(--color-foreground)
365
+ ) !important;
366
+ /* Alpha overlay works consistently on both light and dark backgrounds:
367
+ light bg → pale tint, dark bg → visible colored tint */
368
+ background: oklch(from var(--color-alert) l c h / 0.1);
369
+ border-left: var(--stroke-width) solid
370
+ oklch(from var(--color-alert) l c h / 0.5);
371
+ box-shadow: var(--shadow-raised);
372
+ text-shadow: none !important;
373
+ }
374
+
375
+ // Callout Color Variants
376
+ .alert.warning {
377
+ --color-alert: var(--color-warning);
378
+ }
379
+
380
+ .alert.error {
381
+ --color-alert: var(--color-error);
382
+ }
383
+
384
+ .alert.success {
385
+ --color-alert: var(--color-success);
386
+ }
387
+
388
+ .alert.info {
389
+ --color-alert: var(--color-info);
390
+ }
391
+
392
+ /**
393
+ * @name Card Component
394
+ * @group components-layout
395
+ * @author Francis Fontaine
396
+ * @since 0.11.0
397
+ *
398
+ * In 1991, Edward Tufte published "Envisioning Information" and introduced
399
+ * the concept of "small multiples"—the idea that human brains excel at
400
+ * comparing information when it's presented in identical visual containers.
401
+ * Show someone seven weather forecasts in seven different layouts, and they'll
402
+ * struggle. Show them seven identical cards with different data, and patterns
403
+ * emerge instantly. The structure disappears, the content shines.
404
+ *
405
+ * But here's the catch: small multiples only work when they're truly identical.
406
+ * One card with 16px padding, another with 20px, a third with 18px—your brain
407
+ * registers the inconsistency before it processes the content. This component
408
+ * solves that problem by providing a single source of truth for card structure.
409
+ * Every card gets the same padding, the same borders, the same rhythm. Build
410
+ * one card or build a hundred—they'll feel like family.
411
+ *
412
+ * The Swiss designers understood this in the 1950s. Josef Müller-Brockmann's
413
+ * concert posters used rigid grids not to constrain creativity, but to amplify
414
+ * it. When the structure is invisible, when it just works, your content can
415
+ * breathe. That's what `.card` does—it handles the boring consistency so you
416
+ * can focus on making something beautiful.
417
+ *
418
+ * ### Future Improvements
419
+ *
420
+ * - Elevation variants (flat, raised, floating) with shadow scales
421
+ * - Interactive hover states for clickable cards with smooth transitions
422
+ * - Horizontal card layout variant for image + content side-by-side
423
+ * - Dark mode shadow adjustments for better depth perception
424
+ * - Optional card image hero with object-fit controls
425
+ *
426
+ * @see {class} .grid - Often used to layout multiple cards in columns
427
+ * @see {variable} --base - Controls internal spacing rhythm
428
+ * @see {class} .prose - Can be used inside card-body for rich content
429
+ *
430
+ * @link https://en.wikipedia.org/wiki/Edward_Tufte Information Design Pioneer
431
+ * @link https://www.nngroup.com/articles/cards-component/ NN/g Cards Research
432
+ *
433
+ * @example html - Basic card structure
434
+ * <article class="card">
435
+ * <header class="card-header">
436
+ * <h3>Card Title</h3>
437
+ * </header>
438
+ * <div class="card-body">
439
+ * <p>Card content with automatic spacing and rhythm.</p>
440
+ * </div>
441
+ * <footer class="card-footer">
442
+ * <a href="#">Read more →</a>
443
+ * </footer>
444
+ * </article>
445
+ *
446
+ * @example html - Cards in grid layout (3-column responsive)
447
+ * <div class="grid">
448
+ * <article class="card col-4 col-sm-12">
449
+ * <div class="card-body">
450
+ * <h3>Feature One</h3>
451
+ * <p>Description...</p>
452
+ * </div>
453
+ * </article>
454
+ * <article class="card col-4 col-sm-12">...</article>
455
+ * <article class="card col-4 col-sm-12">...</article>
456
+ * </div>
457
+ *
458
+ * @example html - Clickable card (entire card is a link)
459
+ * <a href="/article" class="card card-clickable">
460
+ * <div class="card-body">
461
+ * <h3>Article Title</h3>
462
+ * <p>Preview text that entices you to click...</p>
463
+ * </div>
464
+ * </a>
465
+ *
466
+ * @example scss - Customizing card via CSS variables
467
+ * .card.custom {
468
+ * --card-border-color: var(--color-accent);
469
+ * --card-padding: var(--size-lg);
470
+ * --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
471
+ * }
472
+ */
473
+
474
+ /**
475
+ * @name Clickable Card Variant
476
+ * @group components-layout
477
+ * @since 0.11.0
478
+ *
479
+ * Sometimes your entire card should be clickable—a blog post preview, a product
480
+ * listing, a project showcase. This variant ensures proper hover states, focus
481
+ * indicators, and cursor feedback while maintaining the card's structural integrity.
482
+ *
483
+ * The subtle lift on hover (2px translateY) and enhanced shadow create the
484
+ * illusion of depth—like the card is rising toward you. It's a tactile metaphor
485
+ * for "this is interactive." The focus-visible outline ensures keyboard users
486
+ * can see exactly where they are.
487
+ *
488
+ * Accessibility note: When using clickable cards, ensure the link text is
489
+ * descriptive. "Read more" alone isn't enough—screen readers need context.
490
+ * Use "Read more about [article title]" or aria-label.
491
+ *
492
+ * @see {class} .card - Base component
493
+ * @see {element} a - Applied to anchor tag wrapping card content
494
+ *
495
+ * @example html - Accessible clickable card
496
+ * <a href="/article/typography-history" class="card card-clickable"
497
+ * aria-label="Read full article about Typography History">
498
+ * <div class="card-body">
499
+ * <h3>Typography History</h3>
500
+ * <p>The evolution of type from Gutenberg to now...</p>
501
+ * </div>
502
+ * <div class="card-footer">
503
+ * Read more →
504
+ * </div>
505
+ * </a>
506
+ */
507
+ .card {
508
+ @extend %surface;
509
+ padding: var(--space);
510
+ box-shadow: var(--shadow-raised), var(--shadow-lift);
511
+ background-color: var(--color-surface);
512
+ transition: all var(--transition);
513
+ border-radius: var(--radius);
514
+ border: var(--border);
515
+
516
+ &.hero {
517
+ border-radius: 0;
518
+ }
519
+
520
+ h3 {
521
+ font-size: var(--scale-2);
522
+ }
523
+
524
+ h2 {
525
+ font-size: var(--scale-3);
526
+ }
527
+
528
+ h1 {
529
+ font-size: var(--scale-4);
530
+ }
531
+ }
532
+
533
+ .card > header:first-child {
534
+ background: var(--color-surface);
535
+ box-shadow: var(--shadow-lift);
536
+ border-bottom: var(--border);
537
+ border-radius: var(--radius) var(--radius) 0 0;
538
+ padding: var(--space);
539
+ margin: calc(var(--space) * -1);
540
+ margin-block-end: 0;
541
+
542
+ :is(h1, h2, h3, h4, h5, h6) {
543
+ margin-block: 0;
544
+ }
545
+
546
+ &.surface {
547
+ margin-bottom: 0;
548
+ border-bottom: var(--border);
549
+
550
+ box-shadow: var(--shadow);
551
+ background-color: var(--color-surface);
552
+ }
553
+
554
+ p {
555
+ margin-top: var(--space-d2);
556
+ color: var(--color-muted);
557
+ font-size: var(--size-sm);
558
+ }
559
+
560
+ + * {
561
+ margin-block-start: var(--space);
562
+ }
563
+ }
564
+
565
+ .card > header:has(svg):first-child {
566
+ display: flex;
567
+ align-items: center;
568
+ justify-content: space-between;
569
+ a {
570
+ margin-top: 0;
571
+ }
572
+ }
573
+
574
+ .card > footer:last-child {
575
+ background: var(--color-surface-low);
576
+ border-top: var(--border);
577
+ border-radius: 0 0 var(--radius) var(--radius);
578
+ padding: var(--space-d2) var(--space);
579
+ font-size: var(--size-sm);
580
+ margin: calc(var(--space) * -1);
581
+ margin-top: var(--space);
582
+ }
583
+
584
+ .card.clickable {
585
+ a {
586
+ text-decoration: none;
587
+ }
588
+
589
+ color: inherit;
590
+ cursor: pointer;
591
+
592
+ &:hover {
593
+ transform: translateY(-2px);
594
+ /* Subtle lift with shadow preset */
595
+ box-shadow: var(--shadow-lg);
596
+ }
597
+
598
+ &:focus-visible {
599
+ outline: 3px solid var(--color-accent);
600
+ outline-offset: 2px;
601
+ }
602
+
603
+ &:active {
604
+ transform: translateY(0);
605
+ /* Press down on click */
606
+ }
607
+ }
608
+
609
+ .inset,
610
+ card.inset {
611
+ box-shadow: inset var(--shadow) !important;
612
+ }
613
+
614
+ .callout {
615
+ /* Raised effect for callout cards */
616
+ box-shadow: var(--shadow-raised), var(--shadow-ring);
617
+
618
+ border-radius: var(--radius-sm);
619
+ padding: var(--space-d8);
620
+ padding-top: 0;
621
+ --color-callout: var(--color-surface);
622
+ --color-border: oklch(from var(--color-callout) l c h / 0.15);
623
+ background: color-mix(
624
+ in srgb,
625
+ var(--color-callout) 10%,
626
+ var(--color-surface-high)
627
+ );
628
+ font-size: var(--size-sm);
629
+
630
+ .callout-title,
631
+ > summary {
632
+ position: relative;
633
+ color: color-mix(
634
+ in oklch,
635
+ var(--color-callout) 50%,
636
+ var(--color-foreground)
637
+ );
638
+ display: flex;
639
+ gap: var(--leading);
640
+ font-weight: var(--font-weight-bold, bold);
641
+
642
+ user-select: none;
643
+ padding: var(--space-d2);
644
+ margin: 0 !important;
645
+
646
+ .callout-title-inner {
647
+ margin: 0;
648
+ }
649
+ }
650
+
651
+ .callout-content:has(> p:empty:only-child) {
652
+ display: none;
653
+ }
654
+
655
+ .callout-content {
656
+ color: var(--color-foreground);
657
+ background: color-mix(
658
+ in srgb,
659
+ var(--color-callout) 10%,
660
+ var(--color-surface-low)
661
+ );
662
+ line-height: var(--line-height-compact);
663
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
664
+ border-radius: var(--radius-sm);
665
+ padding: var(--space-d2);
666
+ margin-top: 0;
667
+ margin-left: 0;
668
+ text-align: left;
669
+
670
+ p:first-child,
671
+ p:first-child:empty + p {
672
+ margin-top: 0 !important;
673
+ }
674
+
675
+ p:last-child {
676
+ margin-bottom: 0 !important;
677
+ }
678
+
679
+ ul,
680
+ ol {
681
+ padding: 0 var(--space-d2);
682
+ list-style: none;
683
+ }
684
+
685
+ pre {
686
+ margin: var(--space-d2) 0;
687
+ }
688
+
689
+ > .callout {
690
+ margin: calc(var(--space) * -1);
691
+
692
+ .callout-content {
693
+ padding: var(--space);
694
+ }
695
+
696
+ .callout-title {
697
+ padding-left: var(--space);
698
+ padding-right: var(--space);
699
+ }
700
+ }
701
+ }
702
+
703
+ .callout-title-icon {
704
+ display: none;
705
+ }
706
+
707
+ img {
708
+ margin-left: 0;
709
+ margin-right: 0;
710
+ }
711
+ }
712
+
713
+ // Callout Color Variants
714
+ .callout[data-callout="warning" i] {
715
+ --color-callout: var(--color-red);
716
+ }
717
+
718
+ .callout[data-callout="important" i] {
719
+ --color-callout: var(--color-orange);
720
+ }
721
+
722
+ // Notion Color Variants
723
+ .callout[data-callout*="gray" i] {
724
+ --color-callout: var(--color-foreground);
725
+ }
726
+
727
+ .callout[data-callout*="red" i] {
728
+ --color-callout: var(--color-red);
729
+ }
730
+
731
+ .callout[data-callout*="brown" i] {
732
+ --color-callout: var(--color-brown);
733
+ }
734
+
735
+ .callout[data-callout*="orange" i] {
736
+ --color-callout: var(--color-orange);
737
+ }
738
+
739
+ .callout[data-callout*="yellow" i] {
740
+ --color-callout: var(--color-yellow);
741
+ }
742
+
743
+ .callout[data-callout*="green" i] {
744
+ --color-callout: var(--color-green);
745
+ }
746
+
747
+ .callout[data-callout*="cyan" i] {
748
+ --color-callout: var(--color-cyan);
749
+ }
750
+
751
+ .callout[data-callout*="blue" i] {
752
+ --color-callout: var(--color-blue);
753
+ }
754
+
755
+ .callout[data-callout*="magenta" i] {
756
+ --color-callout: var(--color-magenta);
757
+ }
758
+
759
+ .callout[data-callout*="purple" i] {
760
+ --color-callout: var(--color-purple);
761
+ }
762
+
763
+ .callout[data-callout*="pink" i] {
764
+ --color-callout: var(--color-pink);
765
+ }
766
+
767
+ // Details/Summary specific callout styles
768
+ details > summary {
769
+ list-style: none;
770
+ /* removes marker in Firefox */
771
+ }
772
+
773
+ details .callout-title::before {
774
+ content: "▸";
775
+ display: inline-block;
776
+ transform: rotate(0deg);
777
+ margin-right: 0;
778
+ text-align: center;
779
+ text-box-trim: trim-both;
780
+ text-box-edge: cap alphabetic;
781
+ transform-origin: center;
782
+ transition: all var(--transition);
783
+ }
784
+
785
+ details[open] .callout-title::before {
786
+ transform: rotate(90deg);
787
+ }
788
+
789
+ details .callout-title-inner {
790
+ display: inline;
791
+ }
792
+
793
+ details.callout {
794
+ interpolate-size: allow-keywords;
795
+
796
+ &::details-content {
797
+ height: 0;
798
+ overflow: hidden;
799
+ transition:
800
+ height var(--transition),
801
+ content-visibility var(--transition) allow-discrete;
802
+ }
803
+
804
+ &[open]::details-content {
805
+ height: auto;
806
+ }
807
+ }
808
+
809
+ details .callout-fold {
810
+ margin: 0;
811
+ }
812
+
813
+ // Caption Callout (after an image)
814
+ p:has(img) + .callout[data-callout="caption" i] {
815
+ padding: 0;
816
+ background: none;
817
+ padding-block-start: var(--gap);
818
+ border: none;
819
+ margin: 0 var(--space);
820
+ box-shadow: none;
821
+
822
+ .callout-title {
823
+ display: none;
824
+ }
825
+
826
+ .callout-content {
827
+ padding: 0;
828
+ background: none;
829
+ color: var(--color-muted);
830
+ border: none;
831
+
832
+ box-shadow: none;
833
+ text-align: center;
834
+ text-wrap: balance;
835
+ }
836
+ }
837
+
838
+ details .callout-title-inner {
839
+ display: inline;
840
+ }
841
+
842
+ details .callout-content {
843
+ max-height: 0;
844
+ opacity: 0;
845
+ overflow: hidden;
846
+ transition:
847
+ max-height var(--transition),
848
+ opacity var(--transition);
849
+ }
850
+
851
+ details[open] .callout-content {
852
+ max-height: 1000px;
853
+ opacity: 1;
854
+ }
855
+
856
+ details .callout-fold {
857
+ margin: 0;
858
+ }
859
+
860
+ /**
861
+ * @name Comments
862
+ * @group comments
863
+ * @since 0.11.0
864
+ */
865
+
866
+ #comments {
867
+ * {
868
+ margin-block-end: 0;
869
+ }
870
+
871
+ font-size: var(--size-sm);
872
+
873
+ .comment {
874
+ border: var(--border);
875
+ box-shadow: var(--shadow);
876
+ border-radius: var(--radius);
877
+ background: var(--color-surface);
878
+ padding: var(--space) var(--space-d2);
879
+ margin-block-end: var(--space);
880
+
881
+ .comment-header {
882
+ display: flex;
883
+ align-items: baseline;
884
+ gap: var(--space-d2);
885
+
886
+ .comment-author {
887
+ font-weight: var(--font-weight-bold);
888
+ }
889
+
890
+ .comment-date,
891
+ .comment-pending {
892
+ color: var(--color-subtle);
893
+ font-size: var(--size-xs);
894
+ }
895
+
896
+ .comment-pending {
897
+ font-style: italic;
898
+ color: var(--color-orange);
899
+ }
900
+ }
901
+
902
+ .comment-content {
903
+ margin-inline: var(--space-d2);
904
+ margin-block-start: var(--space-d2);
905
+ border-left: var(--border);
906
+ padding: var(--space-d2);
907
+ color: var(--color-muted);
908
+ font-size: var(--size-sm);
909
+ line-height: var(--line-height-compact);
910
+ }
911
+ }
912
+
913
+ :last-child {
914
+ margin-block-end: 0;
915
+ }
916
+ }
917
+
918
+ /**
919
+ * @name Alert Action Links
920
+ * @group components-feedback
921
+ * @since 0.11.0
922
+ *
923
+ * Actions within alerts (links, buttons) should be visually distinct but not
924
+ * overwhelming. This provides subtle styling that inherits the alert's color.
925
+ */
926
+ .alert-action {
927
+ display: inline-block;
928
+ margin-inline-start: var(--space-d2);
929
+ color: var(--alert-border-color);
930
+ text-decoration: underline;
931
+ font-weight: var(--font-weight-bold);
932
+
933
+ &:hover {
934
+ text-decoration-thickness: 0.15em;
935
+ }
936
+ }
937
+
938
+ a.skip-link {
939
+ /* Positioning - absolute to top-left corner */
940
+ position: absolute;
941
+ top: var(--space-d3);
942
+ left: var(--space-d3);
943
+ z-index: var(--z-modal);
944
+ /* Above everything else */
945
+
946
+ /* Styling - high contrast, unmissable */
947
+ background: var(--color-accent);
948
+ color: var(--color-background);
949
+ padding: var(--space-d3);
950
+ border-radius: var(--radius);
951
+ font-weight: var(--font-weight-bold);
952
+ font-size: var(--size-sm);
953
+ text-decoration: none;
954
+ box-shadow: var(--shadow-xl);
955
+
956
+ /* Animation */
957
+
958
+ /* Hidden by default (accessible hiding) */
959
+ transform: translateY(-120%);
960
+ opacity: 0;
961
+
962
+ /* Visible on focus (Tab key) */
963
+ &:focus {
964
+ transform: translateY(0);
965
+ opacity: 1;
966
+ outline: 3px solid var(--color-background);
967
+ outline-offset: 2px;
968
+ }
969
+
970
+ /* Hover state (if user moves mouse while focused) */
971
+ &:hover {
972
+ background: color-mix(
973
+ in srgb,
974
+ var(--color-accent) 90%,
975
+ var(--color-background)
976
+ );
977
+ color: var(--color-background);
978
+ }
979
+
980
+ /* Active state (on click) */
981
+ &:active {
982
+ transform: translateY(0) scale(0.98);
983
+ }
984
+ }
985
+
986
+ .skip-links {
987
+ position: absolute;
988
+ top: 0;
989
+ left: 0;
990
+ z-index: var(--z-modal);
991
+ display: flex;
992
+ flex-direction: column;
993
+ gap: var(--space);
994
+ padding: var(--space-d3);
995
+ }
996
+
997
+ /* =========================== */
998
+ /* MENUS / POPOVERS */
999
+ /* =========================== */
1000
+
1001
+ @keyframes std-menu-in {
1002
+ from {
1003
+ opacity: 0;
1004
+ transform: scale(0.95) translateY(-5px);
1005
+ }
1006
+ to {
1007
+ opacity: 1;
1008
+ transform: scale(1) translateY(0);
1009
+ }
1010
+ }
1011
+
1012
+ .std-menu-content {
1013
+ padding: var(--space-d4);
1014
+ background: var(--color-surface-high);
1015
+ border: none;
1016
+ border-radius: var(--radius-sm);
1017
+ box-shadow: var(--shadow-raised), var(--shadow-glow);
1018
+ display: flex;
1019
+ flex-direction: column;
1020
+ z-index: var(--z-dropdown);
1021
+ animation: std-menu-in var(--transition-fast);
1022
+ transform-origin: top left;
1023
+
1024
+ * {
1025
+ text-shadow: none !important;
1026
+ }
1027
+ }
1028
+
1029
+ .std-menu-label {
1030
+ padding: var(--space-d4);
1031
+ font-family: var(--font-interface);
1032
+ font-size: var(--size-2xs);
1033
+ font-weight: var(--font-weight);
1034
+ color: var(--color-subtle);
1035
+ user-select: none;
1036
+ }
1037
+
1038
+ .std-menu-separator {
1039
+ all: unset;
1040
+ display: block;
1041
+ height: var(--stroke-width);
1042
+ background: var(--color-border) !important;
1043
+ margin: var(--space-d4) 0;
1044
+ opacity: 1;
1045
+
1046
+ &::after {
1047
+ display: none;
1048
+ }
1049
+ }
1050
+
1051
+ .std-menu-item {
1052
+ all: unset;
1053
+ display: flex;
1054
+ width: 100%;
1055
+ box-sizing: border-box;
1056
+ align-items: center;
1057
+ gap: var(--space-d4);
1058
+ padding: 0 var(--space-d4);
1059
+ border-radius: var(--radius-sm);
1060
+ font-size: var(--size-sm);
1061
+ font-family: var(--font-interface);
1062
+ color: var(--color-foreground);
1063
+ cursor: pointer;
1064
+ user-select: none;
1065
+ transition: all var(--transition-fast);
1066
+ min-height: var(--space);
1067
+ text-decoration: none;
1068
+
1069
+ &:hover:not(.disabled) {
1070
+ background: var(--color-surface-highest);
1071
+ box-shadow: var(--shadow-raised);
1072
+ }
1073
+
1074
+ &:active:not(.disabled) {
1075
+ background: var(--color-surface-low);
1076
+ box-shadow: var(--shadow-inset);
1077
+ }
1078
+
1079
+ &.disabled {
1080
+ opacity: 0.5;
1081
+ cursor: not-allowed;
1082
+ }
1083
+
1084
+ &.destructive {
1085
+ color: var(--color-red);
1086
+
1087
+ &:hover {
1088
+ background: var(--color-red);
1089
+ color: var(--color-on-accent);
1090
+ }
1091
+ }
1092
+
1093
+ .item-icon {
1094
+ display: flex;
1095
+ align-items: center;
1096
+ justify-content: center;
1097
+ color: var(--color-muted);
1098
+ }
1099
+
1100
+ &:hover .item-icon {
1101
+ color: var(--color-foreground);
1102
+ }
1103
+
1104
+ .item-label {
1105
+ flex: 1;
1106
+ white-space: nowrap;
1107
+ }
1108
+
1109
+ .item-shortcut {
1110
+ font-size: var(--size-3xs);
1111
+ color: var(--color-muted);
1112
+ letter-spacing: 0.1em;
1113
+ padding-left: var(--space);
1114
+ }
1115
+ }
1116
+
1117
+ .scroll {
1118
+ /* Container styling */
1119
+ position: relative;
1120
+ width: 100%;
1121
+ overflow-x: auto;
1122
+ overflow-y: auto;
1123
+
1124
+ /* Smooth scrolling with momentum */
1125
+
1126
+ &::before,
1127
+ &::after {
1128
+ content: "";
1129
+ position: absolute;
1130
+ top: 0;
1131
+ bottom: 0;
1132
+ z-index: 2;
1133
+ pointer-events: none;
1134
+ width: var(--space);
1135
+ opacity: 0;
1136
+ box-shadow: var(--shadow-ring), var(--shadow-glow);
1137
+ transition: box-shadow var(--transition);
1138
+
1139
+ /* Not sure if I like the whole idea but dont want to lose the code so I've hidden it for now */
1140
+ display: none;
1141
+ }
1142
+
1143
+ &::before {
1144
+ left: calc((var(--space) * -1) + 1px);
1145
+ }
1146
+
1147
+ /* Define the Right Shadow (initially visible) */
1148
+ &::after {
1149
+ right: calc((var(--space) * -1) + 1px);
1150
+ }
1151
+
1152
+ /* When this class is added, the left shadow fades in. */
1153
+ &.show-left-shadow::before {
1154
+ opacity: 1;
1155
+ }
1156
+
1157
+ /* When this class is added, the right shadow fades in. */
1158
+ &.show-right-shadow::after {
1159
+ opacity: 1;
1160
+ }
1161
+
1162
+ & > * {
1163
+ margin-block-end: 0;
1164
+ /* Remove table's own margin */
1165
+ min-width: 100%;
1166
+ /* Ensure table fills wrapper */
1167
+ width: max-content;
1168
+ /* Allow table to grow beyond wrapper */
1169
+ }
1170
+ }
1171
+
1172
+ .field {
1173
+ /* Field container */
1174
+ display: flex;
1175
+ flex-direction: column;
1176
+ gap: var(--space);
1177
+
1178
+ /* Label styling */
1179
+ label {
1180
+ font-weight: var(--font-weight-bold);
1181
+ font-size: var(--size-sm);
1182
+ color: var(--color-foreground);
1183
+ }
1184
+ }
1185
+
1186
+ [data-tooltip] {
1187
+ position: relative;
1188
+ cursor: help;
1189
+ }
1190
+
1191
+ /* The tooltip bubble */
1192
+ [data-tooltip]::after {
1193
+ content: attr(data-tooltip);
1194
+ position: absolute;
1195
+ bottom: 100%;
1196
+ left: 50%;
1197
+ transform: translateX(-50%) translateY(10px) scale(0.95);
1198
+
1199
+ background: var(--tooltip-background);
1200
+ color: var(--tooltip-text);
1201
+ padding: 6px 12px;
1202
+ border-radius: 4px;
1203
+ font-size: 0.75rem;
1204
+ font-weight: 500;
1205
+ white-space: normal;
1206
+ pointer-events: none;
1207
+ z-index: 1000;
1208
+ box-shadow: var(--shadow-lg), var(--shadow-glow);
1209
+
1210
+ /* Hidden state */
1211
+ opacity: 0;
1212
+ visibility: hidden;
1213
+ width: 200px;
1214
+ transition: opacity var(--transition);
1215
+ }
1216
+
1217
+ /* The arrow */
1218
+ [data-tooltip]::before {
1219
+ content: "";
1220
+ position: absolute;
1221
+ bottom: 100%;
1222
+ left: 50%;
1223
+ transform: translateX(-50%) translateY(10px);
1224
+ border: 5px solid transparent;
1225
+ border-top-color: var(--tooltip-background);
1226
+ margin-bottom: -10px;
1227
+ opacity: 0;
1228
+ visibility: hidden;
1229
+ pointer-events: none;
1230
+ z-index: 1000;
1231
+ transition: opacity var(--transition);
1232
+ }
1233
+
1234
+ /* Hover state */
1235
+ [data-tooltip]:hover::after,
1236
+ [data-tooltip]:hover::before {
1237
+ opacity: 1;
1238
+ visibility: visible;
1239
+ transform: translateX(-50%) translateY(-8px) scale(1);
1240
+ }
1241
+
1242
+ /* Bottom position variant */
1243
+ [data-tooltip-pos="bottom"]::after {
1244
+ bottom: auto;
1245
+ top: 100%;
1246
+ transform: translateX(-50%) translateY(-10px) scale(0.95);
1247
+ }
1248
+
1249
+ [data-tooltip-pos="bottom"]::before {
1250
+ bottom: auto;
1251
+ top: 100%;
1252
+ border-top-color: transparent;
1253
+ border-bottom-color: var(--tooltip-background);
1254
+ margin-bottom: 0;
1255
+ margin-top: -10px;
1256
+ }
1257
+
1258
+ [data-tooltip-pos="bottom"]:hover::after,
1259
+ [data-tooltip-pos="bottom"]:hover::before {
1260
+ transform: translateX(-50%) translateY(8px) scale(1);
1261
+ }