opui-css 3.3.4 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/LICENSE +21 -21
  3. package/MIGRATING.md +105 -0
  4. package/README.md +66 -29
  5. package/astro/index.ts +46 -0
  6. package/components/AGENTS.md +247 -0
  7. package/components/Accordion/Accordion.astro +42 -0
  8. package/components/Anchor/Anchor.astro +51 -0
  9. package/components/Avatar/Avatar.astro +44 -0
  10. package/components/Badge/Badge.astro +54 -0
  11. package/components/Button/Button.astro +45 -0
  12. package/components/ButtonGroup/ButtonGroup.astro +29 -0
  13. package/components/Callout/Callout.astro +75 -0
  14. package/components/Card/Card.astro +38 -0
  15. package/components/Checkbox/Checkbox.astro +76 -0
  16. package/components/Checkbox/CheckboxInput.astro +32 -0
  17. package/components/Chip/Chip.astro +37 -0
  18. package/components/ClassicSelect/ClassicSelect.astro +83 -0
  19. package/components/DescriptionList/Description.astro +12 -0
  20. package/components/DescriptionList/DescriptionList.astro +22 -0
  21. package/components/DescriptionList/Item.astro +12 -0
  22. package/components/DescriptionList/Term.astro +12 -0
  23. package/components/DescriptionList/index.ts +12 -0
  24. package/components/Dialog/Dialog.astro +43 -0
  25. package/components/Divider/Divider.astro +14 -0
  26. package/components/Drawer/Drawer.astro +49 -0
  27. package/components/Drawer/DrawerFooter.astro +14 -0
  28. package/components/Drawer/DrawerHeader.astro +31 -0
  29. package/components/FieldDescription/FieldDescription.astro +13 -0
  30. package/components/FieldGroup/FieldGroup.astro +31 -0
  31. package/components/FieldLegend/FieldLegend.astro +15 -0
  32. package/components/FieldSet/FieldSet.astro +15 -0
  33. package/components/Form/Form.astro +15 -0
  34. package/components/IconButton/IconButton.astro +26 -0
  35. package/components/List/List.astro +36 -0
  36. package/components/ListItem/ListItem.astro +118 -0
  37. package/components/Progress/Progress.astro +40 -0
  38. package/components/Radio/Radio.astro +70 -0
  39. package/components/Radio/RadioInput.astro +24 -0
  40. package/components/Range/Range.astro +136 -0
  41. package/components/Select/Select.astro +106 -0
  42. package/components/Switch/Switch.astro +101 -0
  43. package/components/Switch/SwitchInput.astro +25 -0
  44. package/components/Table/Body.astro +13 -0
  45. package/components/Table/Cell.astro +13 -0
  46. package/components/Table/Column.astro +15 -0
  47. package/components/Table/ColumnGroup.astro +13 -0
  48. package/components/Table/Head.astro +13 -0
  49. package/components/Table/HeaderCell.astro +13 -0
  50. package/components/Table/Row.astro +13 -0
  51. package/components/Table/Table.astro +15 -0
  52. package/components/Table/index.ts +20 -0
  53. package/components/Tabs/Tabs.astro +28 -0
  54. package/components/Tabs/TabsItem.astro +47 -0
  55. package/components/Tabs/TabsPanel.astro +21 -0
  56. package/components/Tabs/TabsTab.astro +19 -0
  57. package/components/Tabs/index.ts +14 -0
  58. package/components/TextField/TextField.astro +128 -0
  59. package/components/Textarea/Textarea.astro +106 -0
  60. package/components/Toast/Toast.astro +42 -0
  61. package/components/ToggleButton/ToggleButton.astro +53 -0
  62. package/components/ToggleGroup/ToggleGroup.astro +49 -0
  63. package/components/Tooltip/Tooltip.astro +30 -0
  64. package/{src/core → core}/normalize.css +194 -196
  65. package/core/palette.css +59 -0
  66. package/{src/core → core}/utils.css +71 -60
  67. package/css/components/accordion.css +174 -0
  68. package/css/components/anchor.css +27 -0
  69. package/{src/themes/theme-two → css}/components/avatar.css +65 -68
  70. package/css/components/badge.css +107 -0
  71. package/css/components/button-group.css +179 -0
  72. package/css/components/button.css +215 -0
  73. package/css/components/callout.css +109 -0
  74. package/css/components/card.css +117 -0
  75. package/css/components/checkbox.css +205 -0
  76. package/{src/themes/theme-one → css}/components/chip.css +87 -135
  77. package/{src/themes/theme-two/components/definition-list.css → css/components/description-list.css} +77 -68
  78. package/{src/themes/theme-two → css}/components/dialog.css +68 -59
  79. package/css/components/divider.css +20 -0
  80. package/css/components/drawer.css +171 -0
  81. package/css/components/form.css +146 -0
  82. package/css/components/icon-button.css +139 -0
  83. package/{src/themes/theme-two → css}/components/link.css +21 -21
  84. package/{src/themes/theme-two → css}/components/list.css +345 -318
  85. package/{src/themes/theme-one → css}/components/progress.css +97 -83
  86. package/css/components/radio.css +172 -0
  87. package/css/components/range.css +337 -0
  88. package/{src/themes/theme-two → css}/components/select.css +169 -162
  89. package/{src/themes/theme-two → css}/components/spinner.css +37 -38
  90. package/{src/themes/theme-two → css}/components/switch.css +268 -225
  91. package/css/components/table.css +179 -0
  92. package/css/components/tabs.css +77 -0
  93. package/css/components/text-field.css +450 -0
  94. package/css/components/text-input.css +53 -0
  95. package/{src/themes/theme-two → css}/components/textarea.css +24 -25
  96. package/css/components/toast.css +161 -0
  97. package/css/components/toggle-button.css +87 -0
  98. package/css/components/toggle-group.css +56 -0
  99. package/css/components/tooltip.css +67 -0
  100. package/css/components/typography.css +585 -0
  101. package/{src/themes/theme-two → css}/components.css +41 -37
  102. package/{src/themes/theme-two → css}/imports.css +16 -16
  103. package/css/js/checkbox.js +21 -0
  104. package/css/js/toast.js +94 -0
  105. package/css/theme.css +132 -0
  106. package/dist/op.css +1001 -32
  107. package/dist/op.css.map +1 -0
  108. package/dist/opui.components.css +5135 -0
  109. package/dist/opui.components.css.map +1 -0
  110. package/dist/opui.css +6604 -0
  111. package/dist/opui.css.map +1 -0
  112. package/env.d.ts +14 -0
  113. package/open-props.css +9 -0
  114. package/package.json +64 -55
  115. package/dist/theme-one/components.css +0 -3869
  116. package/dist/theme-one/theme-one.css +0 -4424
  117. package/dist/theme-two/components.css +0 -3591
  118. package/dist/theme-two/theme-two.css +0 -4141
  119. package/src/open-props.css +0 -10
  120. package/src/themes/theme-one/components/accordion.css +0 -172
  121. package/src/themes/theme-one/components/alert.css +0 -85
  122. package/src/themes/theme-one/components/avatar.css +0 -68
  123. package/src/themes/theme-one/components/badge.css +0 -101
  124. package/src/themes/theme-one/components/button-group.css +0 -69
  125. package/src/themes/theme-one/components/button.css +0 -281
  126. package/src/themes/theme-one/components/card.css +0 -82
  127. package/src/themes/theme-one/components/checkbox-radio.css +0 -123
  128. package/src/themes/theme-one/components/definition-list.css +0 -68
  129. package/src/themes/theme-one/components/dialog.css +0 -59
  130. package/src/themes/theme-one/components/divider.css +0 -7
  131. package/src/themes/theme-one/components/field-group.css +0 -83
  132. package/src/themes/theme-one/components/field.css +0 -494
  133. package/src/themes/theme-one/components/icon-button.css +0 -40
  134. package/src/themes/theme-one/components/link.css +0 -21
  135. package/src/themes/theme-one/components/list.css +0 -318
  136. package/src/themes/theme-one/components/range.css +0 -121
  137. package/src/themes/theme-one/components/rich-text.css +0 -210
  138. package/src/themes/theme-one/components/select.css +0 -163
  139. package/src/themes/theme-one/components/snackbar.css +0 -148
  140. package/src/themes/theme-one/components/spinner.css +0 -38
  141. package/src/themes/theme-one/components/switch.css +0 -225
  142. package/src/themes/theme-one/components/tab-buttons.css +0 -120
  143. package/src/themes/theme-one/components/table.css +0 -92
  144. package/src/themes/theme-one/components/text-field.css +0 -57
  145. package/src/themes/theme-one/components/textarea.css +0 -25
  146. package/src/themes/theme-one/components/toggle-button-group.css +0 -135
  147. package/src/themes/theme-one/components/tooltip.css +0 -94
  148. package/src/themes/theme-one/components/typography.css +0 -209
  149. package/src/themes/theme-one/components.css +0 -37
  150. package/src/themes/theme-one/imports.css +0 -16
  151. package/src/themes/theme-one/theme.css +0 -163
  152. package/src/themes/theme-two/components/accordion.css +0 -172
  153. package/src/themes/theme-two/components/alert.css +0 -85
  154. package/src/themes/theme-two/components/badge.css +0 -101
  155. package/src/themes/theme-two/components/button-group.css +0 -50
  156. package/src/themes/theme-two/components/button.css +0 -229
  157. package/src/themes/theme-two/components/card.css +0 -82
  158. package/src/themes/theme-two/components/checkbox-radio.css +0 -123
  159. package/src/themes/theme-two/components/chip.css +0 -135
  160. package/src/themes/theme-two/components/divider.css +0 -7
  161. package/src/themes/theme-two/components/field-group.css +0 -83
  162. package/src/themes/theme-two/components/field.css +0 -281
  163. package/src/themes/theme-two/components/icon-button.css +0 -40
  164. package/src/themes/theme-two/components/progress.css +0 -83
  165. package/src/themes/theme-two/components/range.css +0 -121
  166. package/src/themes/theme-two/components/rich-text.css +0 -210
  167. package/src/themes/theme-two/components/snackbar.css +0 -148
  168. package/src/themes/theme-two/components/tab-buttons.css +0 -120
  169. package/src/themes/theme-two/components/table.css +0 -99
  170. package/src/themes/theme-two/components/text-field.css +0 -57
  171. package/src/themes/theme-two/components/toggle-button-group.css +0 -135
  172. package/src/themes/theme-two/components/tooltip.css +0 -94
  173. package/src/themes/theme-two/components/typography.css +0 -209
  174. package/src/themes/theme-two/theme.css +0 -158
@@ -0,0 +1,5135 @@
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
+ --_color: light-dark(var(--color-16), var(--color-1));
10
+ --_color-contrast: light-dark(var(--color-1), var(--color-16));
11
+ --_color-tonal: var(--surface-tonal);
12
+
13
+ --_accent: var(--_color);
14
+ --_accent-contrast: var(--_color-contrast);
15
+ --_accent-tonal: var(--_color-tonal);
16
+ --_accent-tonal-contrast: var(--_color);
17
+
18
+ --_default-hover-bg-color: light-dark(oklch(from var(--_accent) l 0.01 h / 10%),
19
+ oklch(from var(--_accent) l 0.01 h / 20%));
20
+ --_default-active-bg-color: light-dark(oklch(from var(--_accent) l 0.06 h / 20%),
21
+ oklch(from var(--_accent) l 0.06 h / 30%));
22
+
23
+ --_filled-hover-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.2) c h),
24
+ oklch(from var(--_accent) calc(l - 0.1) c h));
25
+ --_filled-active-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.3) c h),
26
+ oklch(from var(--_accent) calc(l - 0.15) c h));
27
+ --_outlined-active-bg-color: var(--_filled-active-bg-color);
28
+
29
+ --_bg-color: transparent;
30
+ --_border-color: transparent;
31
+ --_border-width: var(--border-size-1);
32
+ --_font-size: var(--font-size-1);
33
+ --_min-height: var(--button-size);
34
+ --_border-radius: var(--button-border-radius, var(--radius-2));
35
+ --_text-color: var(--_accent);
36
+
37
+ -webkit-tap-highlight-color: transparent;
38
+ -webkit-touch-callout: none;
39
+ align-items: center;
40
+ background-color: var(--_bg-color);
41
+ border: var(--_border-width) solid var(--_border-color);
42
+ border-radius: var(--_border-radius);
43
+ color: var(--_text-color);
44
+ display: inline-flex;
45
+ font-size: var(--_font-size);
46
+ font-weight: 700;
47
+ gap: var(--size-2);
48
+ justify-content: center;
49
+ min-block-size: var(--_min-height);
50
+ padding-block: 0.5ex;
51
+ padding-inline: 1.5ex;
52
+ text-align: center;
53
+ text-decoration: none;
54
+ transition: background-color .1s ease, color .1s ease,
55
+ border-color .1s ease, box-shadow .1s ease;
56
+ user-select: none;
57
+
58
+ /* Colors — shared interaction model for critical and primary.
59
+ Each color modifier below only swaps --_color; the tonal surface,
60
+ contrast text, and hover/active strategy are identical.
61
+ The .critical scope class in theme.css redirects --palette-source so
62
+ --color-6 below becomes a tint of the active color. */
63
+ &.critical,
64
+ &.primary {
65
+ --_color-contrast: var(--gray-1);
66
+ --_color-tonal: var(--color-6);
67
+ --_accent-tonal-contrast: var(--text-primary-contrast);
68
+
69
+ --_default-hover-bg-color: oklch(from var(--_accent) l c h / 15%);
70
+ --_default-active-bg-color: oklch(from var(--_accent) l c h / 25%);
71
+
72
+ --_filled-hover-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
73
+ --_filled-active-bg-color: oklch(from var(--_accent) calc(l - 0.15) c h);
74
+
75
+ --_outlined-active-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
76
+ }
77
+
78
+ &.critical {
79
+ --_color: var(--critical);
80
+ }
81
+
82
+ &.primary {
83
+ --_color: var(--primary);
84
+ }
85
+
86
+ /* Disabled */
87
+ &:where([disabled]) {
88
+ --_text-color: color-mix(in oklch,
89
+ var(--text-muted) 50%,
90
+ var(--surface-default));
91
+
92
+ cursor: not-allowed;
93
+ opacity: 0.64;
94
+ }
95
+
96
+ /* Hover & Active */
97
+ &:where(:not([disabled])) {
98
+ &:where(:not(:active):hover) {
99
+ --_bg-color: var(--_default-hover-bg-color);
100
+ }
101
+
102
+ &:where(:hover:active),
103
+ &[aria-current="page"] {
104
+ --_bg-color: var(--_default-active-bg-color);
105
+ }
106
+ }
107
+
108
+
109
+ /* Icons / Keyboard */
110
+ &:where(:has(svg), &.icon-only) {
111
+ gap: 1ex;
112
+
113
+ svg {
114
+ color: currentColor;
115
+ max-block-size: 0.7lh;
116
+ }
117
+ }
118
+
119
+ /* Keyboard input */
120
+ :is(kbd) {
121
+ background-color: oklch(from currentColor l c h / 10%);
122
+ border: 0;
123
+ color: oklch(from currentColor l c h / 80%);
124
+ font-size: 0.8em;
125
+ font-weight: 400;
126
+ line-height: 1.2;
127
+ }
128
+
129
+ /* Sizes — heights aliased from the shared --control-size scale.
130
+ Override --button-size-* in a parent scope to resize an entire region. */
131
+ &.x-small {
132
+ --_min-height: var(--button-size-x-small);
133
+ --_font-size: var(--font-size-0);
134
+ padding-block: 0;
135
+ padding-inline: .5ex;
136
+ }
137
+
138
+ &.small {
139
+ --_min-height: var(--button-size-small);
140
+ --_font-size: var(--font-size-05);
141
+ padding-block: 0;
142
+ padding-inline: .75ex;
143
+ }
144
+
145
+ &.large {
146
+ --_min-height: var(--button-size-large);
147
+ padding-inline: 4ex;
148
+ }
149
+
150
+ /* Variants */
151
+ &.outlined {
152
+ --_bg-color: transparent;
153
+ --_border-color: var(--_accent);
154
+ --_text-color: var(--_accent);
155
+
156
+ &:where(:not([disabled])) {
157
+ &:where(:not(:active):hover) {
158
+ --_bg-color: var(--_accent);
159
+ --_border-color: var(--_accent);
160
+ --_text-color: var(--_accent-contrast);
161
+ }
162
+
163
+ &:where(:active) {
164
+ --_bg-color: var(--_outlined-active-bg-color);
165
+ --_border-color: var(--_outlined-active-bg-color);
166
+ --_text-color: var(--_accent-contrast);
167
+ }
168
+ }
169
+ }
170
+
171
+ &.tonal {
172
+ --_bg-color: var(--_accent-tonal);
173
+ --_text-color: var(--_accent-tonal-contrast);
174
+
175
+ &:where(:not([disabled])) {
176
+ &:where(:not(:active):hover) {
177
+ --_bg-color: var(--_accent);
178
+ --_text-color: var(--_accent-contrast);
179
+ }
180
+
181
+ &:where(:active) {
182
+ --_bg-color: var(--_outlined-active-bg-color);
183
+ --_text-color: var(--_accent-contrast);
184
+ }
185
+ }
186
+ }
187
+
188
+ &.filled {
189
+ --_bg-color: var(--_accent);
190
+ --_text-color: var(--_accent-contrast);
191
+
192
+ &:where(:not([disabled])) {
193
+ &:where(:not(:active):hover) {
194
+ --_bg-color: var(--_filled-hover-bg-color);
195
+ }
196
+
197
+ &:where(:active) {
198
+ --_bg-color: var(--_filled-active-bg-color);
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ /* file input */
205
+ :where(input[type="file"]) {
206
+ align-self: flex-start;
207
+ border: var(--border-size-1) solid var(--surface-filled);
208
+ border-radius: var(--radius-2);
209
+ box-shadow: var(--inner-shadow-4);
210
+ color: var(--text-muted-contrast);
211
+ cursor: initial;
212
+ max-inline-size: 100%;
213
+ padding: 0;
214
+ }
215
+
216
+ :where(input[type="file"])::-webkit-file-upload-button,
217
+ :where(input[type="file"])::file-selector-button {
218
+ cursor: pointer;
219
+ margin-inline-end: var(--size-relative-6);
220
+ }
221
+ }
222
+
223
+ @layer components.root {
224
+ :where(.callout) {
225
+ --_bg-color: var(--surface-tonal);
226
+ --_border-color: var(--surface-tonal);
227
+ --_color: var(--text-primary);
228
+ --_icon-color: currentColor;
229
+ --_link-hover-color: var(--primary);
230
+ --_padding: var(--size-3);
231
+ --_border-radius: var(--border-radius);
232
+ --_gap: var(--size-3);
233
+ --_content-gap: var(--size-2);
234
+ --_font-size: var(--font-size-05);
235
+ --_title-font-size: var(--font-size-1);
236
+ --_icon-size: var(--size-4);
237
+ --_surface-bg: var(--surface-default);
238
+
239
+ --_outlined-bg-color: var(--surface-default);
240
+ --_outlined-border-color: var(--border-color);
241
+ --_outlined-color: var(--text-primary);
242
+ --_outlined-icon-color: currentColor;
243
+
244
+ background-color: var(--_bg-color, var(--_surface-bg));
245
+ border: 1px solid var(--_border-color, var(--border-color));
246
+ border-radius: var(--_border-radius);
247
+ color: var(--_color);
248
+ isolation: isolate;
249
+ padding: var(--_padding);
250
+ position: relative;
251
+
252
+ &.critical,
253
+ &.info,
254
+ &.neutral,
255
+ &.success,
256
+ &.warning {
257
+ --_bg-color: light-dark(oklch(from var(--color-2) l c h / 20%), oklch(from var(--color-6) l c h / 5%));
258
+ --_border-color: light-dark(var(--color-5), var(--color-11));
259
+ --_color: light-dark(var(--color-16), var(--color-1));
260
+ --_icon-color: var(--color-9);
261
+
262
+ --_outlined-bg-color: var(--surface-default);
263
+ --_outlined-border-color: var(--color-9);
264
+ --_outlined-color: light-dark(var(--color-15), var(--color-1));
265
+ --_outlined-icon-color: var(--color-9);
266
+ }
267
+
268
+ &.outlined {
269
+ --_bg-color: var(--_outlined-bg-color);
270
+ --_border-color: var(--_outlined-border-color);
271
+ --_color: var(--_outlined-color);
272
+ --_icon-color: var(--_outlined-icon-color);
273
+ }
274
+
275
+ &::before {
276
+ background-color: var(--_bg-color);
277
+ border-radius: inherit;
278
+ content: "";
279
+ inset: 0;
280
+ pointer-events: none;
281
+ position: absolute;
282
+ z-index: -1;
283
+ }
284
+
285
+ &>.content {
286
+ display: grid;
287
+ font-size: var(--_font-size);
288
+ gap: var(--_content-gap);
289
+
290
+ h1,
291
+ h2,
292
+ h3,
293
+ h4,
294
+ h5,
295
+ h6 {
296
+ color: inherit;
297
+ font-size: var(--_title-font-size);
298
+ font-weight: 600;
299
+
300
+ * {
301
+ font-size: inherit;
302
+ }
303
+ }
304
+ }
305
+
306
+ /* Links
307
+ * Can't make sure contrast will be acceptable (yet) so we use the current text color instead.
308
+ */
309
+ &:not(.outlined) {
310
+ a[href] {
311
+ color: inherit;
312
+
313
+ &:hover {
314
+ color: var(--_link-hover-color);
315
+ }
316
+ }
317
+ }
318
+
319
+ /* Icon */
320
+ &:has(svg) {
321
+ display: grid;
322
+ gap: var(--_gap);
323
+ grid-template-columns: var(--_icon-size) 1fr;
324
+
325
+ svg {
326
+ margin-block-start: 0.15rem;
327
+ stroke: var(--_icon-color);
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ @layer components.root {
334
+ :where(.icon-button) {
335
+ --_color: light-dark(var(--color-16), var(--color-1));
336
+ --_color-contrast: light-dark(var(--color-1), var(--color-16));
337
+ --_color-tonal: var(--surface-tonal);
338
+
339
+ --_accent: var(--_color);
340
+ --_accent-contrast: var(--_color-contrast);
341
+ --_accent-tonal: var(--_color-tonal);
342
+ --_accent-tonal-contrast: var(--_color);
343
+ --_default-hover-bg-color: light-dark(oklch(from var(--_accent) l 0.01 h / 10%),
344
+ oklch(from var(--_accent) l 0.01 h / 20%));
345
+ --_default-active-bg-color: light-dark(oklch(from var(--_accent) l 0.06 h / 20%),
346
+ oklch(from var(--_accent) l 0.06 h / 30%));
347
+ --_filled-hover-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.2) c h),
348
+ oklch(from var(--_accent) calc(l - 0.1) c h));
349
+ --_filled-active-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.3) c h),
350
+ oklch(from var(--_accent) calc(l - 0.15) c h));
351
+ --_outlined-active-bg-color: var(--_filled-active-bg-color);
352
+
353
+ --_bg-color: transparent;
354
+ --_border-color: transparent;
355
+ --_border-width: var(--border-size-1);
356
+ --_text-color: inherit;
357
+
358
+ align-items: center;
359
+ aspect-ratio: 1;
360
+ background-color: var(--_bg-color);
361
+ block-size: var(--size-6);
362
+ border: var(--_border-width) solid var(--_border-color);
363
+ border-radius: var(--radius-round);
364
+ color: var(--_text-color);
365
+ display: inline-flex;
366
+ inline-size: var(--size-6);
367
+ justify-content: center;
368
+ padding: 0;
369
+ transform-style: preserve-3d;
370
+ transition: background-color .1s ease, color .1s ease,
371
+ border-color .1s ease, box-shadow .1s ease;
372
+
373
+ &:where([disabled]) {
374
+ --_text-color: light-dark(rgb(0, 0, 0/0.3), rgb(255, 255, 255/0.26));
375
+ cursor: not-allowed;
376
+ opacity: 0.64;
377
+ }
378
+
379
+ svg {
380
+ block-size: auto;
381
+ inline-size: auto;
382
+ max-block-size: var(--size-5);
383
+ max-inline-size: var(--size-5);
384
+ pointer-events: none;
385
+ }
386
+
387
+ /* Ripple effect, utils.css */
388
+ &::before {
389
+ --highlight-size: 130%;
390
+ background-color: transparent;
391
+
392
+ @media (prefers-reduced-motion: no-preference) {
393
+ transition: transform 0.2s ease, background-color .1s ease;
394
+ }
395
+ }
396
+
397
+ /* Colors — shared interaction model for critical and primary.
398
+ Each color modifier below only swaps --_color; the tonal surface,
399
+ contrast text, and hover/active strategy are identical.
400
+ The .critical scope class in theme.css redirects --palette-source so
401
+ --color-6 below becomes a tint of the active color. */
402
+ &.critical,
403
+ &.primary {
404
+ --_color-contrast: var(--gray-1);
405
+ --_color-tonal: var(--color-6);
406
+ --_accent-tonal-contrast: var(--text-primary-contrast);
407
+
408
+ --_default-hover-bg-color: oklch(from var(--_accent) l c h / 15%);
409
+ --_default-active-bg-color: oklch(from var(--_accent) l c h / 25%);
410
+
411
+ --_filled-hover-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
412
+ --_filled-active-bg-color: oklch(from var(--_accent) calc(l - 0.15) c h);
413
+
414
+ --_outlined-active-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
415
+ }
416
+
417
+ &.critical {
418
+ --_color: var(--critical);
419
+ }
420
+
421
+ &.primary {
422
+ --_color: var(--primary);
423
+ }
424
+
425
+ /* Element states */
426
+ &:where(:not([disabled])) {
427
+ &:where(:not(:active):hover) {
428
+ &::before {
429
+ background-color: var(--_interaction-hover-color, var(--_default-hover-bg-color));
430
+ }
431
+ }
432
+
433
+ &:where(:hover:active),
434
+ &[aria-current="page"] {
435
+ &::before {
436
+ background-color: var(--_interaction-active-color, var(--_default-active-bg-color));
437
+ }
438
+ }
439
+ }
440
+
441
+ /* Size */
442
+ &.small {
443
+ block-size: var(--size-4);
444
+ inline-size: var(--size-4);
445
+
446
+ svg {
447
+ max-block-size: var(--size-4);
448
+ max-inline-size: var(--size-4);
449
+ }
450
+ }
451
+
452
+ /* Variants */
453
+ &.outlined {
454
+ --_bg-color: transparent;
455
+ --_border-color: var(--_accent);
456
+ --_text-color: var(--_accent);
457
+ }
458
+
459
+ &.tonal {
460
+ --_bg-color: var(--_accent-tonal);
461
+ --_text-color: var(--_accent-tonal-contrast);
462
+ }
463
+
464
+ &.filled {
465
+ --_bg-color: var(--_accent);
466
+ --_interaction-active-color: var(--_filled-active-bg-color);
467
+ --_interaction-hover-color: var(--_filled-hover-bg-color);
468
+ --_text-color: var(--_accent-contrast);
469
+ }
470
+ }
471
+ }
472
+
473
+ @layer components.root {
474
+ :where(.tabs) {
475
+ --_accent-color: var(--primary);
476
+ --_bg-color: transparent;
477
+
478
+ align-items: flex-start;
479
+ display: flex;
480
+ flex-wrap: wrap;
481
+ gap: 0 var(--size-1);
482
+ position: relative;
483
+
484
+ &>.tab-input[type="radio"] {
485
+ /* utils > .sr-only */
486
+ /* TODO: use mixin for this when available */
487
+ block-size: 1px;
488
+ clip-path: inset(50%);
489
+ inline-size: 1px;
490
+ overflow: hidden;
491
+ position: absolute;
492
+ white-space: nowrap;
493
+
494
+ &:checked {
495
+
496
+ /* Checked Tab */
497
+ &+[role="tab"] {
498
+ border-block-end-color: var(--_accent-color);
499
+ color: var(--_accent-color);
500
+
501
+ /* Checked Panel */
502
+ &+[role="tabpanel"] {
503
+ display: block;
504
+ }
505
+ }
506
+ }
507
+
508
+ &:focus-visible {
509
+ &+[role="tab"] {
510
+ --focus-ring-color: var(--text-muted);
511
+ --focus-ring-offset: calc(-1 * var(--size-2));
512
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
513
+ outline-offset: var(--focus-ring-offset);
514
+ }
515
+ }
516
+ }
517
+
518
+ /* Tab */
519
+ &>[role="tab"] {
520
+ align-items: center;
521
+ background-color: transparent;
522
+ border-bottom: 2px solid transparent;
523
+ border-radius: 0;
524
+ color: var(--text-muted);
525
+ cursor: pointer;
526
+ display: inline-flex;
527
+ font-weight: 600;
528
+ justify-content: center;
529
+ line-height: var(--font-lineheight-4);
530
+ order: 1;
531
+ padding: var(--size-2) var(--size-3);
532
+ position: relative;
533
+ transition: color 0.1s;
534
+ user-select: none;
535
+
536
+ &:hover {
537
+ background-color: light-dark(oklch(from var(--_accent-color) calc(l * 0.75) none h / 5%),
538
+ oklch(from var(--_accent-color) calc(l * 1.25) none h / 5%));
539
+ }
540
+ }
541
+
542
+ /* Tab Panel */
543
+ &>[role="tabpanel"] {
544
+ display: none;
545
+ inline-size: 100%;
546
+ order: 2;
547
+ }
548
+ }
549
+ }
550
+
551
+ @layer components.root {
552
+ :where(.toggle-group) {
553
+ --_bg-color: var(--surface-default);
554
+ --_border-color: var(--border-color);
555
+ --_border-radius: var(--button-border-radius);
556
+
557
+ background-color: var(--_bg-color);
558
+ border: 1px solid var(--_border-color);
559
+ border-radius: var(--_border-radius);
560
+ display: inline-flex;
561
+ inline-size: fit-content;
562
+ overflow: hidden;
563
+
564
+ /* Sizes */
565
+ &.small {
566
+ .toggle-button {
567
+ --_size: var(--field-size-small);
568
+ }
569
+ }
570
+
571
+ &.x-small {
572
+ .toggle-button {
573
+ --_size: var(--field-size-x-small);
574
+ }
575
+ }
576
+
577
+ /* Toggle button */
578
+ .toggle-button {
579
+ border: 0;
580
+ border-radius: 0;
581
+ margin: 0;
582
+ }
583
+
584
+ &:not(.vertical) {
585
+ .toggle-button {
586
+ border-inline-end: 1px solid var(--_border-color);
587
+
588
+ &:last-of-type {
589
+ border-inline-end: 0;
590
+ }
591
+ }
592
+ }
593
+
594
+ &.vertical {
595
+ flex-direction: column;
596
+
597
+ .toggle-button {
598
+ border-block-end: 1px solid var(--_border-color);
599
+
600
+ &:last-of-type {
601
+ border-block-end: 0;
602
+ }
603
+ }
604
+ }
605
+ }
606
+ }
607
+
608
+ /* TODO:
609
+ * Somehow handle when a group gets too wide for its container. Should it be handled?
610
+ */
611
+
612
+ @layer components.root {
613
+ :where(.toggle-button) {
614
+ --_button-bg-color: transparent;
615
+ --_size: var(--field-size);
616
+ --_svg-size: var(--size-4);
617
+
618
+ align-items: center;
619
+ background-color: var(--_button-bg-color);
620
+ block-size: var(--_size);
621
+ border: 1px solid var(--border-color);
622
+ border-radius: var(--button-border-radius);
623
+ color: var(--text-primary);
624
+ cursor: pointer;
625
+ display: inline-flex;
626
+ flex: auto;
627
+ gap: var(--size-2);
628
+ inline-size: fit-content;
629
+ justify-content: center;
630
+ min-inline-size: var(--_size);
631
+ outline-offset: calc(-1 * var(--size-2));
632
+ padding: 0 var(--size-2);
633
+ position: relative;
634
+ user-select: none;
635
+
636
+ input[type="checkbox"],
637
+ input[type="radio"] {
638
+ /* utils.css > .sr-only */
639
+ block-size: 1px;
640
+ clip-path: inset(50%);
641
+ inline-size: 1px;
642
+ overflow: hidden;
643
+ position: absolute;
644
+ white-space: nowrap;
645
+ }
646
+
647
+ /* Element states */
648
+ @media (pointer: fine) {
649
+ &:hover:not(.disabled) {
650
+ --_button-bg-color: light-dark(oklch(0% 0 0 / 0.04), oklch(100% 0 0 / 0.08));
651
+ }
652
+ }
653
+
654
+ &:has(input:focus-visible) {
655
+ --focus-ring-color: var(--text-muted);
656
+ --focus-ring-offset: -6px;
657
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
658
+ outline-offset: var(--focus-ring-offset);
659
+ }
660
+
661
+ /* Disabled */
662
+ &.disabled {
663
+ border-color: color-mix(in oklch, var(--border-color) 50%, transparent);
664
+ color: color-mix(in oklch, var(--text-primary) 30%, transparent);
665
+ cursor: not-allowed;
666
+ }
667
+
668
+ /* svgs */
669
+ svg {
670
+ block-size: var(--_svg-size);
671
+ flex-shrink: 0;
672
+ inline-size: var(--_svg-size);
673
+ }
674
+
675
+ /* Selected */
676
+ &:has(:where(input[type="checkbox"], input[type="radio"]):checked) {
677
+ --_button-bg-color: oklch(from var(--primary) l c h / 25%);
678
+
679
+ @media (pointer: fine) {
680
+ &:hover {
681
+ --_button-bg-color: oklch(from var(--primary) l c h / 35%);
682
+ }
683
+ }
684
+ }
685
+
686
+ /* Sizes */
687
+ &.small {
688
+ --_size: var(--field-size-small);
689
+ }
690
+
691
+ &.x-small {
692
+ --_size: var(--field-size-x-small);
693
+ }
694
+ }
695
+ }
696
+
697
+ @layer components.root {
698
+ :where(.anchor) {
699
+ anchor-name: --anchor;
700
+ anchor-scope: --anchor;
701
+ display: inline-block;
702
+ inline-size: fit-content;
703
+
704
+ /* Always-visible */
705
+ &>.anchor-floating:not([popover]) {
706
+ block-size: max-content;
707
+ inline-size: max-content;
708
+ position: absolute;
709
+ position-anchor: --anchor;
710
+ position-area: var(--anchor-position-area, start end);
711
+ translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
712
+ }
713
+
714
+ /* Hover-triggered */
715
+ &>.anchor-floating[popover] {
716
+ inset: unset;
717
+ margin: 0;
718
+ position: absolute;
719
+ position-area: var(--anchor-position-area, start end);
720
+ translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0);
721
+ }
722
+ }
723
+ }
724
+
725
+ @layer components.root {
726
+ :where(.avatar) {
727
+ --_bg-color: var(--primary);
728
+ --_color: var(--color-1);
729
+ --_width: 40px;
730
+
731
+ align-items: center;
732
+ aspect-ratio: 1;
733
+ background-color: var(--_bg-color);
734
+ border-radius: var(--radius-round);
735
+ color: var(--_color);
736
+ display: inline-flex;
737
+ inline-size: var(--_width);
738
+ justify-content: center;
739
+ overflow: clip;
740
+ position: relative;
741
+ text-align: center;
742
+ text-decoration: none;
743
+
744
+ &:has(img) {
745
+ background-color: transparent;
746
+ }
747
+
748
+ svg {
749
+ max-inline-size: var(--size-5);
750
+ }
751
+
752
+ img {
753
+ block-size: 100%;
754
+ inline-size: 100%;
755
+ inset: 0;
756
+ object-fit: cover;
757
+ position: absolute;
758
+ }
759
+
760
+ &.squared {
761
+ border-radius: 0;
762
+ }
763
+
764
+ &.rounded {
765
+ border-radius: var(--radius-2);
766
+ }
767
+
768
+ &.squircle {
769
+ border-radius: var(--radius-3);
770
+
771
+ @supports (corner-shape: squircle) {
772
+ border-radius: var(--radius-round);
773
+ corner-shape: squircle;
774
+ }
775
+ }
776
+ }
777
+
778
+ :where([role="group"]) {
779
+ --_margin: var(--size-3);
780
+ --_outline-color: var(--surface-default);
781
+
782
+ display: flex;
783
+
784
+ .avatar {
785
+ box-shadow: 0 0 0 2px var(--_outline-color);
786
+ margin-inline-end: calc(-1 * var(--_margin));
787
+ }
788
+ }
789
+ }
790
+
791
+ @layer components.root {
792
+ :where(.card) {
793
+ --_bg-tonal: var(--surface-tonal);
794
+ --_bg-elevated: var(--surface-elevated);
795
+ --_bg-surface: var(--surface-default);
796
+ --_border-color: var(--border-color);
797
+ --_card-bg-color: var(--_bg-surface);
798
+ --_card-border-color: transparent;
799
+ --_card-border-width: 0;
800
+
801
+ --_card-shadow: none;
802
+ --_shadow-light: var(--shadow-3);
803
+ --_shadow-dark: var(--shadow-4);
804
+ --_shadow-elevated: var(--_shadow-light);
805
+
806
+ @container style(--color-scheme: dark) {
807
+ --_shadow-elevated: var(--_shadow-dark);
808
+ }
809
+
810
+ background-color: var(--_card-bg-color);
811
+ border-color: var(--_card-border-color);
812
+ border-radius: var(--border-radius);
813
+ border-style: solid;
814
+ border-width: var(--_card-border-width);
815
+ box-shadow: var(--_card-shadow);
816
+ display: flex;
817
+ flex-direction: column;
818
+ gap: var(--size-3);
819
+ overflow: hidden;
820
+ padding-inline: 0;
821
+ position: relative;
822
+
823
+ /* Variants */
824
+ &.text {
825
+ --_card-bg-color: transparent;
826
+ --_card-border-color: transparent;
827
+ --_card-border-width: 0;
828
+ --_card-shadow: none;
829
+ }
830
+
831
+ &.tonal {
832
+ --_card-bg-color: var(--_bg-tonal);
833
+ --_card-border-width: 1px;
834
+ }
835
+
836
+ &.elevated {
837
+ --_card-bg-color: var(--_bg-elevated);
838
+ --_card-shadow: var(--_shadow-elevated);
839
+ }
840
+
841
+ &.outlined {
842
+ --_card-bg-color: var(--_bg-surface);
843
+ --_card-border-color: var(--_border-color);
844
+ --_card-border-width: 1px;
845
+ }
846
+
847
+ &> :where(hgroup, .content) {
848
+ padding-inline: var(--size-3);
849
+
850
+ &:last-child {
851
+ padding-block-end: var(--size-3);
852
+ }
853
+ }
854
+
855
+ /* Header */
856
+ &>hgroup {
857
+ padding-block: var(--size-3) 0;
858
+
859
+ /* Top paragraph */
860
+ &>p:first-of-type:first-child {
861
+ line-height: 1.3;
862
+ }
863
+
864
+ :where(h1, h2, h3, h4, h5, h6):last-child {
865
+ margin-block-end: 0;
866
+ }
867
+
868
+ /* Bottom paragraph */
869
+ &>p:last-of-type:last-child:not(:first-child) {
870
+ font-size: var(--font-size-1);
871
+ }
872
+ }
873
+
874
+ /* Content */
875
+ &>.content:where(:only-child, :first-child) {
876
+ padding-block: var(--size-3) var(--size-4);
877
+ }
878
+
879
+ /* Actions */
880
+ &>.actions {
881
+ display: flex;
882
+ gap: var(--size-2);
883
+ margin-block: var(--size-2) 0;
884
+ padding-block-end: var(--size-2);
885
+ padding-inline: var(--size-3);
886
+
887
+ &:has(.button:first-child[class="button"]) {
888
+ padding-inline: var(--size-1) var(--size-3);
889
+ }
890
+
891
+ &:has(.button:not([class="button"])) {
892
+ padding-block-end: var(--size-2);
893
+ }
894
+
895
+ /* Alignment */
896
+ &.align-end {
897
+ justify-content: end;
898
+
899
+ &:has(.button:first-child[class="button"]) {
900
+ padding-inline: var(--size-3) var(--size-1);
901
+ }
902
+ }
903
+ }
904
+
905
+
906
+ }
907
+ }
908
+
909
+ @layer components.root {
910
+ :where(.chip) {
911
+ --_bg-color: var(--surface-tonal);
912
+ --_border-color: var(--border-color);
913
+ --_color: var(--text-primary);
914
+
915
+ align-items: center;
916
+ background: var(--_bg-color) var(--ripple, none);
917
+ block-size: var(--size-7, 2rem);
918
+ border-radius: var(--radius-2, 0.5rem);
919
+ border: 1px solid var(--_border-color);
920
+ color: var(--_color);
921
+ display: inline-flex;
922
+ font-size: var(--font-size-0, 0.75rem);
923
+ gap: var(--size-1);
924
+ padding-inline: var(--size-2);
925
+ text-decoration: none;
926
+
927
+ /* Variants */
928
+ &.tonal {
929
+ --_bg-color: var(--surface-tonal);
930
+ --_color: var(--text-primary);
931
+ }
932
+
933
+ &.outlined {
934
+ --_bg-color: var(--surface-default);
935
+ --_color: var(--text-primary);
936
+ }
937
+
938
+ &:where(button, a):where(:not([disabled])) {
939
+ &:where(:not(:active)):hover {
940
+ --_bg-color: light-dark(oklch(from var(--surface-tonal) calc(l * 0.98) c h),
941
+ oklch(from var(--surface-tonal) calc(l * 1.1) c h));
942
+ }
943
+ }
944
+
945
+ /* Icon */
946
+ &:has(svg:first-child) {
947
+ padding-inline: var(--size-1) var(--size-2);
948
+ }
949
+
950
+ &:has(svg:last-child) {
951
+ padding-inline: var(--size-2) var(--size-1);
952
+ }
953
+
954
+ &:has(svg) {
955
+ svg {
956
+ flex-shrink: 0;
957
+ inline-size: var(--size-3);
958
+ }
959
+ }
960
+
961
+ /* Sizes */
962
+ &.small {
963
+ block-size: var(--size-5);
964
+ }
965
+
966
+ &.multiline {
967
+ block-size: auto;
968
+ }
969
+
970
+ /* Ripple effect */
971
+ background-position: center;
972
+
973
+ &:where(:not([disabled])) {
974
+ &:where(:not(:active):hover) {
975
+ --ripple: radial-gradient(circle, transparent 1%, var(--_bg-color) 1%) center/15000%;
976
+
977
+ transition: background var(--button-ripple-duration);
978
+ }
979
+
980
+ &:where(:hover:active) {
981
+ background-size: var(--button-ripple-size);
982
+ transition: background 0s;
983
+ }
984
+ }
985
+
986
+ /* Disabled */
987
+ &:where([disabled]) {
988
+ opacity: 0.64;
989
+ --_color: color-mix(in oklch,
990
+ var(--text-muted) 50%,
991
+ var(--surface-default));
992
+ cursor: not-allowed;
993
+ }
994
+ }
995
+ }
996
+
997
+ @layer components.root {
998
+ :where(.description-list) {
999
+ --_border-style: solid;
1000
+ --_border-width: 1px;
1001
+
1002
+ display: grid;
1003
+ gap: var(--size-3);
1004
+ margin: 0;
1005
+ padding: 0;
1006
+
1007
+ &.dotted {
1008
+ --_border-style: dotted;
1009
+ --_border-width: 2px;
1010
+ }
1011
+
1012
+ .item {
1013
+ display: grid;
1014
+ margin: 0;
1015
+ padding: 0;
1016
+
1017
+ dt {
1018
+ display: block;
1019
+ font-weight: 700;
1020
+ overflow: hidden;
1021
+ position: relative;
1022
+ }
1023
+
1024
+ dd {
1025
+ margin: 0;
1026
+ }
1027
+ }
1028
+
1029
+ @container (width > 45ch) {
1030
+ gap: var(--size-1);
1031
+
1032
+ .item {
1033
+ align-items: baseline;
1034
+ display: grid;
1035
+ gap: var(--size-1);
1036
+ grid-template-columns: 1fr auto;
1037
+
1038
+ dt {
1039
+ inline-size: max-content;
1040
+
1041
+ &::after {
1042
+ display: inline-block;
1043
+ }
1044
+ }
1045
+
1046
+ dd {
1047
+ color: var(--text-muted);
1048
+ text-align: end;
1049
+ }
1050
+ }
1051
+
1052
+ &.bordered .item {
1053
+ grid-template-columns: auto 1fr auto;
1054
+
1055
+ dt {
1056
+ order: 0;
1057
+ }
1058
+
1059
+ dd {
1060
+ order: 2;
1061
+ }
1062
+
1063
+ &::after {
1064
+ background-color: transparent;
1065
+ block-size: 2px;
1066
+ border-block-end: var(--_border-width) var(--_border-style) var(--border-color);
1067
+ content: "";
1068
+ order: 1;
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ @layer components.root {
1076
+ :where(hr) {
1077
+ background-color: var(--border-color);
1078
+ block-size: var(--border-size-1);
1079
+ margin-block: var(--size-fluid-3);
1080
+
1081
+ /* Border color */
1082
+ &.border-filled {
1083
+ background-color: var(--surface-filled);
1084
+ }
1085
+
1086
+ &.border-primary {
1087
+ background-color: var(--primary);
1088
+ }
1089
+
1090
+ &.border-tonal {
1091
+ background-color: var(--surface-tonal);
1092
+ }
1093
+ }
1094
+ }
1095
+
1096
+ @layer components.root {
1097
+ :where(.link) {
1098
+ color: var(--primary);
1099
+ cursor: pointer;
1100
+ font-weight: 700;
1101
+ text-decoration: underline;
1102
+ text-decoration-color: var(--primary);
1103
+ text-underline-offset: 2px;
1104
+
1105
+ &[href] {
1106
+ &:hover,
1107
+ &:focus-visible {
1108
+ color: var(--primary-light);
1109
+ }
1110
+ }
1111
+
1112
+ @supports (-moz-appearance: none) {
1113
+ text-underline-offset: 2px;
1114
+ }
1115
+ }
1116
+ }
1117
+
1118
+ @layer components.root {
1119
+ :where(table) {
1120
+ --_table-border-radius: var(--border-radius);
1121
+
1122
+ border-collapse: separate;
1123
+ border-spacing: 0;
1124
+ border: 1px solid var(--border-color);
1125
+ border-radius: var(--_table-border-radius);
1126
+ overflow: hidden;
1127
+ inline-size: 100%;
1128
+ margin: var(--size-3) 0;
1129
+ position: relative;
1130
+
1131
+ /* Rows */
1132
+ tr {
1133
+ &:hover {
1134
+ background-color: oklch(from var(--surface-filled) l c h / 75%);
1135
+ }
1136
+ }
1137
+
1138
+ /* Cells */
1139
+ th,
1140
+ td {
1141
+ background-color: var(--surface-default);
1142
+ border-inline-end: var(--border-width) solid var(--border-color);
1143
+ border-block-end: var(--border-width) solid var(--border-color);
1144
+ padding: var(--size-1) var(--size-2);
1145
+
1146
+ &:last-child {
1147
+ border-inline-end: none;
1148
+ }
1149
+ }
1150
+
1151
+ /* Remove bottom border only on the last row of the table */
1152
+ &>*:last-child tr:last-child {
1153
+
1154
+ th,
1155
+ td {
1156
+ border-block-end: none;
1157
+ }
1158
+ }
1159
+
1160
+ th {
1161
+ background-color: var(--surface-filled);
1162
+ color: var(--text-primary);
1163
+ font-size: var(--font-size-05);
1164
+ font-weight: 600;
1165
+ text-align: start;
1166
+ }
1167
+
1168
+ td {
1169
+ font-size: var(--font-size-05);
1170
+ }
1171
+
1172
+ /* Round corner cells */
1173
+ &>thead:first-of-type tr:first-child {
1174
+ th:first-child {
1175
+ border-start-start-radius: var(--_table-border-radius);
1176
+ }
1177
+
1178
+ th:last-child {
1179
+ border-start-end-radius: var(--_table-border-radius);
1180
+ }
1181
+ }
1182
+
1183
+ /* Logic for tables without thead */
1184
+ &>tbody:first-of-type:not(thead ~ tbody) tr:first-child {
1185
+ td:first-child {
1186
+ border-start-start-radius: var(--_table-border-radius);
1187
+ }
1188
+
1189
+ td:last-child {
1190
+ border-start-end-radius: var(--_table-border-radius);
1191
+ }
1192
+ }
1193
+
1194
+ /* Logic for bottom corners (whether in tbody or tfoot) */
1195
+ &>*:last-child tr:last-child {
1196
+ :where(th, td):first-child {
1197
+ border-end-start-radius: var(--_table-border-radius);
1198
+ }
1199
+
1200
+ :where(th, td):last-child {
1201
+ border-end-end-radius: var(--_table-border-radius);
1202
+ }
1203
+ }
1204
+
1205
+ /* Footer */
1206
+ tfoot {
1207
+ tr td {
1208
+ background-color: var(--surface-filled);
1209
+ padding-block: var(--size-2);
1210
+ }
1211
+
1212
+ td {
1213
+ color: var(--text-primary);
1214
+ font-weight: 600;
1215
+ border-top: var(--border-width) solid var(--border-color);
1216
+ }
1217
+ }
1218
+
1219
+ /* Caption */
1220
+ caption {
1221
+ caption-side: bottom;
1222
+ color: var(--text-muted);
1223
+ font-size: var(--font-size-05);
1224
+ margin-inline-start: var(--size-2);
1225
+ padding: var(--size-2) 0;
1226
+ text-align: start;
1227
+ }
1228
+
1229
+ /* Header */
1230
+ thead {
1231
+ z-index: 1;
1232
+ }
1233
+
1234
+ /* Remove bottom border of the row above the footer to stay single-line */
1235
+ tbody:has(+ tfoot) tr:last-child td {
1236
+ border-block-end: none;
1237
+ }
1238
+
1239
+ /* Column group */
1240
+ colgroup col {
1241
+ border: none;
1242
+ }
1243
+
1244
+ @container (width < 60ch) {
1245
+
1246
+ th,
1247
+ td {
1248
+ padding: var(--size-1) 0.875rem;
1249
+ }
1250
+ }
1251
+
1252
+ /* Spacious */
1253
+ &.spacious {
1254
+
1255
+ th,
1256
+ td {
1257
+ padding: var(--size-3);
1258
+ }
1259
+
1260
+ caption {
1261
+ margin-inline-start: var(--size-3);
1262
+ padding: var(--size-2) 0;
1263
+ }
1264
+
1265
+ @container (width < 60ch) {
1266
+
1267
+ th,
1268
+ td {
1269
+ padding: var(--size-3);
1270
+ }
1271
+ }
1272
+ }
1273
+
1274
+ /* Dense */
1275
+ &.dense {
1276
+
1277
+ th,
1278
+ td {
1279
+ padding: var(--size-1);
1280
+ }
1281
+
1282
+ caption {
1283
+ margin-inline-start: var(--size-1);
1284
+ padding: var(--size-1) 0;
1285
+ }
1286
+
1287
+ @container (width < 60ch) {
1288
+
1289
+ th,
1290
+ td {
1291
+ padding: var(--size-1);
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ @layer components.root {
1299
+ :where(progress) {
1300
+ --_accent-color: var(--primary);
1301
+ --_bg-color: var(--surface-tonal);
1302
+
1303
+ appearance: none;
1304
+ background-color: var(--_bg-color);
1305
+ block-size: var(--size-1);
1306
+ border: 0;
1307
+ border-radius: var(--border-radius, 0.25rem);
1308
+ display: inline-block;
1309
+ inline-size: 100%;
1310
+ overflow: hidden;
1311
+ position: relative;
1312
+ vertical-align: baseline;
1313
+
1314
+ /* Color */
1315
+ &.filled {
1316
+ --_bg-color: var(--surface-filled);
1317
+ }
1318
+
1319
+ &.default {
1320
+ --_bg-color: var(--surface-default);
1321
+ }
1322
+
1323
+ &.tonal {
1324
+ --_bg-color: var(--surface-tonal);
1325
+ }
1326
+
1327
+ &::-webkit-progress-bar {
1328
+ background: none;
1329
+ border-radius: var(--border-radius, 0.25rem);
1330
+ }
1331
+
1332
+ &[value]::-webkit-progress-value {
1333
+ background-color: var(--_accent-color);
1334
+
1335
+ @media (prefers-reduced-motion: no-preference) {
1336
+ transition: inline-size 0.2s var(--ease-out-4, cubic-bezier(0, 0, 0.1, 1));
1337
+ }
1338
+ }
1339
+
1340
+ &::-moz-progress-bar {
1341
+ background-color: var(--_accent-color);
1342
+ }
1343
+ }
1344
+
1345
+ @media (prefers-reduced-motion: no-preference) {
1346
+ progress:indeterminate {
1347
+ background-color: var(--_bg-color);
1348
+
1349
+ &::after {
1350
+ animation: indeterminate 2s linear infinite;
1351
+ background-color: var(--_accent-color);
1352
+ content: "";
1353
+ inset: 0 auto 0 0;
1354
+ position: absolute;
1355
+ will-change: inset-inline-start, inset-inline-end;
1356
+ }
1357
+
1358
+ &[value]::-webkit-progress-value {
1359
+ background-color: transparent;
1360
+ }
1361
+
1362
+ &::-moz-progress-bar {
1363
+ background-color: transparent;
1364
+ }
1365
+ }
1366
+
1367
+ [dir="rtl"] {
1368
+ :where(progress):indeterminate {
1369
+ animation-direction: reverse;
1370
+
1371
+ &::after {
1372
+ animation-direction: reverse;
1373
+ }
1374
+ }
1375
+ }
1376
+ }
1377
+
1378
+ @keyframes indeterminate {
1379
+ 0% {
1380
+ inset-inline-start: -200%;
1381
+ inset-inline-end: 100%;
1382
+ }
1383
+
1384
+ 60% {
1385
+ inset-inline-start: 107%;
1386
+ inset-inline-end: -8%;
1387
+ }
1388
+
1389
+ 100% {
1390
+ inset-inline-start: 107%;
1391
+ inset-inline-end: -8%;
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+ @layer components.root {
1397
+
1398
+ [aria-busy="true"]:not(input,
1399
+ select,
1400
+ textarea,
1401
+ html,
1402
+ progress,
1403
+ [aria-describedby]) {
1404
+ position: relative;
1405
+
1406
+ &::before {
1407
+ animation: spin 0.7s linear infinite;
1408
+ block-size: 1em;
1409
+ border-color: transparent currentColor currentColor;
1410
+ border-radius: 50%;
1411
+ border-style: solid;
1412
+ border-width: 3px;
1413
+ content: "";
1414
+ display: inline-block;
1415
+ inline-size: 1em;
1416
+ opacity: 0.5;
1417
+ vertical-align: -0.14em;
1418
+ }
1419
+
1420
+ &:not(button.button):not(:empty) {
1421
+ &::before {
1422
+ margin-inline-end: 0.5em;
1423
+ }
1424
+ }
1425
+ }
1426
+
1427
+ @keyframes spin {
1428
+ to {
1429
+ transform: rotate(1turn);
1430
+ }
1431
+ }
1432
+ }
1433
+
1434
+ @layer components.root {
1435
+ label.checkbox {
1436
+ --_input-size: var(--size-4);
1437
+
1438
+ align-items: center;
1439
+ color: var(--text-primary);
1440
+ cursor: pointer;
1441
+ display: inline-grid;
1442
+ gap: 0 var(--size-2);
1443
+ grid-auto-columns: auto;
1444
+ grid-auto-flow: column;
1445
+ inline-size: fit-content;
1446
+ line-height: 1.5;
1447
+ transform: translateZ(0);
1448
+ user-select: none;
1449
+
1450
+ /* Disabled */
1451
+ &:has([disabled]) {
1452
+ cursor: not-allowed;
1453
+ opacity: 0.64;
1454
+ user-select: none;
1455
+
1456
+ input {
1457
+ cursor: not-allowed;
1458
+ }
1459
+ }
1460
+
1461
+ /* Required dot */
1462
+ &:has(:invalid) {
1463
+ .label:after {
1464
+ color: var(--red);
1465
+ content: "*";
1466
+ inset: 0 -0.25ex auto auto;
1467
+ position: absolute;
1468
+ }
1469
+ }
1470
+
1471
+ /* Label */
1472
+ .label {
1473
+ color: var(--text-primary);
1474
+ font-size: var(--font-size-05);
1475
+ grid-column: 2;
1476
+ grid-row: 1;
1477
+ position: relative;
1478
+ padding-inline: 0 1ex;
1479
+ }
1480
+
1481
+ /* End text */
1482
+ :where(.end-text) {
1483
+ color: var(--text-muted);
1484
+ font-size: var(--font-size-0);
1485
+ grid-column: 2;
1486
+ grid-row: 2;
1487
+ line-height: 1.5;
1488
+ z-index: 1;
1489
+ }
1490
+
1491
+ /* Spread layout */
1492
+ &.spread {
1493
+ align-items: center;
1494
+ column-gap: var(--size-4);
1495
+ grid-auto-flow: unset;
1496
+ grid-template-columns: 1fr auto;
1497
+ inline-size: 100%;
1498
+
1499
+ .label {
1500
+ font-weight: 600;
1501
+ grid-column: 1;
1502
+ grid-row: 1;
1503
+ inline-size: fit-content;
1504
+ }
1505
+
1506
+ input {
1507
+ grid-column: 2;
1508
+ grid-row: 1;
1509
+ }
1510
+
1511
+ :where(.end-text) {
1512
+ grid-column: 1;
1513
+ grid-row: 2;
1514
+ }
1515
+ }
1516
+
1517
+ /* Stacked layout */
1518
+ &.stack {
1519
+ justify-items: center;
1520
+ grid-auto-columns: unset;
1521
+
1522
+ .label {
1523
+ grid-column: 1/-1;
1524
+ grid-row: 2;
1525
+ margin-block-start: var(--size-1);
1526
+ padding-inline: 1ex;
1527
+
1528
+ /* Required dot */
1529
+ &::after {
1530
+ inset: 0 -0.25ex auto auto;
1531
+ }
1532
+ }
1533
+
1534
+ .end-text {
1535
+ grid-column: 1/-1;
1536
+ grid-row: 3;
1537
+ }
1538
+ }
1539
+
1540
+ /* Input */
1541
+ input[type="checkbox"] {
1542
+ --_input-size: var(--size-4);
1543
+
1544
+ appearance: none;
1545
+ aspect-ratio: 1;
1546
+ background-color: var(--surface-default);
1547
+ block-size: var(--_input-size);
1548
+ border-radius: var(--radius-1);
1549
+ border: 1px solid var(--border-color);
1550
+ box-sizing: border-box;
1551
+ cursor: pointer;
1552
+ display: grid;
1553
+ font-size: var(--_input-size);
1554
+ inline-size: var(--_input-size);
1555
+ margin: 0;
1556
+ padding: 0;
1557
+ place-items: center;
1558
+ position: relative;
1559
+
1560
+ &:checked,
1561
+ &:indeterminate {
1562
+ background-color: var(--primary);
1563
+ border-color: var(--primary);
1564
+ }
1565
+
1566
+
1567
+ /* Checkmark */
1568
+ &::after {
1569
+ background-color: var(--primary-contrast);
1570
+ clip-path: polygon(15% 52%, 40% 77%, 85% 32%, 75% 22%, 40% 57%, 25% 42%);
1571
+ content: "";
1572
+ inset: 0;
1573
+ opacity: 0;
1574
+ position: absolute;
1575
+ }
1576
+
1577
+ &:checked::after,
1578
+ &:indeterminate::after {
1579
+ opacity: 1;
1580
+ }
1581
+
1582
+ /* Indeterminate dash */
1583
+ &:indeterminate::after {
1584
+ clip-path: polygon(20% 45%, 80% 45%, 80% 55%, 20% 55%);
1585
+ }
1586
+
1587
+ &::before {
1588
+ --highlight-size: 175%;
1589
+ }
1590
+ }
1591
+
1592
+ /* Sizes */
1593
+ &.small {
1594
+ input[type="checkbox"] {
1595
+ --_input-size: var(--size-3);
1596
+ }
1597
+ }
1598
+
1599
+ &.large {
1600
+ input[type="checkbox"] {
1601
+ --_input-size: var(--size-5);
1602
+ }
1603
+ }
1604
+
1605
+ /* Validation */
1606
+ &[data-invalid],
1607
+ &:has(:user-invalid) {
1608
+ --palette-source: oklch(0.58 0.21 var(--hue-red));
1609
+
1610
+ :where(.end-text) {
1611
+ color: var(--primary);
1612
+ }
1613
+ }
1614
+
1615
+ /* Touch devices */
1616
+ @media (pointer: coarse) {
1617
+ input {
1618
+ --_input-size: var(--size-4);
1619
+ }
1620
+ }
1621
+
1622
+ @media (forced-colors: active) {
1623
+ input {
1624
+ border: 1px solid CanvasText;
1625
+
1626
+ &:checked,
1627
+ &:indeterminate {
1628
+ background-color: SelectedItem;
1629
+ border-color: SelectedItem;
1630
+
1631
+ &::after {
1632
+ background-color: SelectedItemText;
1633
+ }
1634
+ }
1635
+ }
1636
+ }
1637
+ }
1638
+ }
1639
+
1640
+ @layer components.root {
1641
+ label.radio {
1642
+ --_input-size: 1.125rem;
1643
+ --_indicator-size: 50%;
1644
+
1645
+ align-items: center;
1646
+ color: var(--text-primary);
1647
+ cursor: pointer;
1648
+ display: inline-grid;
1649
+ gap: 0 var(--size-2);
1650
+ grid-auto-columns: auto;
1651
+ grid-auto-flow: column;
1652
+ inline-size: fit-content;
1653
+ line-height: 1.5;
1654
+ transform: translateZ(0);
1655
+ user-select: none;
1656
+
1657
+ /* Disabled */
1658
+ &:has([disabled]) {
1659
+ cursor: not-allowed;
1660
+ opacity: 0.64;
1661
+ user-select: none;
1662
+
1663
+ input {
1664
+ cursor: not-allowed;
1665
+ }
1666
+ }
1667
+
1668
+ /* Required dot */
1669
+ &:has(:invalid) {
1670
+ .label:after {
1671
+ color: var(--red);
1672
+ content: "*";
1673
+ inset: 0 -0.25ex auto auto;
1674
+ position: absolute;
1675
+ }
1676
+ }
1677
+
1678
+ /* Label */
1679
+ .label {
1680
+ color: var(--text-primary);
1681
+ font-size: var(--font-size-05);
1682
+ grid-column: 2;
1683
+ grid-row: 1;
1684
+ padding-inline: 0 1ex;
1685
+ position: relative;
1686
+ }
1687
+
1688
+ /* End text */
1689
+ :where(.end-text) {
1690
+ color: var(--text-muted);
1691
+ font-size: var(--font-size-0);
1692
+ grid-column: 2;
1693
+ grid-row: 2;
1694
+ line-height: 1.5;
1695
+ z-index: 1;
1696
+ }
1697
+
1698
+ /* Stacked layout */
1699
+ &.stack {
1700
+ grid-auto-columns: unset;
1701
+ justify-items: center;
1702
+
1703
+ .label {
1704
+ grid-column: 1/-1;
1705
+ grid-row: 2;
1706
+ margin-block-start: var(--size-1);
1707
+ padding-inline: 1ex;
1708
+
1709
+ /* Required dot */
1710
+ &::after {
1711
+ inset: 0 -0.25ex auto auto;
1712
+ }
1713
+ }
1714
+
1715
+ .end-text {
1716
+ grid-column: 1/-1;
1717
+ grid-row: 3;
1718
+ }
1719
+ }
1720
+
1721
+ /* Input */
1722
+ input[type="radio"] {
1723
+ appearance: none;
1724
+ aspect-ratio: 1;
1725
+ background-color: var(--surface-default);
1726
+ block-size: var(--_input-size);
1727
+ border: 1px solid var(--field-border-color);
1728
+ border-radius: var(--radius-round);
1729
+ box-sizing: border-box;
1730
+ cursor: pointer;
1731
+ display: grid;
1732
+ inline-size: var(--_input-size);
1733
+ margin: 0;
1734
+ padding: 0;
1735
+ place-items: center;
1736
+ position: relative;
1737
+
1738
+ &:checked {
1739
+ background-color: var(--primary);
1740
+ border-color: var(--primary);
1741
+ }
1742
+
1743
+ /* Dot */
1744
+ &::after {
1745
+ background-color: var(--primary-contrast);
1746
+ block-size: var(--_indicator-size);
1747
+ border-radius: var(--radius-round);
1748
+ content: "";
1749
+ inline-size: var(--_indicator-size);
1750
+ margin: auto;
1751
+ opacity: 0;
1752
+ }
1753
+
1754
+ &:checked::after {
1755
+ opacity: 1;
1756
+ }
1757
+
1758
+ &::before {
1759
+ --highlight-size: 175%;
1760
+ }
1761
+ }
1762
+
1763
+ /* Sizes */
1764
+ &.small {
1765
+ input[type="radio"] {
1766
+ --_input-size: var(--size-3);
1767
+
1768
+ }
1769
+ }
1770
+
1771
+ &.large {
1772
+ input[type="radio"] {
1773
+ --_input-size: var(--size-4);
1774
+
1775
+ }
1776
+ }
1777
+
1778
+ /* Validation */
1779
+ &[data-invalid],
1780
+ &:has(:user-invalid) {
1781
+ --palette-source: oklch(0.58 0.21 var(--hue-red));
1782
+
1783
+ :where(.end-text) {
1784
+ color: var(--primary);
1785
+ }
1786
+ }
1787
+
1788
+ /* Touch devices */
1789
+ @media (pointer: coarse) {
1790
+ input[type="radio"] {
1791
+ block-size: var(--size-4);
1792
+ inline-size: var(--size-4);
1793
+ }
1794
+ }
1795
+
1796
+ @media (forced-colors: active) {
1797
+ input[type="radio"] {
1798
+ border: 1px solid CanvasText;
1799
+
1800
+ &:checked {
1801
+ background-color: SelectedItem;
1802
+ border-color: SelectedItem;
1803
+
1804
+ &::after {
1805
+ background-color: SelectedItemText;
1806
+ }
1807
+ }
1808
+ }
1809
+ }
1810
+ }
1811
+ }
1812
+
1813
+ @layer components.root {
1814
+ :where(.range) {
1815
+ display: grid;
1816
+ gap: var(--size-1) 0;
1817
+ /* Two-column base so the optional .value cell can sit next to the
1818
+ label on row 1. Children that span the full width keep using
1819
+ `grid-column: 1/-1`, so this is backwards compatible. */
1820
+ grid-template-columns: 1fr auto;
1821
+ position: relative;
1822
+
1823
+ .label {
1824
+ color: var(--text-primary);
1825
+ font-size: var(--font-size-05);
1826
+ font-weight: 600;
1827
+ grid-column: 1;
1828
+ grid-row: 1;
1829
+ }
1830
+
1831
+ /* Live current-value readout. Pairs with the <output> element
1832
+ rendered by the Range component (or hand-written .value markup). */
1833
+ :where(.value) {
1834
+ color: var(--text-muted);
1835
+ font-size: var(--font-size-0);
1836
+ font-variant-numeric: tabular-nums;
1837
+ font-weight: 600;
1838
+ grid-column: 2;
1839
+ grid-row: 1;
1840
+ line-height: 1.5;
1841
+ text-align: end;
1842
+ }
1843
+
1844
+ .start-text {
1845
+ color: var(--text-muted);
1846
+ font-size: var(--font-size-0);
1847
+ grid-column: 1/-1;
1848
+ grid-row: 2;
1849
+ line-height: 1.5;
1850
+ }
1851
+
1852
+ :where(.end-text) {
1853
+ color: var(--text-muted);
1854
+ font-size: var(--font-size-0);
1855
+ grid-column: 1/-1;
1856
+ grid-row: 5;
1857
+ line-height: 1.5;
1858
+ }
1859
+
1860
+ /* Datalist (tick mark labels) */
1861
+ :where(datalist) {
1862
+ color: var(--text-muted);
1863
+ display: flex;
1864
+ font-size: var(--font-size-0);
1865
+ grid-column: 1/-1;
1866
+ grid-row: 4;
1867
+ justify-content: space-between;
1868
+ margin-top: calc(var(--size-1) * -1);
1869
+ padding-inline: calc(3ex / 2);
1870
+
1871
+ &>option {
1872
+ display: flex;
1873
+ inline-size: 0;
1874
+ justify-content: center;
1875
+ padding: 0;
1876
+ white-space: nowrap;
1877
+ }
1878
+ }
1879
+
1880
+ /* Disabled */
1881
+ &:has([disabled]) {
1882
+ cursor: not-allowed;
1883
+ opacity: 0.64;
1884
+ user-select: none;
1885
+
1886
+ .label,
1887
+ .value,
1888
+ .start-text,
1889
+ .end-text {
1890
+ cursor: not-allowed;
1891
+ }
1892
+ }
1893
+
1894
+ /* Color */
1895
+ &.filled input[type="range"] {
1896
+ --_track-color: var(--surface-filled);
1897
+ }
1898
+
1899
+ &.default input[type="range"] {
1900
+ --_track-color: var(--surface-default);
1901
+ }
1902
+
1903
+ &.tonal input[type="range"] {
1904
+ --_track-color: var(--surface-tonal);
1905
+ }
1906
+
1907
+ /* Orientation */
1908
+ &.spread {
1909
+ align-items: center;
1910
+ column-gap: var(--size-4);
1911
+ container-type: inline-size;
1912
+ grid-template-columns: 1fr auto;
1913
+
1914
+ .label {
1915
+ grid-column: 1;
1916
+ grid-row: 1;
1917
+ }
1918
+
1919
+ .start-text {
1920
+ color: var(--text-muted);
1921
+ display: block;
1922
+ font-size: var(--font-size-0);
1923
+ grid-column: 1;
1924
+ grid-row: 2;
1925
+ line-height: 1.5;
1926
+ }
1927
+
1928
+ input[type="range"] {
1929
+ align-self: center;
1930
+ grid-column: 2;
1931
+ grid-row: 1;
1932
+ min-inline-size: 25ch;
1933
+ }
1934
+
1935
+ /* In spread mode, the value sits below the slider in col 2
1936
+ (where end-text would normally land). When end-text is also
1937
+ present it shifts down a row to avoid collision. */
1938
+ :where(.value) {
1939
+ grid-column: 2;
1940
+ grid-row: 2;
1941
+ }
1942
+
1943
+ :where(.end-text) {
1944
+ grid-column: 2;
1945
+ grid-row: 2;
1946
+ text-align: end;
1947
+ }
1948
+
1949
+ datalist {
1950
+ grid-column: 2;
1951
+ grid-row: 2;
1952
+ }
1953
+
1954
+ /* When both datalist and end-text exist, push end-text below the datalist
1955
+ so they don't collide on the same grid cell. */
1956
+ &:has(datalist) :where(.end-text) {
1957
+ grid-row: 3;
1958
+ }
1959
+
1960
+ &:has(.value) :where(.end-text) {
1961
+ grid-row: 3;
1962
+ }
1963
+
1964
+ &:has(.value):has(datalist) :where(.end-text) {
1965
+ grid-row: 4;
1966
+ }
1967
+
1968
+ @container (width < 400px) {
1969
+ grid-template-columns: 1fr;
1970
+
1971
+ * {
1972
+ grid-column: 1/-1;
1973
+ }
1974
+
1975
+ .label {
1976
+ grid-row: 1;
1977
+ }
1978
+
1979
+ /* Share row 1 with the label: the label's text stays left-aligned
1980
+ in its full-width cell, while the value shrinks to fit and
1981
+ right-aligns. Visually reads as a "[name ........ value]" row. */
1982
+ :where(.value) {
1983
+ grid-row: 1;
1984
+ justify-self: end;
1985
+ text-align: end;
1986
+ }
1987
+
1988
+ .start-text {
1989
+ grid-row: 2;
1990
+ }
1991
+
1992
+ input[type="range"] {
1993
+ grid-column: 1/-1;
1994
+ grid-row: 3;
1995
+ }
1996
+
1997
+ datalist {
1998
+ grid-column: 1/-1;
1999
+ grid-row: 4;
2000
+ }
2001
+
2002
+ :where(.end-text) {
2003
+ grid-row: 5;
2004
+ text-align: start;
2005
+ }
2006
+ }
2007
+ }
2008
+
2009
+ /* Validation */
2010
+ &[data-invalid],
2011
+ &:has(:user-invalid) {
2012
+ --_thumb-bg: var(--color-9);
2013
+ --_thumb-highlight-color: oklch(from var(--color-9) 70% 100% h / 20%);
2014
+
2015
+ .start-text,
2016
+ .end-text,
2017
+ .value {
2018
+ color: var(--color-9);
2019
+ }
2020
+ }
2021
+
2022
+ /* Range input */
2023
+ :where(& > input[type="range"]) {
2024
+ --_thumb-bg: var(--primary);
2025
+ --_thumb-highlight-color: oklch(from var(--primary) 70% 100% h / 20%);
2026
+ --_thumb-highlight-size: 0px;
2027
+ --_thumb-offset: -1.125ex;
2028
+ --_thumb-size: 3ex;
2029
+ --_track-color: var(--field-border-color);
2030
+ --_track-fill: 0%;
2031
+ --_track-fill-color: var(--primary);
2032
+ --_track-height: 0.75ex;
2033
+ --_track-radius: 1e5px;
2034
+
2035
+ appearance: none;
2036
+ background: transparent;
2037
+ block-size: var(--size-4);
2038
+ display: block;
2039
+ grid-column: 1/-1;
2040
+ grid-row: 3;
2041
+ inline-size: 100%;
2042
+ outline-offset: 1ex;
2043
+
2044
+ @media (hover: none) {
2045
+ --_thumb-offset: -11.5px;
2046
+ --_thumb-size: 30px;
2047
+ }
2048
+
2049
+ /* Track */
2050
+ &::-webkit-slider-runnable-track {
2051
+ appearance: none;
2052
+ background: linear-gradient(to right,
2053
+ var(--_track-fill-color) var(--_track-fill, 0%),
2054
+ var(--_track-color) 0%);
2055
+ block-size: var(--_track-height);
2056
+ border-radius: var(--_track-radius);
2057
+ }
2058
+
2059
+ &::-moz-range-track {
2060
+ appearance: none;
2061
+ background: var(--_track-color);
2062
+ block-size: var(--_track-height);
2063
+ border-radius: var(--_track-radius);
2064
+ }
2065
+
2066
+ &::-moz-range-progress {
2067
+ appearance: none;
2068
+ background: var(--_track-fill-color);
2069
+ block-size: var(--_track-height);
2070
+ border-radius: var(--_track-radius);
2071
+ }
2072
+
2073
+ /* Ring */
2074
+ &::-webkit-slider-thumb {
2075
+ appearance: none;
2076
+ background: var(--_thumb-bg);
2077
+ block-size: var(--_thumb-size);
2078
+ border: 3px solid var(--surface-default);
2079
+ border-radius: 50%;
2080
+ box-shadow: 0 0 0 var(--_thumb-highlight-size) var(--_thumb-highlight-color);
2081
+ cursor: ew-resize;
2082
+ inline-size: var(--_thumb-size);
2083
+ margin-block-start: var(--_thumb-offset);
2084
+
2085
+ @media (prefers-reduced-motion: no-preference) {
2086
+ transition: box-shadow 0.1s ease;
2087
+ }
2088
+
2089
+ .fieldset-item:focus-within & {
2090
+ border-color: var(--gray-14);
2091
+ }
2092
+ }
2093
+
2094
+ &::-moz-range-thumb {
2095
+ appearance: none;
2096
+ background: var(--_thumb-bg);
2097
+ block-size: var(--_thumb-size);
2098
+ border: 3px solid var(--surface-default);
2099
+ border-radius: 50%;
2100
+ box-shadow: 0 0 0 var(--_thumb-highlight-size) var(--_thumb-highlight-color);
2101
+ cursor: ew-resize;
2102
+ inline-size: var(--_thumb-size);
2103
+ margin-block-start: var(--_thumb-offset);
2104
+
2105
+ @media (prefers-reduced-motion: no-preference) {
2106
+ transition: box-shadow 0.1s ease;
2107
+ }
2108
+
2109
+ .fieldset-item:focus-within & {
2110
+ border-color: var(--gray-14);
2111
+ }
2112
+ }
2113
+
2114
+ /* Element state */
2115
+ .range:has(:user-invalid) &,
2116
+ .range[data-invalid] & {
2117
+ --_track-fill-color: var(--color-9);
2118
+ }
2119
+
2120
+ &:not([disabled]) {
2121
+ &:hover {
2122
+ --_thumb-highlight-size: var(--size-1);
2123
+ }
2124
+
2125
+ &:active {
2126
+ --_thumb-highlight-size: var(--size-2);
2127
+ --_track-color: light-dark(oklch(from var(--field-border-color) calc(l * 0.9) c h),
2128
+ oklch(from var(--field-border-color) calc(l * 1.1) c h));
2129
+ }
2130
+ }
2131
+
2132
+ &[disabled] {
2133
+ --_thumb-bg: oklch(from var(--text-primary) l c h / 50%);
2134
+ --_track-color: var(--field-border-color);
2135
+
2136
+ cursor: not-allowed;
2137
+
2138
+ &::-webkit-slider-thumb {
2139
+ cursor: not-allowed;
2140
+ }
2141
+
2142
+ &::-moz-range-thumb {
2143
+ cursor: not-allowed;
2144
+ }
2145
+ }
2146
+ }
2147
+ }
2148
+
2149
+ }
2150
+
2151
+ @layer components.root {
2152
+ :where(.switch) {
2153
+ --_accent-color: var(--primary);
2154
+ --_accent-contrast: var(--primary-contrast);
2155
+
2156
+ --_dot-bg-color: light-dark(var(--gray-11), var(--gray-14));
2157
+ --_dot-inset: var(--size-1) auto auto var(--size-1);
2158
+ --_dot-outline-size: 0;
2159
+ --_dot-size: var(--size-3);
2160
+
2161
+ --_track-bg-color: light-dark(var(--gray-3), var(--gray-8));
2162
+ --_track-height: var(--size-5);
2163
+ --_track-width: var(--size-8);
2164
+ --_transition-tf: var(--ease-4);
2165
+ --_transition-time: 0.2s;
2166
+
2167
+ align-items: center;
2168
+ color: var(--text-primary);
2169
+ display: inline-grid;
2170
+ gap: 0 var(--size-2);
2171
+ grid-auto-columns: auto;
2172
+ grid-auto-flow: column;
2173
+ inline-size: fit-content;
2174
+
2175
+ :where(input[type="checkbox"][role="switch"]) {
2176
+ appearance: none;
2177
+ block-size: var(--_track-height);
2178
+ cursor: pointer;
2179
+ inline-size: var(--_track-width);
2180
+ margin: 0;
2181
+ position: relative;
2182
+
2183
+ /* Track */
2184
+ &::before {
2185
+ background-color: var(--_track-bg-color);
2186
+ block-size: var(--_track-height);
2187
+ border: 1px solid var(--_dot-bg-color);
2188
+ border-radius: var(--radius-round);
2189
+ content: "";
2190
+ inline-size: var(--_track-width);
2191
+ inset: 0;
2192
+ position: absolute;
2193
+ }
2194
+
2195
+ &:focus-visible {
2196
+ --focus-ring-color: currentColor;
2197
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2198
+ outline-offset: var(--focus-ring-offset);
2199
+ }
2200
+
2201
+ /* Dot */
2202
+ &::after {
2203
+ background-color: var(--_dot-bg-color);
2204
+ block-size: var(--_dot-size);
2205
+ border-radius: var(--radius-round);
2206
+ content: "";
2207
+ inline-size: var(--_dot-size);
2208
+ inset: var(--_dot-inset);
2209
+ outline: var(--_dot-outline-size) solid var(--_dot-bg-color);
2210
+ outline-offset: -1px;
2211
+ position: absolute;
2212
+ }
2213
+
2214
+ /* Checked */
2215
+ &:checked {
2216
+ &::before {
2217
+ background-color: var(--_accent-color);
2218
+ border-color: var(--_accent-color);
2219
+ transition:
2220
+ background-color var(--_transition-time) var(--_transition-tf),
2221
+ border-color var(--_transition-time) var(--_transition-tf);
2222
+ }
2223
+
2224
+ /* Dot */
2225
+ &::after {
2226
+ --_dot-bg-color: var(--_accent-contrast);
2227
+ --_dot-outline-size: calc(var(--size-1) - 1px);
2228
+
2229
+ inset-inline-start: calc(var(--_track-width) - var(--_dot-size) - var(--size-1));
2230
+ }
2231
+ }
2232
+
2233
+ /* Animation */
2234
+ @media (prefers-reduced-motion: no-preference) {
2235
+
2236
+ /* Track */
2237
+ &::before {
2238
+ transition:
2239
+ background-color var(--_transition-time) var(--_transition-tf),
2240
+ border-color var(--_transition-time) var(--_transition-tf);
2241
+ }
2242
+
2243
+ /* Dot */
2244
+ &::after {
2245
+ transition: all var(--_transition-time) var(--_transition-tf);
2246
+ }
2247
+
2248
+ &:active:after {
2249
+ --_dot-outline-size: calc(var(--size-1) + 1px);
2250
+ }
2251
+
2252
+ &:checked {
2253
+ &:active:after {
2254
+ --_dot-outline-size: calc(var(--size-1) + 1px);
2255
+ }
2256
+ }
2257
+ }
2258
+ }
2259
+
2260
+ /* Icons */
2261
+ &:has(.icon-checked, .icon-unchecked) {
2262
+ [role="switch"] {
2263
+ grid-column: 1 / -1;
2264
+ grid-row: 1;
2265
+ }
2266
+
2267
+ &:has([role="switch"]:checked) {
2268
+ .icon-unchecked {
2269
+ display: none;
2270
+ }
2271
+
2272
+ .icon-checked {
2273
+ display: block;
2274
+ }
2275
+ }
2276
+
2277
+ .icon-checked {
2278
+ display: none;
2279
+ }
2280
+
2281
+ .icon-unchecked,
2282
+ .icon-checked {
2283
+ grid-column: 1;
2284
+ grid-row: 1;
2285
+ pointer-events: none;
2286
+ z-index: 1;
2287
+
2288
+ svg {
2289
+ display: block;
2290
+ inline-size: var(--_dot-size);
2291
+ }
2292
+ }
2293
+
2294
+ .icon-unchecked {
2295
+ margin-inline-start: calc(var(--_track-width) - var(--_dot-size) - var(--size-1));
2296
+ }
2297
+
2298
+ .icon-checked {
2299
+ margin-inline-start: var(--size-1);
2300
+ }
2301
+ }
2302
+
2303
+ /* Required dot */
2304
+ &:has(:invalid) {
2305
+ .label:after {
2306
+ color: var(--red);
2307
+ content: "*";
2308
+ inset: 0 -0.25ex auto auto;
2309
+ position: absolute;
2310
+ }
2311
+ }
2312
+
2313
+ /* Disabled */
2314
+ &:has([disabled]) {
2315
+ cursor: not-allowed;
2316
+ opacity: 0.64;
2317
+ user-select: none;
2318
+
2319
+ input {
2320
+ cursor: not-allowed;
2321
+ }
2322
+ }
2323
+
2324
+ /* Label */
2325
+ .label {
2326
+ color: var(--text-primary);
2327
+ font-size: var(--font-size-05);
2328
+ grid-column: 2;
2329
+ grid-row: 1;
2330
+ min-width: 0;
2331
+ padding-inline: 0 1ex;
2332
+ position: relative;
2333
+ user-select: none;
2334
+ }
2335
+
2336
+ /* End text */
2337
+ :where(.end-text) {
2338
+ color: var(--text-muted);
2339
+ font-size: var(--font-size-0);
2340
+ grid-column: 2;
2341
+ grid-row: 2;
2342
+ line-height: 1.5;
2343
+ z-index: 1;
2344
+ }
2345
+
2346
+ /* Size */
2347
+ &.small {
2348
+ --_dot-size: 0.75rem;
2349
+ --_track-height: var(--size-4);
2350
+ --_track-width: 2.5rem;
2351
+ }
2352
+
2353
+ /* Spread layout */
2354
+ &.spread {
2355
+ align-items: center;
2356
+ column-gap: var(--size-4);
2357
+ grid-auto-flow: unset;
2358
+ grid-template-columns: 1fr auto;
2359
+ inline-size: 100%;
2360
+
2361
+ .label {
2362
+ font-weight: 600;
2363
+ grid-column: 1;
2364
+ grid-row: 1;
2365
+ inline-size: fit-content;
2366
+ }
2367
+
2368
+ input[role="switch"] {
2369
+ grid-column: 2;
2370
+ grid-row: 1;
2371
+ }
2372
+
2373
+ &:has(.icon-checked, .icon-unchecked) {
2374
+
2375
+ input[role="switch"],
2376
+ .icon-checked,
2377
+ .icon-unchecked {
2378
+ grid-column: 2;
2379
+ }
2380
+ }
2381
+
2382
+ :where(.end-text) {
2383
+ grid-column: 1;
2384
+ grid-row: 2;
2385
+ }
2386
+ }
2387
+
2388
+ /* Stacked layout */
2389
+ &.stack {
2390
+ grid-auto-columns: unset;
2391
+ justify-items: center;
2392
+
2393
+ .label {
2394
+ grid-column: 1/-1;
2395
+ grid-row: 2;
2396
+ margin-block-start: var(--size-1);
2397
+ padding-inline: 1ex;
2398
+ }
2399
+
2400
+ .end-text {
2401
+ grid-column: 1/-1;
2402
+ grid-row: 3;
2403
+ }
2404
+ }
2405
+
2406
+ /* Validation */
2407
+ &[data-invalid] {
2408
+ input {
2409
+ border-radius: var(--radius-round);
2410
+ outline: 2px solid var(--color-9);
2411
+ }
2412
+
2413
+ .end-text {
2414
+ color: var(--color-9);
2415
+ }
2416
+ }
2417
+ }
2418
+ }
2419
+
2420
+ @layer components.extended {
2421
+ :where(#toast-manager) {
2422
+ background: none;
2423
+ block-size: auto;
2424
+ border: none;
2425
+ display: none;
2426
+ flex-direction: column-reverse;
2427
+ gap: var(--size-3);
2428
+ inline-size: auto;
2429
+ inset: auto var(--size-4) var(--size-4) auto;
2430
+ margin: 0;
2431
+ max-inline-size: calc(100vi - var(--size-8));
2432
+ overflow: visible;
2433
+ padding: 0;
2434
+ pointer-events: none;
2435
+ position: fixed;
2436
+ z-index: 1000;
2437
+
2438
+ &:popover-open {
2439
+ display: flex;
2440
+ }
2441
+
2442
+ &::backdrop {
2443
+ display: none;
2444
+ }
2445
+
2446
+ /* Optional cap on visible toasts. Older toasts beyond this depth are hidden
2447
+ but still in the DOM so they animate cleanly when newer ones are removed. */
2448
+ /* > .toast:nth-last-child(n + 6) { display: none; } */
2449
+ }
2450
+
2451
+ :where(.toast) {
2452
+ --_anim-enter: 0.3s;
2453
+ --_anim-exit: 0.3s;
2454
+
2455
+ align-items: center;
2456
+ animation:
2457
+ toast-enter var(--_anim-enter) var(--ease-out-3) both,
2458
+ toast-hold attr(data-duration type(<time>), 5s) linear both,
2459
+ toast-exit var(--_anim-exit) var(--ease-in-3) both;
2460
+ animation-delay:
2461
+ 0s,
2462
+ var(--_anim-enter),
2463
+ calc(var(--_anim-enter) + attr(data-duration type(<time>), 5s));
2464
+ background-color: light-dark(var(--gray-15), var(--gray-2));
2465
+ border-radius: var(--border-radius);
2466
+ box-shadow: var(--shadow-3);
2467
+ color: var(--text-primary-contrast);
2468
+ display: flex;
2469
+ gap: var(--size-3);
2470
+ justify-content: space-between;
2471
+ min-inline-size: 30ch;
2472
+ padding: var(--size-3) var(--size-4);
2473
+ pointer-events: auto;
2474
+
2475
+ &:hover {
2476
+ animation-play-state: paused;
2477
+ }
2478
+
2479
+ &.exiting {
2480
+ animation: toast-exit var(--_anim-exit) var(--ease-in-3) forwards;
2481
+ }
2482
+
2483
+ .icon {
2484
+ background: no-repeat center / contain;
2485
+ block-size: var(--size-4);
2486
+ flex-shrink: 0;
2487
+ inline-size: var(--size-4);
2488
+ }
2489
+
2490
+ /* Hide the icon slot when there's no severity to render against. */
2491
+ &:not([data-severity]) .icon {
2492
+ display: none;
2493
+ }
2494
+
2495
+ .content {
2496
+ font-size: var(--font-size-05);
2497
+ word-break: break-word;
2498
+ }
2499
+
2500
+ .title {
2501
+ font-weight: 600;
2502
+ }
2503
+
2504
+ .description {
2505
+ color: oklch(from currentColor l c h / 75%);
2506
+ font-size: var(--font-size-0);
2507
+ }
2508
+
2509
+ .close-button {
2510
+ background: none;
2511
+ border: none;
2512
+ color: inherit;
2513
+ cursor: pointer;
2514
+ display: grid;
2515
+ opacity: 0.7;
2516
+ padding: var(--size-1);
2517
+ place-items: center;
2518
+ transition: opacity 0.2s;
2519
+
2520
+ &:hover {
2521
+ opacity: 1;
2522
+ }
2523
+ }
2524
+
2525
+ /* Severity icons via CSS data URIs — keeps icon assets out of JS strings. */
2526
+ &[data-severity="success"] .icon {
2527
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2322c55e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M22 11.08V12a10 10 0 1 1-5.93-9.14'/><path d='m9 11 3 3L22 4'/></svg>");
2528
+ }
2529
+
2530
+ &[data-severity="info"] .icon {
2531
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%233b82f6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='M12 16v-4'/><path d='M12 8h.01'/></svg>");
2532
+ }
2533
+
2534
+ &[data-severity="warning"] .icon {
2535
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23f59e0b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/><path d='M12 9v4'/><path d='M12 17h.01'/></svg>");
2536
+ }
2537
+
2538
+ &[data-severity="critical"] .icon {
2539
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23ef4444' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='m15 9-6 6'/><path d='m9 9 6 6'/></svg>");
2540
+ }
2541
+ }
2542
+
2543
+ @keyframes toast-enter {
2544
+ from {
2545
+ opacity: 0;
2546
+ translate: var(--size-4) 0;
2547
+ }
2548
+
2549
+ to {
2550
+ opacity: 1;
2551
+ translate: 0 0;
2552
+ }
2553
+ }
2554
+
2555
+ /* Identity keyframe — only purpose is to delay the exit animation by the
2556
+ author-defined duration. */
2557
+ @keyframes toast-hold {
2558
+ from {
2559
+ opacity: 1;
2560
+ }
2561
+
2562
+ to {
2563
+ opacity: 1;
2564
+ }
2565
+ }
2566
+
2567
+ @keyframes toast-exit {
2568
+ from {
2569
+ opacity: 1;
2570
+ scale: 1;
2571
+ translate: 0 0;
2572
+ }
2573
+
2574
+ to {
2575
+ opacity: 0;
2576
+ scale: 0.9;
2577
+ translate: 0 var(--size-4);
2578
+ }
2579
+ }
2580
+ }
2581
+
2582
+ @layer components.root {
2583
+
2584
+ :where(.p) {
2585
+ text-wrap: pretty;
2586
+
2587
+ &.small {
2588
+ font-size: var(--font-size-1);
2589
+ }
2590
+
2591
+ &.large {
2592
+ font-size: var(--font-size-3);
2593
+ }
2594
+ }
2595
+
2596
+ :where(.h1, .h2, .h3, .h4, .h5, .h6) {
2597
+ color: var(--text-primary);
2598
+ font-weight: 700;
2599
+ text-wrap: pretty;
2600
+ }
2601
+
2602
+ :where(.h1) {
2603
+ font-size: var(--font-size-h1, var(--font-size-7));
2604
+ letter-spacing: -0.02em;
2605
+ line-height: 1.15;
2606
+ }
2607
+
2608
+ :where(.h2) {
2609
+ font-size: var(--font-size-h2, var(--font-size-5, 2rem));
2610
+ letter-spacing: -0.02em;
2611
+ line-height: 1.2;
2612
+ }
2613
+
2614
+ :where(.h3) {
2615
+ font-size: var(--font-size-h3, var(--font-size-4, 1.5rem));
2616
+ letter-spacing: -0.01em;
2617
+ line-height: 1.167;
2618
+ }
2619
+
2620
+ :where(.h4) {
2621
+ font-size: var(--font-size-h4, var(--font-size-3, 1.25rem));
2622
+ letter-spacing: -0.01em;
2623
+ line-height: 1.235;
2624
+ }
2625
+
2626
+ :where(.h5) {
2627
+ font-size: var(--font-size-h5, var(--font-size-2, 1.1rem));
2628
+ line-height: 1.334;
2629
+ }
2630
+
2631
+ :where(.h6) {
2632
+ font-size: var(--font-size-h6, var(--font-size-1, 1rem));
2633
+ line-height: 1;
2634
+ }
2635
+
2636
+ /** Overline */
2637
+ :where(.overline) {
2638
+ color: light-dark(oklch(from var(--text-muted) calc(l * 1.25) c h),
2639
+ oklch(from var(--text-muted) calc(l * 0.75) c h));
2640
+ font-size: var(--font-size-0);
2641
+ font-weight: 500;
2642
+ letter-spacing: 0.06em;
2643
+ text-transform: uppercase;
2644
+ }
2645
+
2646
+ :where(.hgroup) {
2647
+ &>p {
2648
+ margin: 0;
2649
+ }
2650
+
2651
+ &> :where(h1, h2, h3, h4, h5, h6) {
2652
+ margin-block: 0 0.4em;
2653
+ }
2654
+
2655
+ /* First p element (overline) */
2656
+ &>p:first-of-type:first-child {
2657
+ color: light-dark(oklch(from var(--text-muted) calc(l * 1.25) c h),
2658
+ oklch(from var(--text-muted) calc(l * 0.75) c h));
2659
+ font-size: var(--font-size-0);
2660
+ font-weight: 500;
2661
+ letter-spacing: 0.06em;
2662
+ text-transform: uppercase;
2663
+ }
2664
+
2665
+ /* Body paragraphs after the heading */
2666
+ &>p:not(:first-of-type:first-child) {
2667
+ color: oklch(from currentColor l c h / 75%);
2668
+ font-size: var(--font-size-3);
2669
+ line-height: 1.6;
2670
+ }
2671
+
2672
+ &>p+p {
2673
+ margin-block-start: 0.75em;
2674
+ }
2675
+ }
2676
+
2677
+ /** Caption */
2678
+ :where(.caption) {
2679
+ color: var(--text-muted);
2680
+ font-size: var(--font-size-0);
2681
+ line-height: 1.6;
2682
+ }
2683
+
2684
+
2685
+
2686
+ /* Inline text elements — class utilities (work anywhere) */
2687
+ :where(.u, .abbr, .dfn) {
2688
+ text-decoration: underline;
2689
+ text-underline-offset: 1px;
2690
+
2691
+ @supports (-moz-appearance: none) {
2692
+ text-underline-offset: 2px;
2693
+ }
2694
+ }
2695
+
2696
+ :where(.abbr, .dfn) {
2697
+ font-style: normal;
2698
+ text-decoration: var(--color-9) underline dotted;
2699
+
2700
+ &[title] {
2701
+ cursor: help;
2702
+ text-underline-offset: 1px;
2703
+ }
2704
+
2705
+ @supports (-moz-appearance: none) {
2706
+ text-underline-offset: 2px;
2707
+ }
2708
+ }
2709
+
2710
+ :where(.sup) {
2711
+ font-size: 0.5em;
2712
+ vertical-align: super;
2713
+ }
2714
+
2715
+ :where(p, span).small {
2716
+ font-size: max(0.5em, var(--font-size-0, 0.75rem));
2717
+ }
2718
+
2719
+ :where(.cite) {
2720
+ font-style: italic;
2721
+ }
2722
+
2723
+ /* Code */
2724
+ :where(.kbd) {
2725
+ font-family: var(--font-mono);
2726
+ background-color: var(--text-muted);
2727
+ border-color: var(--text-muted);
2728
+ border-radius: var(--radius-2);
2729
+ border-width: var(--border-size-1);
2730
+ color: var(--text-muted-contrast);
2731
+ padding: 0.1ex 0.3ex;
2732
+ word-break: break-word;
2733
+ }
2734
+
2735
+ :where(.mark) {
2736
+ border-radius: var(--radius-2);
2737
+ box-decoration-break: clone;
2738
+ padding: .1ex .3ex;
2739
+ vertical-align: baseline;
2740
+ }
2741
+
2742
+ :where(.s) {
2743
+ text-decoration: line-through;
2744
+ }
2745
+
2746
+ :where(.sub) {
2747
+ font-size: 0.75em;
2748
+ vertical-align: sub;
2749
+ }
2750
+
2751
+ :where(.del) {
2752
+ color: var(--color-9);
2753
+ text-decoration: line-through;
2754
+ }
2755
+
2756
+ :where(.ins) {
2757
+ color: var(--color-9);
2758
+ text-decoration: underline;
2759
+ text-underline-offset: 1px;
2760
+ }
2761
+
2762
+ :where(.var) {
2763
+ font-family: var(--font-mono);
2764
+ background-color: var(--text-muted);
2765
+ border-color: var(--text-muted);
2766
+ border-radius: var(--radius-2);
2767
+ border-width: var(--border-size-1);
2768
+ color: var(--text-muted-contrast);
2769
+ padding: 0.1ex 0.3ex;
2770
+ word-break: break-word;
2771
+ }
2772
+
2773
+ :where(.samp) {
2774
+ font-family: var(--font-mono);
2775
+ }
2776
+
2777
+ /* Blockquote */
2778
+ :where(.blockquote) {
2779
+ border-inline-start: var(--border-size-3) solid currentColor;
2780
+ padding-block: var(--size-3);
2781
+ padding-inline: var(--size-4);
2782
+
2783
+ :first-child {
2784
+ margin-block-start: 0;
2785
+ }
2786
+
2787
+ :last-child {
2788
+ margin-block-end: 0;
2789
+ }
2790
+
2791
+ footer {
2792
+ color: var(--text-muted);
2793
+ margin-block-start: var(--size-3);
2794
+ }
2795
+ }
2796
+
2797
+ /* Code block */
2798
+ :where(pre.code-block) {
2799
+ background-color: var(--color-15);
2800
+ border-radius: var(--border-radius);
2801
+ color: var(--color-1);
2802
+ font-family: var(--font-mono);
2803
+ font-size: var(--font-size-05);
2804
+ max-inline-size: 100%;
2805
+ overflow-x: auto;
2806
+ padding-block: var(--size-3);
2807
+ padding-inline: var(--size-4);
2808
+ scrollbar-width: thin;
2809
+ white-space: pre;
2810
+
2811
+ >code {
2812
+ background: none;
2813
+ border-radius: 0;
2814
+ color: inherit;
2815
+ font-size: inherit;
2816
+ padding: 0;
2817
+ word-break: normal;
2818
+ writing-mode: inherit;
2819
+ }
2820
+ }
2821
+
2822
+ }
2823
+
2824
+ /* Rich text */
2825
+
2826
+ @layer components.extended {
2827
+ @scope (.rich-text) to (.not-rich-text) {
2828
+ a {
2829
+ color: var(--primary);
2830
+ cursor: pointer;
2831
+ font-size: inherit;
2832
+ font-weight: 700;
2833
+ line-height: inherit;
2834
+ text-decoration: underline;
2835
+ text-decoration-color: var(--primary);
2836
+ text-underline-offset: 2px;
2837
+
2838
+ &[href] {
2839
+
2840
+ &:hover,
2841
+ &:focus-visible {
2842
+ color: var(--primary-light);
2843
+ }
2844
+ }
2845
+ }
2846
+
2847
+ /* Blockquote */
2848
+ blockquote {
2849
+ border-inline-start: var(--border-size-3) solid currentColor;
2850
+ font-size: inherit;
2851
+ line-height: inherit;
2852
+ padding-block: var(--size-3);
2853
+ padding-inline: var(--size-4);
2854
+
2855
+ :first-child {
2856
+ margin-block-start: 0;
2857
+ }
2858
+
2859
+ :last-child {
2860
+ margin-block-end: 0;
2861
+ }
2862
+
2863
+ footer {
2864
+ color: var(--text-muted);
2865
+ margin-block-start: var(--size-3);
2866
+ }
2867
+ }
2868
+
2869
+ /* Code */
2870
+ pre {
2871
+ border-radius: var(--border-radius);
2872
+ font-size: var(--font-size-05);
2873
+ margin-block: var(--size-6);
2874
+ max-inline-size: max-content;
2875
+ min-inline-size: 0;
2876
+ padding-block: var(--size-3);
2877
+ padding-inline: var(--size-4);
2878
+ white-space: pre;
2879
+ }
2880
+
2881
+ pre:has(> code) {
2882
+ background-color: var(--color-15);
2883
+ border-radius: var(--border-radius);
2884
+ color: var(--color-1);
2885
+ max-inline-size: 100%;
2886
+ overflow-x: auto;
2887
+ scrollbar-width: thin;
2888
+
2889
+ >code {
2890
+ background: none;
2891
+ border-radius: 0;
2892
+ color: inherit;
2893
+ font-size: inherit;
2894
+ padding: 0;
2895
+ word-break: normal;
2896
+ writing-mode: inherit;
2897
+ }
2898
+ }
2899
+
2900
+
2901
+ /* Text */
2902
+ p {
2903
+ font-size: inherit;
2904
+ line-height: inherit;
2905
+ margin-block: 1.25em;
2906
+ text-wrap: pretty;
2907
+ }
2908
+
2909
+ :is(h1, h2, h3, h4, h5, h6) {
2910
+ color: var(--text-primary);
2911
+ font-weight: 700;
2912
+ text-wrap: pretty;
2913
+
2914
+ &+*:not(&) {
2915
+ margin-block-start: 0;
2916
+ }
2917
+ }
2918
+
2919
+ h1 {
2920
+ font-size: var(--font-size-h1, var(--font-size-7));
2921
+ letter-spacing: -0.02em;
2922
+ line-height: 1.1111111;
2923
+ margin-block: 0 0.8888889em;
2924
+ }
2925
+
2926
+ h2 {
2927
+ font-size: var(--font-size-h2, var(--font-size-5, 2rem));
2928
+ letter-spacing: -0.02em;
2929
+ line-height: 1.3333333;
2930
+ margin-block: 2em 1em;
2931
+ }
2932
+
2933
+ h3 {
2934
+ font-size: var(--font-size-h3, var(--font-size-4, 1.5rem));
2935
+ letter-spacing: -0.01em;
2936
+ line-height: 1.6;
2937
+ margin-block: 1.6em 0.6em;
2938
+ }
2939
+
2940
+ h4 {
2941
+ font-size: var(--font-size-h4, var(--font-size-3, 1.25rem));
2942
+ letter-spacing: -0.01em;
2943
+ line-height: 1.5;
2944
+ margin-block: 1.5em 0.5em;
2945
+ }
2946
+
2947
+ h5 {
2948
+ font-size: var(--font-size-h5, var(--font-size-2, 1.1rem));
2949
+ line-height: 1;
2950
+ margin-block: 0 var(--size-1);
2951
+ }
2952
+
2953
+ h6 {
2954
+ font-size: var(--font-size-h6, var(--font-size-1, 1rem));
2955
+ line-height: 1;
2956
+ margin-block: 0 var(--size-1);
2957
+ }
2958
+
2959
+ /** Overline */
2960
+ :is(.overline, hgroup p:first-of-type:first-child) {
2961
+ color: light-dark(oklch(from var(--text-muted) calc(l * 1.25) c h),
2962
+ oklch(from var(--text-muted) calc(l * 0.75) c h));
2963
+ font-size: var(--font-size-0);
2964
+ font-weight: 500;
2965
+ letter-spacing: 0.06em;
2966
+ text-transform: uppercase;
2967
+ }
2968
+
2969
+ hgroup {
2970
+ &>p {
2971
+ margin: 0;
2972
+ }
2973
+
2974
+ &> :where(h1, h2, h3, h4, h5, h6) {
2975
+ margin-block: 0 0.4em;
2976
+ }
2977
+
2978
+ &+* {
2979
+ margin-block-start: 3em;
2980
+ }
2981
+
2982
+ /* Body paragraphs after the heading */
2983
+ &>p:not(:first-of-type:first-child) {
2984
+ color: oklch(from currentColor l c h / 75%);
2985
+ font-size: var(--font-size-3);
2986
+ line-height: 1.6;
2987
+ }
2988
+
2989
+ &>p+p {
2990
+ margin-block-start: 0.75em;
2991
+ }
2992
+ }
2993
+
2994
+ /* Lists */
2995
+ ul:not([class]) {
2996
+ list-style-type: disc;
2997
+ }
2998
+
2999
+ ol:not([class]) {
3000
+ list-style-type: decimal;
3001
+ }
3002
+
3003
+ :where(ul, ol):not([class]) {
3004
+ display: grid;
3005
+ font-size: inherit;
3006
+ gap: 0.5em;
3007
+ line-height: inherit;
3008
+ margin-block-end: 1.25em;
3009
+ margin-block-start: 1.25em;
3010
+ padding-inline-start: 1.625em;
3011
+
3012
+ li {
3013
+ padding-inline-start: 0.375em;
3014
+ }
3015
+ }
3016
+
3017
+ /* Nested lists */
3018
+ :where(ul ul),
3019
+ :where(ul ol),
3020
+ :where(ol ul),
3021
+ :where(ol ol) {
3022
+ margin-block-end: 0.75em;
3023
+ margin-block-start: 0.75em;
3024
+ }
3025
+
3026
+ /* Description lists */
3027
+ :where(dl) {
3028
+ font-size: inherit;
3029
+ line-height: inherit;
3030
+ margin-block-end: 1.25em;
3031
+ margin-block-start: 1.25em;
3032
+
3033
+ dt {
3034
+ font-weight: 700;
3035
+ margin-block-start: 1.25em;
3036
+ }
3037
+
3038
+ dd {
3039
+ margin-block-start: 0.5em;
3040
+ padding-inline-start: 1.625em;
3041
+ }
3042
+ }
3043
+
3044
+ /* Figures */
3045
+ figure {
3046
+ display: grid;
3047
+ gap: var(--size-2);
3048
+ margin-block: var(--size-7);
3049
+ place-items: center;
3050
+
3051
+ &>* {
3052
+ margin-block: 0;
3053
+ }
3054
+
3055
+ & figcaption {
3056
+ font-size: var(--font-size-0);
3057
+ text-wrap: pretty;
3058
+ }
3059
+ }
3060
+
3061
+ /* Remove top margin from first child */
3062
+ &> :first-child {
3063
+ margin-block-start: 0;
3064
+ }
3065
+
3066
+ /* Remove bottom margin from last child */
3067
+ &> :last-child {
3068
+ margin-block-end: 0;
3069
+ }
3070
+
3071
+ /* Horizontal rules */
3072
+ hr {
3073
+ &+* {
3074
+ margin-block-start: 0;
3075
+ }
3076
+ }
3077
+
3078
+ /* Inline text elements */
3079
+ :where(ins, u, abbr, dfn) {
3080
+ text-decoration: underline;
3081
+ text-underline-offset: 1px;
3082
+
3083
+ @supports (-moz-appearance: none) {
3084
+ text-underline-offset: 2px;
3085
+ }
3086
+ }
3087
+
3088
+ :where(abbr, dfn) {
3089
+ font-style: normal;
3090
+ text-decoration: var(--color-9) underline dotted;
3091
+
3092
+ &[title] {
3093
+ cursor: help;
3094
+ text-underline-offset: 1px;
3095
+ }
3096
+
3097
+ @supports (-moz-appearance: none) {
3098
+ text-underline-offset: 2px;
3099
+ }
3100
+ }
3101
+
3102
+ sup {
3103
+ font-size: 0.5em;
3104
+ vertical-align: super;
3105
+ }
3106
+
3107
+ :where(del, ins) {
3108
+ color: var(--color-9);
3109
+ }
3110
+
3111
+ small {
3112
+ font-size: max(0.5em, var(--font-size-0, 0.75rem));
3113
+ }
3114
+
3115
+ cite {
3116
+ font-style: italic;
3117
+ }
3118
+
3119
+ /* Code */
3120
+ :where(code, kbd, samp, pre) {
3121
+ font-family: var(--font-mono);
3122
+ }
3123
+
3124
+ code {
3125
+ background-color: oklch(0 0 0 / 18%);
3126
+ border-radius: var(--border-size-3);
3127
+ font-size: 0.9em;
3128
+ padding: 0.1ex 0.3ex;
3129
+ }
3130
+
3131
+ :where(kbd, var) {
3132
+ background-color: var(--text-muted);
3133
+ border-color: var(--text-muted);
3134
+ border-radius: var(--radius-2);
3135
+ border-width: var(--border-size-1);
3136
+ color: var(--text-muted-contrast);
3137
+ padding: 0.1ex 0.3ex;
3138
+ }
3139
+
3140
+ :not(pre) code,
3141
+ kbd {
3142
+ word-break: break-word;
3143
+ }
3144
+
3145
+ :not(pre) code {
3146
+ border-radius: var(--border-radius, var(--radius-2));
3147
+ padding: 0.5ex;
3148
+ writing-mode: lr;
3149
+ }
3150
+
3151
+ mark {
3152
+ border-radius: var(--radius-2);
3153
+ box-decoration-break: clone;
3154
+ padding: .1ex .3ex;
3155
+ vertical-align: baseline;
3156
+ }
3157
+
3158
+ s {
3159
+ text-decoration: line-through;
3160
+ }
3161
+
3162
+ sub {
3163
+ font-size: 0.75em;
3164
+ vertical-align: sub;
3165
+ }
3166
+ }
3167
+ }
3168
+
3169
+ /*** Extended components (has dependencies) */
3170
+
3171
+ @layer components.extended {
3172
+ :where(.badge) {
3173
+ --_anchor-tx: -50%;
3174
+ --_anchor-ty: 50%;
3175
+ --_badge-inset: auto auto 100% 100%;
3176
+ --_bg-color: var(--primary);
3177
+ --_border-color: var(--primary);
3178
+ --_dot-size: var(--size-2);
3179
+ --_size: var(--size-4);
3180
+ --_text-color: var(--gray-1);
3181
+
3182
+ display: inline-flex;
3183
+ position: relative;
3184
+ vertical-align: middle;
3185
+
3186
+ /* Floating wrapper: traditional inset-based positioning so this works
3187
+ in browsers without position-area support (Firefox, older Safari). */
3188
+ &>.anchor-floating:not([popover]) {
3189
+ inset: var(--_badge-inset);
3190
+ position-anchor: auto;
3191
+ position-area: none;
3192
+ }
3193
+
3194
+ /* Indicator */
3195
+ &>.anchor-floating>.badge-indicator {
3196
+ background-color: var(--_bg-color);
3197
+ block-size: var(--_size);
3198
+ border: 2px solid var(--_border-color);
3199
+ border-radius: var(--radius-round);
3200
+ color: var(--_text-color);
3201
+ display: grid;
3202
+ font-size: 12px;
3203
+ font-weight: 500;
3204
+ inline-size: max-content;
3205
+ line-height: normal;
3206
+ min-inline-size: var(--_size);
3207
+ padding-inline: var(--size-1);
3208
+ place-items: center;
3209
+ text-align: center;
3210
+ transition: opacity 0.2s var(--ease-out-1);
3211
+ }
3212
+
3213
+ /* Colors */
3214
+ &.critical {
3215
+ --_bg-color: var(--critical);
3216
+ --_border-color: var(--critical);
3217
+ }
3218
+
3219
+ &.success {
3220
+ --_bg-color: var(--success);
3221
+ --_border-color: var(--success);
3222
+ }
3223
+
3224
+ &.info {
3225
+ --_bg-color: var(--info);
3226
+ --_border-color: var(--info);
3227
+ }
3228
+
3229
+ &.warning {
3230
+ --_bg-color: var(--warning);
3231
+ --_border-color: var(--warning);
3232
+ }
3233
+
3234
+ &.neutral {
3235
+ --_bg-color: var(--neutral);
3236
+ --_border-color: var(--neutral);
3237
+ }
3238
+
3239
+ /* Alignment */
3240
+ &.start-start {
3241
+ --_anchor-tx: 50%;
3242
+ --_anchor-ty: 50%;
3243
+ --_badge-inset: auto 100% 100% auto;
3244
+ }
3245
+
3246
+ &.end-start {
3247
+ --_anchor-tx: 50%;
3248
+ --_anchor-ty: -50%;
3249
+ --_badge-inset: 100% 100% auto auto;
3250
+ }
3251
+
3252
+ &.end-end {
3253
+ --_anchor-tx: -50%;
3254
+ --_anchor-ty: -50%;
3255
+ --_badge-inset: 100% auto auto 100%;
3256
+ }
3257
+
3258
+ /* Dot */
3259
+ &.dot {
3260
+ --_anchor-tx: calc((var(--_dot-size) - 2px) * -1);
3261
+ --_anchor-ty: var(--_dot-size);
3262
+ }
3263
+
3264
+ &.dot>.anchor-floating>.badge-indicator {
3265
+ block-size: var(--_dot-size);
3266
+ inline-size: var(--_dot-size);
3267
+ min-inline-size: var(--_dot-size);
3268
+ padding: 0;
3269
+ }
3270
+
3271
+ /* Visibility */
3272
+ &.invisible>.anchor-floating>.badge-indicator {
3273
+ opacity: 0;
3274
+ pointer-events: none;
3275
+ }
3276
+ }
3277
+ }
3278
+
3279
+ @layer components.extended {
3280
+ :where([role="group"].button-group) {
3281
+ --_border-radius: var(--button-border-radius);
3282
+
3283
+ border-radius: var(--_border-radius);
3284
+ display: inline-flex;
3285
+ min-width: max-content;
3286
+
3287
+ /* Button */
3288
+ button {
3289
+ border-radius: 0;
3290
+
3291
+ /* button.css > --_accent-tonal */
3292
+ --_divider-color: light-dark(oklch(from var(--_accent-tonal) calc(l - 0.1) c h),
3293
+ oklch(from var(--_accent-tonal) calc(l + 0.1) c h));
3294
+
3295
+ &.outlined {
3296
+ --_divider-color: var(--_border-color);
3297
+ }
3298
+
3299
+ &.filled {
3300
+ --_divider-color: currentColor;
3301
+ }
3302
+
3303
+ &:focus-visible {
3304
+ outline-offset: -4px;
3305
+ }
3306
+
3307
+ /* Color inheritance from Button Group — shared interaction model.
3308
+ The .critical scope class in theme.css redirects --palette-source so
3309
+ --color-6 below becomes a tint of the active color. */
3310
+ :where(.button-group.critical,
3311
+ .button-group.primary) & {
3312
+ --_color-contrast: var(--gray-1);
3313
+ --_color-tonal: var(--color-6);
3314
+ --_accent-tonal-contrast: var(--text-primary-contrast);
3315
+ --_default-hover-bg-color: oklch(from var(--_accent) l c h / 15%);
3316
+ --_default-active-bg-color: oklch(from var(--_accent) l c h / 25%);
3317
+ --_filled-hover-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
3318
+ --_filled-active-bg-color: oklch(from var(--_accent) calc(l - 0.15) c h);
3319
+ --_outlined-active-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
3320
+ }
3321
+
3322
+ :where(.button-group.critical) & {
3323
+ --_color: var(--critical);
3324
+ }
3325
+
3326
+ :where(.button-group.primary) & {
3327
+ --_color: var(--primary);
3328
+ }
3329
+
3330
+ :where(.button-group.small) & {
3331
+ --_min-height: 1.875rem;
3332
+ padding-block: 0;
3333
+ padding-inline: 1ex;
3334
+ }
3335
+
3336
+ :where(.button-group.large) & {
3337
+ --_min-height: 2.875rem;
3338
+ padding-inline: 4ex;
3339
+ }
3340
+
3341
+ :where(.button-group.outlined) & {
3342
+ --_border-color: var(--_accent);
3343
+ --_divider-color: var(--_accent);
3344
+
3345
+ &:where(:not([disabled])) {
3346
+ &:where(:not(:active):hover) {
3347
+ --_bg-color: var(--_accent);
3348
+ --_border-color: var(--_accent);
3349
+ --_text-color: var(--_accent-contrast);
3350
+ }
3351
+
3352
+ &:where(:active) {
3353
+ --_bg-color: var(--_outlined-active-bg-color);
3354
+ --_border-color: var(--_outlined-active-bg-color);
3355
+ --_text-color: var(--_accent-contrast);
3356
+ }
3357
+ }
3358
+ }
3359
+
3360
+ :where(.button-group.tonal) & {
3361
+ --_bg-color: var(--_accent-tonal);
3362
+ --_text-color: var(--_accent-tonal-contrast);
3363
+
3364
+ &:where(:not([disabled])) {
3365
+ &:where(:not(:active):hover) {
3366
+ --_bg-color: var(--_accent);
3367
+ --_text-color: var(--_accent-contrast);
3368
+ }
3369
+
3370
+ &:where(:active) {
3371
+ --_bg-color: var(--_outlined-active-bg-color);
3372
+ --_text-color: var(--_accent-contrast);
3373
+ }
3374
+ }
3375
+ }
3376
+
3377
+ :where(.button-group.filled) & {
3378
+ --_bg-color: var(--_accent);
3379
+ --_text-color: var(--_accent-contrast);
3380
+ --_divider-color: currentColor;
3381
+
3382
+ :where(.button-group.critical,
3383
+ .button-group.primary) & {
3384
+ --_divider-color: light-dark(oklch(from var(--_accent) calc(l - 0.1) c h),
3385
+ oklch(from var(--_accent) calc(l + 0.1) c h));
3386
+ }
3387
+
3388
+ &:where(:not([disabled])) {
3389
+ &:where(:not(:active):hover) {
3390
+ --_bg-color: var(--_filled-hover-bg-color);
3391
+ }
3392
+
3393
+ &:where(:active) {
3394
+ --_bg-color: var(--_filled-active-bg-color);
3395
+ }
3396
+ }
3397
+ }
3398
+ }
3399
+
3400
+ &:not(.vertical) {
3401
+ button {
3402
+ &:first-of-type {
3403
+ border-end-start-radius: var(--_border-radius);
3404
+ border-start-start-radius: var(--_border-radius);
3405
+ }
3406
+
3407
+ &:last-of-type {
3408
+ border-end-end-radius: var(--_border-radius);
3409
+ border-start-end-radius: var(--_border-radius);
3410
+ }
3411
+
3412
+ /* Siblings */
3413
+ &+& {
3414
+ border-inline-start-color: var(--_divider-color);
3415
+ border-inline-width: 1px;
3416
+ margin-inline-start: -1px;
3417
+
3418
+ &[disabled] {
3419
+ border-inline-start-color: color-mix(in oklch, var(--_divider-color) 40%, transparent);
3420
+ }
3421
+ }
3422
+ }
3423
+ }
3424
+
3425
+ &.vertical {
3426
+ flex-direction: column;
3427
+
3428
+ button {
3429
+ padding: var(--size-2);
3430
+
3431
+ &:has(svg) {
3432
+ aspect-ratio: 1;
3433
+ padding: var(--size-1);
3434
+ }
3435
+
3436
+ &:first-of-type {
3437
+ border-start-start-radius: var(--_border-radius);
3438
+ border-start-end-radius: var(--_border-radius);
3439
+ }
3440
+
3441
+ &:last-of-type {
3442
+ border-end-start-radius: var(--_border-radius);
3443
+ border-end-end-radius: var(--_border-radius);
3444
+ }
3445
+
3446
+ &+& {
3447
+ border-block-start: 1px solid var(--_divider-color);
3448
+ margin-block-start: -1px;
3449
+
3450
+ &[disabled] {
3451
+ border-block-start-color: color-mix(in oklch, var(--_divider-color) 40%, transparent);
3452
+ }
3453
+ }
3454
+ }
3455
+ }
3456
+ }
3457
+ }
3458
+
3459
+ @layer components.extended {
3460
+ :where(details.accordion) {
3461
+ --_actions-gap: var(--size-1);
3462
+ --_actions-margin-block-start: var(--size-3);
3463
+ --_actions-padding-block-end: var(--size-1);
3464
+ --_actions-padding-inline: var(--size-3) var(--size-1);
3465
+ --_bg-color: transparent;
3466
+ --_border-color: transparent;
3467
+ --_border-radius: var(--border-radius, 4px);
3468
+ --_border-width: 0;
3469
+ --_content-padding-block: var(--size-2) var(--size-3);
3470
+ --_content-padding-inline: var(--_padding-inline);
3471
+ --_margin-inline: var(--size-1);
3472
+ --_padding-inline: initial;
3473
+ --_shadow: none;
3474
+ --_summary-padding-block: var(--size-3);
3475
+ --_summary-padding-inline: var(--_padding-inline);
3476
+ --_svg-transition: 0.2s var(--ease-1);
3477
+ --_transition: 0.2s;
3478
+
3479
+ background-color: var(--_bg-color);
3480
+ border: var(--_border-width) solid var(--_border-color);
3481
+ border-radius: var(--_border-radius);
3482
+ box-shadow: var(--_shadow);
3483
+ display: block;
3484
+ margin-inline: var(--_margin-inline);
3485
+ transition: all var(--_transition) ease-out;
3486
+
3487
+ &.elevated {
3488
+ --_bg-color: var(--surface-elevated);
3489
+ --_margin-inline: 0;
3490
+ --_padding-inline: var(--size-3);
3491
+ --_shadow: var(--shadow-3);
3492
+ }
3493
+
3494
+ &.outlined {
3495
+ --_bg-color: var(--surface-default);
3496
+ --_border-color: var(--border-color);
3497
+ --_border-width: 1px;
3498
+ --_margin-inline: 0;
3499
+ --_padding-inline: var(--size-3);
3500
+ }
3501
+
3502
+ &.tonal {
3503
+ --_bg-color: var(--surface-tonal);
3504
+ --_margin-inline: 0;
3505
+ --_padding-inline: var(--size-3);
3506
+ }
3507
+
3508
+ /* Accordion animation */
3509
+ /* https://nerdy.dev/open-and-close-transitions-for-the-details-element */
3510
+ @media (prefers-reduced-motion: no-preference) {
3511
+ interpolate-size: allow-keywords;
3512
+ }
3513
+
3514
+ &::details-content {
3515
+ block-size: 0;
3516
+ opacity: 0;
3517
+ overflow-y: clip;
3518
+ transition:
3519
+ content-visibility var(--_transition) allow-discrete,
3520
+ opacity var(--_transition),
3521
+ block-size var(--_transition);
3522
+ }
3523
+
3524
+ &[open]::details-content {
3525
+ block-size: auto;
3526
+ opacity: 1;
3527
+ }
3528
+
3529
+ /* Layout */
3530
+ &>summary {
3531
+ background-color: inherit;
3532
+ cursor: pointer;
3533
+ font-weight: 700;
3534
+ padding-block: var(--_summary-padding-block);
3535
+ padding-inline: var(--_summary-padding-inline);
3536
+ user-select: none;
3537
+
3538
+ &:has(svg) {
3539
+ align-items: center;
3540
+ display: flex;
3541
+ justify-content: space-between;
3542
+ list-style: none;
3543
+
3544
+ &::marker,
3545
+ &::-webkit-details-marker {
3546
+ display: none;
3547
+ }
3548
+ }
3549
+
3550
+ svg {
3551
+ transition: rotate var(--_svg-transition);
3552
+ }
3553
+ }
3554
+
3555
+ &[open]>summary svg {
3556
+ rotate: 180deg;
3557
+ }
3558
+
3559
+ &>.content {
3560
+ margin-block-start: 0;
3561
+ padding-block: var(--_content-padding-block);
3562
+ padding-inline: var(--_content-padding-inline);
3563
+ }
3564
+
3565
+ &>.actions {
3566
+ display: flex;
3567
+ gap: var(--_actions-gap);
3568
+ justify-content: end;
3569
+ margin-block-start: var(--_actions-margin-block-start);
3570
+ padding-block-end: var(--_actions-padding-block-end);
3571
+ padding-inline: var(--_actions-padding-inline);
3572
+ }
3573
+ }
3574
+
3575
+ /* Accordion group */
3576
+ :where(.card[role="group"]:has(details.accordion)) {
3577
+ --_group-radius: var(--border-radius);
3578
+ --_gutter-color: var(--border-color);
3579
+ --_item-padding-inline: var(--size-3);
3580
+ --_item-summary-padding-inline: var(--_item-padding-inline);
3581
+
3582
+ display: block;
3583
+
3584
+ &.card {
3585
+ &:not(.tonal, .outlined, .elevated) {
3586
+ --_item-summary-padding-inline: 0;
3587
+ }
3588
+ }
3589
+
3590
+ &>.content {
3591
+ margin-block: 0;
3592
+ padding: 0;
3593
+ }
3594
+
3595
+ &>details.accordion {
3596
+ --_border-color: transparent;
3597
+ --_border-width: 0;
3598
+ --_margin-inline: 0;
3599
+ --_padding-inline: var(--_item-padding-inline);
3600
+ --_shadow: none;
3601
+ --_summary-padding-inline: var(--_item-summary-padding-inline);
3602
+
3603
+ /* Border between accordion items */
3604
+ &+& {
3605
+ border-block-start: 1px solid var(--_gutter-color);
3606
+ border-radius: 0;
3607
+ }
3608
+
3609
+ /* First item */
3610
+ &:first-of-type {
3611
+ border-start-end-radius: var(--_group-radius);
3612
+ border-start-start-radius: var(--_group-radius);
3613
+
3614
+ summary {
3615
+ border-start-end-radius: var(--_group-radius);
3616
+ border-start-start-radius: var(--_group-radius);
3617
+ }
3618
+ }
3619
+
3620
+ /* Last item */
3621
+ &:last-of-type {
3622
+ border-end-end-radius: var(--_group-radius);
3623
+ border-end-start-radius: var(--_group-radius);
3624
+
3625
+ summary {
3626
+ border-end-end-radius: var(--_group-radius);
3627
+ border-end-start-radius: var(--_group-radius);
3628
+ }
3629
+ }
3630
+ }
3631
+ }
3632
+ }
3633
+
3634
+ @layer components.extended {
3635
+
3636
+ /*
3637
+ Lists meant to be used stand-alone or as part of Select elements
3638
+
3639
+ Intended use-case:
3640
+ - ul.list > li
3641
+ - .select > .list > option
3642
+ */
3643
+ :where(.list) {
3644
+ --_bg-color: var(--surface-filled);
3645
+ --_bg-color-hover: oklch(from var(--primary) l c h / 15%);
3646
+
3647
+ background-color: var(--_bg-color);
3648
+ color: var(--text-primary);
3649
+ list-style: none;
3650
+ padding: var(--size-2) 0;
3651
+
3652
+ @media (pointer: coarse) {
3653
+
3654
+ &,
3655
+ * {
3656
+ user-select: none;
3657
+ }
3658
+ }
3659
+
3660
+ /* Background color */
3661
+ &.transparent {
3662
+ --_bg-color: transparent;
3663
+ }
3664
+
3665
+ &.default {
3666
+ --_bg-color: var(--surface-default);
3667
+ }
3668
+
3669
+ &.tonal {
3670
+ --_bg-color: var(--surface-tonal);
3671
+ }
3672
+
3673
+ /* Borders on all list items */
3674
+ &.bordered {
3675
+ :where(li + li, option + option) {
3676
+ margin-block-start: var(--size-3);
3677
+
3678
+ &::before {
3679
+ block-size: 1px;
3680
+ border-block-start: 1px solid var(--border-color);
3681
+ content: "";
3682
+ display: block;
3683
+ inline-size: 100%;
3684
+ inset: calc(-1 * var(--size-2)) 0 auto 0;
3685
+ position: absolute;
3686
+ visibility: visible;
3687
+ /* override select > option:before style */
3688
+ }
3689
+ }
3690
+ }
3691
+
3692
+ /* Dense - less gaps and spacing */
3693
+ &.dense {
3694
+ :where(li, option) {
3695
+ gap: var(--size-2);
3696
+ min-block-size: var(--size-7);
3697
+ padding: var(--size-1) var(--size-2);
3698
+
3699
+ &.border-top {
3700
+ margin-block-start: var(--size-2);
3701
+
3702
+ &::before {
3703
+ inset: calc(-1 * var(--size-1)) 0 auto 0;
3704
+ }
3705
+ }
3706
+
3707
+ /* Clickable list item */
3708
+ &:has(> a, > button, > label) {
3709
+ min-block-size: auto;
3710
+ padding: 0;
3711
+ }
3712
+
3713
+ &> :where(a, button, label) {
3714
+ gap: var(--size-2);
3715
+ min-block-size: var(--size-7);
3716
+ padding: var(--size-1) var(--size-2);
3717
+ }
3718
+
3719
+ /* Checkbox / Radio */
3720
+ &>label {
3721
+ .end {
3722
+ padding-inline-end: 0.125rem;
3723
+ }
3724
+
3725
+ &:where(.checkbox, .radio) {
3726
+ --_input-size: var(--size-3);
3727
+ }
3728
+ }
3729
+
3730
+ /* Leading and trailing content */
3731
+ .start,
3732
+ .end {
3733
+ .avatar {
3734
+ max-inline-size: var(--size-6);
3735
+ }
3736
+
3737
+ .icon-button,
3738
+ svg {
3739
+ max-inline-size: var(--size-4);
3740
+ }
3741
+
3742
+ .checkbox,
3743
+ .radio {
3744
+ --_input-size: var(--size-3);
3745
+ }
3746
+ }
3747
+ }
3748
+ }
3749
+
3750
+ /* Gutterless */
3751
+ &.gutterless {
3752
+ :where(li, option) {
3753
+ padding-inline: 0;
3754
+
3755
+ &> :where(a, button, label) {
3756
+ padding-inline: 0;
3757
+ }
3758
+ }
3759
+ }
3760
+
3761
+ /* List item */
3762
+ :where(li, option, [role="group"] > label) {
3763
+ align-items: center;
3764
+ background-color: var(--_bg-color);
3765
+ display: flex;
3766
+ font-size: var(--font-size-05);
3767
+ gap: var(--size-3);
3768
+ isolation: isolate;
3769
+ min-block-size: 40px;
3770
+ padding: var(--size-2) var(--size-3);
3771
+ position: relative;
3772
+
3773
+ &::before {
3774
+ display: none;
3775
+ /* removing checkmark from option */
3776
+ }
3777
+
3778
+ * {
3779
+ font-size: inherit;
3780
+ }
3781
+
3782
+ /* Clickable list item */
3783
+ &:has(> a, > button, > label) {
3784
+ background: transparent;
3785
+ display: block;
3786
+ min-block-size: auto;
3787
+ padding: 0;
3788
+
3789
+ &[aria-selected="true"]> :where(a, button, label),
3790
+ &[aria-selected="true"],
3791
+ &:has(> [aria-current="page"])> :where(a, button, label) {
3792
+ background-color: var(--_bg-color-hover);
3793
+ }
3794
+ }
3795
+
3796
+ /* Select option */
3797
+ &:where(option) {
3798
+ align-items: center;
3799
+ background-color: var(--_bg-color);
3800
+ color: inherit;
3801
+ cursor: pointer;
3802
+ display: flex;
3803
+ gap: var(--size-3);
3804
+ inline-size: 100%;
3805
+ margin: 0;
3806
+ min-block-size: 40px;
3807
+ padding: var(--size-2) var(--size-3);
3808
+ text-align: start;
3809
+ text-decoration: none;
3810
+ z-index: 0;
3811
+
3812
+ &:hover {
3813
+ background-color: var(--_bg-color-hover);
3814
+ }
3815
+
3816
+ &[aria-selected="true"] {
3817
+ background-color: var(--_bg-color-hover);
3818
+ color: var(--primary);
3819
+ }
3820
+
3821
+ &:checked {
3822
+ background-color: oklch(from var(--primary) l c h / 30%);
3823
+ }
3824
+ }
3825
+
3826
+ &>a,
3827
+ &>button,
3828
+ &>label {
3829
+ align-items: center;
3830
+ background-color: var(--_bg-color);
3831
+ color: inherit;
3832
+ cursor: pointer;
3833
+ display: flex;
3834
+ gap: var(--size-3);
3835
+ inline-size: 100%;
3836
+ margin: 0;
3837
+ min-block-size: 40px;
3838
+ outline-offset: -3px;
3839
+ padding: var(--size-2) var(--size-3);
3840
+ text-align: start;
3841
+ text-decoration: none;
3842
+ z-index: 0;
3843
+
3844
+ &:hover {
3845
+ background-color: var(--_bg-color-hover);
3846
+ }
3847
+
3848
+ &[aria-selected="true"],
3849
+ &[aria-current="page"] {
3850
+ background-color: var(--_bg-color-hover);
3851
+ }
3852
+ }
3853
+
3854
+ /* Checkbox / Radio / Switch */
3855
+ &>label {
3856
+ &:where(.checkbox, .radio, .switch) {
3857
+ display: flex;
3858
+ }
3859
+
3860
+ .end {
3861
+ padding-inline-end: var(--size-1);
3862
+ }
3863
+
3864
+ &:where(.checkbox, .radio) {
3865
+ inline-size: 100%;
3866
+ }
3867
+
3868
+ /* Switches look comically big in lists, so it's better to use a smaller variant */
3869
+ &.switch {
3870
+ --_dot-size: 0.75rem;
3871
+ --_track-height: var(--size-4);
3872
+ --_track-width: 2.5rem;
3873
+ }
3874
+ }
3875
+
3876
+ /* Video */
3877
+ &:has(video) {
3878
+ padding: 0.75rem var(--size-3) 0.75rem 0;
3879
+ }
3880
+
3881
+ /* Border between list items */
3882
+ &.border-top {
3883
+ margin-block-start: var(--size-3);
3884
+
3885
+ &::before {
3886
+ block-size: 1px;
3887
+ border-block-start: 1px solid var(--border-color);
3888
+ content: "";
3889
+ display: block;
3890
+ inline-size: 100%;
3891
+ inset: calc(-1 * var(--size-2)) 0 auto 0;
3892
+ position: absolute;
3893
+ }
3894
+ }
3895
+
3896
+ /* Text */
3897
+ .text {
3898
+ flex: 1;
3899
+ line-height: 1.6;
3900
+
3901
+ :where(h1, h2, h3, h4, h5, h6, p, span) {
3902
+ color: inherit;
3903
+ font-weight: 400;
3904
+ }
3905
+
3906
+ p+p {
3907
+ color: var(--text-muted);
3908
+ font-size: var(--font-size-0);
3909
+ }
3910
+ }
3911
+
3912
+ /* Leading content */
3913
+ .start {
3914
+ align-items: center;
3915
+ align-self: center;
3916
+ display: grid;
3917
+ z-index: 1;
3918
+
3919
+ &:has(svg) {
3920
+ max-inline-size: var(--size-5);
3921
+ }
3922
+
3923
+ svg {
3924
+ padding-block-start: 0.125rem;
3925
+ }
3926
+
3927
+ img {
3928
+ aspect-ratio: 1;
3929
+ inline-size: 56px;
3930
+ object-fit: cover;
3931
+ }
3932
+
3933
+ video {
3934
+ aspect-ratio: 16/9;
3935
+ block-size: 64px;
3936
+ object-fit: cover;
3937
+ }
3938
+ }
3939
+
3940
+ /* Trailing content */
3941
+ .end {
3942
+ align-items: center;
3943
+ display: flex;
3944
+ font-size: var(--font-size-0);
3945
+ text-align: end;
3946
+ z-index: 1;
3947
+
3948
+ &:not(:has(a, button, input)) {
3949
+ pointer-events: none;
3950
+ }
3951
+
3952
+ kbd {
3953
+ background-color: transparent;
3954
+ border: 0;
3955
+ color: inherit;
3956
+ opacity: 0.6;
3957
+ }
3958
+
3959
+ svg {
3960
+ inline-size: 100%;
3961
+ max-inline-size: var(--size-5);
3962
+ }
3963
+ }
3964
+
3965
+ /* Inset */
3966
+ &.inset {
3967
+ .text {
3968
+ padding-inline-start: calc(var(--size-5) + var(--size-3));
3969
+ }
3970
+
3971
+ /* Safety measure so it won't look bad if there for some reason should exist a leading element inside. */
3972
+ .start {
3973
+ display: none;
3974
+ }
3975
+ }
3976
+ }
3977
+ }
3978
+ }
3979
+
3980
+ @layer components.extended {
3981
+ :where(.dialog) {
3982
+ inline-size: 100%;
3983
+ inset: 0;
3984
+ margin: auto;
3985
+ margin-block-start: 15%;
3986
+ max-inline-size: calc(100% - var(--size-4));
3987
+ padding-block: 0;
3988
+ pointer-events: none;
3989
+ position: fixed;
3990
+
3991
+ @media (width > 600px) {
3992
+ max-inline-size: 60ch;
3993
+ }
3994
+
3995
+ /* Animation */
3996
+ /* There's no close animation, intentionally */
3997
+ opacity: 0;
3998
+
3999
+ &::backdrop {
4000
+ backdrop-filter: blur(1px);
4001
+ background-color: rgba(0, 0, 0, 0.5);
4002
+
4003
+ @media (prefers-reduced-motion: reduce) {
4004
+ backdrop-filter: none;
4005
+ }
4006
+ }
4007
+
4008
+ &:not([open]) {
4009
+ display: none;
4010
+ }
4011
+
4012
+ &[open] {
4013
+ pointer-events: all;
4014
+ }
4015
+
4016
+ .actions {
4017
+ justify-content: end;
4018
+ padding-inline: var(--size-3) var(--size-1);
4019
+ }
4020
+
4021
+ &[open] {
4022
+ opacity: 1;
4023
+ transition: display 0.2s allow-discrete,
4024
+ overlay 0.2s allow-discrete,
4025
+ opacity 0.2s var(--ease-out-1);
4026
+
4027
+ @starting-style {
4028
+ opacity: 0;
4029
+ }
4030
+ }
4031
+
4032
+ @media (prefers-reduced-motion: no-preference) {
4033
+ &[open] {
4034
+ margin-block-start: 15%;
4035
+
4036
+ @starting-style {
4037
+ opacity: 0;
4038
+ }
4039
+ }
4040
+ }
4041
+ }
4042
+
4043
+ :where(html:has(.dialog[open])) {
4044
+ block-size: 100%;
4045
+ overflow: hidden;
4046
+ }
4047
+ }
4048
+
4049
+ @layer components.root {
4050
+ :where(dialog.drawer) {
4051
+ --_backdrop-bg-color: transparent;
4052
+ --_backdrop-blur: blur(2px);
4053
+ --_bg-color: var(--surface-default);
4054
+ --_block-size: min(80vb, 650px);
4055
+ --_border-color: var(--border-color);
4056
+ --_border-width: var(--border-width);
4057
+ --_color: var(--text-primary);
4058
+ --_content-padding: var(--size-4);
4059
+ --_footer-gap: var(--size-3);
4060
+ --_footer-padding: var(--size-3);
4061
+ --_header-font-size: var(--font-size-3);
4062
+ --_header-padding: var(--size-3);
4063
+ --_inline-size: min(375px, 100vi);
4064
+ --_shadow: var(--shadow-2);
4065
+ --_transition-duration: 0.2s;
4066
+ --_transition-timing: var(--ease-out-3);
4067
+
4068
+ background-color: var(--_bg-color);
4069
+ border: none;
4070
+ box-shadow: var(--_shadow);
4071
+ color: var(--_color);
4072
+ display: flex;
4073
+ flex-direction: column;
4074
+ margin: 0;
4075
+ max-inline-size: 100%;
4076
+ padding: 0;
4077
+ position: fixed;
4078
+ transition:
4079
+ display var(--_transition-duration) allow-discrete,
4080
+ overlay var(--_transition-duration) allow-discrete,
4081
+ translate var(--_transition-duration) var(--_transition-timing);
4082
+ z-index: 1000;
4083
+
4084
+ &::backdrop {
4085
+ backdrop-filter: var(--_backdrop-blur);
4086
+ background-color: var(--_backdrop-bg-color);
4087
+ opacity: 0;
4088
+ transition:
4089
+ display var(--_transition-duration) allow-discrete,
4090
+ overlay var(--_transition-duration) allow-discrete,
4091
+ opacity var(--_transition-duration) var(--_transition-timing);
4092
+ }
4093
+
4094
+ &.backdrop-transparent {
4095
+ --_backdrop-blur: none;
4096
+ }
4097
+
4098
+ .header {
4099
+ align-items: center;
4100
+ border-block-end: var(--_border-width) solid var(--_border-color);
4101
+ display: flex;
4102
+ padding: var(--_header-padding);
4103
+
4104
+ :where(h1, h2, h3, h4, h5, h6) {
4105
+ font-size: var(--_header-font-size);
4106
+ margin: 0;
4107
+ }
4108
+
4109
+ :where(.icon-button) {
4110
+ margin-inline-start: auto;
4111
+ }
4112
+ }
4113
+
4114
+ .content {
4115
+ flex: 1;
4116
+ overflow-y: auto;
4117
+ padding: var(--_content-padding);
4118
+ }
4119
+
4120
+ .footer {
4121
+ border-block-start: var(--_border-width) solid var(--_border-color);
4122
+ display: flex;
4123
+ gap: var(--_footer-gap);
4124
+ justify-content: end;
4125
+ padding: var(--_footer-padding);
4126
+ }
4127
+
4128
+ &.inline-start,
4129
+ &.inline-end {
4130
+ block-size: 100dvb;
4131
+ inline-size: var(--_inline-size);
4132
+ inset-block: 0;
4133
+ max-block-size: 100%;
4134
+ }
4135
+
4136
+ &.inline-start {
4137
+ border-inline-end: var(--_border-width) solid var(--_border-color);
4138
+ inset-inline-end: auto;
4139
+ inset-inline-start: 0;
4140
+ translate: -100% 0;
4141
+ }
4142
+
4143
+ &.inline-end {
4144
+ border-inline-start: var(--_border-width) solid var(--_border-color);
4145
+ inset-inline-end: 0;
4146
+ inset-inline-start: auto;
4147
+ translate: 100% 0;
4148
+
4149
+ .footer {
4150
+ justify-content: start;
4151
+ }
4152
+ }
4153
+
4154
+ &.block-start,
4155
+ &.block-end {
4156
+ block-size: var(--_block-size);
4157
+ inline-size: 100dvi;
4158
+ inset-inline: 0;
4159
+ max-block-size: 80dvb;
4160
+ }
4161
+
4162
+ &.block-start {
4163
+ border-block-end: var(--_border-width) solid var(--_border-color);
4164
+ inset-block-end: auto;
4165
+ inset-block-start: 0;
4166
+ translate: 0 -100%;
4167
+ }
4168
+
4169
+ &.block-end {
4170
+ border-block-start: var(--_border-width) solid var(--_border-color);
4171
+ inset-block-end: 0;
4172
+ inset-block-start: auto;
4173
+ translate: 0 100%;
4174
+ }
4175
+
4176
+ &[open] {
4177
+ translate: 0 0;
4178
+
4179
+ &::backdrop {
4180
+ opacity: 1;
4181
+ }
4182
+
4183
+ @starting-style {
4184
+ &::backdrop {
4185
+ opacity: 0;
4186
+ }
4187
+
4188
+ &.inline-start {
4189
+ translate: -100% 0;
4190
+ }
4191
+
4192
+ &.inline-end {
4193
+ translate: 100% 0;
4194
+ }
4195
+
4196
+ &.block-start {
4197
+ translate: 0 -100%;
4198
+ }
4199
+
4200
+ &.block-end {
4201
+ translate: 0 100%;
4202
+ }
4203
+ }
4204
+ }
4205
+ }
4206
+
4207
+ /* Scroll-lock is provided by the shared `.scroll-lock` utility in core/utils.css.
4208
+ This carve-out re-enables page scrolling when a transparent-backdrop drawer is
4209
+ open on wide viewports (where the drawer doesn't visually cover the page). */
4210
+ html:has(dialog.drawer.scroll-lock[open].backdrop-transparent) {
4211
+ overflow: unset;
4212
+ overscroll-behavior: auto;
4213
+
4214
+ @media (width < 500px) {
4215
+ overflow: clip;
4216
+ overscroll-behavior: contain;
4217
+ }
4218
+ }
4219
+ }
4220
+
4221
+ @layer components.extended {
4222
+
4223
+ /* Form */
4224
+ :where(.form) {
4225
+ display: grid;
4226
+ gap: var(--size-8);
4227
+
4228
+ hr {
4229
+ margin-block: 0;
4230
+ }
4231
+ }
4232
+
4233
+ /* Fieldset */
4234
+ :where(.fieldset) {
4235
+ all: unset;
4236
+ border: 0;
4237
+ border-radius: 0;
4238
+ display: grid;
4239
+ gap: var(--size-1);
4240
+ margin: 0;
4241
+ min-inline-size: 0;
4242
+ padding: 0;
4243
+
4244
+ /* Legend */
4245
+ :where(legend, .legend) {
4246
+ all: unset;
4247
+ color: var(--text-primary);
4248
+ font-weight: 600;
4249
+ margin-block-end: var(--size-3);
4250
+ padding: 0;
4251
+
4252
+ &:has(+ :where(.field-description)) {
4253
+ margin-block-end: 0;
4254
+ }
4255
+ }
4256
+
4257
+ /* Field description / supporting text */
4258
+ :where(.field-description) {
4259
+ color: var(--text-muted);
4260
+ font-size: var(--font-size-05);
4261
+ line-height: var(--font-lineheight-3);
4262
+
4263
+ &:has(+ *) {
4264
+ margin-block-end: var(--size-3);
4265
+ }
4266
+ }
4267
+
4268
+ /* End text */
4269
+ :where(.end-text) {
4270
+ color: var(--text-muted);
4271
+ font-size: var(--font-size-0);
4272
+ line-height: var(--font-lineheight-3);
4273
+ }
4274
+
4275
+ &:has(.text-field.row) {
4276
+ row-gap: var(--size-7);
4277
+ }
4278
+
4279
+ /* Disabled */
4280
+ &[disabled] {
4281
+ opacity: 0.64;
4282
+ user-select: none;
4283
+
4284
+ input,
4285
+ label,
4286
+ .label {
4287
+ cursor: not-allowed;
4288
+ }
4289
+ }
4290
+
4291
+ /* Error / validation */
4292
+ &[data-invalid] {
4293
+ :where(.end-text) {
4294
+ color: var(--primary);
4295
+ }
4296
+
4297
+ :where(.checkbox, .radio, .switch) {
4298
+ --palette-source: oklch(0.58 0.21 var(--hue-red));
4299
+
4300
+ :where(.end-text) {
4301
+ color: var(--primary);
4302
+ }
4303
+ }
4304
+
4305
+ :where(.switch) {
4306
+ input {
4307
+ border-radius: var(--radius-round);
4308
+ outline: 2px solid var(--primary);
4309
+ }
4310
+ }
4311
+ }
4312
+
4313
+ /* Required */
4314
+ &:has(:invalid) {
4315
+ :where(legend, .legend) {
4316
+ padding-inline-end: 1ex;
4317
+ position: relative;
4318
+
4319
+ &::after {
4320
+ color: var(--red);
4321
+ content: "*";
4322
+ inset: 0 -0.25ex auto auto;
4323
+ position: absolute;
4324
+ }
4325
+ }
4326
+ }
4327
+ }
4328
+
4329
+ /* Field group */
4330
+ :where(.field-group) {
4331
+ display: flex;
4332
+ flex-direction: column;
4333
+ gap: var(--size-4);
4334
+
4335
+ /* If it only has checkboxes, radios, or switches */
4336
+ &:has(> :where(.checkbox, .radio, .switch)):not(:has(> :not(.checkbox, .radio, .switch))) {
4337
+ gap: var(--size-2);
4338
+ }
4339
+
4340
+ /* If it only has buttons */
4341
+ &:has(.button):not(:has(*:not(.button))) {
4342
+ align-items: center;
4343
+ flex-direction: row;
4344
+ gap: var(--size-2);
4345
+
4346
+ /* If it's not preceeded by an hr */
4347
+ &:not(hr + &) {
4348
+ margin-block-start: var(--size-4);
4349
+ }
4350
+ }
4351
+
4352
+ &+& {
4353
+ margin-block-start: var(--size-5);
4354
+ }
4355
+
4356
+ /* Directions */
4357
+ &.row {
4358
+ flex-direction: row;
4359
+ flex-wrap: wrap;
4360
+
4361
+ &:has(> :where(.checkbox, .radio, .switch)) {
4362
+ gap: var(--size-4);
4363
+ }
4364
+ }
4365
+ }
4366
+ }
4367
+
4368
+ @layer components.extended {
4369
+
4370
+ /*
4371
+ - Common styling for input, textarea and select
4372
+ - Form related styles such as: label, supporting text, error handling
4373
+ */
4374
+ :where(.text-field, .textarea, .select) {
4375
+ --_accent-color: var(--primary);
4376
+ --_bg-color: var(--surface-default);
4377
+ --_border-color: var(--field-border-color);
4378
+ --_field-padding-block: var(--size-2);
4379
+ --_field-padding-inline: var(--size-2);
4380
+ --_filled-border-color: var(--text-primary);
4381
+ --_height: var(--field-size);
4382
+ --_label-color: var(--text-muted);
4383
+ --_end-text-color: var(--text-muted);
4384
+
4385
+ display: grid;
4386
+ gap: var(--size-1) 0;
4387
+ position: relative;
4388
+
4389
+ /* Field - the actual input with a border around it */
4390
+ .field {
4391
+ background-color: var(--_bg-color);
4392
+ border: var(--field-border-width) solid var(--_border-color);
4393
+ border-radius: var(--field-border-radius);
4394
+ display: grid;
4395
+ grid-column: 1/-1;
4396
+ grid-row: 2;
4397
+ grid-template-columns: auto 1fr auto;
4398
+ grid-template-areas:
4399
+ "header header header"
4400
+ "prefix input suffix"
4401
+ "footer footer footer";
4402
+ min-block-size: var(--_height);
4403
+
4404
+ @media (prefers-reduced-motion: no-preference) {
4405
+ transition: border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
4406
+ }
4407
+ }
4408
+
4409
+ :where(.field input, .field textarea, .field select) {
4410
+ background: transparent;
4411
+ border: 0;
4412
+ color: var(--text-primary);
4413
+ font-family: var(--font-sans);
4414
+ font-size: var(--font-size-1);
4415
+ grid-area: input;
4416
+ inline-size: 100%;
4417
+ line-height: var(--font-lineheight-1);
4418
+ min-inline-size: 0;
4419
+ padding: var(--_field-padding-block) var(--_field-padding-inline);
4420
+
4421
+ &:focus,
4422
+ &:focus-visible {
4423
+ outline: 0;
4424
+ }
4425
+ }
4426
+
4427
+ /* Affixes */
4428
+ .prefix,
4429
+ .suffix {
4430
+ align-items: center;
4431
+ color: var(--_label-color);
4432
+ display: inline-flex;
4433
+ padding-inline: var(--_field-padding-inline);
4434
+ white-space: nowrap;
4435
+ }
4436
+
4437
+ .prefix {
4438
+ grid-area: prefix;
4439
+ }
4440
+
4441
+ .suffix {
4442
+ grid-area: suffix;
4443
+ }
4444
+
4445
+ .header,
4446
+ .footer {
4447
+ align-items: center;
4448
+ color: var(--_label-color);
4449
+ display: flex;
4450
+ font-size: var(--font-size-0);
4451
+ gap: var(--size-2);
4452
+ padding: var(--size-1) var(--_field-padding-inline);
4453
+ }
4454
+
4455
+ .header {
4456
+ border-block-end: 1px solid var(--_border-color);
4457
+ grid-area: header;
4458
+ }
4459
+
4460
+ .footer {
4461
+ border-block-start: 1px solid var(--_border-color);
4462
+ grid-area: footer;
4463
+ }
4464
+
4465
+ /* Remove padding on the input when affixes are next to it */
4466
+ .field:has(> .prefix) :where(input, textarea, select) {
4467
+ padding-inline-start: 0;
4468
+ }
4469
+
4470
+ .field:has(> .suffix) :where(input, textarea, select) {
4471
+ padding-inline-end: 0;
4472
+ }
4473
+
4474
+ /* Textarea - keep affix aligned with the first line */
4475
+ &.textarea .field {
4476
+
4477
+ .prefix,
4478
+ .suffix {
4479
+ align-self: start;
4480
+ padding-block: var(--_field-padding-block);
4481
+ }
4482
+ }
4483
+
4484
+ /* Required/Invalid */
4485
+ &:has(:invalid) {
4486
+ .label:after {
4487
+ color: var(--red);
4488
+ content: "*";
4489
+ margin: -0.25em auto auto 0.25em;
4490
+ }
4491
+ }
4492
+
4493
+ /* File */
4494
+ &:has(input[type="file"]) {
4495
+ cursor: pointer;
4496
+
4497
+ input {
4498
+ align-self: flex-start;
4499
+ block-size: var(--_height);
4500
+ box-shadow: none;
4501
+ color: var(--text-primary);
4502
+ cursor: inherit;
4503
+ max-inline-size: 100%;
4504
+ padding: 0;
4505
+ transition: font-size 0.2s var(--ease-3);
4506
+
4507
+ &::-webkit-file-upload-button,
4508
+ &::file-selector-button {
4509
+ background-color: var(--surface-tonal);
4510
+ block-size: calc(100% - var(--size-2) * 2);
4511
+ border: none;
4512
+ border-radius: var(--field-border-radius);
4513
+ cursor: pointer;
4514
+ margin-block-start: var(--size-2);
4515
+ margin-inline-end: 1ex;
4516
+ margin-inline-start: var(--size-2);
4517
+ }
4518
+ }
4519
+
4520
+ /* Variants */
4521
+ &.filled {
4522
+ input {
4523
+
4524
+ &::-webkit-file-upload-button,
4525
+ &::file-selector-button {
4526
+ background-color: var(--surface-default);
4527
+ block-size: calc(100% - var(--size-2) * 2);
4528
+ border-radius: var(--field-border-radius);
4529
+ cursor: pointer;
4530
+ margin-block-start: var(--size-2);
4531
+ }
4532
+ }
4533
+ }
4534
+
4535
+ /* Sizes */
4536
+ &.small {
4537
+ input {
4538
+ font-size: var(--font-size-05);
4539
+
4540
+ &::-webkit-file-upload-button,
4541
+ &::file-selector-button {
4542
+ block-size: calc(100% - var(--size-2));
4543
+ margin-block-start: var(--size-1);
4544
+ }
4545
+ }
4546
+ }
4547
+ }
4548
+
4549
+ /* Autosuggest */
4550
+ &:has(input[list]) {
4551
+ .label {
4552
+ /* Make sure chevron is visible */
4553
+ inline-size: calc(100% - var(--size-6));
4554
+ }
4555
+ }
4556
+
4557
+ /* Select */
4558
+ &:has(select) {
4559
+ .label {
4560
+ /* Make sure chevron is visible */
4561
+ inline-size: calc(100% - var(--size-6));
4562
+
4563
+ }
4564
+ }
4565
+
4566
+ /* Customizable Select */
4567
+ &:has(select button) {
4568
+ select {
4569
+ padding: 0;
4570
+
4571
+ button {
4572
+ outline: 0;
4573
+ padding: var(--_field-padding-block) var(--size-8) var(--_field-padding-block) var(--_field-padding-inline);
4574
+ }
4575
+ }
4576
+ }
4577
+
4578
+ /* Non-customizable Select */
4579
+ &:has(select):not(:has(button)) {
4580
+ select {
4581
+ padding: var(--_field-padding-block) var(--size-8) var(--_field-padding-block) var(--_field-padding-inline);
4582
+ }
4583
+ }
4584
+
4585
+ /* Input - color */
4586
+ &:has(input[type="color"]) {
4587
+ .field {
4588
+ block-size: var(--_height);
4589
+ inline-size: var(--_height);
4590
+ min-block-size: 0;
4591
+ overflow: hidden;
4592
+ }
4593
+
4594
+ input {
4595
+ appearance: none;
4596
+ background: none;
4597
+ block-size: var(--_height);
4598
+ inline-size: var(--_height);
4599
+ overflow: hidden;
4600
+ padding: 0;
4601
+
4602
+ &::-webkit-color-swatch {
4603
+ border: none;
4604
+ }
4605
+
4606
+ &::-webkit-color-swatch-wrapper {
4607
+ padding: 0;
4608
+ }
4609
+ }
4610
+ }
4611
+
4612
+ /* Element states */
4613
+ &:hover {
4614
+ &:not([data-invalid]) {
4615
+ .field {
4616
+ border-color: var(--text-primary);
4617
+ }
4618
+ }
4619
+ }
4620
+
4621
+ &:focus-within {
4622
+ .field {
4623
+ border-color: var(--_accent-color);
4624
+ outline-offset: -2px;
4625
+ }
4626
+ }
4627
+
4628
+ /* Label */
4629
+ .label {
4630
+ color: var(--text-primary);
4631
+ font-size: var(--font-size-05);
4632
+ font-weight: 600;
4633
+ grid-column: 1/-1;
4634
+ grid-row: 1;
4635
+ padding-inline: 0 1ex;
4636
+ }
4637
+
4638
+ /* End text */
4639
+ :where(.end-text) {
4640
+ color: var(--_end-text-color);
4641
+ font-size: var(--font-size-0);
4642
+ grid-column: 1/-1;
4643
+ grid-row: 3;
4644
+ line-height: 1.5;
4645
+ }
4646
+
4647
+ /* Auto-fit */
4648
+ &.auto-fit {
4649
+ inline-size: auto;
4650
+
4651
+ .field {
4652
+ inline-size: auto;
4653
+ }
4654
+
4655
+ :where(& input, & textarea) {
4656
+ field-sizing: content;
4657
+ inline-size: auto;
4658
+ min-inline-size: 25ch;
4659
+ }
4660
+ }
4661
+
4662
+ /* Validation */
4663
+ &[data-invalid],
4664
+ &:has(:user-invalid) {
4665
+ --_accent-color: var(--color-9);
4666
+ --_border-color: var(--color-9);
4667
+ --_filled-border-color: var(--color-9);
4668
+ --_label-color: var(--color-9);
4669
+ --_end-text-color: var(--color-9);
4670
+ }
4671
+
4672
+ /*
4673
+ * Variant: Filled
4674
+ */
4675
+ &.filled {
4676
+ --_bg-color: var(--surface-tonal);
4677
+
4678
+ &:not(:has([disabled], :has(input[type="color"]))) {
4679
+
4680
+ /* Hover */
4681
+ &:hover {
4682
+ --_bg-color: light-dark(oklch(from var(--surface-tonal) calc(l * 0.93) c h),
4683
+ oklch(from var(--surface-tonal) calc(l * 1.1) c h));
4684
+ }
4685
+ }
4686
+ }
4687
+
4688
+ /* Disabled */
4689
+ &:where(:has([disabled])) {
4690
+ cursor: not-allowed;
4691
+ opacity: 0.64;
4692
+ user-select: none;
4693
+
4694
+ &::before {
4695
+ display: none;
4696
+ }
4697
+
4698
+ .field {
4699
+ cursor: not-allowed;
4700
+ }
4701
+
4702
+ :where(input, textarea, select) {
4703
+ cursor: not-allowed;
4704
+
4705
+ * {
4706
+ pointer-events: none;
4707
+ }
4708
+ }
4709
+
4710
+ .label,
4711
+ .start-text,
4712
+ .end-text {
4713
+ cursor: not-allowed;
4714
+ }
4715
+ }
4716
+
4717
+ /* Read-only */
4718
+ &:where(:has([readonly])) {
4719
+ &::before {
4720
+ display: none;
4721
+ }
4722
+
4723
+ :where(input, textarea, select) {
4724
+ cursor: not-allowed;
4725
+
4726
+ * {
4727
+ pointer-events: none;
4728
+ }
4729
+ }
4730
+ }
4731
+
4732
+ /* Sizes */
4733
+ &.small {
4734
+ --_field-padding-block: var(--size-2);
4735
+ --_height: var(--field-size-small);
4736
+
4737
+ &:has(input[type="color"]) {
4738
+ .label {
4739
+ line-height: 1.5;
4740
+ }
4741
+ }
4742
+ }
4743
+
4744
+ /* Orientation */
4745
+ &.spread {
4746
+ align-items: start;
4747
+ column-gap: var(--size-4);
4748
+ container-type: inline-size;
4749
+ grid-template-columns: 1fr auto;
4750
+
4751
+ .label {
4752
+ font-weight: 600;
4753
+ grid-column: 1;
4754
+ grid-row: 1;
4755
+ }
4756
+
4757
+ .start-text {
4758
+ color: var(--_end-text-color);
4759
+ font-size: var(--font-size-0);
4760
+ grid-column: 1;
4761
+ grid-row: 2;
4762
+ line-height: 1.5;
4763
+ }
4764
+
4765
+ .field {
4766
+ align-self: start;
4767
+ grid-column: 2;
4768
+ grid-row: 1 / span 2;
4769
+ }
4770
+
4771
+ .field:has(textarea) {
4772
+ grid-row: 1 / span 3;
4773
+
4774
+ +.end-text {
4775
+ grid-row: 4;
4776
+ }
4777
+ }
4778
+
4779
+ :where(textarea) {
4780
+ min-inline-size: 30ch;
4781
+ }
4782
+
4783
+ :where(.end-text) {
4784
+ grid-column: 2;
4785
+ text-align: end;
4786
+ }
4787
+
4788
+ /* Collapse to column on narrow containers */
4789
+ @container (width < 400px) {
4790
+ column-gap: 0;
4791
+ grid-template-columns: 1fr;
4792
+
4793
+ .label {
4794
+ grid-column: 1;
4795
+ grid-row: 1;
4796
+ }
4797
+
4798
+ .start-text {
4799
+ grid-column: 1;
4800
+ grid-row: 2;
4801
+ }
4802
+
4803
+ .field,
4804
+ .field:has(textarea) {
4805
+ grid-column: 1;
4806
+ grid-row: 3;
4807
+ }
4808
+
4809
+ :where(.end-text) {
4810
+ grid-column: 1;
4811
+ grid-row: 4;
4812
+ text-align: start;
4813
+ }
4814
+ }
4815
+ }
4816
+ }
4817
+ }
4818
+
4819
+ @layer components.extended {
4820
+ :where(.select select) {
4821
+ position: relative;
4822
+
4823
+ /* Default arrow */
4824
+ &::picker-icon {
4825
+ block-size: 0;
4826
+ border-block-start: 5px solid;
4827
+ border-inline: 5px solid transparent;
4828
+ color: currentColor;
4829
+ content: "";
4830
+ inline-size: 0;
4831
+ inset: 50% var(--size-3) auto auto;
4832
+ pointer-events: none;
4833
+ position: absolute;
4834
+ translate: 0 -50%;
4835
+ }
4836
+
4837
+ &:open {
4838
+ &::picker-icon {
4839
+ rotate: 180deg;
4840
+ }
4841
+ }
4842
+
4843
+ /* Select popover */
4844
+ &::picker(select) {
4845
+ /* Animation on-stage styles */
4846
+ border: 0;
4847
+ box-shadow: var(--shadow-2);
4848
+ opacity: 1;
4849
+ padding: 0;
4850
+ scale: 1;
4851
+
4852
+ /* Animation starting styles */
4853
+ @starting-style {
4854
+ opacity: 0;
4855
+ transform: scale(0.9);
4856
+ }
4857
+
4858
+ @media (prefers-reduced-motion: no-preference) {
4859
+ transition: display 0.2s allow-discrete, opacity 0.2s var(--ease-3),
4860
+ overlay 0.2s allow-discrete, scale 0.2s var(--ease-3);
4861
+ }
4862
+ }
4863
+
4864
+ /* Animation off-stage styles */
4865
+ &:not(:open)::picker(select) {
4866
+ opacity: 0;
4867
+ scale: 0.9;
4868
+ }
4869
+
4870
+ button {
4871
+ align-items: center;
4872
+ background-color: transparent;
4873
+ display: flex;
4874
+ inline-size: 100%;
4875
+ margin: 0;
4876
+ position: relative;
4877
+
4878
+ selectedcontent {
4879
+ overflow: hidden;
4880
+ text-overflow: ellipsis;
4881
+ white-space: nowrap;
4882
+ }
4883
+ }
4884
+
4885
+ .list {
4886
+ --_bg-color: var(--surface-filled);
4887
+ border: var(--field-border-width) solid var(--field-border-color);
4888
+ border-radius: var(--field-border-radius);
4889
+
4890
+ /* Groups */
4891
+ [role="group"] {
4892
+ label {
4893
+ background-color: light-dark(var(--gray-3), var(--gray-13));
4894
+ color: light-dark(oklch(from var(--text-primary) calc(l * 0.75) c h),
4895
+ oklch(from var(--text-primary) calc(l * 1.25) c h));
4896
+ font-weight: 500;
4897
+ overflow: hidden;
4898
+ padding-inline: var(--size-2);
4899
+ text-overflow: ellipsis;
4900
+ white-space: nowrap;
4901
+ }
4902
+
4903
+ &:not(:first-child),
4904
+ option:first-of-type {
4905
+ margin-block-start: var(--size-2);
4906
+ }
4907
+
4908
+ option:last-of-type,
4909
+ &:last-child {
4910
+ option:last-of-type {
4911
+ margin-block-end: 0;
4912
+ }
4913
+ }
4914
+ }
4915
+
4916
+ /* Option */
4917
+ option {
4918
+
4919
+ /* Checkmark */
4920
+ /* TODO - checkmark should be the final version of the checkmark API. Follow the development of this and remove redundant psuedo stuff. */
4921
+ &::check {
4922
+ display: none;
4923
+ }
4924
+
4925
+ &::checkmark {
4926
+ display: none;
4927
+ }
4928
+
4929
+ &::before {
4930
+ display: none;
4931
+ }
4932
+
4933
+ &:focus-visible {
4934
+ outline-offset: -1px;
4935
+ }
4936
+ }
4937
+ }
4938
+ }
4939
+
4940
+ :where(.select:has(select)) {
4941
+
4942
+ /* Size */
4943
+ &.small {
4944
+ button {
4945
+ padding-inline: var(--size-2) var(--size-7);
4946
+
4947
+ &::after {
4948
+ inset-inline-end: var(--size-2);
4949
+ }
4950
+ }
4951
+ }
4952
+
4953
+ /*
4954
+ * Non-experimental Select
4955
+ *
4956
+ * Hack to get the arrow working. Pseudo elements aren't allowed on the `<select>` element, so need to add it on the `.select` class instead. Noting this down if an `:after` element would be needed on a `.select`.
4957
+ */
4958
+ &:not(:has(button)) {
4959
+ select {
4960
+ appearance: none;
4961
+ }
4962
+
4963
+ /* Arrow */
4964
+ &::after {
4965
+ align-self: center;
4966
+ block-size: 0;
4967
+ border-block-start: 5px solid;
4968
+ border-inline: 5px solid transparent;
4969
+ content: "";
4970
+ display: inline-block;
4971
+ flex-shrink: 0;
4972
+ grid-column: 1/-1;
4973
+ grid-row: 2;
4974
+ inline-size: 0;
4975
+ inset-inline-end: var(--size-3);
4976
+ justify-self: end;
4977
+ pointer-events: none;
4978
+ position: relative;
4979
+ }
4980
+ }
4981
+ }
4982
+
4983
+ select:has(button),
4984
+ ::picker(select) {
4985
+ appearance: base-select;
4986
+ }
4987
+ }
4988
+
4989
+ @layer components.extended {
4990
+
4991
+ :where(.text-field:has( :where(input[type="date"],
4992
+ input[type="datetime-local"],
4993
+ input[type="email"],
4994
+ input[type="month"],
4995
+ input[type="number"],
4996
+ input[type="password"],
4997
+ input[type="search"],
4998
+ input[type="tel"],
4999
+ input[type="text"],
5000
+ input[type="time"],
5001
+ input[type="url"],
5002
+ input[type="week"]))) {
5003
+
5004
+ /* Sizes */
5005
+ &.small {
5006
+ input {
5007
+ padding-inline: var(--size-2);
5008
+ }
5009
+ }
5010
+ }
5011
+
5012
+ /* Autosuggest */
5013
+ :where(.text-field:has(input[list])) {
5014
+
5015
+ /* Hide native arrow */
5016
+ input::-webkit-calendar-picker-indicator {
5017
+ cursor: pointer;
5018
+ opacity: 0;
5019
+ pointer-events: none;
5020
+ position: absolute;
5021
+ }
5022
+ }
5023
+
5024
+ /* Arrow */
5025
+ :where(.text-field:has(input[list]:placeholder-shown),
5026
+ .text-field:has(input[list]):where(:focus-within, :hover)) {
5027
+ &::after {
5028
+ block-size: 0;
5029
+ border-block-start: 5px solid;
5030
+ border-inline: 5px solid transparent;
5031
+ content: "";
5032
+ display: inline-block;
5033
+ flex-shrink: 0;
5034
+ inline-size: 0;
5035
+ inset: 50% var(--size-3) auto auto;
5036
+ pointer-events: none;
5037
+ position: absolute;
5038
+ translate: 0 -50%;
5039
+ }
5040
+ }
5041
+ }
5042
+
5043
+ @layer components.extended {
5044
+ :where(.textarea) {
5045
+ textarea {
5046
+ block-size: auto;
5047
+ field-sizing: content;
5048
+ min-block-size: calc(var(--_field-padding-block) * 2 + (var(--border-width) * 2) + 3lh);
5049
+ resize: vertical;
5050
+ }
5051
+
5052
+ /* Size */
5053
+ &.small {
5054
+ textarea {
5055
+ min-block-size: var(--size-9);
5056
+ }
5057
+ }
5058
+
5059
+ /* Auto-fit */
5060
+ &.auto-fit {
5061
+ textarea {
5062
+ resize: both;
5063
+ }
5064
+ }
5065
+ }
5066
+ }
5067
+
5068
+ @layer components.extended {
5069
+ :where(.tooltip) {
5070
+ --_tooltip-bg: light-dark(var(--gray-13), var(--gray-3));
5071
+ --_tooltip-color: light-dark(var(--gray-1), var(--gray-15));
5072
+ --_tooltip-offset: var(--size-2);
5073
+
5074
+ &>.anchor-floating {
5075
+ background-color: var(--_tooltip-bg);
5076
+ border-radius: var(--radius-2);
5077
+ color: var(--_tooltip-color);
5078
+ font-size: var(--font-size-05);
5079
+ line-height: 1.3;
5080
+ margin: var(--_tooltip-offset);
5081
+ max-inline-size: 240px;
5082
+ /* UA sets overflow: auto on [popover], which clips the arrow. */
5083
+ overflow: visible;
5084
+ padding-block: var(--size-1);
5085
+ padding-inline: var(--size-2);
5086
+ position-area: var(--anchor-position-area, block-start);
5087
+ position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
5088
+ position-visibility: anchors-visible;
5089
+ text-align: center;
5090
+ text-wrap: pretty;
5091
+ }
5092
+
5093
+ /* Optional arrow pointing from the tooltip toward the trigger.
5094
+ Anchored to the same --anchor so it flips together with the
5095
+ tooltip when position-try-fallbacks kicks in. */
5096
+ &.with-arrow {
5097
+ --_arrow-size: var(--size-2);
5098
+
5099
+ &>.anchor-floating {
5100
+ /* Reserve space so the arrow doesn't overlap the trigger. */
5101
+ --_tooltip-offset: calc(var(--size-2) + var(--_arrow-size) / 2);
5102
+ }
5103
+
5104
+ &>.anchor-floating::before {
5105
+ background-color: var(--_tooltip-bg);
5106
+ block-size: var(--_arrow-size);
5107
+ content: "";
5108
+ inline-size: var(--_arrow-size);
5109
+ inset-block-end: calc(var(--_arrow-size) / -2);
5110
+ inset-inline-start: 50%;
5111
+ position: absolute;
5112
+ rotate: 45deg;
5113
+ translate: -50% 0;
5114
+ }
5115
+ }
5116
+
5117
+ /* Fade */
5118
+ &>.anchor-floating[popover] {
5119
+ opacity: 0;
5120
+ transition:
5121
+ display 0.15s allow-discrete,
5122
+ opacity 0.15s var(--ease-out-1),
5123
+ overlay 0.15s allow-discrete;
5124
+
5125
+ &:popover-open {
5126
+ opacity: 1;
5127
+
5128
+ @starting-style {
5129
+ opacity: 0;
5130
+ }
5131
+ }
5132
+ }
5133
+ }
5134
+ }
5135
+ /*# sourceMappingURL=opui.components.css.map */