opui-css 3.3.2 → 3.3.3

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,3869 @@
1
+ /*
2
+ * Components are divided into two categories - if they are stand-alone (root) or if they are built on top of others (extended).
3
+ */
4
+
5
+ /*** Root components (no dependencies) */
6
+
7
+ @layer components.root {
8
+ :where(.button) {
9
+ --_bg-color: transparent;
10
+ --_border-color: transparent;
11
+ --_border-radius: var(--button-border-radius);
12
+ --_font-size: initial;
13
+ --_min-height: 2.375rem;
14
+ --_text-color: var(--primary);
15
+
16
+ -webkit-tap-highlight-color: transparent;
17
+ -webkit-touch-callout: none;
18
+ align-items: center;
19
+ background: var(--_bg-color) var(--ripple, none);
20
+ border-radius: var(--_border-radius);
21
+ border: var(--border-size-1) solid var(--_border-color);
22
+ color: var(--_text-color);
23
+ display: inline-flex;
24
+ font-size: var(--_font-size);
25
+ font-weight: 700;
26
+ gap: var(--size-2);
27
+ justify-content: center;
28
+ min-block-size: var(--_min-height);
29
+ padding-block: 0.5ex;
30
+ padding-inline: 1.5ex;
31
+ text-align: center;
32
+ text-decoration: none;
33
+
34
+ user-select: none;
35
+
36
+ &:where([disabled]) {
37
+ cursor: not-allowed;
38
+ opacity: 0.64;
39
+ }
40
+
41
+ @media (prefers-reduced-motion: no-preference) {
42
+ transition:
43
+ background-color 0.2s var(--ease-out-3),
44
+ box-shadow 0.2s var(--ease-out-3),
45
+ border-color 0.2s var(--ease-out-3),
46
+ color 0.2s var(--ease-out-3),
47
+ outline-offset 0.05s var(--ease-1);
48
+
49
+ /* Ripple effect */
50
+ background-position: center;
51
+
52
+ &:where(:not([disabled])) {
53
+ &:where(:not(:active):hover) {
54
+ --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%)
55
+ center/15000%;
56
+
57
+ transition: background var(--button-ripple-duration);
58
+ }
59
+
60
+ &:where(:hover:active) {
61
+ background-size: var(--button-ripple-size);
62
+ transition: background 0s;
63
+ }
64
+ }
65
+ }
66
+
67
+ /* Element states */
68
+ &:where(:not([disabled])) {
69
+ &:where(:not(:active):hover) {
70
+ --_bg-color: light-dark(
71
+ oklch(from var(--primary) l 0.01 h / 20%),
72
+ oklch(from var(--primary) l 0.01 h / 40%)
73
+ );
74
+ }
75
+
76
+ &:where(:hover:active) {
77
+ --_bg-color: light-dark(
78
+ oklch(from var(--primary) l 0.06 h / 30%),
79
+ oklch(from var(--primary) l 0.06 h / 40%)
80
+ );
81
+ }
82
+ }
83
+
84
+ /* Disabled */
85
+ &:where([disabled]) {
86
+ --_text-color: color-mix(
87
+ in oklch,
88
+ var(--text-color-2) 50%,
89
+ var(--surface-default)
90
+ );
91
+ }
92
+
93
+ /* Icon */
94
+ &:where(:has(svg), &.icon-only) {
95
+ gap: 1ex;
96
+
97
+ svg {
98
+ max-block-size: 0.7lh;
99
+ color: currentColor;
100
+ }
101
+ }
102
+
103
+ /* Keyboard input */
104
+ :is(kbd) {
105
+ background-color: inherit;
106
+ border-color: currentColor;
107
+ color: inherit;
108
+ font-size: 0.85em;
109
+ line-height: 1.2;
110
+ }
111
+
112
+ /* Sizes */
113
+ &.small {
114
+ --_min-height: 1.875rem;
115
+ padding-block: 0;
116
+ padding-inline: 1ex;
117
+ }
118
+
119
+ &.large {
120
+ --_min-height: 2.875rem;
121
+ padding-inline: 4ex;
122
+ }
123
+
124
+ /* Variants */
125
+ &.outlined {
126
+ --_bg-color: var(--surface-default);
127
+ --_border-color: var(--color-8);
128
+ --_text-color: var(--color-8);
129
+
130
+ &:where(:not([disabled])) {
131
+ &:where(:not(:active):hover) {
132
+ --_bg-color: var(--color-10);
133
+ --_border-color: var(--color-10);
134
+ --_text-color: var(--color-1);
135
+ }
136
+
137
+ &:where(:active) {
138
+ --_bg-color: var(--color-9);
139
+ --_border-color: var(--color-9);
140
+ --_text-color: var(--color-1);
141
+ }
142
+ }
143
+
144
+ &:where([disabled]) {
145
+ --_bg-color: var(--surface-default);
146
+ --_border-color: color-mix(
147
+ in oklch,
148
+ var(--text-color-2) 20%,
149
+ var(--surface-default)
150
+ );
151
+ --_text-color: color-mix(
152
+ in oklch,
153
+ var(--text-color-2) 40%,
154
+ var(--surface-default)
155
+ );
156
+ }
157
+ }
158
+ &.tonal {
159
+ --_bg-color: var(--color-6);
160
+ --_text-color: var(--color-16);
161
+
162
+ &:where(:not([disabled])) {
163
+ &:where(:not(:active):hover) {
164
+ --_bg-color: var(--color-9);
165
+ --_border-color: var(--color-9);
166
+ }
167
+
168
+ &:where(:active) {
169
+ --_bg-color: var(--color-7);
170
+ --_border-color: var(--color-7);
171
+ }
172
+ }
173
+
174
+ &:where([disabled]) {
175
+ --_bg-color: color-mix(
176
+ in oklch,
177
+ var(--text-color-2) 8%,
178
+ var(--surface-default)
179
+ );
180
+ --_text-color: color-mix(
181
+ in oklch,
182
+ var(--text-color-2) 70%,
183
+ var(--surface-default)
184
+ );
185
+ }
186
+ }
187
+ &.filled {
188
+ --_bg-color: var(--color-8);
189
+ --_text-color: var(--color-1);
190
+
191
+ &:where(:not([disabled])) {
192
+ &:where(:not(:active):hover) {
193
+ --_bg-color: var(--color-10);
194
+ --_border-color: var(--color-10);
195
+ }
196
+
197
+ &:where(:active) {
198
+ --_bg-color: var(--color-9);
199
+ --_border-color: var(--color-9);
200
+ }
201
+ }
202
+
203
+ &:where([disabled]) {
204
+ --_bg-color: color-mix(
205
+ in oklch,
206
+ var(--text-color-2) 20%,
207
+ var(--surface-default)
208
+ );
209
+ --_text-color: color-mix(
210
+ in oklch,
211
+ var(--text-color-2) 70%,
212
+ var(--surface-default)
213
+ );
214
+ }
215
+ }
216
+ &.elevated {
217
+ --_bg-color: light-dark(
218
+ color-mix(in oklch, var(--gray-2) 97%, var(--color-16)),
219
+ color-mix(in oklch, var(--gray-13) 97%, var(--color-1))
220
+ );
221
+ --_ripple-color: light-dark(
222
+ color-mix(in oklch, var(--gray-2) 80%, var(--color-8)),
223
+ color-mix(in oklch, var(--gray-13) 80%, var(--color-8))
224
+ );
225
+ --_text-color: var(--color-8);
226
+
227
+ box-shadow:
228
+ 0px 3px 1px -2px oklch(0 0 0 / 20%),
229
+ 0px 2px 2px 0px oklch(0 0 0 / 14%),
230
+ 0px 1px 5px 0px oklch(0 0 0 / 12%);
231
+
232
+ &:where(:not([disabled])) {
233
+ &:where(:not(:active):hover) {
234
+ --ripple: radial-gradient(
235
+ circle,
236
+ transparent 1%,
237
+ var(--_ripple-color) 1%
238
+ )
239
+ center/15000%;
240
+
241
+ --_bg-color: light-dark(
242
+ color-mix(in oklch, var(--gray-2) 93%, var(--color-8)),
243
+ color-mix(in oklch, var(--gray-13) 93%, var(--color-8))
244
+ );
245
+ }
246
+
247
+ &:where(:hover:active) {
248
+ --_bg-color: light-dark(
249
+ color-mix(in oklch, var(--gray-2) 91%, var(--color-8)),
250
+ color-mix(in oklch, var(--gray-13) 91%, var(--color-8))
251
+ );
252
+ }
253
+ }
254
+
255
+ &:where([disabled]) {
256
+ --_bg-color: color-mix(
257
+ in oklch,
258
+ var(--text-color-2) 8%,
259
+ var(--surface-elevated)
260
+ );
261
+ --_text-color: color-mix(
262
+ in oklch,
263
+ var(--text-color-2) 70%,
264
+ var(--surface-elevated)
265
+ );
266
+ }
267
+ }
268
+ }
269
+
270
+ /* file input */
271
+ :where(input[type="file"]) {
272
+ align-self: flex-start;
273
+ border-radius: var(--radius-2);
274
+ border: var(--border-size-1) solid var(--surface-filled);
275
+ box-shadow: var(--inner-shadow-4);
276
+ color: var(--text-color-2-contrast);
277
+ cursor: initial;
278
+ max-inline-size: 100%;
279
+ padding: 0;
280
+ }
281
+
282
+ :where(input[type="file"])::-webkit-file-upload-button,
283
+ :where(input[type="file"])::file-selector-button {
284
+ cursor: pointer;
285
+ margin-inline-end: var(--size-relative-6);
286
+ }
287
+ }
288
+
289
+ @layer components.root {
290
+ :where(.icon-button) {
291
+ --_text-color: inherit;
292
+
293
+ align-items: center;
294
+ aspect-ratio: 1;
295
+ background-color: transparent;
296
+ border: 0;
297
+ border-radius: var(--radius-round);
298
+ display: inline-flex;
299
+ inline-size: var(--size-6);
300
+ justify-content: center;
301
+ padding: 0;
302
+ transform-style: preserve-3d;
303
+
304
+ &:where([disabled]) {
305
+ color: light-dark(rgb(0, 0, 0/0.3), rgb(255, 255, 255/0.26));
306
+ cursor: not-allowed;
307
+ opacity: 0.64;
308
+ }
309
+
310
+ svg {
311
+ max-inline-size: var(--size-5);
312
+ pointer-events: none;
313
+ }
314
+
315
+ /* Ripple effect, utils.css */
316
+ &::before {
317
+ --highlight-size: 130%;
318
+ }
319
+
320
+ /* Size */
321
+ &.small {
322
+ inline-size: var(--size-4);
323
+ svg {
324
+ max-inline-size: var(--size-4);
325
+ }
326
+ }
327
+ }
328
+ }
329
+
330
+ @layer components.root {
331
+ :where(nav.tabs) {
332
+ --_bg-color: transparent;
333
+
334
+ & > [role="tablist"] {
335
+ button {
336
+ outline-color: transparent;
337
+ outline-offset: -4px;
338
+
339
+ &[aria-selected="true"] {
340
+ &:focus-visible {
341
+ outline: 2px solid var(--text-color-1);
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ /* Underlined */
348
+ &.underlined {
349
+ /* Tab list */
350
+ & > [role="tablist"] {
351
+ border-bottom: 1px solid var(--border-color);
352
+
353
+ button {
354
+ --_ripple-color: light-dark(
355
+ color-mix(in oklch, var(--gray-2) 80%, var(--color-8)),
356
+ color-mix(in oklch, var(--gray-13) 80%, var(--color-8))
357
+ );
358
+
359
+ background: var(--_bg-color) var(--ripple, none);
360
+ font-weight: 500;
361
+ line-height: var(--font-lineheight-4);
362
+ padding: var(--size-2) var(--size-3);
363
+
364
+ &:focus-visible {
365
+ border-radius: 0;
366
+ }
367
+
368
+ &[aria-selected="true"] {
369
+ border-block-end: 2px solid var(--primary);
370
+ color: var(--primary);
371
+ }
372
+
373
+ @media (prefers-reduced-motion: no-preference) {
374
+ transition: background-color 0.2s var(--ease-out-3),
375
+ border-color 0.2s var(--ease-out-3), color 0.2s var(--ease-out-3),
376
+ outline-offset 0.05s var(--ease-1);
377
+
378
+ /*** Ripple effect */
379
+ background-position: center;
380
+ transition: background var(--button-ripple-duration);
381
+ &:where(:not(:active):hover) {
382
+ --ripple: radial-gradient(
383
+ circle,
384
+ transparent 1%,
385
+ var(--_ripple-color) 1%
386
+ )
387
+ center/15000%;
388
+ }
389
+
390
+ &:where(:hover:active) {
391
+ background-size: var(--button-ripple-size);
392
+ transition: background 0s;
393
+ }
394
+
395
+ &:hover {
396
+ background-color: light-dark(
397
+ oklch(from var(--primary) calc(l * 0.75) none h / 5%),
398
+ oklch(from var(--primary) calc(l * 1.25) none h / 5%)
399
+ );
400
+ }
401
+ }
402
+ }
403
+ }
404
+ }
405
+
406
+ /* Filled */
407
+ &.filled {
408
+ --_bg-color: var(--surface-default);
409
+ --_radius: var(--border-radius);
410
+ --_selected-bg: var(--surface-filled);
411
+
412
+ & > [role="tablist"] {
413
+ background-color: var(--_bg-color);
414
+ border: var(--border-width) solid var(--border-color);
415
+ border-radius: var(--_radius);
416
+ overflow: hidden;
417
+ padding: 0.792ex;
418
+ width: fit-content;
419
+
420
+ button {
421
+ background-color: var(--_bg-color);
422
+ border-radius: var(--_radius);
423
+ line-height: var(--font-lineheight-4);
424
+ padding-inline: var(--size-3);
425
+
426
+ &:hover {
427
+ background-color: oklch(from var(--_bg-color) calc(l * 1.25) c h);
428
+ }
429
+
430
+ &[aria-selected="true"] {
431
+ background-color: var(--_selected-bg);
432
+
433
+ &:hover {
434
+ background-color: oklch(
435
+ from var(--_selected-bg) calc(l * 1.25) c h
436
+ );
437
+ }
438
+ }
439
+
440
+ @media (prefers-reduced-motion: no-preference) {
441
+ transition: background-color 0.2s var(--ease-out-3),
442
+ border-color 0.2s var(--ease-out-3), color 0.2s var(--ease-out-3),
443
+ outline-offset 0.05s var(--ease-1);
444
+ }
445
+ }
446
+ }
447
+ }
448
+ }
449
+ }
450
+
451
+ @layer components.root {
452
+ :where([role="group"].toggle-button-group) {
453
+ --_border-radius: var(--radius-round);
454
+ --_button-padding-inline: clamp(var(--size-2), 3cqi, var(--size-4));
455
+ --_max-width: auto;
456
+ --_icon-size: var(--size-4);
457
+
458
+ background-color: var(--surface-default);
459
+ border: 1px solid var(--border-color);
460
+ border-radius: var(--_border-radius);
461
+ display: flex;
462
+ grid-auto-columns: 1fr;
463
+ grid-auto-flow: column;
464
+ max-inline-size: var(--_max-width);
465
+ min-inline-size: max-content;
466
+ overflow: clip;
467
+
468
+ /* Size */
469
+ &.small {
470
+ button {
471
+ min-block-size: 2.1875rem; /* 35px */
472
+ }
473
+ }
474
+
475
+ &.x-small {
476
+ button {
477
+ min-block-size: var(--size-6); /* 30px */
478
+ }
479
+ }
480
+
481
+ &.fullwidth {
482
+ inline-size: 100%;
483
+ }
484
+
485
+ /* Button */
486
+ button {
487
+ --_bg-color: transparent;
488
+
489
+ align-items: center;
490
+ background: var(--_bg-color) var(--ripple, none);
491
+ border-radius: 0;
492
+ border-inline: 1px solid var(--border-color);
493
+ border-inline-start-width: 0;
494
+ color: var(--text-color-1);
495
+ display: inline-flex;
496
+ flex: auto;
497
+ gap: 1ex;
498
+ justify-content: center;
499
+ min-block-size: 2.5rem; /* 40px */
500
+ min-inline-size: 5ex;
501
+ outline-offset: calc(-1 * var(--size-2));
502
+ padding: 0 var(--_button-padding-inline);
503
+ position: relative;
504
+ user-select: none;
505
+
506
+ @media (prefers-reduced-motion: no-preference) {
507
+ transition: background-color 0.2s var(--ease-out-3),
508
+ box-shadow 0.2s var(--ease-out-3), border-color 0.2s var(--ease-out-3),
509
+ color 0.2s var(--ease-out-3), outline-offset 0.05s var(--ease-1);
510
+ }
511
+
512
+ /* Element states */
513
+ &:hover {
514
+ --_bg-color: light-dark(oklch(0% 0 0 / 0.04), oklch(100% 0 0 / 0.08));
515
+ }
516
+
517
+ &:focus-visible {
518
+ outline-offset: -6px;
519
+ }
520
+
521
+ /* Disabled */
522
+ &[disabled] {
523
+ border-color: color-mix(in oklch, var(--border-color) 50%, transparent);
524
+ cursor: not-allowed;
525
+ color: color-mix(in oklch, var(--text-color-1) 30%, transparent);
526
+ }
527
+
528
+ &[disabled] + &:not([disabled]):not(:last-of-type) {
529
+ border-inline-end-width: 1px;
530
+ }
531
+
532
+ /* Assign border radius for outline */
533
+ &:first-of-type {
534
+ border-bottom-left-radius: var(--_border-radius);
535
+ border-top-left-radius: var(--_border-radius);
536
+ }
537
+ &:last-of-type {
538
+ border-bottom-right-radius: var(--_border-radius);
539
+ border-top-right-radius: var(--_border-radius);
540
+ }
541
+
542
+ &:last-of-type {
543
+ border-inline-end-width: 0;
544
+ }
545
+
546
+ /* Ripple effect */
547
+ background-position: center;
548
+
549
+ &:where(:not([disabled])) {
550
+ &:where(:not(:active):hover) {
551
+ --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%)
552
+ center/15000%;
553
+
554
+ transition: background var(--button-ripple-duration);
555
+ }
556
+
557
+ &:where(:hover:active) {
558
+ background-size: var(--button-ripple-size);
559
+ transition: background 0s;
560
+ }
561
+ }
562
+
563
+ /* Icons */
564
+ svg {
565
+ inline-size: var(--_icon-size);
566
+ inset-inline-start: calc(var(--_button-padding-inline));
567
+
568
+ & + svg {
569
+ max-block-size: var(--size-5);
570
+ max-inline-size: var(--size-7);
571
+ }
572
+ }
573
+
574
+ /* Selected */
575
+ &.selected {
576
+ --_bg-color: oklch(from var(--primary) l c h / 25%);
577
+
578
+ /* Checkmark */
579
+ svg:first-of-type {
580
+ margin-block-end: -3px;
581
+ }
582
+ }
583
+ }
584
+ }
585
+ }
586
+
587
+ @layer components.root {
588
+ :where(.avatar) {
589
+ --_bg-color: var(--color-8);
590
+ --_color: var(--text-color-1);
591
+ --_width: 40px;
592
+
593
+ align-items: center;
594
+ background-color: var(--_bg-color);
595
+ color: var(--_color);
596
+ aspect-ratio: 1;
597
+ border-radius: 100vmax;
598
+ display: inline-flex;
599
+ inline-size: var(--_width);
600
+ justify-content: center;
601
+ overflow: clip;
602
+ position: relative;
603
+ text-align: center;
604
+ text-decoration: none;
605
+
606
+ &:has(img) {
607
+ background-color: transparent;
608
+ }
609
+
610
+ svg {
611
+ max-inline-size: var(--size-5);
612
+ }
613
+
614
+ img {
615
+ block-size: 100%;
616
+ inline-size: 100%;
617
+ inset: 0;
618
+ object-fit: cover;
619
+ position: absolute;
620
+ }
621
+
622
+ &.squared {
623
+ border-radius: 0;
624
+ }
625
+
626
+ &.rounded {
627
+ border-radius: var(--border-size-3);
628
+ }
629
+ }
630
+
631
+ /*
632
+ TODO: implement reading-order if that becomes a thing.
633
+ https://developer.chrome.com/blog/reading-order/
634
+ */
635
+ :where(.avatar-group) {
636
+ --_margin: var(--size-1);
637
+
638
+ display: flex;
639
+ flex-direction: row-reverse;
640
+
641
+ &.gap-small {
642
+ --_margin: var(--size-2);
643
+ }
644
+
645
+ &.gap-x-small {
646
+ --_margin: var(--size-3);
647
+ }
648
+
649
+ .avatar {
650
+ margin-inline-end: calc(-1 * var(--_margin));
651
+ outline: 2px solid var(--surface-default);
652
+ }
653
+ }
654
+ }
655
+
656
+ @layer components.root {
657
+ :where(.badge) {
658
+ --_bg-color: var(--primary);
659
+ --_border-color: var(--primary);
660
+ --_color: var(--gray-1);
661
+ --_inset-offset: 16px;
662
+ --_inset: auto auto calc(100% - var(--_inset-offset))
663
+ calc(100% - var(--_inset-offset));
664
+ --_translate: 0;
665
+
666
+ display: inline-flex;
667
+ position: relative;
668
+
669
+ &::after {
670
+ background-color: var(--_bg-color);
671
+ border: 2px solid var(--_border-color);
672
+ border-radius: 100vmax;
673
+ color: var(--_color);
674
+ content: attr(aria-label);
675
+ font-size: 12px;
676
+ font-weight: 500;
677
+ block-size: var(--size-4);
678
+ line-height: normal;
679
+ min-inline-size: var(--size-4, 1.125rem);
680
+ padding-inline: var(--size-1);
681
+ inset: var(--_inset);
682
+ position: absolute;
683
+ text-align: center;
684
+ translate: var(--_translate);
685
+ transition: opacity 0.2s var(--ease-out-1);
686
+ inline-size: max-content;
687
+ }
688
+
689
+ /* Alignment */
690
+ &.start-start {
691
+ --_inset: auto calc(100% - var(--_inset-offset))
692
+ calc(100% - var(--_inset-offset)) auto;
693
+ }
694
+ &.start-end {
695
+ --_inset: auto auto calc(100% - var(--_inset-offset))
696
+ calc(100% - var(--_inset-offset));
697
+ }
698
+ &.end-start {
699
+ --_inset: calc(100% - var(--_inset-offset))
700
+ calc(100% - var(--_inset-offset)) auto auto;
701
+ }
702
+ &.end-end {
703
+ --_inset: calc(100% - var(--_inset-offset)) auto auto
704
+ calc(100% - var(--_inset-offset));
705
+ }
706
+
707
+ /* Dot */
708
+ &.dot {
709
+ --_inset: 0 -1px auto auto;
710
+ &::after {
711
+ content: "";
712
+ min-inline-size: var(--size-2);
713
+ block-size: var(--size-2);
714
+ inline-size: var(--size-2);
715
+ padding: 0;
716
+ }
717
+ }
718
+
719
+ /* Visibility */
720
+ &.invisible {
721
+ &::after {
722
+ opacity: 0;
723
+ pointer-events: none;
724
+ }
725
+ }
726
+
727
+ /* Colors */
728
+ &.error,
729
+ &.good,
730
+ &.ok,
731
+ &.warning {
732
+ --_bg-color: var(--color-8);
733
+ --_border-color: var(--color-8);
734
+ }
735
+ }
736
+
737
+ [dir="rtl"] {
738
+ :where(.badge) {
739
+ --_inset: auto calc(100% - 16px) calc(100% - 16px) auto;
740
+
741
+ /* Alignment */
742
+ &.start-start {
743
+ --_inset: auto auto calc(100% - 16px) calc(100% - 16px);
744
+ }
745
+ &.start-end {
746
+ --_inset: auto calc(100% - 16px) calc(100% - 16px) auto;
747
+ }
748
+ &.end-start {
749
+ --_inset: calc(100% - 16px) auto auto calc(100% - 16px);
750
+ }
751
+ &.end-end {
752
+ --_inset: calc(100% - 16px) calc(100% - 16px) auto auto;
753
+ }
754
+ }
755
+ }
756
+ }
757
+
758
+ @layer components.root {
759
+ :where(.card) {
760
+ --_bg-color: transparent;
761
+ --_border-color: transparent;
762
+ --_border-width: 0;
763
+ --_shadow: none;
764
+
765
+ background-color: var(--_bg-color);
766
+ border-color: var(--_border-color);
767
+ border-radius: var(--border-radius, 0.25rem);
768
+ border-style: solid;
769
+ border-width: var(--_border-width);
770
+ box-shadow: var(--_shadow);
771
+ display: flex;
772
+ flex-direction: column;
773
+ gap: var(--size-3);
774
+ overflow: hidden;
775
+ padding-inline: 0;
776
+
777
+ /* Variants */
778
+ &.text {
779
+ --_bg-color: transparent;
780
+ --_border-color: transparent;
781
+ --_border-width: 0;
782
+ --_shadow: none;
783
+ padding-inline: 0;
784
+ }
785
+
786
+ &.tonal {
787
+ --_bg-color: var(--surface-tonal);
788
+ --_border-width: 1px;
789
+ }
790
+
791
+ &.elevated {
792
+ --_bg-color: var(--surface-elevated);
793
+ --_border-color: transparent;
794
+ --_border-width: 0;
795
+ --_shadow: var(--shadow-3);
796
+
797
+ /* Adjust shadow in dark mode */
798
+ @container style(--color-scheme: dark) {
799
+ --_shadow: var(--shadow-4);
800
+ }
801
+ }
802
+
803
+ &.outlined {
804
+ --_bg-color: var(--surface-default);
805
+ --_border-color: var(--border-color);
806
+ --_border-width: 1px;
807
+ }
808
+
809
+ & > :where(hgroup, .content) {
810
+ padding-inline: var(--size-3);
811
+ }
812
+
813
+ & > hgroup {
814
+ padding-block: var(--size-3) 0;
815
+
816
+ /* Top paragraph */
817
+ & > p:first-of-type:first-child {
818
+ line-height: 1.3;
819
+ }
820
+
821
+ /* Bottom paragraph */
822
+ & > p:last-of-type:last-child:not(:first-child) {
823
+ font-size: var(--font-size-1, 1rem);
824
+ }
825
+ }
826
+
827
+ & > .content:where(:only-child, :first-child) {
828
+ padding-block: var(--size-3) var(--size-4);
829
+ }
830
+
831
+ & > .actions {
832
+ display: flex;
833
+ gap: var(--size-1);
834
+ margin-block: var(--size-2) 0;
835
+ padding-block-end: var(--size-1);
836
+ padding-inline: var(--size-1) var(--size-3);
837
+ }
838
+ }
839
+ }
840
+
841
+ @layer components.root {
842
+ :where(.chip) {
843
+ --_bg-color: var(--surface-tonal);
844
+ --_border-color: var(--border-color);
845
+ --_color: var(--text-color-1);
846
+
847
+ align-items: center;
848
+ background: var(--_bg-color) var(--ripple, none);
849
+ border: 1px solid var(--_border-color);
850
+ border-radius: var(--radius-2, 0.5rem);
851
+ color: var(--_color);
852
+ display: inline-flex;
853
+ font-size: var(--font-size-0, 0.75rem);
854
+ gap: var(--size-1);
855
+ block-size: var(--size-7, 2rem);
856
+ padding-inline: var(--size-2);
857
+ text-decoration: none;
858
+
859
+ /* Variants */
860
+ &.tonal {
861
+ --_bg-color: var(--surface-tonal);
862
+ --_color: var(--text-color-1);
863
+ }
864
+
865
+ &.outlined {
866
+ --_bg-color: var(--surface-default);
867
+ --_color: var(--text-color-1);
868
+ }
869
+
870
+ /* TODO: should this be out of the box? */
871
+ /* Colors */
872
+ /* &:hover {
873
+ --_bg-color: var(--color-11);
874
+ --_border-color: var(--color-11);
875
+ --_color: var(--text-color-1);
876
+ } */
877
+ /* &.red,
878
+ &.blue,
879
+ &.green,
880
+ &.orange,
881
+ &.primary {
882
+ --_bg-color: var(--color-5);
883
+ --_border-color: var(--color-7);
884
+ --_color: var(--text-color-1-contrast);
885
+
886
+ &:hover {
887
+ --_bg-color: var(--color-7);
888
+ --_border-color: var(--color-7);
889
+ --_color: var(--text-color-1-contrast);
890
+
891
+ &:active {
892
+ --_bg-color: var(--color-8);
893
+ --_border-color: var(--color-8);
894
+ }
895
+ }
896
+
897
+ &.outlined {
898
+ --_bg-color: var(--surface-tonal);
899
+ --_color: var(--text-color-1);
900
+ --_border-color: var(--color-9);
901
+
902
+ &:hover {
903
+ --_bg-color: var(--color-9);
904
+ --_border-color: var(--color-9);
905
+ --_color: var(--text-color-1);
906
+
907
+ &:active {
908
+ --_bg-color: var(--color-11);
909
+ --_border-color: var(--color-11);
910
+ }
911
+ }
912
+ }
913
+ } */
914
+
915
+ &:where(button, a):where(:not([disabled])) {
916
+ &:where(:not(:active)):hover {
917
+ --_bg-color: light-dark(
918
+ oklch(from var(--surface-tonal) calc(l * 0.98) c h),
919
+ oklch(from var(--surface-tonal) calc(l * 1.1) c h)
920
+ );
921
+ }
922
+ }
923
+
924
+ /* Icon */
925
+ &:has(svg:first-child) {
926
+ padding-inline: var(--size-1) var(--size-2);
927
+ }
928
+ &:has(svg:last-child) {
929
+ padding-inline: var(--size-2) var(--size-1);
930
+ }
931
+
932
+ &:has(svg) {
933
+ svg {
934
+ flex-shrink: 0;
935
+ inline-size: var(--size-3);
936
+ }
937
+ }
938
+
939
+ /* Sizes */
940
+ &.small {
941
+ block-size: var(--size-5);
942
+ }
943
+ &.multiline {
944
+ block-size: auto;
945
+ }
946
+
947
+ /* Ripple effect */
948
+ background-position: center;
949
+
950
+ &:where(:not([disabled])) {
951
+ &:where(:not(:active):hover) {
952
+ --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%)
953
+ center/15000%;
954
+
955
+ transition: background var(--button-ripple-duration);
956
+ }
957
+
958
+ &:where(:hover:active) {
959
+ background-size: var(--button-ripple-size);
960
+ transition: background 0s;
961
+ }
962
+ }
963
+
964
+ /* Disabled */
965
+ &:where([disabled]) {
966
+ opacity: 0.64;
967
+ --_text-color: color-mix(
968
+ in oklch,
969
+ var(--text-color-2) 50%,
970
+ var(--surface-default)
971
+ );
972
+ cursor: not-allowed;
973
+ }
974
+ }
975
+ }
976
+
977
+ @layer components.root {
978
+ :where(.definition-list) {
979
+ --_border-style: solid;
980
+ --_border-width: 1px;
981
+
982
+ display: grid;
983
+ gap: var(--size-3);
984
+ padding: 0;
985
+
986
+ &.dotted {
987
+ --_border-style: dotted;
988
+ --_border-width: 2px;
989
+ }
990
+
991
+ li {
992
+ display: grid;
993
+ margin: 0;
994
+ padding: 0;
995
+
996
+ .term {
997
+ display: block;
998
+ font-weight: 700;
999
+ overflow: hidden;
1000
+ position: relative;
1001
+ }
1002
+
1003
+ hr {
1004
+ display: none;
1005
+ margin: 0;
1006
+ }
1007
+ }
1008
+
1009
+ @container (width > 45ch) {
1010
+ gap: var(--size-1);
1011
+
1012
+ li {
1013
+ align-items: baseline;
1014
+ display: grid;
1015
+ gap: var(--size-1);
1016
+ grid-template-columns: 1fr auto;
1017
+
1018
+ &:has(hr) {
1019
+ grid-template-columns: auto 1fr auto;
1020
+ }
1021
+
1022
+ hr {
1023
+ background-color: transparent;
1024
+ border-block-end: var(--_border-width) var(--_border-style)
1025
+ var(--border-color);
1026
+ block-size: 2px;
1027
+ display: block;
1028
+ }
1029
+
1030
+ .term {
1031
+ inline-size: max-content;
1032
+
1033
+ &::after {
1034
+ display: inline-block;
1035
+ }
1036
+ }
1037
+ .description {
1038
+ color: var(--text-color-2);
1039
+ text-align: end;
1040
+ }
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+ @layer components.root {
1047
+ :where(hr) {
1048
+ background-color: var(--border-color);
1049
+ block-size: var(--border-size-1);
1050
+ margin-block: var(--size-fluid-3);
1051
+ }
1052
+ }
1053
+
1054
+ @layer components.root {
1055
+ :where(.link) {
1056
+ color: var(--primary);
1057
+ cursor: pointer;
1058
+ font-weight: 700;
1059
+ text-decoration: underline;
1060
+ text-decoration-color: var(--primary);
1061
+ text-underline-offset: 2px;
1062
+
1063
+ &[href] {
1064
+ &:hover,
1065
+ &:focus-visible {
1066
+ color: var(--primary-light);
1067
+ }
1068
+ }
1069
+
1070
+ @supports (-moz-appearance: none) {
1071
+ text-underline-offset: 2px;
1072
+ }
1073
+ }
1074
+ }
1075
+
1076
+ @layer components.root {
1077
+ :where(table) {
1078
+ border-collapse: collapse;
1079
+ display: block;
1080
+ margin: var(--size-3) 0;
1081
+ max-inline-size: 100%;
1082
+ position: relative;
1083
+
1084
+ /* Rows */
1085
+ tr {
1086
+ background-color: var(--surface-default);
1087
+ border-top: 1px solid var(--border-color);
1088
+
1089
+ &:hover {
1090
+ background-color: oklch(from var(--surface-filled) l c h / 75%);
1091
+ }
1092
+ }
1093
+
1094
+ /* Cells */
1095
+ th,
1096
+ td {
1097
+ border: 1px solid var(--border-color);
1098
+ padding: var(--size-1) var(--size-2);
1099
+ }
1100
+
1101
+ th {
1102
+ background-color: var(--surface-filled);
1103
+ color: var(--text-color-1);
1104
+ font-size: var(--font-size-sm, 0.75rem);
1105
+ font-weight: 600;
1106
+ text-align: start;
1107
+ }
1108
+
1109
+ td {
1110
+ font-size: var(--font-size-sm, 0.75rem);
1111
+ }
1112
+
1113
+ /* Caption */
1114
+ caption {
1115
+ caption-side: bottom;
1116
+ color: var(--text-color-2);
1117
+ font-size: var(--font-size-sm, 0.75rem);
1118
+ padding: var(--size-2) 0;
1119
+ text-align: start;
1120
+ }
1121
+
1122
+ /* Footer */
1123
+ tfoot {
1124
+ border-top: 2px solid var(--border-color);
1125
+
1126
+ tr {
1127
+ background-color: var(--surface-filled);
1128
+ }
1129
+
1130
+ td {
1131
+ color: var(--text-color-1);
1132
+ font-weight: 600;
1133
+ }
1134
+ }
1135
+
1136
+ /* Column group */
1137
+ colgroup col {
1138
+ border: none;
1139
+ }
1140
+
1141
+ @container (width < 60ch) {
1142
+ th,
1143
+ td {
1144
+ padding: var(--size-1) 0.875rem;
1145
+ }
1146
+ }
1147
+
1148
+ /* Dense */
1149
+ &.dense {
1150
+ th,
1151
+ td {
1152
+ padding: var(--size-1) var(--size-2);
1153
+ }
1154
+
1155
+ caption {
1156
+ padding: var(--size-1) 0;
1157
+ }
1158
+
1159
+ @container (width < 60ch) {
1160
+ th,
1161
+ td {
1162
+ padding: var(--size-1) var(--size-2);
1163
+ }
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+
1169
+ @layer components.root {
1170
+ :where(progress) {
1171
+ --_accent-color: var(--primary);
1172
+ --_bg-color: var(--surface-tonal);
1173
+
1174
+ appearance: none;
1175
+ background-color: var(--_bg-color);
1176
+ border-radius: var(--border-radius, 0.25rem);
1177
+ border: 0;
1178
+ display: inline-block;
1179
+ block-size: var(--size-1);
1180
+ overflow: hidden;
1181
+ position: relative;
1182
+ vertical-align: baseline;
1183
+ inline-size: 100%;
1184
+
1185
+ &::-webkit-progress-bar {
1186
+ border-radius: var(--border-radius, 0.25rem);
1187
+ background: none;
1188
+ }
1189
+
1190
+ &[value]::-webkit-progress-value {
1191
+ background-color: var(--_accent-color);
1192
+
1193
+ @media (prefers-reduced-motion: no-preference) {
1194
+ transition: inline-size 0.2s
1195
+ var(--ease-out-4, cubic-bezier(0, 0, 0.1, 1));
1196
+ }
1197
+ }
1198
+
1199
+ &::-moz-progress-bar {
1200
+ background-color: var(--_accent-color);
1201
+ }
1202
+ }
1203
+
1204
+ @media (prefers-reduced-motion: no-preference) {
1205
+ progress:indeterminate {
1206
+ background-color: var(--_bg-color);
1207
+
1208
+ &::after {
1209
+ animation: indeterminate 2s linear infinite;
1210
+ background-color: var(--_accent-color);
1211
+ content: "";
1212
+ inset: 0 auto 0 0;
1213
+ position: absolute;
1214
+ will-change: inset-inline-start, inset-inline-end;
1215
+ }
1216
+
1217
+ &[value]::-webkit-progress-value {
1218
+ background-color: transparent;
1219
+ }
1220
+
1221
+ &::-moz-progress-bar {
1222
+ background-color: transparent;
1223
+ }
1224
+ }
1225
+
1226
+ [dir="rtl"] {
1227
+ :where(progress):indeterminate {
1228
+ animation-direction: reverse;
1229
+
1230
+ &::after {
1231
+ animation-direction: reverse;
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+
1237
+ @keyframes indeterminate {
1238
+ 0% {
1239
+ left: -200%;
1240
+ right: 100%;
1241
+ }
1242
+ 60% {
1243
+ left: 107%;
1244
+ right: -8%;
1245
+ }
1246
+ 100% {
1247
+ left: 107%;
1248
+ right: -8%;
1249
+ }
1250
+ }
1251
+ }
1252
+
1253
+ @layer components.root {
1254
+ [aria-busy="true"]:not(
1255
+ input,
1256
+ select,
1257
+ textarea,
1258
+ html,
1259
+ progress,
1260
+ [aria-describedby]
1261
+ ) {
1262
+ position: relative;
1263
+
1264
+ &::before {
1265
+ animation: spin 0.7s linear infinite;
1266
+ border-color: transparent currentColor currentColor;
1267
+ border-radius: 50%;
1268
+ border-style: solid;
1269
+ border-width: 3px;
1270
+ content: "";
1271
+ display: inline-block;
1272
+ block-size: 1em;
1273
+ opacity: 0.5;
1274
+ vertical-align: -0.14em;
1275
+ inline-size: 1em;
1276
+ }
1277
+
1278
+ &:not(button.button):not(:empty) {
1279
+ &::before {
1280
+ margin-inline-end: 0.5em;
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ @keyframes spin {
1286
+ to {
1287
+ transform: rotate(1turn);
1288
+ }
1289
+ }
1290
+ }
1291
+
1292
+ @layer components.root {
1293
+ label:where(.checkbox, .radio) {
1294
+ align-items: center;
1295
+ color: var(--text-color-1);
1296
+ cursor: pointer;
1297
+ display: inline-grid;
1298
+ gap: 0 var(--size-2);
1299
+ grid-auto-columns: auto;
1300
+ grid-auto-flow: column;
1301
+ inline-size: fit-content;
1302
+ line-height: 1.5;
1303
+ transform: translateZ(0);
1304
+ user-select: none;
1305
+
1306
+ /* Disabled */
1307
+ &:has([disabled]) {
1308
+ cursor: not-allowed;
1309
+ opacity: 0.64;
1310
+ user-select: none;
1311
+
1312
+ input {
1313
+ cursor: not-allowed;
1314
+ }
1315
+ }
1316
+
1317
+ /* Required dot */
1318
+ &:has([required]:not([type="checkbox"]:checked)) {
1319
+ .label:after {
1320
+ color: var(--red);
1321
+ content: "*";
1322
+ inset: 0 -0.25ex auto auto;
1323
+ position: absolute;
1324
+ }
1325
+ }
1326
+
1327
+ /* Label */
1328
+ .label {
1329
+ grid-column: 2;
1330
+ grid-row: 1;
1331
+ position: relative;
1332
+ padding-inline: 0 1ex;
1333
+ }
1334
+
1335
+ /* Supporting text */
1336
+ .supporting-text {
1337
+ color: var(--text-color-2);
1338
+ font-size: var(--font-size-xs);
1339
+ grid-column: 2;
1340
+ grid-row: 2;
1341
+ line-height: 1.5;
1342
+ z-index: 1;
1343
+ }
1344
+
1345
+ /* Stacked layout */
1346
+ &.stack {
1347
+ justify-items: center;
1348
+ grid-auto-columns: unset;
1349
+
1350
+ .label {
1351
+ grid-column: 1/-1;
1352
+ grid-row: 2;
1353
+ margin-block-start: var(--size-1);
1354
+ padding-inline: 1ex;
1355
+
1356
+ /* Required dot */
1357
+ &::after {
1358
+ inset: 0 -0.25ex auto auto;
1359
+ }
1360
+ }
1361
+
1362
+ .supporting-text {
1363
+ grid-column: 1/-1;
1364
+ grid-row: 3;
1365
+ }
1366
+ }
1367
+
1368
+ /* Input */
1369
+ input {
1370
+ aspect-ratio: 1;
1371
+ block-size: 1.125rem;
1372
+ cursor: pointer;
1373
+ inline-size: 1.125rem;
1374
+
1375
+ &::before {
1376
+ --highlight-size: 175%;
1377
+ }
1378
+ }
1379
+
1380
+ /* Sizes */
1381
+ &.small {
1382
+ input {
1383
+ block-size: var(--size-3);
1384
+ inline-size: var(--size-3);
1385
+ }
1386
+ }
1387
+
1388
+ &.large {
1389
+ input {
1390
+ block-size: var(--size-4);
1391
+ inline-size: var(--size-4);
1392
+ }
1393
+ }
1394
+
1395
+ /* Validation */
1396
+ &.error {
1397
+ input[type="checkbox"] {
1398
+ accent-color: var(--color-9);
1399
+
1400
+ & ~ :where(.label, .supporting-text) {
1401
+ color: var(--color-9);
1402
+ }
1403
+ }
1404
+ }
1405
+
1406
+ /* Touch devices */
1407
+ @media (pointer: coarse) {
1408
+ input {
1409
+ block-size: var(--size-4);
1410
+ inline-size: var(--size-4);
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1415
+
1416
+ @layer components.root {
1417
+ :where(.switch) {
1418
+ --_accent-color: var(--primary);
1419
+ --_accent-contrast: var(--primary-contrast);
1420
+
1421
+ --_dot-bg-color: light-dark(var(--gray-11), var(--gray-14));
1422
+ --_dot-inset: var(--size-1) auto auto var(--size-1);
1423
+ --_dot-outline-size: 0;
1424
+ --_dot-size: var(--size-3);
1425
+
1426
+ --_track-bg-color: light-dark(var(--gray-3), var(--gray-8));
1427
+ --_track-height: var(--size-5);
1428
+ --_track-width: var(--size-8);
1429
+ --_transition-tf: var(--ease-4);
1430
+ --_transition-time: 0.2s;
1431
+
1432
+ align-items: center;
1433
+ color: var(--text-color-1);
1434
+ display: inline-grid;
1435
+ gap: 0 var(--size-2);
1436
+ grid-auto-columns: auto;
1437
+ grid-auto-flow: column;
1438
+ inline-size: fit-content;
1439
+
1440
+ input[type="checkbox"][role="switch"] {
1441
+ appearance: none;
1442
+ block-size: var(--_track-height);
1443
+ cursor: pointer;
1444
+ inline-size: var(--_track-width);
1445
+ margin: 0;
1446
+ position: relative;
1447
+
1448
+ /* Track */
1449
+ &::before {
1450
+ background-color: var(--_track-bg-color);
1451
+ block-size: var(--_track-height);
1452
+ border: 1px solid var(--_dot-bg-color);
1453
+ border-radius: 100vmax;
1454
+ content: "";
1455
+ inline-size: var(--_track-width);
1456
+ inset: 0;
1457
+ position: absolute;
1458
+ }
1459
+
1460
+ &:focus-visible {
1461
+ outline-offset: 2px;
1462
+ outline: 2px solid currentColor;
1463
+ }
1464
+
1465
+ /* Dot */
1466
+ &::after {
1467
+ background-color: var(--_dot-bg-color);
1468
+ block-size: var(--_dot-size);
1469
+ border-radius: 100vmax;
1470
+ content: "";
1471
+ inline-size: var(--_dot-size);
1472
+ inset: var(--_dot-inset);
1473
+ outline-offset: -1px;
1474
+ outline: var(--_dot-outline-size) solid var(--_dot-bg-color);
1475
+ position: absolute;
1476
+ }
1477
+
1478
+ /* Checked */
1479
+ &:checked {
1480
+ &::before {
1481
+ background-color: var(--_accent-color);
1482
+ border-color: var(--_accent-color);
1483
+ transition:
1484
+ background-color var(--_transition-time) var(--_transition-tf),
1485
+ border-color var(--_transition-time) var(--_transition-tf);
1486
+ }
1487
+
1488
+ /* Dot */
1489
+ &::after {
1490
+ --_dot-bg-color: var(--_accent-contrast);
1491
+ --_dot-outline-size: calc(var(--size-1) - 1px);
1492
+
1493
+ inset-inline-start: calc(
1494
+ var(--_track-width) - var(--_dot-size) - var(--size-1)
1495
+ );
1496
+ }
1497
+ }
1498
+
1499
+ /* Animation */
1500
+ @media (prefers-reduced-motion: no-preference) {
1501
+ /* Track */
1502
+ &::before {
1503
+ transition:
1504
+ background-color var(--_transition-time) var(--_transition-tf),
1505
+ border-color var(--_transition-time) var(--_transition-tf);
1506
+ }
1507
+
1508
+ /* Dot */
1509
+ &::after {
1510
+ transition: all var(--_transition-time) var(--_transition-tf);
1511
+ }
1512
+
1513
+ &:active:after {
1514
+ --_dot-outline-size: calc(var(--size-1) + 1px);
1515
+ }
1516
+
1517
+ &:checked {
1518
+ &:active:after {
1519
+ --_dot-outline-size: calc(var(--size-1) + 1px);
1520
+ }
1521
+ }
1522
+ }
1523
+ }
1524
+
1525
+ /* Icons */
1526
+ &:has(.icon-checked, .icon-unchecked) {
1527
+ [role="switch"] {
1528
+ grid-column: 1 / -1;
1529
+ grid-row: 1;
1530
+ }
1531
+
1532
+ &:has([role="switch"]:checked) {
1533
+ .icon-unchecked {
1534
+ display: none;
1535
+ }
1536
+ .icon-checked {
1537
+ display: block;
1538
+ }
1539
+ }
1540
+
1541
+ .icon-checked {
1542
+ display: none;
1543
+ }
1544
+
1545
+ svg {
1546
+ grid-column: 1;
1547
+ grid-row: 1;
1548
+ inline-size: var(--_dot-size);
1549
+ margin-inline-start: calc(
1550
+ var(--_track-width) - var(--_dot-size) - var(--size-1)
1551
+ );
1552
+ pointer-events: none;
1553
+ z-index: 1;
1554
+
1555
+ &.icon-checked {
1556
+ margin-inline-start: var(--size-1);
1557
+ }
1558
+ }
1559
+ }
1560
+
1561
+ /* Required dot */
1562
+ &:has([required]:not(:checked)) {
1563
+ .label:after {
1564
+ color: var(--red);
1565
+ content: "*";
1566
+ inset: 0 -0.25ex auto auto;
1567
+ position: absolute;
1568
+ }
1569
+ }
1570
+
1571
+ /* Disabled */
1572
+ &:has([disabled]) {
1573
+ cursor: not-allowed;
1574
+ opacity: 0.64;
1575
+ user-select: none;
1576
+
1577
+ input {
1578
+ cursor: not-allowed;
1579
+ }
1580
+ }
1581
+
1582
+ /* Label */
1583
+ .label {
1584
+ grid-column: 2;
1585
+ grid-row: 1;
1586
+ min-width: 0;
1587
+ padding-inline: 0 1ex;
1588
+ position: relative;
1589
+ user-select: none;
1590
+ }
1591
+
1592
+ /* Supporting text */
1593
+ .supporting-text {
1594
+ color: var(--text-color-2);
1595
+ font-size: var(--font-size-xs);
1596
+ grid-column: 2;
1597
+ grid-row: 2;
1598
+ line-height: 1.5;
1599
+ z-index: 1;
1600
+ }
1601
+
1602
+ /* Size */
1603
+ &.small {
1604
+ --_dot-size: 0.75rem;
1605
+ --_track-height: var(--size-4);
1606
+ --_track-width: 2.5rem;
1607
+ }
1608
+
1609
+ /* Stacked layout */
1610
+ &.stack {
1611
+ justify-items: center;
1612
+ grid-auto-columns: unset;
1613
+
1614
+ .label {
1615
+ grid-column: 1/-1;
1616
+ grid-row: 2;
1617
+ margin-block-start: var(--size-1);
1618
+ padding-inline: 1ex;
1619
+ }
1620
+
1621
+ .supporting-text {
1622
+ grid-column: 1/-1;
1623
+ grid-row: 3;
1624
+ }
1625
+ }
1626
+
1627
+ /* Validation */
1628
+ &.error {
1629
+ input {
1630
+ outline: 2px solid var(--color-9);
1631
+ border-radius: var(--radius-round);
1632
+ }
1633
+
1634
+ .label,
1635
+ .supporting-text {
1636
+ color: var(--color-9);
1637
+ }
1638
+ }
1639
+ }
1640
+ }
1641
+
1642
+ @layer components.root {
1643
+ :where(.range > input[type="range"]) {
1644
+ --thumb-bg: var(--primary);
1645
+ --thumb-highlight-color: oklch(from var(--primary) 70% 100% h / 20%);
1646
+ --thumb-highlight-size: 0px;
1647
+ --thumb-offset: -1ex;
1648
+ --thumb-size: 3ex;
1649
+ --track-color: var(--field-border-color);
1650
+ --track-fill: 0%;
1651
+ --track-height: 1ex;
1652
+
1653
+ appearance: none;
1654
+ background: transparent;
1655
+ display: block;
1656
+ inline-size: 100%;
1657
+ margin: 1ex 0 3ex;
1658
+ outline-offset: 1ex;
1659
+
1660
+ @media (hover: none) {
1661
+ --thumb-offset: -14px;
1662
+ --thumb-size: 30px;
1663
+ }
1664
+
1665
+ /* Track */
1666
+ &::-webkit-slider-runnable-track {
1667
+ appearance: none;
1668
+ background: linear-gradient(
1669
+ to right,
1670
+ transparent var(--track-fill),
1671
+ var(--track-color) 0%
1672
+ ),
1673
+ var(--primary);
1674
+ block-size: var(--track-height);
1675
+ border-radius: 5ex;
1676
+ box-shadow: var(--inner-shadow-1);
1677
+ }
1678
+
1679
+ &::-moz-range-track {
1680
+ appearance: none;
1681
+ background: linear-gradient(
1682
+ to right,
1683
+ transparent var(--track-fill),
1684
+ var(--track-color) 0%
1685
+ ),
1686
+ var(--primary);
1687
+ block-size: var(--track-height);
1688
+ border-radius: 5ex;
1689
+ box-shadow: var(--inner-shadow-2);
1690
+ }
1691
+
1692
+ /* Ring */
1693
+ &::-webkit-slider-thumb {
1694
+ appearance: none;
1695
+ background: var(--thumb-bg);
1696
+ block-size: var(--thumb-size);
1697
+ border-radius: 50%;
1698
+ border: 3px solid var(--surface-default);
1699
+ box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
1700
+ cursor: ew-resize;
1701
+ inline-size: var(--thumb-size);
1702
+ margin-block-start: var(--thumb-offset);
1703
+
1704
+ @media (prefers-reduced-motion: no-preference) {
1705
+ transition: box-shadow 0.1s ease;
1706
+ }
1707
+
1708
+ .fieldset-item:focus-within & {
1709
+ border-color: var(--gray-14);
1710
+ }
1711
+ }
1712
+
1713
+ &::-moz-range-thumb {
1714
+ appearance: none;
1715
+ background: var(--thumb-bg);
1716
+ block-size: var(--thumb-size);
1717
+ border-radius: 50%;
1718
+ border: 3px solid var(--primary);
1719
+ box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
1720
+ cursor: ew-resize;
1721
+ inline-size: var(--thumb-size);
1722
+ margin-block-start: var(--thumb-offset);
1723
+
1724
+ @media (prefers-reduced-motion: no-preference) {
1725
+ transition: box-shadow 0.1s ease;
1726
+ }
1727
+
1728
+ .fieldset-item:focus-within & {
1729
+ border-color: var(--gray-14);
1730
+ }
1731
+ }
1732
+
1733
+ /* Element state */
1734
+ &:not([disabled]) {
1735
+ &:hover {
1736
+ --thumb-highlight-size: var(--size-1);
1737
+ }
1738
+
1739
+ &:active {
1740
+ --thumb-highlight-size: var(--size-2);
1741
+ --track-color: light-dark(
1742
+ oklch(from var(--field-border-color) calc(l * 0.9) c h),
1743
+ oklch(from var(--field-border-color) calc(l * 1.1) c h)
1744
+ );
1745
+ }
1746
+ }
1747
+
1748
+ &[disabled] {
1749
+ --thumb-bg: oklch(from var(--text-color-1) l c h / 50%);
1750
+ --track-color: var(--field-border-color);
1751
+
1752
+ cursor: not-allowed;
1753
+
1754
+ &::-webkit-slider-thumb {
1755
+ cursor: not-allowed;
1756
+ }
1757
+ &::-moz-range-thumb {
1758
+ cursor: not-allowed;
1759
+ }
1760
+ }
1761
+ }
1762
+ }
1763
+
1764
+ @layer components.root {
1765
+ /* Base typography */
1766
+ :where(h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6) {
1767
+ color: var(--text-color-1);
1768
+ font-weight: 700;
1769
+ text-wrap: pretty;
1770
+ }
1771
+
1772
+ :where(h1, .h1) {
1773
+ font-size: var(--font-size-h1, var(--font-size-7));
1774
+ letter-spacing: -0.02em;
1775
+ line-height: 1.15;
1776
+ }
1777
+
1778
+ :where(h2, .h2) {
1779
+ font-size: var(--font-size-h2, var(--font-size-5, 2rem));
1780
+ letter-spacing: -0.02em;
1781
+ line-height: 1.2;
1782
+ }
1783
+
1784
+ :where(h3, .h3) {
1785
+ font-size: var(--font-size-h3, var(--font-size-4, 1.5rem));
1786
+ letter-spacing: -0.01em;
1787
+ line-height: 1.167;
1788
+ }
1789
+
1790
+ :where(h4, .h4) {
1791
+ font-size: var(--font-size-h4, var(--font-size-3, 1.25rem));
1792
+ letter-spacing: -0.01em;
1793
+ line-height: 1.235;
1794
+ }
1795
+
1796
+ :where(h5, .h5) {
1797
+ font-size: var(--font-size-h5, var(--font-size-2, 1.1rem));
1798
+ line-height: 1.334;
1799
+ }
1800
+
1801
+ :where(h6, .h6) {
1802
+ font-size: var(--font-size-h6, var(--font-size-1, 1rem));
1803
+ line-height: 1;
1804
+ }
1805
+
1806
+ :where(hgroup) {
1807
+ & > :where(p, .p) {
1808
+ margin: 0;
1809
+ }
1810
+
1811
+ & > :where(h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6) {
1812
+ margin-block-end: 0.4em;
1813
+ }
1814
+
1815
+ /* The second p element */
1816
+ & > :where(p, .p):last-of-type:last-child:not(:first-child) {
1817
+ color: oklch(from currentColor l c h / 75%);
1818
+ font-size: var(--font-size-lg);
1819
+ line-height: 1.6;
1820
+ }
1821
+ }
1822
+
1823
+ /** Overline */
1824
+ :where(.overline, hgroup > :where(p, .p):first-of-type:first-child) {
1825
+ color: light-dark(
1826
+ oklch(from var(--text-color-2) calc(l * 1.25) c h),
1827
+ oklch(from var(--text-color-2) calc(l * 0.75) c h)
1828
+ );
1829
+ font-size: var(--font-size-xs);
1830
+ font-weight: 500;
1831
+ letter-spacing: 0.06em;
1832
+ line-height: 2.5;
1833
+ text-transform: uppercase;
1834
+ }
1835
+
1836
+ :where(p, .p) {
1837
+ text-wrap: pretty;
1838
+
1839
+ &.small {
1840
+ font-size: var(--font-size-md);
1841
+ }
1842
+ &.large {
1843
+ font-size: var(--font-size-lg);
1844
+ }
1845
+ }
1846
+
1847
+ /* Inline text elements */
1848
+ :where(ins, u, abbr, dfn) {
1849
+ text-decoration: underline;
1850
+ text-underline-offset: 1px;
1851
+
1852
+ @supports (-moz-appearance: none) {
1853
+ text-underline-offset: 2px;
1854
+ }
1855
+ }
1856
+
1857
+ :where(abbr, dfn) {
1858
+ font-style: normal;
1859
+ text-decoration: var(--color-9) underline dotted;
1860
+
1861
+ &[title] {
1862
+ cursor: help;
1863
+ text-underline-offset: 1px;
1864
+ }
1865
+
1866
+ @supports (-moz-appearance: none) {
1867
+ text-underline-offset: 2px;
1868
+ }
1869
+ }
1870
+
1871
+ :where(sup) {
1872
+ font-size: 0.5em;
1873
+ }
1874
+
1875
+ :where(del, ins) {
1876
+ color: var(--color-9);
1877
+ }
1878
+
1879
+ :where(small) {
1880
+ font-size: max(0.5em, var(--font-size-0, 0.75rem));
1881
+ max-inline-size: var(--size-content-1);
1882
+ }
1883
+
1884
+ :where(cite) {
1885
+ font-style: italic;
1886
+ }
1887
+
1888
+ /* Blockquote */
1889
+ :where(blockquote) {
1890
+ border-inline-start-width: var(--border-size-3);
1891
+ display: grid;
1892
+ gap: var(--size-3);
1893
+ padding-block: var(--size-3);
1894
+ padding-inline: var(--size-4);
1895
+
1896
+ :first-child {
1897
+ margin-block-start: 0;
1898
+ }
1899
+
1900
+ :last-child {
1901
+ margin-block-end: 0;
1902
+ }
1903
+
1904
+ footer {
1905
+ color: var(--text-color-2);
1906
+ }
1907
+ }
1908
+
1909
+ /* Code */
1910
+ :where(pre) {
1911
+ border-radius: 0.375rem;
1912
+ direction: ltr;
1913
+ font-size: 0.875rem;
1914
+ line-height: 1.7142857;
1915
+ margin-block: 1.7142857em;
1916
+ max-inline-size: max-content;
1917
+ min-inline-size: 0;
1918
+ padding-block: 0.8571429em;
1919
+ padding-inline: 1.1428571em;
1920
+ white-space: pre;
1921
+ writing-mode: lr;
1922
+ }
1923
+
1924
+ :where(code, kbd, samp, pre) {
1925
+ font-family: var(--font-mono);
1926
+ }
1927
+
1928
+ :where(code) {
1929
+ background-color: oklch(00 0 0 /18%);
1930
+ border-radius: var(--border-size-3);
1931
+ font-size: 0.9em;
1932
+ padding: 0.2ex 0.5ex;
1933
+ }
1934
+
1935
+ :where(kbd, var) {
1936
+ background-color: var(--text-color-2);
1937
+ border-color: var(--text-color-2);
1938
+ border-radius: var(--border-radius, var(--radius-2));
1939
+ border-width: var(--border-size-1);
1940
+ color: var(--text-color-2-contrast);
1941
+ padding: calc(var(--size-1) / 2) var(--size-1);
1942
+ }
1943
+
1944
+ :where(:not(pre) code, kbd) {
1945
+ word-break: break-word;
1946
+ }
1947
+
1948
+ :where(:not(pre) code) {
1949
+ border-radius: var(--border-radius, var(--radius-2));
1950
+ padding: var(--size-1) var(--size-2);
1951
+ writing-mode: lr;
1952
+ }
1953
+
1954
+ :where(mark) {
1955
+ border-radius: var(--border-radius, 0);
1956
+ box-decoration-break: clone;
1957
+ padding: calc(var(--size-1) / 2) var(--size-1);
1958
+ vertical-align: baseline;
1959
+ }
1960
+
1961
+ /* Misc */
1962
+ :where(dt) {
1963
+ font-weight: 700;
1964
+ }
1965
+
1966
+ :where(figure) {
1967
+ & > :where(figcaption) {
1968
+ font-size: var(--font-size-1, 1rem);
1969
+ text-wrap: balance;
1970
+ }
1971
+ }
1972
+ }
1973
+
1974
+ /*** Extended components (has dependencies) */
1975
+
1976
+ @layer components.extended {
1977
+ :where([role="group"].button-group) {
1978
+ --_border-radius: var(--button-border-radius);
1979
+
1980
+ border-radius: var(--_border-radius);
1981
+ display: inline-flex;
1982
+ min-width: max-content;
1983
+
1984
+ button {
1985
+ border-radius: 0;
1986
+
1987
+ svg {
1988
+ max-inline-size: 0.7lh;
1989
+ }
1990
+
1991
+ &:focus-visible {
1992
+ outline-offset: -4px;
1993
+ }
1994
+
1995
+ & + & {
1996
+ border-inline-width: 1px;
1997
+ margin-inline-start: -1px;
1998
+ }
1999
+
2000
+ &:first-of-type {
2001
+ border-bottom-left-radius: var(--_border-radius);
2002
+ border-top-left-radius: var(--_border-radius);
2003
+ }
2004
+ &:last-of-type {
2005
+ border-bottom-right-radius: var(--_border-radius);
2006
+ border-top-right-radius: var(--_border-radius);
2007
+ }
2008
+
2009
+ /* Variants */
2010
+ /*** Text & Elevated */
2011
+ &:not(:where(.tonal, .filled, .outlined)) {
2012
+ & + button {
2013
+ border-inline-start: 1px solid var(--border-color);
2014
+ }
2015
+ }
2016
+
2017
+ &:where(.tonal, .filled) {
2018
+ & + button {
2019
+ border-inline-start-color: var(--color-7);
2020
+ }
2021
+ }
2022
+
2023
+ &:where(.tonal, .filled, .elevated) {
2024
+ & + &[disabled] {
2025
+ border-inline-start-color: color-mix(
2026
+ in oklch,
2027
+ var(--border-color) 90%,
2028
+ white
2029
+ );
2030
+ }
2031
+ }
2032
+
2033
+ &:where(.elevated) {
2034
+ box-shadow: var(--shadow-1);
2035
+
2036
+ button {
2037
+ &:not(:hover) {
2038
+ box-shadow: none;
2039
+ }
2040
+ }
2041
+ }
2042
+ }
2043
+ }
2044
+ }
2045
+
2046
+ @layer components.extended {
2047
+ :where(details) {
2048
+ --_accordion-transition-time: 0.2s;
2049
+ --_bg-color: transparent;
2050
+ --_margin-inline: var(--size-1);
2051
+ --_shadow: none;
2052
+
2053
+ background-color: var(--_bg-color);
2054
+ box-shadow: var(--_shadow);
2055
+ border-radius: var(--border-radius, 4px);
2056
+ display: block;
2057
+ margin-inline: var(--_margin-inline);
2058
+ transition: all var(--_accordion-transition-time) ease-out;
2059
+
2060
+ /* Accordion animation */
2061
+ /* https://nerdy.dev/open-and-close-transitions-for-the-details-element */
2062
+ @media (prefers-reduced-motion: no-preference) {
2063
+ interpolate-size: allow-keywords;
2064
+ }
2065
+
2066
+ &::details-content {
2067
+ block-size: 0;
2068
+ opacity: 0;
2069
+ overflow-y: clip;
2070
+ transition:
2071
+ content-visibility var(--_accordion-transition-time) allow-discrete,
2072
+ opacity var(--_accordion-transition-time),
2073
+ block-size var(--_accordion-transition-time);
2074
+ }
2075
+
2076
+ &[open]::details-content {
2077
+ block-size: auto;
2078
+ opacity: 1;
2079
+ }
2080
+ /***/
2081
+
2082
+ & > summary {
2083
+ background-color: inherit;
2084
+ cursor: pointer;
2085
+ font-weight: 700;
2086
+ padding-block: var(--size-3);
2087
+ user-select: none;
2088
+ }
2089
+
2090
+ /* Custom arrow */
2091
+ /* summary {
2092
+ align-items: center;
2093
+ background-color: inherit;
2094
+ cursor: pointer;
2095
+ display: flex;
2096
+ justify-content: space-between;
2097
+ list-style: none;
2098
+ padding-block: var(--size-3);
2099
+ user-select: none;
2100
+
2101
+ &::marker,
2102
+ &::-webkit-details-marker {
2103
+ display: none;
2104
+ }
2105
+
2106
+ svg {
2107
+ transition: rotate 0.2s ease-out;
2108
+ }
2109
+ }
2110
+
2111
+ &[open] > summary svg {
2112
+ rotate: 180deg;
2113
+ } */
2114
+
2115
+ & > .content {
2116
+ margin-block-start: 0;
2117
+ padding-block: var(--size-2) var(--size-3);
2118
+ }
2119
+
2120
+ & > .actions {
2121
+ display: flex;
2122
+ gap: var(--size-1);
2123
+ justify-content: end;
2124
+ margin-block-start: var(--size-3);
2125
+ padding-block-end: var(--size-1);
2126
+ padding-inline: var(--size-3) var(--size-1);
2127
+ }
2128
+
2129
+ /* Variants */
2130
+ &.card,
2131
+ &.text {
2132
+ --_bg-color: transparent;
2133
+ --_margin-inline: var(--size-1);
2134
+ }
2135
+
2136
+ &.elevated {
2137
+ --_bg-color: var(--surface-elevated);
2138
+ --_margin-inline: 0;
2139
+ --_shadow: var(--shadow-2);
2140
+ }
2141
+
2142
+ &.outlined {
2143
+ --_bg-color: var(--surface-default);
2144
+ --_margin-inline: 0;
2145
+ border: 1px solid var(--border-color);
2146
+ }
2147
+
2148
+ &.tonal {
2149
+ --_bg-color: var(--surface-tonal);
2150
+ --_margin-inline: 0;
2151
+ }
2152
+
2153
+ &:where(.elevated, .outlined, .tonal) > * {
2154
+ padding-inline: var(--size-3);
2155
+ }
2156
+ }
2157
+
2158
+ /* Accordion group */
2159
+ :where(.card:has(details)) {
2160
+ --_gutter-color: var(--border-color);
2161
+
2162
+ display: block;
2163
+
2164
+ & > .content {
2165
+ margin-block: 0;
2166
+ padding: 0;
2167
+ }
2168
+
2169
+ &.card,
2170
+ &.text {
2171
+ &:not(.tonal, .outlined, .elevated) {
2172
+ summary {
2173
+ padding-inline: 0;
2174
+ }
2175
+ }
2176
+ }
2177
+
2178
+ & > details {
2179
+ --_margin-inline: 0;
2180
+
2181
+ border: 0;
2182
+ box-shadow: none;
2183
+
2184
+ & > * {
2185
+ padding-inline: var(--size-3);
2186
+ }
2187
+
2188
+ /* Border between accordion items */
2189
+ & + & {
2190
+ summary {
2191
+ border-radius: 0;
2192
+ border-block-start: 1px solid var(--_gutter-color);
2193
+ }
2194
+ }
2195
+
2196
+ /* First item */
2197
+ &:first-of-type {
2198
+ border-start-start-radius: var(--border-radius, 0.25rem);
2199
+ border-start-end-radius: var(--border-radius, 0.25rem);
2200
+ summary {
2201
+ border-start-start-radius: var(--border-radius, 0.25rem);
2202
+ border-start-end-radius: var(--border-radius, 0.25rem);
2203
+ }
2204
+ }
2205
+
2206
+ /* Last item */
2207
+ &:last-of-type {
2208
+ border-end-start-radius: var(--border-radius, 0.25rem);
2209
+ border-end-end-radius: var(--border-radius, 0.25rem);
2210
+ summary {
2211
+ border-end-start-radius: var(--border-radius, 0.25rem);
2212
+ border-end-end-radius: var(--border-radius, 0.25rem);
2213
+ }
2214
+ }
2215
+ }
2216
+ }
2217
+ }
2218
+
2219
+ @layer components.extended {
2220
+ /*
2221
+ Lists meant to be used stand-alone or as part of Select elements
2222
+
2223
+ Intended use-case:
2224
+ - ul.list > li
2225
+ - .select > .list > option
2226
+ */
2227
+ :where(.list) {
2228
+ --_bg-color: light-dark(var(--gray-1), var(--gray-15));
2229
+ --_bg-color-hover: light-dark(var(--gray-2), var(--gray-14));
2230
+
2231
+ background-color: var(--_bg-color);
2232
+ list-style: none;
2233
+ padding: var(--size-2) 0;
2234
+
2235
+ @media (pointer: coarse) {
2236
+ &,
2237
+ * {
2238
+ user-select: none;
2239
+ }
2240
+ }
2241
+
2242
+ /* Borders on all list items */
2243
+ &.bordered {
2244
+ :where(li + li, option + option) {
2245
+ margin-block-start: var(--size-3);
2246
+ &::before {
2247
+ block-size: 1px;
2248
+ border-block-start: 1px solid var(--border-color);
2249
+ content: "";
2250
+ display: block;
2251
+ inline-size: 100%;
2252
+ inset: calc(-1 * var(--size-2)) 0 auto 0;
2253
+ position: absolute;
2254
+ visibility: visible; /* override select > option:before style */
2255
+ }
2256
+ }
2257
+ }
2258
+
2259
+ /* Dense - less gaps and spacing */
2260
+ &.dense {
2261
+ :where(li, option) {
2262
+ gap: var(--size-2);
2263
+ min-block-size: var(--size-7);
2264
+ padding: var(--size-1) var(--size-2);
2265
+
2266
+ &.border-top {
2267
+ margin-block-start: var(--size-2);
2268
+ &::before {
2269
+ inset: calc(-1 * var(--size-1)) 0 auto 0;
2270
+ }
2271
+ }
2272
+
2273
+ /* Clickable list item */
2274
+ &:has(> a, > button, > label) {
2275
+ min-block-size: auto;
2276
+ padding: 0;
2277
+ }
2278
+
2279
+ & > :where(a, button, label) {
2280
+ gap: var(--size-2);
2281
+ min-block-size: var(--size-7);
2282
+ padding: var(--size-1) var(--size-2);
2283
+ }
2284
+
2285
+ /* Checkbox / Radio */
2286
+ & > label {
2287
+ .end {
2288
+ padding-inline-end: 0.125rem;
2289
+ }
2290
+ }
2291
+
2292
+ /* Leading and trailing content */
2293
+ .start,
2294
+ .end {
2295
+ .avatar {
2296
+ max-inline-size: var(--size-6);
2297
+ }
2298
+
2299
+ .icon-button,
2300
+ svg {
2301
+ max-inline-size: var(--size-4);
2302
+ }
2303
+
2304
+ .checkbox,
2305
+ .radio {
2306
+ max-inline-size: var(--size-3);
2307
+ }
2308
+ }
2309
+ }
2310
+ }
2311
+
2312
+ /* Gutterless */
2313
+ &.gutterless {
2314
+ :where(li, option) {
2315
+ padding-inline: 0;
2316
+
2317
+ & > :where(a, button, label) {
2318
+ padding-inline: 0;
2319
+ }
2320
+ }
2321
+ }
2322
+
2323
+ /* List item */
2324
+ :where(li, option, [role="group"] > label) {
2325
+ align-items: center;
2326
+ background: var(--_bg-color) var(--ripple, none);
2327
+ display: flex;
2328
+ font-size: var(--font-size-sm);
2329
+ gap: var(--size-3);
2330
+ isolation: isolate;
2331
+ min-block-size: 40px;
2332
+ padding: var(--size-2) var(--size-3);
2333
+ position: relative;
2334
+
2335
+ &::before {
2336
+ display: none; /* removing checkmark from option */
2337
+ }
2338
+
2339
+ * {
2340
+ font-size: inherit;
2341
+ }
2342
+
2343
+ /* Clickable list item */
2344
+ &:has(> a, > button, > label) {
2345
+ background: transparent;
2346
+ display: block;
2347
+ min-block-size: auto;
2348
+ padding: 0;
2349
+ }
2350
+
2351
+ /* Select option */
2352
+ &:where(option) {
2353
+ align-items: center;
2354
+ background-color: var(--_bg-color);
2355
+ color: inherit;
2356
+ cursor: pointer;
2357
+ display: flex;
2358
+ gap: var(--size-3);
2359
+ inline-size: 100%;
2360
+ margin: 0;
2361
+ min-block-size: 40px;
2362
+ padding: var(--size-2) var(--size-3);
2363
+ text-align: start;
2364
+ text-decoration: none;
2365
+ z-index: 0;
2366
+
2367
+ &:hover {
2368
+ background-color: var(--_bg-color-hover);
2369
+ }
2370
+
2371
+ &:checked {
2372
+ background-color: oklch(from var(--primary) l c h / 30%);
2373
+ }
2374
+ }
2375
+
2376
+ & > a,
2377
+ & > button,
2378
+ & > label {
2379
+ align-items: center;
2380
+ background: var(--_bg-color) var(--ripple, none);
2381
+ color: inherit;
2382
+ cursor: pointer;
2383
+ display: flex;
2384
+ gap: var(--size-3);
2385
+ inline-size: 100%;
2386
+ margin: 0;
2387
+ min-block-size: 40px;
2388
+ outline-offset: -3px;
2389
+ padding: var(--size-2) var(--size-3);
2390
+ text-align: start;
2391
+ text-decoration: none;
2392
+ z-index: 0;
2393
+
2394
+ /*** Ripple effect */
2395
+ background-position: center;
2396
+ transition: background var(--button-ripple-duration);
2397
+ &:where(:not(:active):hover) {
2398
+ --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%)
2399
+ center/15000%;
2400
+ }
2401
+
2402
+ &:where(:hover:active) {
2403
+ background-size: var(--button-ripple-size);
2404
+ transition: background 0s;
2405
+ }
2406
+
2407
+ &:hover {
2408
+ background-color: var(--_bg-color-hover);
2409
+ }
2410
+
2411
+ /*** Remove ripple effect when trailing button is clicked */
2412
+ &:has(.end:hover) {
2413
+ &:where(:not(:active):hover) {
2414
+ --ripple: none;
2415
+ }
2416
+ }
2417
+ }
2418
+
2419
+ /* Checkbox / Radio / Switch */
2420
+ & > label {
2421
+ .end {
2422
+ padding-inline-end: var(--size-1);
2423
+ }
2424
+
2425
+ &:where(.checkbox, .radio) {
2426
+ inline-size: 100%;
2427
+ }
2428
+
2429
+ &.switch {
2430
+ --_dot-size: 0.75rem;
2431
+ --_track-height: var(--size-4);
2432
+ --_track-width: 2.5rem;
2433
+ }
2434
+ }
2435
+
2436
+ /* Video */
2437
+ &:has(video) {
2438
+ padding: 0.75rem var(--size-3) 0.75rem 0;
2439
+ }
2440
+
2441
+ /* Border between list items */
2442
+ &.border-top {
2443
+ margin-block-start: var(--size-3);
2444
+ &::before {
2445
+ block-size: 1px;
2446
+ border-block-start: 1px solid var(--border-color);
2447
+ content: "";
2448
+ display: block;
2449
+ inline-size: 100%;
2450
+ inset: calc(-1 * var(--size-2)) 0 auto 0;
2451
+ position: absolute;
2452
+ }
2453
+ }
2454
+
2455
+ /* Text */
2456
+ .text {
2457
+ flex: 1;
2458
+ line-height: 1.6;
2459
+
2460
+ :where(h1, h2, h3, h4, h5, h6, p, span) {
2461
+ color: inherit;
2462
+ font-weight: 400;
2463
+ }
2464
+
2465
+ p + p {
2466
+ font-size: var(--font-size-xs);
2467
+ }
2468
+ }
2469
+
2470
+ /* Leading content */
2471
+ .start {
2472
+ align-self: center;
2473
+ align-items: center;
2474
+ display: grid;
2475
+ z-index: 1;
2476
+
2477
+ &:has(svg) {
2478
+ max-inline-size: var(--size-5);
2479
+ }
2480
+
2481
+ svg {
2482
+ padding-block-start: 0.125rem;
2483
+ }
2484
+
2485
+ img {
2486
+ aspect-ratio: 1;
2487
+ inline-size: 56px;
2488
+ object-fit: cover;
2489
+ }
2490
+
2491
+ video {
2492
+ aspect-ratio: 16/9;
2493
+ block-size: 64px;
2494
+ object-fit: cover;
2495
+ }
2496
+ }
2497
+
2498
+ /* Trailing content */
2499
+ .end {
2500
+ align-items: center;
2501
+ display: flex;
2502
+ font-size: var(--font-size-xs);
2503
+ text-align: end;
2504
+ z-index: 1;
2505
+
2506
+ &:not(:has(a, button, input)) {
2507
+ pointer-events: none;
2508
+ }
2509
+
2510
+ kbd {
2511
+ background-color: transparent;
2512
+ border: 0;
2513
+ color: inherit;
2514
+ opacity: 0.6;
2515
+ }
2516
+
2517
+ svg {
2518
+ max-inline-size: var(--size-5);
2519
+ inline-size: 100%;
2520
+ }
2521
+ }
2522
+
2523
+ /* Inset */
2524
+ &.inset {
2525
+ .text {
2526
+ padding-inline-start: calc(var(--size-5) + var(--size-3));
2527
+ }
2528
+
2529
+ /* Safety measure so it won't look bad if there for some reason should exist a leading element inside. */
2530
+ .start {
2531
+ display: none;
2532
+ }
2533
+ }
2534
+ }
2535
+ }
2536
+ }
2537
+
2538
+ @layer components.extended {
2539
+ :where(.alert) {
2540
+ --_bg-color: var(--surface-tonal);
2541
+ --_border-color: var(--surface-tonal);
2542
+ --_color: var(--text-color-1);
2543
+
2544
+ &.outlined {
2545
+ --_bg-color: var(--surface-default);
2546
+ --_border-color: var(--border-color);
2547
+ --_color: var(--text-color-1);
2548
+ }
2549
+
2550
+ background-color: var(--_bg-color);
2551
+ border: 1px solid var(--_border-color);
2552
+ border-radius: var(--border-radius);
2553
+ color: var(--_color);
2554
+ padding: var(--size-3);
2555
+
2556
+ & > .content {
2557
+ display: grid;
2558
+ gap: var(--size-2);
2559
+ font-size: var(--font-size-sm);
2560
+
2561
+ h1,
2562
+ h2,
2563
+ h3,
2564
+ h4,
2565
+ h5,
2566
+ h6 {
2567
+ color: inherit;
2568
+ font-size: var(--font-size-md);
2569
+ font-weight: 600;
2570
+
2571
+ * {
2572
+ font-size: inherit;
2573
+ }
2574
+ }
2575
+ }
2576
+
2577
+ /* Colors */
2578
+ &.error,
2579
+ &.ok,
2580
+ &.warning {
2581
+ --_bg-color: var(--color-4);
2582
+ --_border-color: var(--color-9);
2583
+ --_color: var(--color-15);
2584
+
2585
+ &.outlined {
2586
+ --_bg-color: var(--surface-default);
2587
+ --_border-color: var(--color-9);
2588
+ --_color: light-dark(var(--color-15), var(--color-1));
2589
+ }
2590
+
2591
+ svg {
2592
+ margin-block-start: 0.15rem;
2593
+ stroke: var(--color-9);
2594
+ }
2595
+ }
2596
+
2597
+ /* Links
2598
+ * Can't make sure contrast will be acceptable (yet) so we use the current text color instead.
2599
+ */
2600
+ &:not(.outlined) {
2601
+ a[href] {
2602
+ color: inherit;
2603
+
2604
+ &:hover {
2605
+ color: var(--primary);
2606
+ }
2607
+ }
2608
+ }
2609
+
2610
+ /* Icon */
2611
+ &:has(svg) {
2612
+ display: grid;
2613
+ gap: var(--size-3);
2614
+ grid-template-columns: var(--size-4) 1fr;
2615
+
2616
+ svg {
2617
+ margin-block-start: 0.15rem;
2618
+ stroke: currentColor;
2619
+ }
2620
+ }
2621
+ }
2622
+ }
2623
+
2624
+ @layer components.extended {
2625
+ :where(dialog) {
2626
+ margin-block-start: 15%; /* vertical alignment */
2627
+ padding-block: 0;
2628
+ pointer-events: none;
2629
+
2630
+ &::backdrop {
2631
+ background-color: rgba(0, 0, 0, 0.5);
2632
+ backdrop-filter: blur(5px);
2633
+
2634
+ @media (prefers-reduced-motion: reduce) {
2635
+ backdrop-filter: none;
2636
+ }
2637
+ }
2638
+
2639
+ &:not([open]) {
2640
+ display: none;
2641
+ }
2642
+
2643
+ &[open] {
2644
+ pointer-events: all;
2645
+ }
2646
+
2647
+ .actions {
2648
+ justify-content: end;
2649
+ padding-inline: var(--size-3) var(--size-1);
2650
+ }
2651
+
2652
+ /* Animation */
2653
+ /* There's no close animation, intentionally */
2654
+ opacity: 0;
2655
+
2656
+ &[open] {
2657
+ opacity: 1;
2658
+ transition: display 0.2s allow-discrete,
2659
+ margin-block-start 0.3s var(--ease-1), overlay 0.2s allow-discrete,
2660
+ opacity 0.2s var(--ease-out-1);
2661
+
2662
+ @starting-style {
2663
+ opacity: 0;
2664
+ }
2665
+ }
2666
+
2667
+ @media (prefers-reduced-motion: no-preference) {
2668
+ margin-block-start: 17%;
2669
+ &[open] {
2670
+ margin-block-start: 15%;
2671
+
2672
+ @starting-style {
2673
+ margin-block-start: 17%;
2674
+ }
2675
+ }
2676
+ }
2677
+ }
2678
+
2679
+ :where(html:has(dialog[open])) {
2680
+ overflow: hidden;
2681
+ }
2682
+ }
2683
+
2684
+ @layer components.extended {
2685
+ :where(.snackbar) {
2686
+ align-items: center;
2687
+ /* Inverse surface-filled */
2688
+ background-color: light-dark(var(--gray-15), var(--gray-2));
2689
+ border-radius: var(--border-radius);
2690
+ box-shadow: var(--shadow-2);
2691
+ color: var(--text-color-1-contrast);
2692
+ display: flex;
2693
+ font-size: var(--font-size-sm);
2694
+ gap: var(--size-3);
2695
+ inset-block: auto var(--size-3);
2696
+ inset-inline: var(--size-3) auto;
2697
+ justify-content: space-between;
2698
+ min-inline-size: min(100%, 37ch);
2699
+ padding: var(--size-2) var(--size-3);
2700
+ position: fixed;
2701
+ inline-size: calc(100% - var(--size-6, 1.75rem));
2702
+ z-index: 100;
2703
+
2704
+ &::backdrop {
2705
+ display: none;
2706
+ }
2707
+
2708
+ * {
2709
+ word-break: break-word;
2710
+ }
2711
+
2712
+ /* Global positioning (in relation to the window) */
2713
+ /*** Default (end-start) */
2714
+ inset-block: auto var(--size-3);
2715
+ inset-inline: 50% 0;
2716
+ translate: -50% 0;
2717
+
2718
+ &.start-start,
2719
+ &.start-center,
2720
+ &.start-end {
2721
+ inset-block: var(--size-3) auto;
2722
+ }
2723
+
2724
+ /* TODO use @custom-media instead? */
2725
+ @container (width > 480px) {
2726
+ /* Default (end-start) */
2727
+ inset-block: auto var(--size-7, 2rem);
2728
+ inset-inline: var(--size-7, 2rem) auto;
2729
+ translate: revert;
2730
+ inline-size: fit-content;
2731
+
2732
+ &.end-start,
2733
+ &.end-end,
2734
+ &.start-start,
2735
+ &.start-end {
2736
+ translate: revert;
2737
+ }
2738
+
2739
+ &.start-start {
2740
+ inset-block: var(--size-7, 2rem) auto;
2741
+ inset-inline: var(--size-7, 2rem) auto;
2742
+ }
2743
+ &.start-center {
2744
+ inset-block: var(--size-7, 2rem) auto;
2745
+ inset-inline: 50% 0;
2746
+ translate: -50% 0;
2747
+ }
2748
+ &.start-end {
2749
+ inset-block: var(--size-7, 2rem) auto;
2750
+ inset-inline: auto var(--size-7, 2rem);
2751
+ }
2752
+ &.end-start {
2753
+ inset-block-end: var(--size-7, 2rem);
2754
+ inset-inline: var(--size-7, 2rem) auto;
2755
+ }
2756
+ &.end-center {
2757
+ inset-block: auto var(--size-7, 2rem);
2758
+ inset-inline: 50% 0;
2759
+ translate: -50% 0;
2760
+ }
2761
+ &.end-end {
2762
+ inset-block: auto var(--size-7, 2rem);
2763
+ inset-inline: auto var(--size-7, 2rem);
2764
+ }
2765
+ }
2766
+
2767
+ /* Absolute positioning */
2768
+ &.absolute {
2769
+ position: absolute;
2770
+ }
2771
+
2772
+ /* Actions */
2773
+ .actions {
2774
+ align-items: center;
2775
+ display: flex;
2776
+ flex-shrink: 0;
2777
+ gap: var(--size-3);
2778
+ padding-inline: 0;
2779
+
2780
+ button {
2781
+ /* Inverse hover and active backgrounds */
2782
+ &:where(:not([disabled])) {
2783
+ &:where(:not(:active):hover) {
2784
+ --_bg-color: light-dark(
2785
+ color-mix(in oklch, white 40%, black),
2786
+ color-mix(in oklch, white 85%, black)
2787
+ );
2788
+ }
2789
+
2790
+ &:where(:hover:active) {
2791
+ --_bg-color: light-dark(
2792
+ color-mix(in oklch, white 45%, black),
2793
+ color-mix(in oklch, white 80%, black)
2794
+ );
2795
+ }
2796
+ }
2797
+ }
2798
+
2799
+ button:not(:has(svg)) {
2800
+ border-radius: var(--border-radius);
2801
+ font-size: inherit;
2802
+ max-block-size: var(--size-6, 1.5rem);
2803
+ padding: 1ex;
2804
+ }
2805
+
2806
+ button:has(svg) {
2807
+ color: inherit;
2808
+ max-inline-size: var(--size-6, 1.75rem);
2809
+ margin: var(--size-00);
2810
+ padding: var(--size-1);
2811
+ }
2812
+ }
2813
+
2814
+ /* Animations */
2815
+ opacity: 0;
2816
+ transition: display 0.075s allow-discrete, overlay 0.075s allow-discrete,
2817
+ opacity 0.075s var(--ease-out-1);
2818
+
2819
+ &:popover-open,
2820
+ &:popover-open::backdrop,
2821
+ &.visible {
2822
+ opacity: 1;
2823
+ transition: display 0.25s allow-discrete, overlay 0.25s allow-discrete,
2824
+ opacity 0.25s var(--ease-out-1);
2825
+
2826
+ @starting-style {
2827
+ opacity: 0;
2828
+ }
2829
+ }
2830
+ }
2831
+ }
2832
+
2833
+ @layer components.extended {
2834
+ /* Common styling for checkbox, radio and switch groups */
2835
+ :where(fieldset.field-group) {
2836
+ border: 0;
2837
+ border-radius: 0;
2838
+ gap: 0;
2839
+ padding: 0;
2840
+ z-index: 1;
2841
+
2842
+ legend {
2843
+ color: var(--text-color-2);
2844
+ padding: 0 1ex 0 0;
2845
+ }
2846
+
2847
+ /* Disabled */
2848
+ &[disabled] {
2849
+ cursor: not-allowed;
2850
+ opacity: 0.64;
2851
+ user-select: none;
2852
+
2853
+ input {
2854
+ cursor: not-allowed;
2855
+ }
2856
+ }
2857
+
2858
+ /* Validation */
2859
+ &.error {
2860
+ legend,
2861
+ .supporting-text {
2862
+ color: var(--color-9);
2863
+ }
2864
+ }
2865
+
2866
+ /* Required */
2867
+ &:has([required]) {
2868
+ &:not(:has(input:where([type="radio"], [type="checkbox"]):checked)) {
2869
+ legend {
2870
+ position: relative;
2871
+
2872
+ &::after {
2873
+ color: var(--red);
2874
+ content: "*";
2875
+ inset: 0 -0.25ex auto auto;
2876
+ position: absolute;
2877
+ }
2878
+ }
2879
+ }
2880
+ }
2881
+ :where(.radio, .checkbox, .switch) .label:after {
2882
+ display: none;
2883
+ }
2884
+
2885
+ /* Supporting text */
2886
+ .supporting-text {
2887
+ color: var(--text-color-2);
2888
+ font-size: var(--font-size-xs);
2889
+ line-height: 1.5;
2890
+ z-index: 1;
2891
+ }
2892
+
2893
+ /* Fields */
2894
+ .fields {
2895
+ display: flex;
2896
+ flex-direction: column;
2897
+ gap: var(--size-2);
2898
+
2899
+ * ~ & {
2900
+ padding: var(--size-2) 0;
2901
+ }
2902
+ }
2903
+
2904
+ :last-child {
2905
+ padding-block-end: 0;
2906
+ }
2907
+
2908
+ /* Directions */
2909
+ &.row {
2910
+ .fields {
2911
+ flex-direction: row;
2912
+ }
2913
+ }
2914
+ }
2915
+ }
2916
+
2917
+ @layer components.extended {
2918
+ /*
2919
+ - Common styling for input, textarea and select
2920
+ - Form related styles such as: label, supporting text, error handling
2921
+ */
2922
+ :where(.field) {
2923
+ --_accent-color: var(--primary);
2924
+ --_bg-color: var(--surface-default);
2925
+ --_border-color: var(--field-border-color);
2926
+ --_field-padding-block: 0.75rem;
2927
+ --_field-padding-inline: var(--size-2);
2928
+ --_filled-border-color: var(--text-color-1);
2929
+ --_height: var(--field-size);
2930
+ --_label-color: var(--text-color-2);
2931
+ --_supporting-text-color: var(--text-color-2);
2932
+
2933
+ contain: layout;
2934
+ display: inline-grid;
2935
+ position: relative;
2936
+
2937
+ /* Input/Select base */
2938
+ & input,
2939
+ & textarea,
2940
+ & select {
2941
+ background-color: var(--_bg-color);
2942
+ block-size: var(--_height);
2943
+ border-radius: var(--field-border-radius);
2944
+ border: var(--field-border-width) solid var(--_border-color);
2945
+ color: var(--text-color-1);
2946
+ font-family: var(--font-sans);
2947
+ font-size: var(--font-size-1);
2948
+ grid-column: 1/-1;
2949
+ grid-row: 1;
2950
+ inline-size: 100%;
2951
+ line-height: var(--font-lineheight-1);
2952
+ min-inline-size: 0;
2953
+ padding: var(--_field-padding-block) var(--_field-padding-inline);
2954
+
2955
+ @media (prefers-reduced-motion: no-preference) {
2956
+ transition: border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
2957
+ padding-block 0.2s var(--ease-3);
2958
+ }
2959
+ }
2960
+
2961
+ /* Required/Invalid */
2962
+ &:has(
2963
+ :not(:placeholder-shown):invalid,
2964
+ :where(
2965
+ :placeholder-shown,
2966
+ option[value=""]:not(:checked),
2967
+ option:checked:not([value=""])
2968
+ ):required
2969
+ ) {
2970
+ .label:after {
2971
+ color: var(--red);
2972
+ content: "*";
2973
+ margin: -0.25em auto auto 0.25em;
2974
+ }
2975
+ }
2976
+
2977
+ /* File */
2978
+ &:has(input[type="file"]) {
2979
+ cursor: pointer;
2980
+
2981
+ input {
2982
+ align-self: flex-start;
2983
+ block-size: var(--_height);
2984
+ box-shadow: none;
2985
+ color: var(--text-color-1);
2986
+ cursor: inherit;
2987
+ max-inline-size: 100%;
2988
+ padding: 0;
2989
+ transition: font-size 0.2s var(--ease-3);
2990
+
2991
+ &::-webkit-file-upload-button,
2992
+ &::file-selector-button {
2993
+ background-color: var(--surface-tonal);
2994
+ border: none;
2995
+ block-size: calc(100% - var(--size-2) * 2);
2996
+ border-radius: var(--field-border-radius);
2997
+ cursor: pointer;
2998
+ margin-inline-end: 1ex;
2999
+ margin-block-start: var(--size-2);
3000
+ margin-inline-start: var(--size-2);
3001
+ }
3002
+ }
3003
+
3004
+ /* Variants */
3005
+ &.filled {
3006
+ input {
3007
+ &::-webkit-file-upload-button,
3008
+ &::file-selector-button {
3009
+ background-color: var(--surface-default);
3010
+ block-size: calc(100% - var(--size-2) * 2);
3011
+ border-radius: var(--field-border-radius);
3012
+ cursor: pointer;
3013
+ margin-block-start: var(--size-2);
3014
+ }
3015
+ }
3016
+ }
3017
+
3018
+ /* Sizes */
3019
+ &.small {
3020
+ input {
3021
+ font-size: var(--font-size-sm);
3022
+ &::-webkit-file-upload-button,
3023
+ &::file-selector-button {
3024
+ block-size: calc(100% - var(--size-2));
3025
+ margin-block-start: var(--size-1);
3026
+ }
3027
+ }
3028
+ }
3029
+ }
3030
+
3031
+ /* Autosuggest */
3032
+ &:has(input[list]) {
3033
+ .label {
3034
+ /* Make sure chevron is visible */
3035
+ inline-size: calc(100% - var(--size-6));
3036
+ }
3037
+ }
3038
+
3039
+ /* Select */
3040
+ &:has(select) {
3041
+ .label {
3042
+ /* Make sure chevron is visible */
3043
+ inline-size: calc(100% - var(--size-6));
3044
+ }
3045
+ }
3046
+
3047
+ /* Experimental Select */
3048
+ &:has(select button) {
3049
+ select {
3050
+ padding: 0;
3051
+
3052
+ button {
3053
+ outline: 0;
3054
+ padding: var(--_field-padding-block) var(--size-8)
3055
+ var(--_field-padding-block) var(--_field-padding-inline);
3056
+ }
3057
+ }
3058
+ }
3059
+
3060
+ /* Non-experimental Select */
3061
+ &:has(select):not(:has(button)) {
3062
+ select {
3063
+ padding: var(--_field-padding-block) var(--size-8)
3064
+ var(--_field-padding-block) var(--_field-padding-inline);
3065
+ }
3066
+ }
3067
+
3068
+ /* Input - color */
3069
+ &:has(input[type="color"]) {
3070
+ input {
3071
+ appearance: none;
3072
+ background: none;
3073
+ block-size: var(--_height);
3074
+ overflow: hidden;
3075
+ padding: 0;
3076
+
3077
+ &::-webkit-color-swatch {
3078
+ border: none;
3079
+ }
3080
+
3081
+ &::-webkit-color-swatch-wrapper {
3082
+ padding: 0;
3083
+ }
3084
+ }
3085
+
3086
+ .label {
3087
+ border: 1px solid var(--field-border-color);
3088
+ inline-size: fit-content;
3089
+ margin-inline-start: var(--size-2);
3090
+ }
3091
+ }
3092
+
3093
+ /* Textarea */
3094
+ &:has(textarea) {
3095
+ .label {
3096
+ align-self: start;
3097
+ margin-block-start: var(--_field-padding-block);
3098
+ }
3099
+ }
3100
+
3101
+ /*
3102
+ * Variant: Outlined
3103
+ */
3104
+ &:not(.filled) {
3105
+ /* Element states */
3106
+ &:hover {
3107
+ &:not(.error) {
3108
+ :where(input, textarea, select) {
3109
+ --_border-color: var(--text-color-1);
3110
+ }
3111
+ }
3112
+ }
3113
+ }
3114
+
3115
+ &:not(.filled):focus-within {
3116
+ & input,
3117
+ & textarea,
3118
+ & select {
3119
+ border-color: var(--_accent-color);
3120
+ outline-offset: -2px;
3121
+ outline: 2px solid var(--_accent-color);
3122
+ }
3123
+ }
3124
+
3125
+ /* Label */
3126
+ .label {
3127
+ align-self: center;
3128
+ background-color: var(--_bg-color);
3129
+ border-radius: var(--field-border-radius);
3130
+ color: var(--_label-color);
3131
+ border-radius: var(--radius-1);
3132
+ display: inline-flex;
3133
+ font-size: var(--font-size-md);
3134
+ grid-column: 1/-1;
3135
+ grid-row: 1;
3136
+ inline-size: calc(100% - (var(--field-border-width) * 2));
3137
+ margin-inline-start: var(--field-border-width);
3138
+ padding-inline: var(--_field-padding-inline);
3139
+ pointer-events: none;
3140
+ z-index: 1;
3141
+
3142
+ @media (prefers-reduced-motion: no-preference) {
3143
+ transition: border-color 0.2s var(--ease-3),
3144
+ font-size 0.2s var(--ease-3), inline-size 0.05s var(--ease-3),
3145
+ margin 0.2s var(--ease-3), padding-inline 0.2s var(--ease-3);
3146
+ }
3147
+ }
3148
+
3149
+ /*
3150
+ * Label transitions
3151
+ * Triggered by:
3152
+ * - focus
3153
+ * - filled form fields (except color inputs)
3154
+ * - non-empty select options
3155
+ */
3156
+ &:focus-within,
3157
+ &:has(:where(input:not([type="color"]), textarea):not(:placeholder-shown)),
3158
+ &:has(option[value=""]:not(:checked)),
3159
+ &:has(option:checked:not([value=""])) {
3160
+ .label {
3161
+ border-color: transparent;
3162
+ color: var(--_accent-color);
3163
+ font-size: 0.75rem;
3164
+ inline-size: max-content;
3165
+ letter-spacing: 0.15px;
3166
+ line-height: 1.15;
3167
+ margin-block-start: -2.7rem;
3168
+ margin-inline-start: var(--_field-padding-inline);
3169
+ padding-inline: 0.125rem;
3170
+ }
3171
+
3172
+ /* Neutral label color reset */
3173
+ &:not(:focus-within):not(.error) {
3174
+ .label {
3175
+ color: var(--text-color-2);
3176
+ }
3177
+ }
3178
+
3179
+ &:has(textarea) {
3180
+ .label {
3181
+ margin-block-start: -0.35rem;
3182
+ }
3183
+
3184
+ &.small {
3185
+ .label {
3186
+ align-self: start;
3187
+ margin-block-start: var(--_field-padding-block);
3188
+ }
3189
+ }
3190
+ }
3191
+ }
3192
+
3193
+ /* Supporting text */
3194
+ .supporting-text {
3195
+ color: var(--_supporting-text-color);
3196
+ font-size: var(--font-size-xs);
3197
+ grid-row: 3;
3198
+ line-height: 1.5;
3199
+ margin-inline-start: var(--field-border-width);
3200
+ padding-inline: var(--_field-padding-inline);
3201
+ z-index: 1;
3202
+ }
3203
+
3204
+ /* Auto-fit */
3205
+ &.auto-fit {
3206
+ inline-size: auto;
3207
+ :where(& input, & textarea) {
3208
+ field-sizing: content;
3209
+ }
3210
+ }
3211
+
3212
+ /* Validation */
3213
+ &.error {
3214
+ --_accent-color: var(--color-9);
3215
+ --_border-color: var(--color-9);
3216
+ --_filled-border-color: var(--color-9);
3217
+ --_label-color: var(--color-9);
3218
+ --_supporting-text-color: var(--color-9);
3219
+ }
3220
+
3221
+ /*
3222
+ * Variant: Filled
3223
+ */
3224
+ &.filled {
3225
+ --_bg-color: var(--surface-tonal);
3226
+ *:focus-visible {
3227
+ outline: 0;
3228
+ }
3229
+
3230
+ /* Base style */
3231
+ & input,
3232
+ & textarea,
3233
+ & select {
3234
+ border-block-end-color: var(--_filled-border-color);
3235
+ border-block-start-color: transparent;
3236
+ border-inline-color: transparent;
3237
+ border-radius: 0;
3238
+ }
3239
+
3240
+ & input[type="color"] {
3241
+ border-inline: none;
3242
+ }
3243
+
3244
+ /* Bottom line */
3245
+ &::before {
3246
+ background-color: var(--_filled-border-color);
3247
+ block-size: calc(var(--field-border-width) + 1px);
3248
+ content: "";
3249
+ inline-size: 100%;
3250
+ margin-block-end: calc(-1 * (var(--field-border-width) * 2));
3251
+ transform: scaleX(0);
3252
+ translate: 0 calc(-1 * (var(--field-border-width) * 2));
3253
+ z-index: 1;
3254
+
3255
+ @media (prefers-reduced-motion: no-preference) {
3256
+ transition: transform 0.3s var(--ease-3), translate 0.2s var(--ease-3);
3257
+ }
3258
+ }
3259
+
3260
+ /* Label */
3261
+ .label {
3262
+ background-color: var(--_bg-color);
3263
+ }
3264
+
3265
+ &:not(:has([disabled], :has(input[type="color"]))) {
3266
+ /* Hover */
3267
+ &:hover {
3268
+ --_bg-color: light-dark(
3269
+ oklch(from var(--surface-tonal) calc(l * 0.93) c h),
3270
+ oklch(from var(--surface-tonal) calc(l * 1.1) c h)
3271
+ );
3272
+ }
3273
+ }
3274
+
3275
+ /*
3276
+ * Label transitions
3277
+ * Triggered by:
3278
+ * - focus
3279
+ * - filled form fields (except color inputs)
3280
+ * - non-empty select options
3281
+ */
3282
+ &:has(.label) {
3283
+ &:focus-within,
3284
+ &:has(
3285
+ :where(input:not(:where([type="color"])), textarea):not(
3286
+ :placeholder-shown
3287
+ )
3288
+ ),
3289
+ &:has(option[value=""]:not(:checked)),
3290
+ &:has(option:checked:not([value=""])) {
3291
+ :where(input, textarea) {
3292
+ padding-block: calc(var(--_field-padding-block) * 1.7)
3293
+ calc(var(--_field-padding-block) * 0.3);
3294
+ }
3295
+
3296
+ select > button,
3297
+ select:not(:has(button)) {
3298
+ padding-block: calc(var(--_field-padding-block) * 1.7)
3299
+ calc(var(--_field-padding-block) * 0.3);
3300
+ }
3301
+
3302
+ .label {
3303
+ margin-block-start: calc(-1 * var(--size-5));
3304
+ margin-inline-start: calc(var(--_field-padding-inline) / 2);
3305
+ padding-inline: calc(var(--_field-padding-inline) / 2);
3306
+ }
3307
+
3308
+ &:has(textarea) {
3309
+ .label {
3310
+ margin-block-start: var(--size-1);
3311
+ }
3312
+ }
3313
+ }
3314
+ }
3315
+
3316
+ /* Element states */
3317
+ &:hover {
3318
+ &::before {
3319
+ transform: scaleX(1);
3320
+ }
3321
+ }
3322
+ &:focus-within {
3323
+ & input,
3324
+ & textarea,
3325
+ & select {
3326
+ border-block-end-color: var(--_accent-color);
3327
+ }
3328
+
3329
+ &::before {
3330
+ background-color: var(--_accent-color);
3331
+ transform: scaleX(1) translateX(0px);
3332
+ }
3333
+ }
3334
+ }
3335
+
3336
+ /* Disabled */
3337
+ &:where(:has([disabled])) {
3338
+ &::before {
3339
+ display: none;
3340
+ }
3341
+ :where(input, textarea, select) {
3342
+ cursor: not-allowed;
3343
+ opacity: 0.7;
3344
+
3345
+ * {
3346
+ pointer-events: none;
3347
+ }
3348
+ }
3349
+ }
3350
+
3351
+ /* Read-only */
3352
+ &:where(:has([readonly])) {
3353
+ &::before {
3354
+ display: none;
3355
+ }
3356
+ :where(input, textarea, select) {
3357
+ cursor: not-allowed;
3358
+
3359
+ * {
3360
+ pointer-events: none;
3361
+ }
3362
+ }
3363
+ }
3364
+
3365
+ /* Sizes */
3366
+ &.small {
3367
+ --_field-padding-block: var(--size-2);
3368
+ --_height: var(--field-size-small);
3369
+
3370
+ &:has(input[type="color"]) {
3371
+ .label {
3372
+ line-height: 1.5;
3373
+ }
3374
+ }
3375
+
3376
+ &:has(textarea) {
3377
+ .label {
3378
+ align-self: center;
3379
+ margin-block-start: unset;
3380
+ }
3381
+ }
3382
+
3383
+ /*
3384
+ * Label transitions
3385
+ * Triggered by:
3386
+ * - focus
3387
+ * - filled form fields (except color inputs)
3388
+ * - non-empty select options
3389
+ */
3390
+ &:focus-within,
3391
+ &:has(
3392
+ :where(input:not([type="color"]), textarea):not(:placeholder-shown)
3393
+ ),
3394
+ &:has(option[value=""]:not(:checked)),
3395
+ &:has(option:checked:not([value=""])) {
3396
+ .label {
3397
+ margin-block-start: -2.2rem;
3398
+ margin-inline-start: var(--size-1);
3399
+ padding-inline: var(--size-1);
3400
+ }
3401
+
3402
+ &:not(.filled):has(textarea) {
3403
+ .label {
3404
+ margin-block-start: -0.35rem;
3405
+ }
3406
+ }
3407
+ }
3408
+ }
3409
+ }
3410
+ }
3411
+
3412
+ @layer components.extended {
3413
+ :where(.field > select) {
3414
+ position: relative;
3415
+
3416
+ /* Default arrow */
3417
+ &::picker-icon {
3418
+ block-size: 0;
3419
+ border-block-start: 5px solid;
3420
+ border-inline: 5px solid transparent;
3421
+ color: currentColor;
3422
+ content: "";
3423
+ inline-size: 0;
3424
+ inset: 50% var(--size-3) auto auto;
3425
+ pointer-events: none;
3426
+ position: absolute;
3427
+ translate: 0 -50%;
3428
+ }
3429
+
3430
+ &:open {
3431
+ &::picker-icon {
3432
+ rotate: 180deg;
3433
+ }
3434
+ }
3435
+
3436
+ /* Select popover */
3437
+ &::picker(select) {
3438
+ /* Animation on-stage styles */
3439
+ border: 0;
3440
+ box-shadow: var(--shadow-2);
3441
+ opacity: 1;
3442
+ padding: 0;
3443
+ scale: 1;
3444
+
3445
+ /* Animation starting styles */
3446
+ @starting-style {
3447
+ opacity: 0;
3448
+ transform: scale(0.9);
3449
+ }
3450
+
3451
+ @media (prefers-reduced-motion: no-preference) {
3452
+ transition: display 0.2s allow-discrete, opacity 0.2s var(--ease-3),
3453
+ overlay 0.2s allow-discrete, scale 0.2s var(--ease-3);
3454
+ }
3455
+ }
3456
+
3457
+ /* Animation off-stage styles */
3458
+ &:not(:open)::picker(select) {
3459
+ opacity: 0;
3460
+ scale: 0.9;
3461
+ }
3462
+
3463
+ button {
3464
+ background-color: transparent;
3465
+ display: flex;
3466
+ inline-size: 100%;
3467
+ margin: 0;
3468
+ position: relative;
3469
+
3470
+ selectedcontent {
3471
+ overflow: hidden;
3472
+ text-overflow: ellipsis;
3473
+ white-space: nowrap;
3474
+ }
3475
+ }
3476
+
3477
+ .list {
3478
+ /* Groups */
3479
+ [role="group"] {
3480
+ label {
3481
+ background-color: light-dark(var(--gray-3), var(--gray-13));
3482
+ color: light-dark(
3483
+ oklch(from var(--text-color-1) calc(l * 0.75) c h),
3484
+ oklch(from var(--text-color-1) calc(l * 1.25) c h)
3485
+ );
3486
+ font-weight: 500;
3487
+ overflow: hidden;
3488
+ padding-inline: var(--size-2);
3489
+ text-overflow: ellipsis;
3490
+ white-space: nowrap;
3491
+ }
3492
+
3493
+ &:not(:first-child),
3494
+ option:first-of-type {
3495
+ margin-block-start: var(--size-2);
3496
+ }
3497
+
3498
+ option:last-of-type,
3499
+ &:last-child {
3500
+ option:last-of-type {
3501
+ margin-block-end: 0;
3502
+ }
3503
+ }
3504
+ }
3505
+
3506
+ /* Option */
3507
+ option {
3508
+ /* Checkmark */
3509
+ /* TODO - checkmark should be the final version of the checkmark API. Follow the development of this and remove redundant psuedo stuff. */
3510
+ &::check {
3511
+ display: none;
3512
+ }
3513
+ &::checkmark {
3514
+ display: none;
3515
+ }
3516
+ &::before {
3517
+ display: none;
3518
+ }
3519
+
3520
+ &:focus-visible {
3521
+ outline-offset: -1px;
3522
+ }
3523
+ }
3524
+ }
3525
+ }
3526
+
3527
+ :where(.field:has(> select)) {
3528
+ /* Size */
3529
+ &.small {
3530
+ button {
3531
+ padding-block: var(--size-1);
3532
+ padding-inline: var(--size-2) var(--size-7);
3533
+
3534
+ &::after {
3535
+ inset-inline-end: var(--size-2);
3536
+ }
3537
+ }
3538
+ }
3539
+
3540
+ /*
3541
+ * Non-experimental Select
3542
+ *
3543
+ * Hack to get the arrow working. Pseudo elements aren't allowed on the `<select>` element, so need to add it on the `.field` class instead. Noting this down if an `:after` element would be needed on a `.field`.
3544
+ */
3545
+ &:not(:has(button)) {
3546
+ select {
3547
+ appearance: none;
3548
+ }
3549
+
3550
+ /* Arrow */
3551
+ &::after {
3552
+ align-self: center;
3553
+ block-size: 0;
3554
+ border-block-start: 5px solid;
3555
+ border-inline: 5px solid transparent;
3556
+ content: "";
3557
+ display: inline-block;
3558
+ flex-shrink: 0;
3559
+ grid-column: 1/-1;
3560
+ grid-row: 1;
3561
+ inline-size: 0;
3562
+ inset-inline-end: var(--size-3);
3563
+ justify-self: end;
3564
+ pointer-events: none;
3565
+ position: relative;
3566
+ }
3567
+ }
3568
+ }
3569
+
3570
+ select:has(button),
3571
+ ::picker(select) {
3572
+ appearance: base-select;
3573
+ }
3574
+ }
3575
+
3576
+ @layer components.extended {
3577
+ :where(
3578
+ .field:has(
3579
+ :where(
3580
+ input[type="date"],
3581
+ input[type="datetime-local"],
3582
+ input[type="email"],
3583
+ input[type="month"],
3584
+ input[type="number"],
3585
+ input[type="password"],
3586
+ input[type="search"],
3587
+ input[type="tel"],
3588
+ input[type="text"],
3589
+ input[type="time"],
3590
+ input[type="url"],
3591
+ input[type="week"]
3592
+ )
3593
+ )
3594
+ ) {
3595
+ /* Sizes */
3596
+ &.small {
3597
+ input {
3598
+ padding-inline: var(--size-2);
3599
+ }
3600
+ }
3601
+ }
3602
+
3603
+ /* Autosuggest */
3604
+ :where(.field:has(input[list])) {
3605
+ /* Hide native arrow */
3606
+ input::-webkit-calendar-picker-indicator {
3607
+ opacity: 0;
3608
+ position: absolute;
3609
+ cursor: pointer;
3610
+ pointer-events: none;
3611
+ }
3612
+ }
3613
+ :where(
3614
+ .field:has(input[list]:placeholder-shown),
3615
+ .field:has(input[list]):where(:focus-within, :hover)
3616
+ ) {
3617
+ /* Arrow */
3618
+ &::after {
3619
+ block-size: 0;
3620
+ border-block-start: 5px solid;
3621
+ border-inline: 5px solid transparent;
3622
+ content: "";
3623
+ display: inline-block;
3624
+ flex-shrink: 0;
3625
+ inline-size: 0;
3626
+ inset: 50% var(--size-3) auto auto;
3627
+ pointer-events: none;
3628
+ position: absolute;
3629
+ translate: 0 -50%;
3630
+ }
3631
+ }
3632
+ }
3633
+
3634
+ @layer components.extended {
3635
+ :where(.field:has(textarea)) {
3636
+ textarea {
3637
+ block-size: auto;
3638
+ field-sizing: content;
3639
+ min-block-size: 5rem;
3640
+ resize: vertical;
3641
+ }
3642
+
3643
+ /* Size */
3644
+ &.small {
3645
+ textarea {
3646
+ min-block-size: var(--_height);
3647
+ }
3648
+ }
3649
+
3650
+ /* Auto-fit */
3651
+ &.auto-fit {
3652
+ textarea {
3653
+ min-block-size: var(--_height);
3654
+ resize: both;
3655
+ }
3656
+ }
3657
+ }
3658
+ }
3659
+
3660
+ @layer components.extended {
3661
+ @scope (.rich-text) to (.not-rich-text) {
3662
+ a {
3663
+ color: var(--primary);
3664
+ cursor: pointer;
3665
+ font-size: inherit;
3666
+ font-weight: 700;
3667
+ line-height: inherit;
3668
+ text-decoration: underline;
3669
+ text-decoration-color: var(--primary);
3670
+ text-underline-offset: 2px;
3671
+
3672
+ &[href] {
3673
+ &:hover,
3674
+ &:focus-visible {
3675
+ color: var(--primary-light);
3676
+ }
3677
+ }
3678
+ }
3679
+
3680
+ /* Blockquote */
3681
+ blockquote {
3682
+ font-size: inherit;
3683
+ line-height: inherit;
3684
+ :first-child {
3685
+ margin-block-start: 0;
3686
+ }
3687
+
3688
+ :last-child {
3689
+ margin-block-end: 0;
3690
+ }
3691
+ }
3692
+
3693
+ /* Text */
3694
+ p {
3695
+ font-size: inherit;
3696
+ line-height: inherit;
3697
+ margin-block: 1.25em;
3698
+ }
3699
+
3700
+ :is(h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6) {
3701
+ color: var(--text-color-1);
3702
+
3703
+ & + *:not(&) {
3704
+ margin-block-start: 0;
3705
+ }
3706
+ }
3707
+
3708
+ h1,
3709
+ .h1 {
3710
+ font-size: var(--font-size-h1, var(--font-size-7));
3711
+ letter-spacing: -0.02em;
3712
+ line-height: 1.1111111;
3713
+ margin-block: 0 0.8888889em;
3714
+ }
3715
+
3716
+ h2,
3717
+ .h2 {
3718
+ font-size: var(--font-size-h2, var(--font-size-5, 2rem));
3719
+ letter-spacing: -0.02em;
3720
+ line-height: 1.3333333;
3721
+ margin-block: 2em 1em;
3722
+ }
3723
+
3724
+ h3,
3725
+ .h3 {
3726
+ font-size: var(--font-size-h3, var(--font-size-4, 1.5rem));
3727
+ letter-spacing: -0.01em;
3728
+ line-height: 1.6;
3729
+ margin-block: 1.6em 0.6em;
3730
+ }
3731
+
3732
+ h4,
3733
+ .h4 {
3734
+ font-size: var(--font-size-h4, var(--font-size-3, 1.25rem));
3735
+ letter-spacing: -0.01em;
3736
+ line-height: 1.5;
3737
+ margin-block: 1.5em 0.5em;
3738
+ }
3739
+
3740
+ h5,
3741
+ .h5 {
3742
+ font-size: var(--font-size-h5, var(--font-size-2, 1.1rem));
3743
+ line-height: 1;
3744
+ margin-block: 0 var(--size-1);
3745
+ }
3746
+
3747
+ h6,
3748
+ .h6 {
3749
+ font-size: var(--font-size-h6, var(--font-size-1, 1rem));
3750
+ line-height: 1;
3751
+ margin-block: 0 var(--size-1);
3752
+ }
3753
+
3754
+ /** Overline */
3755
+ :where(.overline, hgroup > :where(p, .p):first-of-type:first-child) {
3756
+ color: light-dark(
3757
+ oklch(from var(--text-color-2) calc(l * 1.25) c h),
3758
+ oklch(from var(--text-color-2) calc(l * 0.75) c h)
3759
+ );
3760
+ font-size: var(--font-size-xs);
3761
+ font-weight: 500;
3762
+ letter-spacing: 0.06em;
3763
+ line-height: 2.5;
3764
+ text-transform: uppercase;
3765
+ }
3766
+
3767
+ hgroup {
3768
+ & > p {
3769
+ margin: 0;
3770
+ }
3771
+
3772
+ & > :where(h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6) {
3773
+ margin-block-end: 0.4em;
3774
+ }
3775
+
3776
+ & + * {
3777
+ margin-block-start: 3em;
3778
+ }
3779
+
3780
+ /* The second p element */
3781
+ & > :where(p, .p):last-of-type:last-child:not(:first-child) {
3782
+ color: oklch(from currentColor l c h / 75%);
3783
+ font-size: var(--font-size-lg);
3784
+ line-height: 1.6;
3785
+ }
3786
+ }
3787
+
3788
+ /* Lists */
3789
+ ul:not([class]) {
3790
+ list-style-type: disc;
3791
+ }
3792
+
3793
+ ol:not([class]) {
3794
+ list-style-type: decimal;
3795
+ }
3796
+
3797
+ :where(ul, ol):not([class]) {
3798
+ display: grid;
3799
+ font-size: inherit;
3800
+ gap: 0.5em;
3801
+ line-height: inherit;
3802
+ margin-block-start: 1.25em;
3803
+ margin-block-end: 1.25em;
3804
+ padding-inline-start: 1.625em;
3805
+
3806
+ li {
3807
+ padding-inline-start: 0.375em;
3808
+ }
3809
+ }
3810
+
3811
+ /* Nested lists */
3812
+ :where(ul ul),
3813
+ :where(ul ol),
3814
+ :where(ol ul),
3815
+ :where(ol ol) {
3816
+ margin-block-start: 0.75em;
3817
+ margin-block-end: 0.75em;
3818
+ }
3819
+
3820
+ /* Description lists */
3821
+ :where(dl) {
3822
+ font-size: inherit;
3823
+ line-height: inherit;
3824
+ margin-block-start: 1.25em;
3825
+ margin-block-end: 1.25em;
3826
+
3827
+ dt {
3828
+ margin-block-start: 1.25em;
3829
+ }
3830
+
3831
+ dd {
3832
+ margin-block-start: 0.5em;
3833
+ padding-inline-start: 1.625em;
3834
+ }
3835
+ }
3836
+
3837
+ /* Figures */
3838
+ figure {
3839
+ margin-block: 2em;
3840
+
3841
+ & > * {
3842
+ margin-block: 0;
3843
+ }
3844
+
3845
+ & figcaption {
3846
+ font-size: 0.875em;
3847
+ line-height: 1.4285714;
3848
+ margin-block-start: 0.8571429em;
3849
+ }
3850
+ }
3851
+
3852
+ /* Remove top margin from first child */
3853
+ & > :first-child {
3854
+ margin-block-start: 0;
3855
+ }
3856
+
3857
+ /* Remove bottom margin from last child */
3858
+ & > :last-child {
3859
+ margin-block-end: 0;
3860
+ }
3861
+
3862
+ /* Horizontal rules */
3863
+ hr {
3864
+ & + * {
3865
+ margin-block-start: 0;
3866
+ }
3867
+ }
3868
+ }
3869
+ }