@slotted/styles 0.1.0-beta.1 → 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
@@ -36,7 +36,7 @@
36
36
  * description-list has a `description`, a card has `actions` and a `header`
37
37
  * — and a descendant rule would restyle theirs.
38
38
  */
39
- [data-ui='page-header'] {
39
+ [data-ui-page-header] {
40
40
  --_surface: var(--slotted-page-header-background, var(--slotted-surface, Canvas));
41
41
  /* What the root and the title area paint; `plain` takes it away at rest. */
42
42
  --_ground: var(--_surface);
@@ -117,7 +117,7 @@
117
117
  overflow-x: clip;
118
118
  }
119
119
 
120
- [data-ui='page-header'][data-size='sm'] {
120
+ [data-ui-page-header][data-size='sm'] {
121
121
  --_heading-size: var(
122
122
  --slotted-page-header-heading-size-sm,
123
123
  var(--slotted-font-size-xl, 1.125rem)
@@ -130,7 +130,7 @@
130
130
  --_snapped-heading-line-height: var(--slotted-line-height-md, 1.5);
131
131
  }
132
132
 
133
- [data-ui='page-header'][data-size='lg'] {
133
+ [data-ui-page-header][data-size='lg'] {
134
134
  --_heading-size: var(
135
135
  --slotted-page-header-heading-size-lg,
136
136
  var(--slotted-font-size-3xl, 1.5rem)
@@ -150,9 +150,9 @@
150
150
  * and `pressed` is its word. Under `collapse="manual"` the offset is what
151
151
  * the scroll would use, so it is zero for good.
152
152
  */
153
- [data-ui='page-header'][data-revealed],
154
- [data-ui='page-header'][data-collapse='manual'],
155
- [data-ui='page-header']:has([data-part='pin'][data-pressed]) {
153
+ [data-ui-page-header][data-revealed],
154
+ [data-ui-page-header][data-collapse='manual'],
155
+ [data-ui-page-header]:has([data-part-pin][data-pressed]) {
156
156
  inset-block-start: var(--_sticky-inset);
157
157
  }
158
158
 
@@ -166,7 +166,7 @@
166
166
  * ground would show the page through its title. The hairline stays in
167
167
  * both: it is where the chrome ends.
168
168
  */
169
- [data-ui='page-header'][data-variant='plain']:not([data-stuck]) {
169
+ [data-ui-page-header][data-variant='plain']:not([data-stuck]) {
170
170
  --_ground: transparent;
171
171
  }
172
172
 
@@ -179,19 +179,19 @@
179
179
  * sat an inset down over the content under it. The title area paints its
180
180
  * own ground, so its top corners follow the root's, and it slides with it.
181
181
  */
182
- [data-ui='page-header'][data-variant='floating'] {
182
+ [data-ui-page-header][data-variant='floating'] {
183
183
  --_radius: var(--slotted-page-header-radius, var(--slotted-radius-lg, 8px));
184
184
 
185
185
  border: var(--_rule-size) solid var(--_rule);
186
186
  border-radius: var(--_radius);
187
187
  box-sizing: border-box;
188
188
  }
189
- [data-ui='page-header'][data-variant='floating'] > * > [data-part='title-area'] {
189
+ [data-ui-page-header][data-variant='floating'] > * > [data-part-title-area] {
190
190
  border-start-end-radius: calc(var(--_radius) - var(--_rule-size));
191
191
  border-start-start-radius: calc(var(--_radius) - var(--_rule-size));
192
192
  transition: inset-block-start var(--_duration) var(--_easing);
193
193
  }
194
- [data-ui='page-header'][data-variant='floating'][data-stuck] {
194
+ [data-ui-page-header][data-variant='floating'][data-stuck] {
195
195
  --_sticky-inset: var(--slotted-page-header-inset, var(--slotted-space-4, 0.5rem));
196
196
 
197
197
  box-shadow: var(--slotted-page-header-shadow, var(--slotted-shadow-sm));
@@ -203,14 +203,14 @@
203
203
  * record's header and tabs held 40 per cent of the screen for the whole
204
204
  * scroll. `relative` and not `static`, so the root keeps the stacking the
205
205
  * pill straddling its edge relies on, at an offset of nought. The binding
206
- * writes the attribute from the root's own width: a container query cannot
207
- * select the container it measures.
206
+ * writes the attribute from the frame's width, so a header in a narrow pane
207
+ * of a wide frame still sticks inside the pane.
208
208
  */
209
- [data-ui='page-header'][data-compact] {
209
+ [data-ui-page-header][data-compact] {
210
210
  inset-block-start: 0;
211
211
  position: relative;
212
212
  }
213
- [data-ui='page-header'][data-compact] > * > [data-part='title-area'] {
213
+ [data-ui-page-header][data-compact] > * > [data-part-title-area] {
214
214
  inset-block-start: 0;
215
215
  position: relative;
216
216
  }
@@ -222,7 +222,7 @@
222
222
  * renders to align its rows to the page's measure, and it is not named,
223
223
  * because a family does not select another family's identity.
224
224
  */
225
- [data-ui='page-header'] > * > [data-part='title-area'] {
225
+ [data-ui-page-header] > * > [data-part-title-area] {
226
226
  background-color: var(--_ground);
227
227
  display: flex;
228
228
  flex-direction: column;
@@ -234,6 +234,41 @@
234
234
  z-index: 2;
235
235
  }
236
236
 
237
+ /**
238
+ * The title area paints the ground only where something passes under it:
239
+ * the header area, which it covers while it collapses. Without one, the
240
+ * root's ground is the one layer under the title, so a ground with alpha is
241
+ * composited once — painted on both, 0.5 read as 0.75. With a header area
242
+ * the title keeps its own ground, because a title that let the area show
243
+ * through would print the area's words under its own.
244
+ */
245
+ [data-ui-page-header]:not(:has(> * > [data-part-header-area])) > * > [data-part-title-area] {
246
+ background-color: transparent;
247
+ }
248
+
249
+ /**
250
+ * Stuck, the chrome stands over the content, and a theme may blur what passes
251
+ * under it: `--slotted-page-header-backdrop-filter`, `none` unless set. It
252
+ * composes with a ground that has alpha, which is what lets the content show
253
+ * at all. The filter is the stuck state's alone, so a `plain` header,
254
+ * transparent at rest, filters nothing at rest.
255
+ */
256
+ [data-ui-page-header][data-stuck] {
257
+ -webkit-backdrop-filter: var(--slotted-page-header-backdrop-filter, none);
258
+ backdrop-filter: var(--slotted-page-header-backdrop-filter, none);
259
+ }
260
+
261
+ /**
262
+ * A reader who asked for less transparency gets none of the effect, and under
263
+ * forced colours the ground is the system's and the blur has nothing to add.
264
+ */
265
+ @media (prefers-reduced-transparency: reduce), (forced-colors: active) {
266
+ [data-ui-page-header][data-stuck] {
267
+ -webkit-backdrop-filter: none;
268
+ backdrop-filter: none;
269
+ }
270
+ }
271
+
237
272
  /**
238
273
  * The pill straddles the chrome's edge, so whatever ends at that edge
239
274
  * keeps half a pill clear of it: the title area, because stuck the edge
@@ -242,11 +277,11 @@
242
277
  * because a padding that changed at the snap would move the tabs by that
243
278
  * much at the moment the header area left.
244
279
  */
245
- [data-ui='page-header']:has([data-part='controls'] > *) > * > [data-part='title-area'] {
280
+ [data-ui-page-header]:has([data-part-controls] > *) > * > [data-part-title-area] {
246
281
  padding-block-end: calc(var(--slotted-space-4, 0.5rem) + var(--_control-size) / 2);
247
282
  }
248
283
 
249
- [data-ui='page-header'] > * > [data-part='title-area'] > [data-part='nav'] {
284
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-nav] {
250
285
  align-items: center;
251
286
  color: var(--_muted);
252
287
  display: flex;
@@ -255,7 +290,7 @@
255
290
  line-height: var(--slotted-line-height-sm, 1.45);
256
291
  min-inline-size: 0;
257
292
  }
258
- [data-ui='page-header'] > * > [data-part='title-area'] > [data-part='nav']:empty {
293
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-nav]:empty {
259
294
  display: none;
260
295
  }
261
296
  /**
@@ -264,11 +299,11 @@
264
299
  * breadcrumbs go and the arrow is what remains. A consumer writes both
265
300
  * once and the width decides.
266
301
  */
267
- [data-ui='page-header']
302
+ [data-ui-page-header]
268
303
  > *
269
- > [data-part='title-area']
270
- > [data-part='nav']
271
- > [data-part='back']:has(~ [data-part='breadcrumbs']:not(:empty)) {
304
+ > [data-part-title-area]
305
+ > [data-part-nav]
306
+ > [data-part-back]:has(~ [data-part-breadcrumbs]:not(:empty)) {
272
307
  display: none;
273
308
  }
274
309
 
@@ -278,7 +313,7 @@
278
313
  * label, and it points along the reading direction, so its `directional`
279
314
  * box mirrors it in a right-to-left document.
280
315
  */
281
- [data-ui='page-header'] > * > [data-part='title-area'] > [data-part='nav'] > [data-part='back'] {
316
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-nav] > [data-part-back] {
282
317
  --slotted-icon-size: var(--_icon-size);
283
318
 
284
319
  align-items: center;
@@ -302,11 +337,7 @@
302
337
  reaches the comfortable size by padding and gives it back as a negative
303
338
  margin, so the nav row keeps its height and nothing under it moves. */
304
339
  @media (pointer: coarse) {
305
- [data-ui='page-header']
306
- > *
307
- > [data-part='title-area']
308
- > [data-part='nav']
309
- > [data-part='back'] {
340
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-nav] > [data-part-back] {
310
341
  --_reach: max(
311
342
  0px,
312
343
  calc((var(--slotted-target-comfortable, 44px) - var(--slotted-target-min, 24px)) / 2)
@@ -316,27 +347,23 @@
316
347
  padding-block: var(--_reach);
317
348
  }
318
349
  }
319
- [data-ui='page-header']
350
+ [data-ui-page-header]
320
351
  > *
321
- > [data-part='title-area']
322
- > [data-part='nav']
323
- > [data-part='back']:not([data-disabled]):not(:disabled):hover {
352
+ > [data-part-title-area]
353
+ > [data-part-nav]
354
+ > [data-part-back]:not([data-disabled]):not(:disabled):hover {
324
355
  color: var(--_text);
325
356
  }
326
- [data-ui='page-header']
357
+ [data-ui-page-header]
327
358
  > *
328
- > [data-part='title-area']
329
- > [data-part='nav']
330
- > [data-part='back']:focus-visible {
359
+ > [data-part-title-area]
360
+ > [data-part-nav]
361
+ > [data-part-back]:focus-visible {
331
362
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
332
363
  outline-offset: var(--slotted-focus-ring-offset, 2px);
333
364
  }
334
365
 
335
- [data-ui='page-header']
336
- > *
337
- > [data-part='title-area']
338
- > [data-part='nav']
339
- > [data-part='breadcrumbs'] {
366
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-nav] > [data-part-breadcrumbs] {
340
367
  min-inline-size: 0;
341
368
  }
342
369
 
@@ -345,7 +372,7 @@
345
372
  * navigation pushed to the end. Everything after the title wraps under it
346
373
  * when the width runs out, in the order it has in the DOM.
347
374
  */
348
- [data-ui='page-header'] > * > [data-part='title-area'] > [data-part='title-row'] {
375
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-title-row] {
349
376
  align-items: flex-start;
350
377
  display: flex;
351
378
  flex-wrap: wrap;
@@ -353,11 +380,7 @@
353
380
  min-inline-size: 0;
354
381
  }
355
382
 
356
- [data-ui='page-header']
357
- > *
358
- > [data-part='title-area']
359
- > [data-part='title-row']
360
- > [data-part='visual'] {
383
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-title-row] > [data-part-visual] {
361
384
  align-items: center;
362
385
  /* On the title's first line, as Primer's LeadingVisual: centred on the
363
386
  whole column it sank beside the second line of a wrapped title. */
@@ -372,11 +395,7 @@
372
395
  * aligned to the text" asks for — and the subheading, forced to a full
373
396
  * row, takes the line under it.
374
397
  */
375
- [data-ui='page-header']
376
- > *
377
- > [data-part='title-area']
378
- > [data-part='title-row']
379
- > [data-part='title'] {
398
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-title-row] > [data-part-title] {
380
399
  align-items: center;
381
400
  column-gap: var(--slotted-space-4, 0.5rem);
382
401
  display: flex;
@@ -403,12 +422,12 @@
403
422
  * width to the flex algorithm that is not the width it then paints, and the
404
423
  * marks beside it ran past the container in the first capture.
405
424
  */
406
- [data-ui='page-header']
425
+ [data-ui-page-header]
407
426
  > *
408
- > [data-part='title-area']
409
- > [data-part='title-row']
410
- > [data-part='title']
411
- > [data-part='heading'] {
427
+ > [data-part-title-area]
428
+ > [data-part-title-row]
429
+ > [data-part-title]
430
+ > [data-part-heading] {
412
431
  -webkit-box-orient: vertical;
413
432
  color: var(--_text);
414
433
  display: -webkit-box;
@@ -429,12 +448,12 @@
429
448
  /* No transition on the size: text re-rasterised on every frame of a
430
449
  font-size change blurs and settles with a jolt, so the step is a cut. */
431
450
  }
432
- [data-ui='page-header']:not([data-expanded])
451
+ [data-ui-page-header]:not([data-expanded])
433
452
  > *
434
- > [data-part='title-area']
435
- > [data-part='title-row']
436
- > [data-part='title']
437
- > [data-part='heading'] {
453
+ > [data-part-title-area]
454
+ > [data-part-title-row]
455
+ > [data-part-title]
456
+ > [data-part-heading] {
438
457
  display: block;
439
458
  flex: 0 1 auto;
440
459
  font-size: var(--_snapped-heading-size);
@@ -443,33 +462,33 @@
443
462
  white-space: nowrap;
444
463
  }
445
464
 
446
- [data-ui='page-header']
465
+ [data-ui-page-header]
447
466
  > *
448
- > [data-part='title-area']
449
- > [data-part='title-row']
450
- > [data-part='title']
451
- > [data-part='marks'] {
467
+ > [data-part-title-area]
468
+ > [data-part-title-row]
469
+ > [data-part-title]
470
+ > [data-part-marks] {
452
471
  align-items: center;
453
472
  display: inline-flex;
454
473
  flex-wrap: wrap;
455
474
  gap: var(--slotted-space-2, 0.25rem);
456
475
  min-inline-size: 0;
457
476
  }
458
- [data-ui='page-header']
477
+ [data-ui-page-header]
459
478
  > *
460
- > [data-part='title-area']
461
- > [data-part='title-row']
462
- > [data-part='title']
463
- > [data-part='marks']:empty {
479
+ > [data-part-title-area]
480
+ > [data-part-title-row]
481
+ > [data-part-title]
482
+ > [data-part-marks]:empty {
464
483
  display: none;
465
484
  }
466
485
 
467
- [data-ui='page-header']
486
+ [data-ui-page-header]
468
487
  > *
469
- > [data-part='title-area']
470
- > [data-part='title-row']
471
- > [data-part='title']
472
- > [data-part='subheading'] {
488
+ > [data-part-title-area]
489
+ > [data-part-title-row]
490
+ > [data-part-title]
491
+ > [data-part-subheading] {
473
492
  -webkit-box-orient: vertical;
474
493
  color: var(--_muted);
475
494
  display: -webkit-box;
@@ -485,23 +504,19 @@
485
504
  text-wrap: pretty;
486
505
  }
487
506
  /* Snapped, the bar has one line to give it. */
488
- [data-ui='page-header']:not([data-expanded])
507
+ [data-ui-page-header]:not([data-expanded])
489
508
  > *
490
- > [data-part='title-area']
491
- > [data-part='title-row']
492
- > [data-part='title']
493
- > [data-part='subheading'] {
509
+ > [data-part-title-area]
510
+ > [data-part-title-row]
511
+ > [data-part-title]
512
+ > [data-part-subheading] {
494
513
  display: block;
495
514
  overflow: hidden;
496
515
  text-overflow: ellipsis;
497
516
  white-space: nowrap;
498
517
  }
499
518
 
500
- [data-ui='page-header']
501
- > *
502
- > [data-part='title-area']
503
- > [data-part='title-row']
504
- > [data-part='actions'] {
519
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-title-row] > [data-part-actions] {
505
520
  align-items: center;
506
521
  display: flex;
507
522
  flex: 0 1 auto;
@@ -522,20 +537,20 @@
522
537
  * that scrolls — written from the same public tokens; a framed bar keeps
523
538
  * its box.
524
539
  */
525
- [data-ui='page-header']
540
+ [data-ui-page-header]
526
541
  > *
527
- > [data-part='title-area']
528
- > [data-part='title-row']
529
- > [data-part='actions']
530
- > [data-ui='toolbar']:not([data-variant='outline']) {
542
+ > [data-part-title-area]
543
+ > [data-part-title-row]
544
+ > [data-part-actions]
545
+ > [data-ui-toolbar]:not([data-variant='outline']) {
531
546
  margin-block: calc(-1 * var(--slotted-toolbar-inset, var(--slotted-space-2, 0.25rem)));
532
547
  }
533
- [data-ui='page-header']
548
+ [data-ui-page-header]
534
549
  > *
535
- > [data-part='title-area']
536
- > [data-part='title-row']
537
- > [data-part='actions']
538
- > [data-ui='toolbar']:not([data-variant='outline']):is(
550
+ > [data-part-title-area]
551
+ > [data-part-title-row]
552
+ > [data-part-actions]
553
+ > [data-ui-toolbar]:not([data-variant='outline']):is(
539
554
  [data-overflow='menu'],
540
555
  [data-overflow='scroll']
541
556
  ) {
@@ -564,12 +579,10 @@
564
579
  * its observer never fired, and the actions stayed folded after the window
565
580
  * widened again, while a fresh load at the same width showed them all.
566
581
  */
567
- [data-ui='page-header']
582
+ [data-ui-page-header]
568
583
  > *
569
- > [data-part='title-area']
570
- > [data-part='title-row']:has(
571
- > [data-part='actions'] > [data-ui='toolbar'][data-overflow='menu']
572
- ) {
584
+ > [data-part-title-area]
585
+ > [data-part-title-row]:has(> [data-part-actions] > [data-ui-toolbar][data-overflow='menu']) {
573
586
  flex-wrap: nowrap;
574
587
  }
575
588
  /* The title starts from its own width, not from the basis a wrapping row gives it, at every
@@ -580,48 +593,42 @@
580
593
  of 420, and the toolbar beside them folded every command into its menu next to empty room. As
581
594
  a grid — the heading and its marks on the first line, the subheading across both columns
582
595
  under them — the title is as wide as its widest line. */
583
- [data-ui='page-header']
596
+ [data-ui-page-header]
584
597
  > *
585
- > [data-part='title-area']
586
- > [data-part='title-row']:has(
587
- > [data-part='actions'] > [data-ui='toolbar'][data-overflow='menu']
588
- )
589
- > [data-part='title'] {
598
+ > [data-part-title-area]
599
+ > [data-part-title-row]:has(> [data-part-actions] > [data-ui-toolbar][data-overflow='menu'])
600
+ > [data-part-title] {
590
601
  align-items: center;
591
602
  display: grid;
592
603
  flex: 0 1 auto;
593
604
  grid-template-columns: minmax(0, auto) auto;
594
605
  justify-content: start;
595
606
  }
596
- [data-ui='page-header']
607
+ [data-ui-page-header]
597
608
  > *
598
- > [data-part='title-area']
599
- > [data-part='title-row']:has(
600
- > [data-part='actions'] > [data-ui='toolbar'][data-overflow='menu']
601
- )
602
- > [data-part='title']
603
- > [data-part='heading'] {
609
+ > [data-part-title-area]
610
+ > [data-part-title-row]:has(> [data-part-actions] > [data-ui-toolbar][data-overflow='menu'])
611
+ > [data-part-title]
612
+ > [data-part-heading] {
604
613
  grid-column: 1;
605
614
  }
606
- [data-ui='page-header']
615
+ [data-ui-page-header]
607
616
  > *
608
- > [data-part='title-area']
609
- > [data-part='title-row']:has(
610
- > [data-part='actions'] > [data-ui='toolbar'][data-overflow='menu']
611
- )
612
- > [data-part='title']
613
- > [data-part='subheading'] {
617
+ > [data-part-title-area]
618
+ > [data-part-title-row]:has(> [data-part-actions] > [data-ui-toolbar][data-overflow='menu'])
619
+ > [data-part-title]
620
+ > [data-part-subheading] {
614
621
  grid-column: 1 / -1;
615
622
  }
616
623
  /* The cluster starts from nothing and grows into what the title leaves, so its width follows
617
624
  the row's in both directions. It never gives way below its menu's trigger, a medium control,
618
625
  and the toolbar's inset on either side: under it the trigger stood past the screen's edge on
619
626
  a phone. */
620
- [data-ui='page-header']
627
+ [data-ui-page-header]
621
628
  > *
622
- > [data-part='title-area']
623
- > [data-part='title-row']
624
- > [data-part='actions']:has(> [data-ui='toolbar'][data-overflow='menu']) {
629
+ > [data-part-title-area]
630
+ > [data-part-title-row]
631
+ > [data-part-actions]:has(> [data-ui-toolbar][data-overflow='menu']) {
625
632
  flex: 1 1 0%;
626
633
  min-inline-size: calc(
627
634
  var(--slotted-control-height-md, 34px) + 2 *
@@ -638,12 +645,12 @@
638
645
  stand at the end of the row as they did when the cluster was their own width. `safe`, because
639
646
  a bar of pinned controls wider than the room scrolls, and overflow at the start of a scroll
640
647
  container cannot be scrolled to. */
641
- [data-ui='page-header']
648
+ [data-ui-page-header]
642
649
  > *
643
- > [data-part='title-area']
644
- > [data-part='title-row']
645
- > [data-part='actions']
646
- > [data-ui='toolbar'][data-overflow='menu'] {
650
+ > [data-part-title-area]
651
+ > [data-part-title-row]
652
+ > [data-part-actions]
653
+ > [data-ui-toolbar][data-overflow='menu'] {
647
654
  flex: 1 1 0%;
648
655
  justify-content: safe flex-end;
649
656
  }
@@ -652,11 +659,11 @@
652
659
  * Previous and next record, after the actions and set apart from them by a
653
660
  * rule, which is where sap.f puts navigationActions.
654
661
  */
655
- [data-ui='page-header']
662
+ [data-ui-page-header]
656
663
  > *
657
- > [data-part='title-area']
658
- > [data-part='title-row']
659
- > [data-part='navigation'] {
664
+ > [data-part-title-area]
665
+ > [data-part-title-row]
666
+ > [data-part-navigation] {
660
667
  align-items: center;
661
668
  border-inline-start: var(--_rule-size) solid var(--_rule);
662
669
  display: flex;
@@ -676,12 +683,12 @@
676
683
  * for the other direction. The glyphs mirror; the order is already the
677
684
  * row's.
678
685
  */
679
- [data-ui='page-header']
686
+ [data-ui-page-header]
680
687
  > *
681
- > [data-part='title-area']
682
- > [data-part='title-row']
683
- > [data-part='navigation']:dir(rtl)
684
- :is(svg, [data-ui='icon']) {
688
+ > [data-part-title-area]
689
+ > [data-part-title-row]
690
+ > [data-part-navigation]:dir(rtl)
691
+ :is(svg, [data-ui-icon]) {
685
692
  scale: -1 1;
686
693
  }
687
694
 
@@ -692,7 +699,7 @@
692
699
  * to 0fr — the content's own height at every frame, nothing measured — as
693
700
  * collapsible does. Figure and content share the row.
694
701
  */
695
- [data-ui='page-header'] > * > [data-part='header-area'] {
702
+ [data-ui-page-header] > * > [data-part-header-area] {
696
703
  display: grid;
697
704
  grid-template-columns: auto minmax(0, 1fr);
698
705
  grid-template-rows: 1fr;
@@ -702,10 +709,10 @@
702
709
  grid-template-rows var(--_duration) var(--_easing),
703
710
  opacity var(--_duration) var(--_easing);
704
711
  }
705
- [data-ui='page-header'] > * > [data-part='header-area']:not(:has([data-part='figure'])) {
712
+ [data-ui-page-header] > * > [data-part-header-area]:not(:has([data-part-figure])) {
706
713
  grid-template-columns: minmax(0, 1fr);
707
714
  }
708
- [data-ui='page-header'] > * > [data-part='header-area'] > * {
715
+ [data-ui-page-header] > * > [data-part-header-area] > * {
709
716
  min-block-size: 0;
710
717
  }
711
718
 
@@ -715,26 +722,24 @@
715
722
  * offset is what hides the area — a 0fr row there would shorten the root
716
723
  * under the reader and jump the scroll by the area's height.
717
724
  */
718
- [data-ui='page-header']:not([data-expanded]):not([data-scrolled])
719
- > *
720
- > [data-part='header-area'] {
725
+ [data-ui-page-header]:not([data-expanded]):not([data-scrolled]) > * > [data-part-header-area] {
721
726
  grid-template-rows: 0fr;
722
727
  opacity: 0;
723
728
  }
724
- [data-ui='page-header']:not([data-expanded]):not([data-scrolled])
729
+ [data-ui-page-header]:not([data-expanded]):not([data-scrolled])
725
730
  > *
726
- > [data-part='header-area']
731
+ > [data-part-header-area]
727
732
  > * {
728
733
  overflow: clip;
729
734
  }
730
735
 
731
- [data-ui='page-header'] > * > [data-part='header-area'] > [data-part='figure'] {
736
+ [data-ui-page-header] > * > [data-part-header-area] > [data-part-figure] {
732
737
  display: flex;
733
738
  padding-block-end: var(--_padding-block);
734
739
  padding-inline-end: var(--slotted-space-6, 1rem);
735
740
  }
736
741
 
737
- [data-ui='page-header'] > * > [data-part='header-area'] > [data-part='content'] {
742
+ [data-ui-page-header] > * > [data-part-header-area] > [data-part-content] {
738
743
  display: flex;
739
744
  flex-direction: column;
740
745
  gap: var(--_gap);
@@ -742,11 +747,11 @@
742
747
  padding-block-end: var(--_padding-block);
743
748
  }
744
749
 
745
- [data-ui='page-header']
750
+ [data-ui-page-header]
746
751
  > *
747
- > [data-part='header-area']
748
- > [data-part='content']
749
- > [data-part='description'] {
752
+ > [data-part-header-area]
753
+ > [data-part-content]
754
+ > [data-part-description] {
750
755
  -webkit-box-orient: vertical;
751
756
  color: var(--_muted);
752
757
  display: -webkit-box;
@@ -761,14 +766,14 @@
761
766
 
762
767
  /* The half pill the header area's columns keep clear of the edge; see the
763
768
  title area's reservation above. After the columns' own rules, so it wins. */
764
- [data-ui='page-header']:has([data-part='controls'] > *)
769
+ [data-ui-page-header]:has([data-part-controls] > *)
765
770
  > *
766
- > [data-part='header-area']
767
- > [data-part='figure'],
768
- [data-ui='page-header']:has([data-part='controls'] > *)
771
+ > [data-part-header-area]
772
+ > [data-part-figure],
773
+ [data-ui-page-header]:has([data-part-controls] > *)
769
774
  > *
770
- > [data-part='header-area']
771
- > [data-part='content'] {
775
+ > [data-part-header-area]
776
+ > [data-part-content] {
772
777
  padding-block-end: calc(var(--_padding-block) + var(--_control-size) / 2);
773
778
  }
774
779
 
@@ -777,9 +782,9 @@
777
782
  * reserved would keep the area 27 pixels tall: the reservation goes with
778
783
  * the content, and the pill straddles the title area's own reservation.
779
784
  */
780
- [data-ui='page-header']:not([data-expanded]):not([data-scrolled])
785
+ [data-ui-page-header]:not([data-expanded]):not([data-scrolled])
781
786
  > *
782
- > [data-part='header-area']
787
+ > [data-part-header-area]
783
788
  > * {
784
789
  padding-block: 0;
785
790
  }
@@ -797,7 +802,7 @@
797
802
  * The row is `relative` and the pill `absolute`, so the tabs under it lay
798
803
  * out as if it were not there; the pill overlaps their top edge.
799
804
  */
800
- [data-ui='page-header'] > * > [data-part='controls'] {
805
+ [data-ui-page-header] > * > [data-part-controls] {
801
806
  block-size: 0;
802
807
  position: relative;
803
808
  /* Above the title area, and above the wait drawn on the same edge. */
@@ -810,16 +815,14 @@
810
815
  * Without tabs the root's edge is where the pill sits, and no second rule
811
816
  * is drawn.
812
817
  */
813
- [data-ui='page-header']:has(> * > [data-part='tabs']:not(:empty))
814
- > *
815
- > [data-part='controls']::before {
818
+ [data-ui-page-header]:has(> * > [data-part-tabs]:not(:empty)) > * > [data-part-controls]::before {
816
819
  border-block-start: var(--_rule-size) solid var(--_rule);
817
820
  content: '';
818
821
  inset-block-start: 0;
819
822
  inset-inline: -50vw;
820
823
  position: absolute;
821
824
  }
822
- [data-ui='page-header'] > * > [data-part='controls'] > * {
825
+ [data-ui-page-header] > * > [data-part-controls] > * {
823
826
  /* The pill is a control on the hairline: it keeps the surface in every variant. */
824
827
  background-color: var(--_surface);
825
828
  border: var(--_rule-size) solid var(--_rule);
@@ -842,8 +845,8 @@
842
845
  * and nothing else does; press goes one step further; both hold back for a
843
846
  * disabled control.
844
847
  */
845
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='toggle'],
846
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='pin'] {
848
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle],
849
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin] {
847
850
  /* One step above the nav row's arrow: a mark on a hairline pill reads
848
851
  thin at the small step, and the reviewer asked for weight. The marks
849
852
  are the Glyph elements the bindings render — `chevron-down` in the
@@ -869,20 +872,15 @@
869
872
  background-color var(--slotted-duration-short) var(--_easing),
870
873
  color var(--slotted-duration-short) var(--_easing);
871
874
  }
872
- [data-ui='page-header']
873
- > *
874
- > [data-part='controls']
875
- > *
876
- > [data-part='toggle']
877
- > [data-ui='icon'] {
875
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle] > [data-ui-icon] {
878
876
  transition: rotate var(--slotted-duration-short) var(--_easing);
879
877
  }
880
- [data-ui='page-header'][data-expanded]
878
+ [data-ui-page-header][data-expanded]
881
879
  > *
882
- > [data-part='controls']
880
+ > [data-part-controls]
883
881
  > *
884
- > [data-part='toggle']
885
- > [data-ui='icon'] {
882
+ > [data-part-toggle]
883
+ > [data-ui-icon] {
886
884
  rotate: 180deg;
887
885
  }
888
886
  /**
@@ -892,54 +890,38 @@
892
890
  * read, so the pin is not offered — the binding writes the fact and lets a
893
891
  * held header go — and below 600 pixels the sheet hides it on its own.
894
892
  */
895
- [data-ui='page-header'][data-tall] > * > [data-part='controls'] > * > [data-part='pin'] {
893
+ [data-ui-page-header][data-tall] > * > [data-part-controls] > * > [data-part-pin] {
896
894
  display: none;
897
895
  }
898
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='pin'][data-pressed] {
896
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin][data-pressed] {
899
897
  background-color: var(--slotted-tone-accent-surface, transparent);
900
898
  color: var(--slotted-tone-accent-text, LinkText);
901
899
  }
902
- [data-ui='page-header']
900
+ [data-ui-page-header]
903
901
  > *
904
- > [data-part='controls']
902
+ > [data-part-controls]
905
903
  > *
906
- > [data-part='pin'][data-pressed]:not(:disabled):hover {
904
+ > [data-part-pin][data-pressed]:not(:disabled):hover {
907
905
  background-color: var(--slotted-tone-accent-subtle-hover, ButtonFace);
908
906
  color: var(--slotted-tone-accent-text, LinkText);
909
907
  }
910
908
 
911
- [data-ui='page-header']
912
- > *
913
- > [data-part='controls']
914
- > *
915
- > [data-part='toggle']:not(:disabled):hover,
916
- [data-ui='page-header']
917
- > *
918
- > [data-part='controls']
919
- > *
920
- > [data-part='pin']:not(:disabled):hover {
909
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle]:not(:disabled):hover,
910
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin]:not(:disabled):hover {
921
911
  background-color: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
922
912
  color: var(--_text);
923
913
  }
924
- [data-ui='page-header']
925
- > *
926
- > [data-part='controls']
927
- > *
928
- > [data-part='toggle']:not(:disabled):active,
929
- [data-ui='page-header']
930
- > *
931
- > [data-part='controls']
932
- > *
933
- > [data-part='pin']:not(:disabled):active {
914
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle]:not(:disabled):active,
915
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin]:not(:disabled):active {
934
916
  background-color: var(--slotted-tone-secondary-subtle-active, ButtonFace);
935
917
  }
936
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='toggle']:focus-visible,
937
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='pin']:focus-visible {
918
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle]:focus-visible,
919
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin]:focus-visible {
938
920
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
939
921
  outline-offset: var(--slotted-focus-ring-offset, 2px);
940
922
  }
941
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='toggle']:disabled,
942
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='pin']:disabled {
923
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-toggle]:disabled,
924
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin]:disabled {
943
925
  color: var(--slotted-disabled-foreground, GrayText);
944
926
  cursor: default;
945
927
  }
@@ -951,18 +933,18 @@
951
933
  * why it needs no sticky of its own. The pill above it needs the room its
952
934
  * lower half takes, so the slot starts half a control down.
953
935
  */
954
- [data-ui='page-header'] > * > [data-part='tabs'] {
936
+ [data-ui-page-header] > * > [data-part-tabs] {
955
937
  /* The root's bottom edge is the tabs' track: one line, the whole width. */
956
938
  --slotted-tabs-track-color: transparent;
957
939
 
958
940
  min-inline-size: 0;
959
941
  padding-block-start: calc(var(--_control-size) / 2 + var(--slotted-space-2, 0.25rem));
960
942
  }
961
- [data-ui='page-header'] > * > [data-part='tabs']:empty {
943
+ [data-ui-page-header] > * > [data-part-tabs]:empty {
962
944
  display: none;
963
945
  }
964
946
  /* Without a pill the tabs sit on the rule. */
965
- [data-ui='page-header'] > * > [data-part='controls']:empty + [data-part='tabs'] {
947
+ [data-ui-page-header] > * > [data-part-controls]:empty + [data-part-tabs] {
966
948
  padding-block-start: 0;
967
949
  }
968
950
 
@@ -979,13 +961,13 @@
979
961
  * well and comes later. It is honoured on parts, which is where a consumer
980
962
  * writes it.
981
963
  */
982
- [data-ui='page-header'][data-expanded]
964
+ [data-ui-page-header][data-expanded]
983
965
  > *
984
- > [data-part='title-area']
966
+ > [data-part-title-area]
985
967
  [data-part][data-when='snapped'][data-when],
986
- [data-ui='page-header']:not([data-expanded])
968
+ [data-ui-page-header]:not([data-expanded])
987
969
  > *
988
- > [data-part='title-area']
970
+ > [data-part-title-area]
989
971
  [data-part][data-when='expanded'][data-when] {
990
972
  display: none;
991
973
  }
@@ -998,31 +980,31 @@
998
980
  * of the text it replaces, which is what keeps the height still when the
999
981
  * title arrives.
1000
982
  */
1001
- [data-ui='page-header'][data-loading]
983
+ [data-ui-page-header][data-loading]
1002
984
  > *
1003
- > [data-part='title-area']
1004
- > [data-part='title-row']
1005
- > [data-part='title']
1006
- > [data-part='heading'] {
985
+ > [data-part-title-area]
986
+ > [data-part-title-row]
987
+ > [data-part-title]
988
+ > [data-part-heading] {
1007
989
  /* The width a title has, and no growth: grown, the heading pushed the
1008
990
  marks to the far end and they jumped back beside it when the title
1009
991
  arrived. The bar is what the words will be. */
1010
992
  --slotted-skeleton-inline-size: 24ch;
1011
993
  flex: 0 1 auto;
1012
994
  }
1013
- [data-ui='page-header'][data-loading]
995
+ [data-ui-page-header][data-loading]
1014
996
  > *
1015
- > [data-part='title-area']
1016
- > [data-part='title-row']
1017
- > [data-part='title']
1018
- > [data-part='subheading'] {
997
+ > [data-part-title-area]
998
+ > [data-part-title-row]
999
+ > [data-part-title]
1000
+ > [data-part-subheading] {
1019
1001
  --slotted-skeleton-inline-size: 32ch;
1020
1002
  }
1021
- [data-ui='page-header'][data-loading]
1003
+ [data-ui-page-header][data-loading]
1022
1004
  > *
1023
- > [data-part='header-area']
1024
- > [data-part='content']
1025
- > [data-part='description'] {
1005
+ > [data-part-header-area]
1006
+ > [data-part-content]
1007
+ > [data-part-description] {
1026
1008
  --slotted-skeleton-inline-size: 40ch;
1027
1009
  }
1028
1010
 
@@ -1036,26 +1018,37 @@
1036
1018
  * the lines the container's own breakout part spans — so the bar is the
1037
1019
  * header's width, as the line is, and not the measure's.
1038
1020
  *
1039
- * Written after the controls and before the tabs, as the controls are, it
1040
- * stands on the edge the pill straddles; on the root's own edge the bar
1041
- * would run under the tabs and read as the selected tab's indicator drawn
1042
- * across the whole row. With no tabs it is the root's own hairline. The bar
1043
- * stands on the frame's block-end edge and its thickness rises above it,
1044
- * which is why the frame does not clip.
1021
+ * With a pill over the tabs it stands on the edge the pill straddles, the
1022
+ * line the reader already sees as the chrome's end. Otherwise it is the
1023
+ * root's own hairline, under the tabs when there are tabs: it is the only
1024
+ * line there is. The bar stands on the frame's block-end edge and its
1025
+ * thickness rises above it, which is why the frame does not clip.
1045
1026
  *
1046
1027
  * A snapped header keeps its edge on screen, and the frame keeps its place
1047
1028
  * beside the controls, so the bar stays with it. Above the title area,
1048
1029
  * whose ground would cover the bar's upper pixel once the area has slid
1049
1030
  * under the title; below the controls, whose pill straddles the same line.
1031
+ *
1032
+ * The place is the stylesheet's, not the order the parts are written in:
1033
+ * the frame is the last row, on the root's hairline, and with a pill over
1034
+ * the tabs the tabs move after it, so the frame is the row under the
1035
+ * controls. Written before the tabs with no pill, the frame was a row of
1036
+ * its own between the title and the strip, over no line.
1050
1037
  */
1051
- [data-ui='page-header'] > * > [data-part='progress'] {
1038
+ [data-ui-page-header] > * > [data-part-progress] {
1052
1039
  block-size: var(--_rule-size);
1053
1040
  grid-column: full;
1054
1041
  margin-block-end: calc(-1 * var(--_rule-size));
1042
+ order: 1;
1055
1043
  pointer-events: none;
1056
1044
  position: relative;
1057
1045
  z-index: 3;
1058
1046
  }
1047
+ [data-ui-page-header]:has(> * > [data-part-controls]):has(> * > [data-part-tabs]:not(:empty))
1048
+ > *
1049
+ > [data-part-tabs] {
1050
+ order: 2;
1051
+ }
1059
1052
 
1060
1053
  /**
1061
1054
  * One wait at a time. The title's skeleton is the first load, and a
@@ -1064,8 +1057,8 @@
1064
1057
  * inside it. The second rule reads an ARIA state rather than another
1065
1058
  * family's identity, so any region a consumer marks busy takes it.
1066
1059
  */
1067
- [data-ui='page-header'][data-loading] > * > [data-part='progress'],
1068
- [aria-busy='true'] [data-ui='page-header'] > * > [data-part='progress'] {
1060
+ [data-ui-page-header][data-loading] > * > [data-part-progress],
1061
+ [aria-busy='true'] [data-ui-page-header] > * > [data-part-progress] {
1069
1062
  display: none;
1070
1063
  }
1071
1064
 
@@ -1079,7 +1072,7 @@
1079
1072
  * against the component's own width rather than the viewport.
1080
1073
  */
1081
1074
  @container page-header (width < 600px) {
1082
- [data-ui='page-header'] {
1075
+ [data-ui-page-header] {
1083
1076
  --_heading-size: var(
1084
1077
  --slotted-page-header-heading-size-sm,
1085
1078
  var(--slotted-font-size-xl, 1.125rem)
@@ -1091,29 +1084,25 @@
1091
1084
  );
1092
1085
  --_snapped-heading-line-height: var(--slotted-line-height-md, 1.5);
1093
1086
  }
1094
- [data-ui='page-header']
1087
+ [data-ui-page-header]
1095
1088
  > *
1096
- > [data-part='title-area']
1097
- > [data-part='nav']
1098
- > [data-part='back']
1099
- ~ [data-part='breadcrumbs'] {
1089
+ > [data-part-title-area]
1090
+ > [data-part-nav]
1091
+ > [data-part-back]
1092
+ ~ [data-part-breadcrumbs] {
1100
1093
  display: none;
1101
1094
  }
1102
- [data-ui='page-header']
1095
+ [data-ui-page-header]
1103
1096
  > *
1104
- > [data-part='title-area']
1105
- > [data-part='nav']
1106
- > [data-part='back']:has(~ [data-part='breadcrumbs']:not(:empty)) {
1097
+ > [data-part-title-area]
1098
+ > [data-part-nav]
1099
+ > [data-part-back]:has(~ [data-part-breadcrumbs]:not(:empty)) {
1107
1100
  display: inline-flex;
1108
1101
  }
1109
- [data-ui='page-header'] > * > [data-part='controls'] > * > [data-part='pin'] {
1102
+ [data-ui-page-header] > * > [data-part-controls] > * > [data-part-pin] {
1110
1103
  display: none;
1111
1104
  }
1112
- [data-ui='page-header']
1113
- > *
1114
- > [data-part='title-area']
1115
- > [data-part='title-row']
1116
- > [data-part='title'] {
1105
+ [data-ui-page-header] > * > [data-part-title-area] > [data-part-title-row] > [data-part-title] {
1117
1106
  flex: 1 1 0;
1118
1107
  min-inline-size: 60%;
1119
1108
  }
@@ -1123,57 +1112,55 @@
1123
1112
  * title that leaves it room, the grown box put one button at its own
1124
1113
  * start, mid-row, off the edge every other width aligns it to.
1125
1114
  */
1126
- [data-ui='page-header']
1115
+ [data-ui-page-header]
1127
1116
  > *
1128
- > [data-part='title-area']
1129
- > [data-part='title-row']
1130
- > [data-part='actions'] {
1117
+ > [data-part-title-area]
1118
+ > [data-part-title-row]
1119
+ > [data-part-actions] {
1131
1120
  flex: 1 1 auto;
1132
1121
  justify-content: flex-end;
1133
1122
  }
1134
1123
  /* The marks take a line of their own under the heading: beside it their break depends on
1135
1124
  what they say, which the waiting header cannot know, and the header grew when it landed. */
1136
- [data-ui='page-header']
1125
+ [data-ui-page-header]
1137
1126
  > *
1138
- > [data-part='title-area']
1139
- > [data-part='title-row']
1140
- > [data-part='title']
1141
- > [data-part='marks'] {
1127
+ > [data-part-title-area]
1128
+ > [data-part-title-row]
1129
+ > [data-part-title]
1130
+ > [data-part-marks] {
1142
1131
  flex-basis: 100%;
1143
1132
  }
1144
- [data-ui='page-header']
1133
+ [data-ui-page-header]
1145
1134
  > *
1146
- > [data-part='title-area']
1147
- > [data-part='title-row']:has(
1148
- > [data-part='actions'] > [data-ui='toolbar'][data-overflow='menu']
1149
- )
1150
- > [data-part='title']
1151
- > [data-part='marks'] {
1135
+ > [data-part-title-area]
1136
+ > [data-part-title-row]:has(> [data-part-actions] > [data-ui-toolbar][data-overflow='menu'])
1137
+ > [data-part-title]
1138
+ > [data-part-marks] {
1152
1139
  grid-column: 1 / -1;
1153
1140
  }
1154
1141
  /* One line, as snapped: the phone has no second one to give it. */
1155
- [data-ui='page-header']
1142
+ [data-ui-page-header]
1156
1143
  > *
1157
- > [data-part='title-area']
1158
- > [data-part='title-row']
1159
- > [data-part='title']
1160
- > [data-part='subheading'] {
1144
+ > [data-part-title-area]
1145
+ > [data-part-title-row]
1146
+ > [data-part-title]
1147
+ > [data-part-subheading] {
1161
1148
  display: block;
1162
1149
  text-overflow: ellipsis;
1163
1150
  white-space: nowrap;
1164
1151
  }
1165
- [data-ui='page-header']
1152
+ [data-ui-page-header]
1166
1153
  > *
1167
- > [data-part='title-area']
1168
- > [data-part='title-row']
1169
- > [data-part='navigation'] {
1154
+ > [data-part-title-area]
1155
+ > [data-part-title-row]
1156
+ > [data-part-navigation] {
1170
1157
  border-inline-start: 0;
1171
1158
  padding-inline-start: 0;
1172
1159
  }
1173
- [data-ui='page-header'] > * > [data-part='header-area'] {
1160
+ [data-ui-page-header] > * > [data-part-header-area] {
1174
1161
  grid-template-columns: minmax(0, 1fr);
1175
1162
  }
1176
- [data-ui='page-header'] > * > [data-part='header-area'] > [data-part='figure'] {
1163
+ [data-ui-page-header] > * > [data-part-header-area] > [data-part-figure] {
1177
1164
  padding-block-end: var(--_gap);
1178
1165
  padding-inline-end: 0;
1179
1166
  }