@slotted/styles 0.1.0-beta.0 → 0.1.0-beta.10

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 (176) hide show
  1. package/package.json +1 -1
  2. package/src/accordion/accordion.css +10 -10
  3. package/src/action-bar/action-bar.css +31 -32
  4. package/src/action-sheet/action-sheet.css +36 -36
  5. package/src/alert/alert.css +43 -35
  6. package/src/alert/alert.tokens.json +5 -0
  7. package/src/app-shell/app-shell.css +356 -301
  8. package/src/aspect-ratio/aspect-ratio.css +9 -9
  9. package/src/attachment/attachment.css +91 -99
  10. package/src/avatar/avatar.css +71 -41
  11. package/src/avatar/avatar.tokens.json +7 -0
  12. package/src/avatar-group/avatar-group.css +21 -22
  13. package/src/badge/badge.css +45 -37
  14. package/src/badge/badge.tokens.json +5 -0
  15. package/src/breadcrumb/breadcrumb.css +37 -37
  16. package/src/button/button.css +139 -64
  17. package/src/button/button.tokens.json +10 -0
  18. package/src/button-group/button-group.css +76 -72
  19. package/src/button-group/button-group.tokens.json +2 -0
  20. package/src/calendar/calendar.css +93 -103
  21. package/src/card/card.css +54 -61
  22. package/src/carousel/carousel.css +150 -161
  23. package/src/cascader/cascader.css +152 -153
  24. package/src/cascader/cascader.tokens.json +1 -0
  25. package/src/chart/chart.css +242 -239
  26. package/src/chart/chart.tokens.json +1 -0
  27. package/src/checkbox/checkbox.css +119 -124
  28. package/src/checkbox-group/checkbox-group.css +7 -7
  29. package/src/code-block/code-block.css +81 -85
  30. package/src/collapsible/collapsible.css +69 -76
  31. package/src/color-picker/color-picker.css +83 -91
  32. package/src/column-manager/column-manager.css +106 -114
  33. package/src/combobox/combobox.css +132 -107
  34. package/src/combobox/combobox.tokens.json +1 -0
  35. package/src/command-palette/command-palette.css +84 -90
  36. package/src/container/container.css +24 -24
  37. package/src/context-menu/context-menu.css +8 -8
  38. package/src/currency-field/currency-field.css +210 -88
  39. package/src/currency-field/currency-field.tokens.json +13 -0
  40. package/src/dashboard-grid/dashboard-grid.css +148 -116
  41. package/src/data-grid/data-grid.css +504 -469
  42. package/src/data-grid/data-grid.tokens.json +2 -0
  43. package/src/data-list/data-list.css +81 -70
  44. package/src/data-list/data-list.tokens.json +2 -1
  45. package/src/date-field/date-field.css +55 -52
  46. package/src/date-field/date-field.tokens.json +1 -0
  47. package/src/date-picker/date-picker.css +40 -42
  48. package/src/date-range-picker/date-range-picker.css +114 -118
  49. package/src/datetime-field/datetime-field.css +78 -80
  50. package/src/datetime-field/datetime-field.tokens.json +1 -0
  51. package/src/datetime-picker/datetime-picker.css +61 -63
  52. package/src/datetime-range-picker/datetime-range-picker.css +149 -156
  53. package/src/description-list/description-list.css +61 -64
  54. package/src/detail-panel/detail-panel.css +70 -70
  55. package/src/dialog/dialog.css +334 -153
  56. package/src/dialog/dialog.tokens.json +5 -0
  57. package/src/divider/divider.css +18 -18
  58. package/src/drawer/drawer.css +186 -209
  59. package/src/entity-picker/entity-picker.css +238 -241
  60. package/src/entity-picker/entity-picker.tokens.json +1 -0
  61. package/src/event-calendar/event-calendar.css +343 -385
  62. package/src/field/field.css +74 -78
  63. package/src/field-group/field-group.css +22 -25
  64. package/src/filter-bar/filter-bar.css +193 -209
  65. package/src/form/form.css +34 -24
  66. package/src/form/form.tokens.json +1 -0
  67. package/src/fullscreen/fullscreen.css +24 -25
  68. package/src/grid/grid.css +28 -28
  69. package/src/highlight/highlight.css +6 -6
  70. package/src/hover-card/hover-card.css +6 -6
  71. package/src/icon/icon.css +19 -15
  72. package/src/icon/icon.tokens.json +1 -0
  73. package/src/image/image.css +39 -39
  74. package/src/import-export-center/import-export-center.css +135 -156
  75. package/src/inline/inline.css +27 -27
  76. package/src/inline-message/inline-message.css +52 -28
  77. package/src/inline-message/inline-message.tokens.json +4 -0
  78. package/src/kbd/kbd.css +30 -26
  79. package/src/link/link.css +15 -15
  80. package/src/list/list.css +44 -17
  81. package/src/list/list.tokens.json +4 -0
  82. package/src/list-item/list-item.css +80 -66
  83. package/src/list-item/list-item.tokens.json +7 -0
  84. package/src/listbox/listbox.css +56 -59
  85. package/src/loading-overlay/loading-overlay.css +75 -92
  86. package/src/markdown/markdown.css +17 -17
  87. package/src/menu/menu.css +83 -63
  88. package/src/menubar/menubar.css +13 -13
  89. package/src/message/message.css +182 -202
  90. package/src/message/message.tokens.json +5 -0
  91. package/src/message-scroller/message-scroller.css +41 -42
  92. package/src/multi-select/multi-select.css +152 -145
  93. package/src/multi-select/multi-select.tokens.json +1 -0
  94. package/src/navigation-menu/navigation-menu.css +167 -188
  95. package/src/notification-center/notification-center.css +140 -148
  96. package/src/notification-center/notification-center.tokens.json +3 -0
  97. package/src/number-field/number-field.css +84 -83
  98. package/src/number-field/number-field.tokens.json +1 -0
  99. package/src/otp-input/otp-input.css +67 -57
  100. package/src/otp-input/otp-input.tokens.json +1 -0
  101. package/src/page/page.css +23 -23
  102. package/src/page-header/page-header.css +268 -281
  103. package/src/page-header/page-header.tokens.json +1 -0
  104. package/src/pagination/pagination.css +68 -72
  105. package/src/popover/popover.css +40 -49
  106. package/src/progress-indicator/progress-indicator.css +177 -120
  107. package/src/progress-indicator/progress-indicator.tokens.json +1 -1
  108. package/src/prompt-composer/prompt-composer.css +221 -102
  109. package/src/prompt-composer/prompt-composer.tokens.json +15 -0
  110. package/src/prose/prose.css +71 -75
  111. package/src/radio-group/radio-group.css +98 -103
  112. package/src/rating/rating.css +136 -132
  113. package/src/rating/rating.tokens.json +1 -0
  114. package/src/result-state/result-state.css +74 -77
  115. package/src/runtime-properties.mjs +2 -0
  116. package/src/saved-views/saved-views.css +41 -47
  117. package/src/scroll-area/scroll-area.css +39 -32
  118. package/src/section/section.css +161 -41
  119. package/src/section/section.tokens.json +7 -2
  120. package/src/segmented-control/segmented-control.css +254 -97
  121. package/src/segmented-control/segmented-control.tokens.json +15 -11
  122. package/src/select/select.css +118 -117
  123. package/src/select/select.tokens.json +1 -0
  124. package/src/side-navigation/side-navigation.css +179 -182
  125. package/src/side-navigation/side-navigation.tokens.json +1 -0
  126. package/src/skeleton/skeleton.css +47 -48
  127. package/src/slider/slider.css +86 -88
  128. package/src/sparkline/sparkline.css +62 -40
  129. package/src/sparkline/sparkline.tokens.json +2 -0
  130. package/src/spinner/spinner.css +39 -182
  131. package/src/spinner/spinner.tokens.json +0 -2
  132. package/src/split-button/split-button.css +30 -31
  133. package/src/split-button/split-button.tokens.json +1 -0
  134. package/src/splitter/splitter.css +35 -35
  135. package/src/stack/stack.css +24 -24
  136. package/src/stat-card/stat-card.css +341 -224
  137. package/src/stat-card/stat-card.tokens.json +3 -0
  138. package/src/status-indicator/status-indicator.css +28 -28
  139. package/src/stepper/stepper.css +58 -62
  140. package/src/switch/switch.css +86 -92
  141. package/src/table/table.css +310 -165
  142. package/src/table/table.tokens.json +6 -0
  143. package/src/table-of-contents/table-of-contents.css +51 -54
  144. package/src/tabs/tabs.css +330 -302
  145. package/src/tabs/tabs.tokens.json +8 -5
  146. package/src/tag/tag.css +79 -71
  147. package/src/tag/tag.tokens.json +9 -0
  148. package/src/tags-input/tags-input.css +145 -82
  149. package/src/tags-input/tags-input.tokens.json +7 -1
  150. package/src/text-field/text-field.css +132 -136
  151. package/src/text-field/text-field.tokens.json +1 -0
  152. package/src/textarea/textarea.css +31 -28
  153. package/src/textarea/textarea.tokens.json +1 -0
  154. package/src/time-field/time-field.css +72 -69
  155. package/src/time-field/time-field.tokens.json +1 -0
  156. package/src/time-picker/time-picker.css +56 -58
  157. package/src/time-range-picker/time-range-picker.css +126 -133
  158. package/src/timeline/timeline.css +254 -266
  159. package/src/timeline/timeline.tokens.json +5 -0
  160. package/src/toast/toast.css +89 -90
  161. package/src/toast/toast.tokens.json +5 -0
  162. package/src/toggle/toggle.css +62 -25
  163. package/src/toggle/toggle.tokens.json +8 -0
  164. package/src/toggle-group/toggle-group.css +106 -60
  165. package/src/toggle-group/toggle-group.tokens.json +10 -0
  166. package/src/toolbar/toolbar.css +30 -35
  167. package/src/tooltip/tooltip.css +26 -26
  168. package/src/top-navigation/top-navigation.css +243 -259
  169. package/src/tour/tour.css +51 -60
  170. package/src/transfer/transfer.css +160 -164
  171. package/src/tree/tree.css +103 -111
  172. package/src/typography/typography.css +40 -36
  173. package/src/typography/typography.tokens.json +1 -0
  174. package/src/upload/upload.css +224 -224
  175. package/src/visually-hidden/visually-hidden.css +1 -1
  176. package/src/wizard/wizard.css +185 -197
@@ -10,7 +10,7 @@
10
10
  * in: a container cannot change its own tracks
11
11
  * (`docs/build-briefing.md`, _Decisions already taken_).
12
12
  */
13
- [data-ui='stat-card'] {
13
+ [data-ui-stat-card] {
14
14
  --_edge-width: var(--slotted-stat-card-border-width, var(--slotted-border-width-thin, 1px));
15
15
  --_radius: var(--slotted-stat-card-radius, var(--slotted-radius-lg, 8px));
16
16
  --_inset-block: var(--slotted-stat-card-padding-block, var(--slotted-space-6, 1rem));
@@ -87,7 +87,7 @@
87
87
  }
88
88
 
89
89
  /* The edge, out of flow, so a frame that changes width moves no text. */
90
- [data-ui='stat-card']::before {
90
+ [data-ui-stat-card]::before {
91
91
  border: var(--_edge-width) solid var(--_edge);
92
92
  border-radius: inherit;
93
93
  content: '';
@@ -96,7 +96,7 @@
96
96
  position: absolute;
97
97
  }
98
98
 
99
- [data-ui='stat-card'][data-size='sm'] {
99
+ [data-ui-stat-card][data-size='sm'] {
100
100
  --_inset-block: var(--slotted-stat-card-padding-block-sm, var(--slotted-space-5, 0.75rem));
101
101
  --_inset-inline: var(--slotted-stat-card-padding-inline-sm, var(--slotted-space-5, 0.75rem));
102
102
  --_region-gap: var(--slotted-stat-card-region-gap-sm, var(--slotted-space-2, 0.25rem));
@@ -126,7 +126,7 @@
126
126
  --_value-line-narrow: var(--slotted-line-height-xl, 1.45);
127
127
  }
128
128
 
129
- [data-ui='stat-card'][data-size='lg'] {
129
+ [data-ui-stat-card][data-size='lg'] {
130
130
  --_inset-block: var(--slotted-stat-card-padding-block-lg, var(--slotted-space-8, 1.5rem));
131
131
  --_inset-inline: var(--slotted-stat-card-padding-inline-lg, var(--slotted-space-8, 1.5rem));
132
132
  --_region-gap: var(--slotted-stat-card-region-gap-lg, var(--slotted-space-4, 0.5rem));
@@ -170,11 +170,11 @@
170
170
 
171
171
  /* ── Fill: the three frames a card has, and none ─────────────────────── */
172
172
 
173
- [data-ui='stat-card'][data-fill='elevated'] {
173
+ [data-ui-stat-card][data-fill='elevated'] {
174
174
  --_shadow: var(--slotted-stat-card-shadow-elevated, var(--slotted-shadow-md));
175
175
  }
176
176
 
177
- [data-ui='stat-card'][data-fill='subtle'] {
177
+ [data-ui-stat-card][data-fill='subtle'] {
178
178
  --_surface: var(--slotted-stat-card-background-subtle, var(--slotted-surface-sunken, Canvas));
179
179
  }
180
180
 
@@ -183,7 +183,7 @@
183
183
  * of metrics separated by dividers, inside a card that is already a card.
184
184
  * It keeps no inset either, because the host's inset is the inset.
185
185
  */
186
- [data-ui='stat-card'][data-fill='plain'] {
186
+ [data-ui-stat-card][data-fill='plain'] {
187
187
  --_surface: transparent;
188
188
  --_edge: transparent;
189
189
  --_shadow: none;
@@ -218,28 +218,32 @@
218
218
  * number is broken only when it is wider than the card itself. A floor on
219
219
  * the trend was tried and pushed the trend through the card's edge.
220
220
  */
221
- [data-ui='stat-card'] [data-part='body'] {
222
- column-gap: var(--_trend-gap);
223
- display: grid;
224
- flex: 1 1 auto;
225
- grid-template-areas:
226
- 'header header'
227
- 'figure trend'
228
- 'message message';
229
- grid-template-columns: minmax(min-content, 1fr) minmax(0, var(--_trend-size));
230
- grid-template-rows: auto minmax(0, 1fr) auto;
231
- min-inline-size: 0;
232
- row-gap: var(--_region-gap);
233
- }
234
-
235
- [data-ui='stat-card'][data-layout='stacked'] [data-part='body'] {
236
- grid-template-areas:
237
- 'header'
238
- 'figure'
239
- 'trend'
240
- 'message';
241
- grid-template-columns: minmax(0, 1fr);
242
- grid-template-rows: auto minmax(0, 1fr) auto auto;
221
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
222
+ :scope [data-part-body] {
223
+ column-gap: var(--_trend-gap);
224
+ display: grid;
225
+ flex: 1 1 auto;
226
+ grid-template-areas:
227
+ 'header header'
228
+ 'figure trend'
229
+ 'message message';
230
+ grid-template-columns: minmax(min-content, 1fr) minmax(0, var(--_trend-size));
231
+ grid-template-rows: auto minmax(0, 1fr) auto;
232
+ min-inline-size: 0;
233
+ row-gap: var(--_region-gap);
234
+ }
235
+ }
236
+
237
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
238
+ :scope[data-layout='stacked'] [data-part-body] {
239
+ grid-template-areas:
240
+ 'header'
241
+ 'figure'
242
+ 'trend'
243
+ 'message';
244
+ grid-template-columns: minmax(0, 1fr);
245
+ grid-template-rows: auto minmax(0, 1fr) auto auto;
246
+ }
243
247
  }
244
248
 
245
249
  /**
@@ -250,15 +254,19 @@
250
254
  * inline axis gives these regions no intrinsic width: the figure alone
251
255
  * decides the column, and the text is cut or wrapped by the card's width.
252
256
  */
253
- [data-ui='stat-card'] [data-part='header'] {
254
- contain: inline-size;
255
- grid-area: header;
257
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
258
+ :scope [data-part-header] {
259
+ contain: inline-size;
260
+ grid-area: header;
261
+ }
256
262
  }
257
263
 
258
- [data-ui='stat-card'] [data-part='figure'] {
259
- align-self: start;
260
- grid-area: figure;
261
- min-inline-size: 0;
264
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
265
+ :scope [data-part-figure] {
266
+ align-self: start;
267
+ grid-area: figure;
268
+ min-inline-size: 0;
269
+ }
262
270
  }
263
271
 
264
272
  /**
@@ -268,32 +276,40 @@
268
276
  * width is the space a wide value left, which a query on the card cannot
269
277
  * see.
270
278
  */
271
- [data-ui='stat-card'] [data-part='trend'] {
272
- /* The marker's ring is the card's ground, not the page's. */
273
- --slotted-sparkline-ring-color: var(--_surface);
274
-
275
- align-self: center;
276
- container-name: stat-card-trend;
277
- container-type: inline-size;
278
- grid-area: trend;
279
- inline-size: 100%;
280
- min-inline-size: 0;
279
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
280
+ :scope [data-part-trend] {
281
+ /* The marker's ring is the card's ground, not the page's. */
282
+ --slotted-sparkline-ring-color: var(--_surface);
283
+
284
+ align-self: center;
285
+ container-name: stat-card-trend;
286
+ container-type: inline-size;
287
+ grid-area: trend;
288
+ inline-size: 100%;
289
+ min-inline-size: 0;
290
+ }
281
291
  }
282
292
 
283
293
  @container stat-card-trend (max-width: 39px) {
284
- [data-ui='stat-card'] [data-part='trend'] > * {
285
- visibility: hidden;
294
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
295
+ :scope [data-part-trend] > * {
296
+ visibility: hidden;
297
+ }
286
298
  }
287
299
  }
288
300
 
289
- [data-ui='stat-card'][data-layout='stacked'] [data-part='trend'] {
290
- align-self: end;
291
- margin-block-start: var(--slotted-space-2, 0.25rem);
301
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
302
+ :scope[data-layout='stacked'] [data-part-trend] {
303
+ align-self: end;
304
+ margin-block-start: var(--slotted-space-2, 0.25rem);
305
+ }
292
306
  }
293
307
 
294
- [data-ui='stat-card'] [data-part='message'] {
295
- contain: inline-size;
296
- grid-area: message;
308
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
309
+ :scope [data-part-message] {
310
+ contain: inline-size;
311
+ grid-area: message;
312
+ }
297
313
  }
298
314
 
299
315
  /**
@@ -303,29 +319,37 @@
303
319
  * (`docs/token-foundation.md`, rule 4).
304
320
  */
305
321
  @container stat-card (max-width: 219px) {
306
- [data-ui='stat-card'] [data-part='body'] {
307
- grid-template-areas:
308
- 'header'
309
- 'figure'
310
- 'trend'
311
- 'message';
312
- grid-template-columns: minmax(0, 1fr);
313
- grid-template-rows: auto minmax(0, 1fr) auto auto;
322
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
323
+ :scope [data-part-body] {
324
+ grid-template-areas:
325
+ 'header'
326
+ 'figure'
327
+ 'trend'
328
+ 'message';
329
+ grid-template-columns: minmax(0, 1fr);
330
+ grid-template-rows: auto minmax(0, 1fr) auto auto;
331
+ }
314
332
  }
315
333
 
316
- [data-ui='stat-card'] [data-part='trend'] {
317
- align-self: end;
318
- margin-block-start: var(--slotted-space-2, 0.25rem);
334
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
335
+ :scope [data-part-trend] {
336
+ align-self: end;
337
+ margin-block-start: var(--slotted-space-2, 0.25rem);
338
+ }
319
339
  }
320
340
 
321
- [data-ui='stat-card'] [data-part='value'] {
322
- font-size: var(--_value-size-narrow);
323
- line-height: var(--_value-line-narrow);
341
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
342
+ :scope [data-part-value] {
343
+ font-size: var(--_value-size-narrow);
344
+ line-height: var(--_value-line-narrow);
345
+ }
324
346
  }
325
347
 
326
348
  /* The value steps down here, and so does the line its placeholder keeps. */
327
- [data-ui='stat-card'][data-loading] [data-part='value'] {
328
- min-block-size: calc(var(--_value-size-narrow) * var(--_value-line-narrow));
349
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
350
+ :scope[data-loading] [data-part-value] {
351
+ min-block-size: calc(var(--_value-size-narrow) * var(--_value-line-narrow));
352
+ }
329
353
  }
330
354
  }
331
355
 
@@ -337,13 +361,15 @@
337
361
  * them as part of the name, instead of floating them at the middle of the
338
362
  * block.
339
363
  */
340
- [data-ui='stat-card'] [data-part='header'] {
341
- align-items: baseline;
342
- column-gap: var(--slotted-space-3, 0.375rem);
343
- display: flex;
344
- flex-wrap: wrap;
345
- min-inline-size: 0;
346
- row-gap: var(--slotted-space-2, 0.25rem);
364
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
365
+ :scope [data-part-header] {
366
+ align-items: baseline;
367
+ column-gap: var(--slotted-space-3, 0.375rem);
368
+ display: flex;
369
+ flex-wrap: wrap;
370
+ min-inline-size: 0;
371
+ row-gap: var(--slotted-space-2, 0.25rem);
372
+ }
347
373
  }
348
374
 
349
375
  /**
@@ -355,32 +381,58 @@
355
381
  * proportion of the type rather than a scale step: it is a width of
356
382
  * words, and it scales with them.
357
383
  */
358
- [data-ui='stat-card'] [data-part='label'] {
359
- color: var(--_ink-muted);
360
- flex: 1 1 0%;
361
- font-size: var(--_label-size);
362
- font-weight: var(--slotted-font-weight-medium, 500);
363
- line-height: var(--_label-line);
364
- margin: 0;
365
- min-inline-size: min(100%, 10rem);
366
- overflow-wrap: break-word;
384
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
385
+ :scope [data-part-label] {
386
+ color: var(--_ink-muted);
387
+ flex: 1 1 0%;
388
+ font-size: var(--_label-size);
389
+ font-weight: var(--slotted-font-weight-medium, 500);
390
+ line-height: var(--_label-line);
391
+ margin: 0;
392
+ min-inline-size: min(100%, 10rem);
393
+ overflow-wrap: break-word;
394
+ }
367
395
  }
368
396
 
369
- [data-ui='stat-card'] [data-part='status'] {
370
- display: inline-flex;
371
- flex: none;
397
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
398
+ :scope [data-part-status] {
399
+ display: inline-flex;
400
+ flex: none;
401
+ }
372
402
  }
373
403
 
374
404
  /* The action takes the end of the header's first line and stays there
375
405
  when the label wraps: it is the one thing on the card the reader presses,
376
406
  and a corner is where a control is looked for. */
377
- [data-ui='stat-card'] [data-part='action'] {
378
- flex: none;
379
- /* The label's line, so a link here is as tall in the fallback face as in
380
- the web face and the header does not grow when the font arrives. */
381
- font-size: var(--_label-size);
382
- line-height: var(--_label-line);
383
- margin-inline-start: auto;
407
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
408
+ :scope [data-part-action] {
409
+ flex: none;
410
+ /* The label's line, so a link here is as tall in the fallback face as in
411
+ the web face and the header does not grow when the font arrives. */
412
+ font-size: var(--_label-size);
413
+ line-height: var(--_label-line);
414
+ margin-inline-start: auto;
415
+ }
416
+ }
417
+
418
+ /* On a finger the card's one control is a full target among 44-pixel
419
+ controls: a transparent `::before` centred on the link or button — the
420
+ part itself when `render` made it one — reaches
421
+ the comfortable size in both axes, and the header keeps its height. */
422
+ @media (pointer: coarse) {
423
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
424
+ :scope :is([data-part-action]:is(a, button), [data-part-action] > :is(a, button)) {
425
+ position: relative;
426
+ }
427
+ }
428
+
429
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
430
+ :scope :is([data-part-action]:is(a, button), [data-part-action] > :is(a, button))::before {
431
+ content: '';
432
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
433
+ position: absolute;
434
+ }
435
+ }
384
436
  }
385
437
 
386
438
  /* ── Figure: the value, its unit, the delta ───────────────────────────── */
@@ -391,17 +443,21 @@
391
443
  * so a delta that does not fit beside a wide number drops under it rather
392
444
  * than pushing the number.
393
445
  */
394
- [data-ui='stat-card'] [data-part='figure'] {
395
- align-items: baseline;
396
- column-gap: var(--slotted-space-3, 0.375rem);
397
- display: flex;
398
- flex-wrap: wrap;
399
- row-gap: 0;
446
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
447
+ :scope [data-part-figure] {
448
+ align-items: baseline;
449
+ column-gap: var(--slotted-space-3, 0.375rem);
450
+ display: flex;
451
+ flex-wrap: wrap;
452
+ row-gap: 0;
453
+ }
400
454
  }
401
455
 
402
- [data-ui='stat-card'] [data-part='comparison'] {
403
- contain: inline-size;
404
- flex: 1 1 100%;
456
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
457
+ :scope [data-part-comparison] {
458
+ contain: inline-size;
459
+ flex: 1 1 100%;
460
+ }
405
461
  }
406
462
 
407
463
  /**
@@ -414,38 +470,44 @@
414
470
  * to pull a large numeral's counters back together, and it is the same
415
471
  * fraction at every size.
416
472
  */
417
- [data-ui='stat-card'] [data-part='value'] {
418
- /* The figure and its unit are two flex items on one baseline — the text
419
- node is an item of its own — so the gap spaces the unit from the digit
420
- on whichever side it stands. A margin on the unit, reset by
421
- `:first-child` for a leading unit, hugged a trailing one: after a bare
422
- figure the unit is the first element child. */
423
- align-items: baseline;
424
- color: var(--_ink);
425
- display: inline-flex;
426
- flex-wrap: wrap;
427
- gap: 0.15em;
428
- font-size: var(--_value-size);
429
- font-variant-numeric: proportional-nums;
430
- font-weight: var(--slotted-font-weight-semibold, 600);
431
- letter-spacing: -0.02em;
432
- unicode-bidi: plaintext;
433
- line-height: var(--_value-line);
434
- margin: 0;
435
- min-inline-size: 0;
436
- /* A number is never truncated: a value wider than its column breaks
437
- rather than clips, and a consumer who wants it whole formats it
438
- compact or stacks the card. */
439
- overflow-wrap: break-word;
473
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
474
+ :scope [data-part-value] {
475
+ /* The figure and its unit are two flex items on one baseline — the text
476
+ node is an item of its own — so the gap spaces the unit from the digit
477
+ on whichever side it stands. A margin on the unit, reset by
478
+ `:first-child` for a leading unit, hugged a trailing one: after a bare
479
+ figure the unit is the first element child. */
480
+ align-items: baseline;
481
+ color: var(--_ink);
482
+ display: inline-flex;
483
+ flex-wrap: wrap;
484
+ gap: 0.15em;
485
+ font-size: var(--_value-size);
486
+ font-variant-numeric: proportional-nums;
487
+ font-weight: var(--slotted-font-weight-semibold, 600);
488
+ /* The figure is set at the 3xl or 4xl step, where the theme's tighter
489
+ tracking applies. */
490
+ letter-spacing: var(--slotted-letter-spacing-tighter, -0.03em);
491
+ unicode-bidi: plaintext;
492
+ line-height: var(--_value-line);
493
+ margin: 0;
494
+ min-inline-size: 0;
495
+ /* A number is never truncated: a value wider than its column breaks
496
+ rather than clips, and a consumer who wants it whole formats it
497
+ compact or stacks the card. */
498
+ overflow-wrap: break-word;
499
+ }
440
500
  }
441
501
 
442
502
  /* The unit is in the value's own line, a step down in size and weight, so
443
503
  `$` and `%` read as annotation of the number rather than as digits. */
444
- [data-ui='stat-card'] [data-part='unit'] {
445
- color: var(--_ink-muted);
446
- font-size: var(--_delta-size);
447
- font-weight: var(--slotted-font-weight-medium, 500);
448
- letter-spacing: 0;
504
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
505
+ :scope [data-part-unit] {
506
+ color: var(--_ink-muted);
507
+ font-size: var(--_delta-size);
508
+ font-weight: var(--slotted-font-weight-medium, 500);
509
+ letter-spacing: 0;
510
+ }
449
511
  }
450
512
 
451
513
  /**
@@ -454,44 +516,62 @@
454
516
  * metrics, and the tone's text role already clears the reading ratio on
455
517
  * the surface. It sits on the value's baseline.
456
518
  */
457
- [data-ui='stat-card'] [data-part='delta'] {
458
- align-items: center;
459
- color: var(--_tone-text);
460
- column-gap: var(--slotted-space-1, 0.125rem);
461
- display: inline-flex;
462
- font-size: var(--_delta-size);
463
- font-variant-numeric: tabular-nums;
464
- font-weight: var(--slotted-font-weight-semibold, 600);
465
- line-height: 1;
466
- /* A signed number is a run of its own: in a right-to-left document the
467
- sign of `+12.4%` is a neutral character and drifts to the far end of
468
- the run, so the run is laid out by its own content. */
469
- unicode-bidi: plaintext;
470
- white-space: nowrap;
471
- }
472
-
473
- [data-ui='stat-card'] [data-part='delta'][data-tone='neutral'] {
474
- --_tone-text: var(--_ink-muted);
519
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
520
+ :scope [data-part-delta] {
521
+ align-items: center;
522
+ color: var(--_tone-text);
523
+ column-gap: var(--slotted-space-1, 0.125rem);
524
+ display: inline-flex;
525
+ font-size: var(--_delta-size);
526
+ font-variant-numeric: tabular-nums;
527
+ font-weight: var(--slotted-font-weight-semibold, 600);
528
+ line-height: 1;
529
+ /* A signed number is a run of its own: in a right-to-left document the
530
+ sign of `+12.4%` is a neutral character and drifts to the far end of
531
+ the run, so the run is laid out by its own content. */
532
+ unicode-bidi: plaintext;
533
+ white-space: nowrap;
534
+ }
475
535
  }
476
536
 
477
- [data-ui='stat-card'] [data-part='delta'][data-tone='accent'] {
478
- --_tone-text: var(--slotted-tone-accent-text);
537
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
538
+ :scope [data-part-delta][data-tone='neutral'] {
539
+ --_tone-text: var(--_ink-muted);
540
+ }
479
541
  }
480
542
 
481
- [data-ui='stat-card'] [data-part='delta'][data-tone='secondary'] {
482
- --_tone-text: var(--slotted-tone-secondary-text);
543
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
544
+ :scope [data-part-delta][data-tone='accent'] {
545
+ --_tone-text: var(--slotted-tone-accent-text);
546
+ }
483
547
  }
484
548
 
485
- [data-ui='stat-card'] [data-part='delta'][data-tone='success'] {
486
- --_tone-text: var(--slotted-tone-success-text);
549
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
550
+ :scope [data-part-delta][data-tone='secondary'] {
551
+ --_tone-text: var(--slotted-tone-secondary-text);
552
+ }
487
553
  }
488
554
 
489
- [data-ui='stat-card'] [data-part='delta'][data-tone='warning'] {
490
- --_tone-text: var(--slotted-tone-warning-text);
555
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
556
+ :scope [data-part-delta][data-tone='success'] {
557
+ --_tone-text: var(--slotted-tone-success-text);
558
+ }
559
+
560
+ :scope [data-part-delta][data-tone='info'] {
561
+ --_tone-text: var(--slotted-tone-info-text);
562
+ }
563
+ }
564
+
565
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
566
+ :scope [data-part-delta][data-tone='warning'] {
567
+ --_tone-text: var(--slotted-tone-warning-text);
568
+ }
491
569
  }
492
570
 
493
- [data-ui='stat-card'] [data-part='delta'][data-tone='danger'] {
494
- --_tone-text: var(--slotted-tone-danger-text);
571
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
572
+ :scope [data-part-delta][data-tone='danger'] {
573
+ --_tone-text: var(--slotted-tone-danger-text);
574
+ }
495
575
  }
496
576
 
497
577
  /**
@@ -502,38 +582,43 @@
502
582
  * change draws `minus`. The binding renders the glyph inside the icon box;
503
583
  * the part hands the box its size, and the box inherits the delta's ink.
504
584
  */
505
- [data-ui='stat-card'] [data-part='indicator'] {
506
- --slotted-icon-size: var(--_indicator-size);
585
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
586
+ :scope [data-part-indicator] {
587
+ --slotted-icon-size: var(--_indicator-size);
507
588
 
508
- display: inline-flex;
509
- flex: none;
589
+ display: inline-flex;
590
+ flex: none;
591
+ }
510
592
  }
511
593
 
512
594
  /* A reflection across the horizontal axis, not motion: nothing travels when
513
595
  a rise becomes a fall. Time runs from the right in a right-to-left
514
596
  document, so the rise points the other way there, as the sparkline beside
515
597
  it does — the `directional` icon box the binding draws does that. */
516
- [data-ui='stat-card']
517
- [data-part='delta'][data-trend='down']
518
- [data-part='indicator']
519
- > [data-ui='icon'] {
520
- rotate: x 180deg;
598
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
599
+ :scope [data-part-delta][data-trend='down'] [data-part-indicator] > [data-ui-icon] {
600
+ rotate: x 180deg;
601
+ }
521
602
  }
522
603
 
523
604
  /* ── Comparison: the prose under the figure ───────────────────────────── */
524
605
 
525
- [data-ui='stat-card'] [data-part='comparison'] {
526
- color: var(--_ink-muted);
527
- font-size: var(--_prose-size);
528
- line-height: var(--_prose-line);
529
- margin-block-start: var(--_region-gap);
530
- margin: 0;
531
- min-inline-size: 0;
532
- overflow-wrap: anywhere;
606
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
607
+ :scope [data-part-comparison] {
608
+ color: var(--_ink-muted);
609
+ font-size: var(--_prose-size);
610
+ line-height: var(--_prose-line);
611
+ margin-block-start: var(--_region-gap);
612
+ margin: 0;
613
+ min-inline-size: 0;
614
+ overflow-wrap: anywhere;
615
+ }
533
616
  }
534
617
 
535
- [data-ui='stat-card'] [data-part='period'] {
536
- color: var(--_ink-muted);
618
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
619
+ :scope [data-part-period] {
620
+ color: var(--_ink-muted);
621
+ }
537
622
  }
538
623
 
539
624
  /* ── Trend: where a sparkline goes ────────────────────────────────────── */
@@ -546,55 +631,79 @@
546
631
  * — a card with no delta, or a metric with no valence, draws its trend in
547
632
  * the theme's blue and not in grey.
548
633
  */
549
- [data-ui='stat-card'] [data-part='trend'] {
550
- align-self: center;
551
- display: flex;
634
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
635
+ :scope [data-part-trend] {
636
+ align-self: center;
637
+ display: flex;
638
+ }
552
639
  }
553
640
 
554
- [data-ui='stat-card'][data-tone='success'] [data-part='trend'] {
555
- --slotted-sparkline-color: var(--slotted-tone-success-text);
641
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
642
+ :scope[data-tone='success'] [data-part-trend] {
643
+ --slotted-sparkline-color: var(--slotted-tone-success-text);
644
+ }
645
+
646
+ :scope[data-tone='info'] [data-part-trend] {
647
+ --slotted-sparkline-color: var(--slotted-tone-info-text);
648
+ }
556
649
  }
557
650
 
558
- [data-ui='stat-card'][data-tone='danger'] [data-part='trend'] {
559
- --slotted-sparkline-color: var(--slotted-tone-danger-text);
651
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
652
+ :scope[data-tone='danger'] [data-part-trend] {
653
+ --slotted-sparkline-color: var(--slotted-tone-danger-text);
654
+ }
560
655
  }
561
656
 
562
- [data-ui='stat-card'][data-tone='warning'] [data-part='trend'] {
563
- --slotted-sparkline-color: var(--slotted-tone-warning-text);
657
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
658
+ :scope[data-tone='warning'] [data-part-trend] {
659
+ --slotted-sparkline-color: var(--slotted-tone-warning-text);
660
+ }
564
661
  }
565
662
 
566
- [data-ui='stat-card'][data-tone='accent'] [data-part='trend'] {
567
- --slotted-sparkline-color: var(--slotted-tone-accent-text);
663
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
664
+ :scope[data-tone='accent'] [data-part-trend] {
665
+ --slotted-sparkline-color: var(--slotted-tone-accent-text);
666
+ }
568
667
  }
569
668
 
570
- [data-ui='stat-card'][data-tone='secondary'] [data-part='trend'] {
571
- --slotted-sparkline-color: var(--slotted-tone-secondary-text);
669
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
670
+ :scope[data-tone='secondary'] [data-part-trend] {
671
+ --slotted-sparkline-color: var(--slotted-tone-secondary-text);
672
+ }
572
673
  }
573
674
 
574
- [data-ui='stat-card'][data-fill='plain'] [data-part='trend'] {
575
- --slotted-sparkline-ring-color: var(--slotted-surface-raised, Canvas);
675
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
676
+ :scope[data-fill='plain'] [data-part-trend] {
677
+ --slotted-sparkline-ring-color: var(--slotted-surface-raised, Canvas);
678
+ }
576
679
  }
577
680
 
578
681
  /* ── Message: what stands in for a value that is missing or failed ────── */
579
682
 
580
- [data-ui='stat-card'] [data-part='message'] {
581
- color: var(--_ink-muted);
582
- font-size: var(--_prose-size);
583
- line-height: var(--_prose-line);
584
- margin: 0;
585
- min-inline-size: 0;
586
- overflow-wrap: anywhere;
683
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
684
+ :scope [data-part-message] {
685
+ color: var(--_ink-muted);
686
+ font-size: var(--_prose-size);
687
+ line-height: var(--_prose-line);
688
+ margin: 0;
689
+ min-inline-size: 0;
690
+ overflow-wrap: anywhere;
691
+ }
587
692
  }
588
693
 
589
- [data-ui='stat-card'][data-status='error'] [data-part='message'] {
590
- color: var(--slotted-tone-danger-text);
694
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
695
+ :scope[data-status='error'] [data-part-message] {
696
+ color: var(--slotted-tone-danger-text);
697
+ }
591
698
  }
592
699
 
593
700
  /* A value that is not there is a dash in the muted step, at the value's
594
701
  own size, so the row keeps its height and its rhythm. */
595
- [data-ui='stat-card'][data-status='empty'] [data-part='value'],
596
- [data-ui='stat-card'][data-status='error'] [data-part='value'] {
597
- color: var(--_ink-muted);
702
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
703
+ :scope[data-status='empty'] [data-part-value],
704
+ :scope[data-status='error'] [data-part-value] {
705
+ color: var(--_ink-muted);
706
+ }
598
707
  }
599
708
 
600
709
  /* ── Loading ──────────────────────────────────────────────────────────── */
@@ -614,28 +723,36 @@
614
723
  * arrived. The floor is one line of the value's own type, so the two states
615
724
  * occupy the same box.
616
725
  */
617
- [data-ui='stat-card'][data-loading] [data-part='value'] {
618
- min-block-size: calc(var(--_value-size) * var(--_value-line));
726
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
727
+ :scope[data-loading] [data-part-value] {
728
+ min-block-size: calc(var(--_value-size) * var(--_value-line));
729
+ }
619
730
  }
620
731
 
621
- [data-ui='stat-card'][data-loading] [data-part='trend'] {
622
- --slotted-skeleton-block-size: var(
623
- --slotted-sparkline-block-size,
624
- var(--slotted-space-9, 2rem)
625
- );
732
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
733
+ :scope[data-loading] [data-part-trend] {
734
+ --slotted-skeleton-block-size: var(
735
+ --slotted-sparkline-block-size,
736
+ var(--slotted-space-9, 2rem)
737
+ );
738
+ }
626
739
  }
627
740
 
628
- [data-ui='stat-card'][data-loading][data-size='sm'] [data-part='trend'] {
629
- --slotted-skeleton-block-size: var(
630
- --slotted-sparkline-block-size-sm,
631
- var(--slotted-space-7, 1.25rem)
632
- );
741
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
742
+ :scope[data-loading][data-size='sm'] [data-part-trend] {
743
+ --slotted-skeleton-block-size: var(
744
+ --slotted-sparkline-block-size-sm,
745
+ var(--slotted-space-7, 1.25rem)
746
+ );
747
+ }
633
748
  }
634
749
 
635
- [data-ui='stat-card'][data-loading][data-size='lg'] [data-part='trend'] {
636
- --slotted-skeleton-block-size: var(
637
- --slotted-sparkline-block-size-lg,
638
- var(--slotted-space-11, 3rem)
639
- );
750
+ @scope ([data-ui-stat-card]) to (:scope [data-ui] > *) {
751
+ :scope[data-loading][data-size='lg'] [data-part-trend] {
752
+ --slotted-skeleton-block-size: var(
753
+ --slotted-sparkline-block-size-lg,
754
+ var(--slotted-space-11, 3rem)
755
+ );
756
+ }
640
757
  }
641
758
  }