@slotted/styles 0.0.0-stage → 0.1.0-beta.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 (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/package.json +276 -3
  4. package/src/accordion/accordion.css +96 -0
  5. package/src/accordion/accordion.tokens.json +14 -0
  6. package/src/action-bar/action-bar.css +455 -0
  7. package/src/action-bar/action-bar.tokens.json +50 -0
  8. package/src/action-sheet/action-sheet.css +462 -0
  9. package/src/action-sheet/action-sheet.tokens.json +59 -0
  10. package/src/alert/alert.css +764 -0
  11. package/src/alert/alert.tokens.json +77 -0
  12. package/src/app-shell/app-shell.css +1899 -0
  13. package/src/app-shell/app-shell.tokens.json +88 -0
  14. package/src/aspect-ratio/aspect-ratio.css +131 -0
  15. package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
  16. package/src/attachment/attachment.css +906 -0
  17. package/src/attachment/attachment.tokens.json +85 -0
  18. package/src/avatar/avatar.css +598 -0
  19. package/src/avatar/avatar.tokens.json +64 -0
  20. package/src/avatar-group/avatar-group.css +268 -0
  21. package/src/avatar-group/avatar-group.tokens.json +16 -0
  22. package/src/badge/badge.css +462 -0
  23. package/src/badge/badge.tokens.json +58 -0
  24. package/src/breadcrumb/breadcrumb.css +441 -0
  25. package/src/breadcrumb/breadcrumb.tokens.json +50 -0
  26. package/src/button/button.css +754 -0
  27. package/src/button/button.tokens.json +72 -0
  28. package/src/button-group/button-group.css +455 -0
  29. package/src/button-group/button-group.tokens.json +11 -0
  30. package/src/calendar/calendar.css +846 -0
  31. package/src/calendar/calendar.tokens.json +67 -0
  32. package/src/card/card.css +602 -0
  33. package/src/card/card.tokens.json +68 -0
  34. package/src/carousel/carousel.css +860 -0
  35. package/src/carousel/carousel.tokens.json +62 -0
  36. package/src/cascader/cascader.css +1320 -0
  37. package/src/cascader/cascader.tokens.json +103 -0
  38. package/src/chart/chart.css +1473 -0
  39. package/src/chart/chart.tokens.json +107 -0
  40. package/src/checkbox/checkbox.css +1011 -0
  41. package/src/checkbox/checkbox.tokens.json +102 -0
  42. package/src/checkbox-group/checkbox-group.css +70 -0
  43. package/src/checkbox-group/checkbox-group.tokens.json +6 -0
  44. package/src/code-block/code-block.css +555 -0
  45. package/src/code-block/code-block.tokens.json +69 -0
  46. package/src/collapsible/collapsible.css +546 -0
  47. package/src/collapsible/collapsible.tokens.json +55 -0
  48. package/src/color-picker/color-picker.css +607 -0
  49. package/src/color-picker/color-picker.tokens.json +58 -0
  50. package/src/column-manager/column-manager.css +452 -0
  51. package/src/column-manager/column-manager.tokens.json +43 -0
  52. package/src/combobox/combobox.css +1048 -0
  53. package/src/combobox/combobox.tokens.json +112 -0
  54. package/src/command-palette/command-palette.css +1000 -0
  55. package/src/command-palette/command-palette.tokens.json +75 -0
  56. package/src/container/container.css +198 -0
  57. package/src/container/container.tokens.json +18 -0
  58. package/src/context-menu/context-menu.css +104 -0
  59. package/src/context-menu/context-menu.tokens.json +11 -0
  60. package/src/currency-field/currency-field.css +787 -0
  61. package/src/currency-field/currency-field.tokens.json +80 -0
  62. package/src/dashboard-grid/dashboard-grid.css +748 -0
  63. package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
  64. package/src/data-grid/data-grid.css +2484 -0
  65. package/src/data-grid/data-grid.tokens.json +100 -0
  66. package/src/data-list/data-list.css +455 -0
  67. package/src/data-list/data-list.tokens.json +35 -0
  68. package/src/date-field/date-field.css +560 -0
  69. package/src/date-field/date-field.tokens.json +80 -0
  70. package/src/date-picker/date-picker.css +420 -0
  71. package/src/date-picker/date-picker.tokens.json +49 -0
  72. package/src/date-range-picker/date-range-picker.css +983 -0
  73. package/src/date-range-picker/date-range-picker.tokens.json +109 -0
  74. package/src/datetime-field/datetime-field.css +850 -0
  75. package/src/datetime-field/datetime-field.tokens.json +91 -0
  76. package/src/datetime-picker/datetime-picker.css +843 -0
  77. package/src/datetime-picker/datetime-picker.tokens.json +78 -0
  78. package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
  79. package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
  80. package/src/description-list/description-list.css +675 -0
  81. package/src/description-list/description-list.tokens.json +66 -0
  82. package/src/detail-panel/detail-panel.css +329 -0
  83. package/src/detail-panel/detail-panel.tokens.json +33 -0
  84. package/src/dialog/dialog.css +968 -0
  85. package/src/dialog/dialog.tokens.json +66 -0
  86. package/src/divider/divider.css +131 -0
  87. package/src/divider/divider.tokens.json +18 -0
  88. package/src/drawer/drawer.css +1303 -0
  89. package/src/drawer/drawer.tokens.json +75 -0
  90. package/src/entity-picker/entity-picker.css +1367 -0
  91. package/src/entity-picker/entity-picker.tokens.json +118 -0
  92. package/src/event-calendar/event-calendar.css +2148 -0
  93. package/src/event-calendar/event-calendar.tokens.json +87 -0
  94. package/src/field/field.css +707 -0
  95. package/src/field/field.tokens.json +58 -0
  96. package/src/field-group/field-group.css +226 -0
  97. package/src/field-group/field-group.tokens.json +33 -0
  98. package/src/filter-bar/filter-bar.css +1306 -0
  99. package/src/filter-bar/filter-bar.tokens.json +78 -0
  100. package/src/form/form.css +218 -0
  101. package/src/form/form.tokens.json +32 -0
  102. package/src/fullscreen/fullscreen.css +376 -0
  103. package/src/fullscreen/fullscreen.tokens.json +50 -0
  104. package/src/grid/grid.css +173 -0
  105. package/src/grid/grid.tokens.json +20 -0
  106. package/src/highlight/highlight.css +135 -0
  107. package/src/highlight/highlight.tokens.json +16 -0
  108. package/src/hover-card/hover-card.css +93 -0
  109. package/src/hover-card/hover-card.tokens.json +17 -0
  110. package/src/icon/icon.css +136 -0
  111. package/src/icon/icon.tokens.json +14 -0
  112. package/src/image/image.css +449 -0
  113. package/src/image/image.tokens.json +27 -0
  114. package/src/import-export-center/import-export-center.css +1175 -0
  115. package/src/import-export-center/import-export-center.tokens.json +84 -0
  116. package/src/inline/inline.css +149 -0
  117. package/src/inline/inline.tokens.json +14 -0
  118. package/src/inline-message/inline-message.css +396 -0
  119. package/src/inline-message/inline-message.tokens.json +19 -0
  120. package/src/kbd/kbd.css +490 -0
  121. package/src/kbd/kbd.tokens.json +40 -0
  122. package/src/link/link.css +237 -0
  123. package/src/link/link.tokens.json +25 -0
  124. package/src/list/list.css +240 -0
  125. package/src/list/list.tokens.json +42 -0
  126. package/src/list-item/list-item.css +937 -0
  127. package/src/list-item/list-item.tokens.json +114 -0
  128. package/src/listbox/listbox.css +674 -0
  129. package/src/listbox/listbox.tokens.json +72 -0
  130. package/src/loading-overlay/loading-overlay.css +730 -0
  131. package/src/loading-overlay/loading-overlay.tokens.json +48 -0
  132. package/src/markdown/markdown.css +168 -0
  133. package/src/markdown/markdown.tokens.json +18 -0
  134. package/src/menu/menu.css +817 -0
  135. package/src/menu/menu.tokens.json +78 -0
  136. package/src/menubar/menubar.css +170 -0
  137. package/src/menubar/menubar.tokens.json +32 -0
  138. package/src/message/message.css +1453 -0
  139. package/src/message/message.tokens.json +85 -0
  140. package/src/message-scroller/message-scroller.css +371 -0
  141. package/src/message-scroller/message-scroller.tokens.json +47 -0
  142. package/src/multi-select/multi-select.css +1427 -0
  143. package/src/multi-select/multi-select.tokens.json +114 -0
  144. package/src/navigation-menu/navigation-menu.css +1029 -0
  145. package/src/navigation-menu/navigation-menu.tokens.json +70 -0
  146. package/src/notification-center/notification-center.css +856 -0
  147. package/src/notification-center/notification-center.tokens.json +84 -0
  148. package/src/number-field/number-field.css +794 -0
  149. package/src/number-field/number-field.tokens.json +80 -0
  150. package/src/otp-input/otp-input.css +525 -0
  151. package/src/otp-input/otp-input.tokens.json +69 -0
  152. package/src/page/page.css +179 -0
  153. package/src/page/page.tokens.json +20 -0
  154. package/src/page-header/page-header.css +1181 -0
  155. package/src/page-header/page-header.tokens.json +71 -0
  156. package/src/pagination/pagination.css +500 -0
  157. package/src/pagination/pagination.tokens.json +56 -0
  158. package/src/popover/popover.css +526 -0
  159. package/src/popover/popover.tokens.json +60 -0
  160. package/src/progress-indicator/progress-indicator.css +1584 -0
  161. package/src/progress-indicator/progress-indicator.tokens.json +50 -0
  162. package/src/prompt-composer/prompt-composer.css +680 -0
  163. package/src/prompt-composer/prompt-composer.tokens.json +99 -0
  164. package/src/prose/prose.css +733 -0
  165. package/src/prose/prose.tokens.json +79 -0
  166. package/src/radio-group/radio-group.css +778 -0
  167. package/src/radio-group/radio-group.tokens.json +103 -0
  168. package/src/rating/rating.css +1071 -0
  169. package/src/rating/rating.tokens.json +88 -0
  170. package/src/result-state/result-state.css +980 -0
  171. package/src/result-state/result-state.tokens.json +63 -0
  172. package/src/runtime-properties.mjs +321 -0
  173. package/src/saved-views/saved-views.css +394 -0
  174. package/src/saved-views/saved-views.tokens.json +41 -0
  175. package/src/scroll-area/scroll-area.css +481 -0
  176. package/src/scroll-area/scroll-area.tokens.json +15 -0
  177. package/src/section/section.css +177 -0
  178. package/src/section/section.tokens.json +39 -0
  179. package/src/segmented-control/segmented-control.css +564 -0
  180. package/src/segmented-control/segmented-control.tokens.json +67 -0
  181. package/src/select/select.css +1593 -0
  182. package/src/select/select.tokens.json +110 -0
  183. package/src/side-navigation/side-navigation.css +1096 -0
  184. package/src/side-navigation/side-navigation.tokens.json +87 -0
  185. package/src/skeleton/skeleton.css +431 -0
  186. package/src/skeleton/skeleton.tokens.json +29 -0
  187. package/src/slider/slider.css +792 -0
  188. package/src/slider/slider.tokens.json +75 -0
  189. package/src/sparkline/sparkline.css +282 -0
  190. package/src/sparkline/sparkline.tokens.json +45 -0
  191. package/src/spinner/spinner.css +224 -0
  192. package/src/spinner/spinner.tokens.json +8 -0
  193. package/src/split-button/split-button.css +253 -0
  194. package/src/split-button/split-button.tokens.json +12 -0
  195. package/src/splitter/splitter.css +336 -0
  196. package/src/splitter/splitter.tokens.json +24 -0
  197. package/src/stack/stack.css +128 -0
  198. package/src/stack/stack.tokens.json +14 -0
  199. package/src/stat-card/stat-card.css +641 -0
  200. package/src/stat-card/stat-card.tokens.json +95 -0
  201. package/src/status-indicator/status-indicator.css +481 -0
  202. package/src/status-indicator/status-indicator.tokens.json +38 -0
  203. package/src/stepper/stepper.css +629 -0
  204. package/src/stepper/stepper.tokens.json +72 -0
  205. package/src/switch/switch.css +703 -0
  206. package/src/switch/switch.tokens.json +75 -0
  207. package/src/table/table.css +1482 -0
  208. package/src/table/table.tokens.json +69 -0
  209. package/src/table-of-contents/table-of-contents.css +533 -0
  210. package/src/table-of-contents/table-of-contents.tokens.json +53 -0
  211. package/src/tabs/tabs.css +998 -0
  212. package/src/tabs/tabs.tokens.json +82 -0
  213. package/src/tag/tag.css +768 -0
  214. package/src/tag/tag.tokens.json +85 -0
  215. package/src/tags-input/tags-input.css +757 -0
  216. package/src/tags-input/tags-input.tokens.json +84 -0
  217. package/src/text-field/text-field.css +900 -0
  218. package/src/text-field/text-field.tokens.json +87 -0
  219. package/src/textarea/textarea.css +365 -0
  220. package/src/textarea/textarea.tokens.json +59 -0
  221. package/src/time-field/time-field.css +719 -0
  222. package/src/time-field/time-field.tokens.json +86 -0
  223. package/src/time-picker/time-picker.css +665 -0
  224. package/src/time-picker/time-picker.tokens.json +66 -0
  225. package/src/time-range-picker/time-range-picker.css +1287 -0
  226. package/src/time-range-picker/time-range-picker.tokens.json +134 -0
  227. package/src/timeline/timeline.css +1596 -0
  228. package/src/timeline/timeline.tokens.json +96 -0
  229. package/src/toast/toast.css +943 -0
  230. package/src/toast/toast.tokens.json +90 -0
  231. package/src/toggle/toggle.css +290 -0
  232. package/src/toggle/toggle.tokens.json +54 -0
  233. package/src/toggle-group/toggle-group.css +463 -0
  234. package/src/toggle-group/toggle-group.tokens.json +54 -0
  235. package/src/toolbar/toolbar.css +434 -0
  236. package/src/toolbar/toolbar.tokens.json +49 -0
  237. package/src/tooltip/tooltip.css +368 -0
  238. package/src/tooltip/tooltip.tokens.json +39 -0
  239. package/src/top-navigation/top-navigation.css +1287 -0
  240. package/src/top-navigation/top-navigation.tokens.json +91 -0
  241. package/src/tour/tour.css +680 -0
  242. package/src/tour/tour.tokens.json +67 -0
  243. package/src/transfer/transfer.css +571 -0
  244. package/src/transfer/transfer.tokens.json +49 -0
  245. package/src/tree/tree.css +1000 -0
  246. package/src/tree/tree.tokens.json +80 -0
  247. package/src/typography/typography.css +211 -0
  248. package/src/typography/typography.tokens.json +31 -0
  249. package/src/upload/upload.css +1706 -0
  250. package/src/upload/upload.tokens.json +123 -0
  251. package/src/visually-hidden/visually-hidden.css +52 -0
  252. package/src/visually-hidden/visually-hidden.tokens.json +1 -0
  253. package/src/wizard/wizard.css +740 -0
  254. package/src/wizard/wizard.tokens.json +63 -0
@@ -0,0 +1,733 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * Prose is the typography of a region the application did not author element
4
+ * by element. The tree arrives from a Markdown renderer, a CMS or a language
5
+ * model, and the page never gets to put an attribute on the `h2`.
6
+ *
7
+ * Three things style those bare tags, and this family must lose to the other
8
+ * two: a Slotted family placed inside the region, selected by `data-ui` at
9
+ * 0-1-0, and the consumer's own rule. So every content rule below is written
10
+ *
11
+ * [data-ui='prose'] :where(<tag>):not(:where(<the donut>))
12
+ *
13
+ * which weighs 0-1-0 — the root and nothing else. `:where()` has no weight,
14
+ * and `:not()` takes the weight of its argument, which here is also none.
15
+ *
16
+ * The donut is the opt-out: `data-part='exclude'` and everything inside it.
17
+ * `@scope ([data-ui='prose']) to ([data-part='exclude'])` says the same thing
18
+ * in one line and resolves lower still, and it was refused on a date rather
19
+ * than on a principle: it reached Baseline in March 2026, and an `@scope`
20
+ * block a browser cannot parse drops this whole stylesheet instead of one
21
+ * declaration. The attribute is the same either way, so the move costs no
22
+ * contract change. `specs/components/prose/contract.json` holds the note.
23
+ */
24
+ [data-ui='prose'] {
25
+ /**
26
+ * The space between blocks. Typeset proves one number governs a whole page
27
+ * — heading gaps, list gaps and the room around a rule all derive from it —
28
+ * and the `flow` axis names the three values worth having instead of asking
29
+ * every consumer to pick a length.
30
+ *
31
+ * It is stated in `em`, like the heading ladder below, because block rhythm
32
+ * that did not follow the type would tighten as the reader enlarged it.
33
+ */
34
+ --_flow: var(--slotted-prose-flow-normal, 1.15em);
35
+
36
+ /**
37
+ * The heading ladder, and the family's only other literals. A heading in
38
+ * editorial content is sized relative to the text it introduces; the
39
+ * foundation type scale is a scale of absolute control steps that stops at
40
+ * 1.5rem because no control needs more. An `h1` taken from it would be 1.33
41
+ * times its own body text at `size="xl"`, and adding a fourth step to the
42
+ * scale would change ground thirty-four families stand on to serve this
43
+ * one. `docs/history/designs/2026-09-04-prose-design.md` section 5 holds
44
+ * the trade; `docs/token-foundation.md` rule 1 grants the exemption to a
45
+ * family token whose reason is recorded, which is what `container` already
46
+ * used for its three page widths.
47
+ */
48
+ --_h1: var(--slotted-prose-h1-size, 2em);
49
+ --_h2: var(--slotted-prose-h2-size, 1.5em);
50
+ --_h3: var(--slotted-prose-h3-size, 1.25em);
51
+ --_h4: var(--slotted-prose-h4-size, 1.125em);
52
+ --_h5: var(--slotted-prose-h5-size, 1em);
53
+ --_h6: var(--slotted-prose-h6-size, 0.875em);
54
+
55
+ --_muted: var(--slotted-text-muted, GrayText);
56
+ --_rule: var(--slotted-border-subtle, ButtonBorder);
57
+ --_ground: var(--slotted-surface-sunken, Canvas);
58
+
59
+ /**
60
+ * The query container. It restyles descendants only and never the root's
61
+ * own tracks, so the family needs one element rather than the two
62
+ * `docs/build-briefing.md` requires of a family that resizes its own grid.
63
+ */
64
+ container-name: slotted-prose;
65
+ container-type: inline-size;
66
+
67
+ font-family: var(
68
+ --slotted-prose-font-family,
69
+ var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif)
70
+ );
71
+ /* One rem, not the control step: a paragraph is not a button label. */
72
+ font-size: var(--slotted-font-size-lg, 1rem);
73
+ /**
74
+ * The reading leading, stated once rather than taken per step. The scale
75
+ * pairs 1.45 with its two largest steps because a control's label is one
76
+ * line; SC 1.4.8 asks a paragraph for at least 1.5, and a paragraph is
77
+ * what this family sets.
78
+ */
79
+ line-height: var(--slotted-prose-line-height, var(--slotted-line-height-md, 1.5));
80
+ /**
81
+ * A word longer than its column breaks rather than escaping it, in the
82
+ * form that also lowers the element's min-content size — so a pasted URL
83
+ * cannot widen the table cell or the grid track that holds it. The
84
+ * property inherits, which is the point: it reaches every tag below
85
+ * without a rule of its own.
86
+ */
87
+ overflow-wrap: anywhere;
88
+ /* No colour is painted: text on a tonal surface reads that surface. */
89
+ }
90
+
91
+ /* ── The two axes ───────────────────────────────────────────────────── */
92
+
93
+ /**
94
+ * Named for the type-scale step the body takes, as `typography`'s own axis
95
+ * is, so the offset from control type is a fact a reader can check rather
96
+ * than one hidden behind `sm`.
97
+ */
98
+ [data-ui='prose'][data-size='md'] {
99
+ font-size: var(--slotted-font-size-md, 0.875rem);
100
+ }
101
+
102
+ [data-ui='prose'][data-size='lg'] {
103
+ font-size: var(--slotted-font-size-lg, 1rem);
104
+ }
105
+
106
+ [data-ui='prose'][data-size='xl'] {
107
+ font-size: var(--slotted-font-size-xl, 1.125rem);
108
+ }
109
+
110
+ [data-ui='prose'][data-flow='tight'] {
111
+ --_flow: var(--slotted-prose-flow-tight, 0.75em);
112
+ }
113
+
114
+ [data-ui='prose'][data-flow='normal'] {
115
+ --_flow: var(--slotted-prose-flow-normal, 1.15em);
116
+ }
117
+
118
+ [data-ui='prose'][data-flow='loose'] {
119
+ --_flow: var(--slotted-prose-flow-loose, 1.6em);
120
+ }
121
+
122
+ /* ── Flow ───────────────────────────────────────────────────────────────
123
+ *
124
+ * Every gap in this family is a `margin-block-start` on the block that
125
+ * arrives, and nothing selects forward. `:last-child`, `:has()` and `:empty`
126
+ * each change their own match when a block is appended, which restyles text
127
+ * already under the reader's eye — the failure a page streaming a language
128
+ * model's answer hits on every token. `:first-child` and `+` look backwards
129
+ * and are stable, and `prose.styles.test.mjs` holds the distinction.
130
+ */
131
+
132
+ [data-ui='prose']
133
+ :where(
134
+ p,
135
+ ul,
136
+ ol,
137
+ dl,
138
+ pre,
139
+ table,
140
+ figure,
141
+ blockquote,
142
+ details,
143
+ hr,
144
+ h1,
145
+ h2,
146
+ h3,
147
+ h4,
148
+ h5,
149
+ h6,
150
+ [data-part='scroll'],
151
+ [data-part='footnotes']
152
+ ):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
153
+ margin-block-end: 0;
154
+ margin-block-start: var(--_flow);
155
+ }
156
+
157
+ /**
158
+ * Nothing opens with space it did not ask for. The rule reaches the first
159
+ * child of the region and of every box that holds blocks of its own, so a
160
+ * quotation, a list item and a table cell each start flush.
161
+ */
162
+ [data-ui='prose'] > :first-child,
163
+ [data-ui='prose']
164
+ :where(li, blockquote, td, th, details, figure, [data-part='scroll'])
165
+ > :first-child {
166
+ margin-block-start: 0;
167
+ }
168
+
169
+ /**
170
+ * A heading binds to the text it introduces: more room above it than below.
171
+ * The pair is what keeps two consecutive headings — a section title followed
172
+ * by its first subsection — from collapsing into one block.
173
+ */
174
+ [data-ui='prose']
175
+ :where(h1, h2, h3, h4, h5, h6):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
176
+ color: var(--slotted-text, CanvasText);
177
+ font-family: var(
178
+ --slotted-font-family-heading,
179
+ var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif)
180
+ );
181
+ font-weight: var(--slotted-font-weight-semibold, 600);
182
+ line-height: var(--slotted-line-height-2xl, 1.4);
183
+ /**
184
+ * The gap above a heading is stated in the heading's own `em`, so it grows
185
+ * with the level: 48 pixels above an `h2` and 40 above an `h3` at the
186
+ * default step. That compounding is the decision, not a side effect —
187
+ * Tailwind reaches the same two distances by tuning six per-level values
188
+ * by hand, and one ratio that follows the ladder is the same result
189
+ * without the table.
190
+ */
191
+ margin-block-start: calc(var(--_flow) * 1.75);
192
+ /**
193
+ * A heading reached by its own anchor stops below the top edge rather than
194
+ * against it, so the reader lands on a title with its text under it.
195
+ */
196
+ scroll-margin-block-start: var(--_flow);
197
+ text-wrap: balance;
198
+ }
199
+
200
+ [data-ui='prose']
201
+ :where(h1, h2, h3, h4, h5, h6)
202
+ + :not(:where([data-part='exclude'], [data-part='exclude'] *)) {
203
+ margin-block-start: calc(var(--_flow) * 0.5);
204
+ }
205
+
206
+ [data-ui='prose'] :where(h1):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
207
+ font-size: var(--_h1);
208
+ line-height: var(--slotted-line-height-3xl, 1.3);
209
+ }
210
+
211
+ [data-ui='prose'] :where(h2):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
212
+ font-size: var(--_h2);
213
+ line-height: var(--slotted-line-height-3xl, 1.3);
214
+ }
215
+
216
+ [data-ui='prose'] :where(h3):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
217
+ font-size: var(--_h3);
218
+ }
219
+
220
+ [data-ui='prose'] :where(h4):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
221
+ font-size: var(--_h4);
222
+ }
223
+
224
+ [data-ui='prose'] :where(h5):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
225
+ font-size: var(--_h5);
226
+ }
227
+
228
+ /**
229
+ * The sixth level is smaller than the body text, so weight and case are what
230
+ * carry it. A heading that is merely smaller reads as a caption.
231
+ */
232
+ [data-ui='prose'] :where(h6):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
233
+ color: var(--_muted);
234
+ font-size: var(--_h6);
235
+ letter-spacing: var(--slotted-prose-h6-tracking, 0.06em);
236
+ text-transform: uppercase;
237
+ }
238
+
239
+ /**
240
+ * The Arabic script joins its letters and has no case at all, so the
241
+ * tracking that pays back what capitals took would sever the joins. The list
242
+ * is the common languages written in it, which is the correction
243
+ * `typography` already carries.
244
+ */
245
+ [data-ui='prose']
246
+ :where(h6):not(:where([data-part='exclude'], [data-part='exclude'] *)):where(
247
+ :lang(ar),
248
+ :lang(fa),
249
+ :lang(ur)
250
+ ) {
251
+ letter-spacing: normal;
252
+ text-transform: none;
253
+ }
254
+
255
+ /* ── Running text ───────────────────────────────────────────────────── */
256
+
257
+ [data-ui='prose'] :where(p):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
258
+ /**
259
+ * `pretty` asks the browser for the last few lines rather than the whole
260
+ * paragraph, which is what keeps a widow off the end without the cost
261
+ * `balance` carries over a long block.
262
+ */
263
+ text-wrap: pretty;
264
+ }
265
+
266
+ [data-ui='prose'] :where(strong, b):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
267
+ font-weight: var(--slotted-font-weight-semibold, 600);
268
+ }
269
+
270
+ [data-ui='prose'] :where(small):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
271
+ font-size: var(--slotted-prose-small-size, 0.875em);
272
+ }
273
+
274
+ /**
275
+ * The one element in editorial text that carries a colour of its own. The
276
+ * warning tone is the highlighter a reader recognises, and the pair is the
277
+ * theme's own — a mark painted with a background and no matching ink is a
278
+ * mark that vanishes in the dark scheme.
279
+ */
280
+ [data-ui='prose'] :where(mark):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
281
+ background-color: var(--slotted-tone-warning-surface, Mark);
282
+ border-radius: var(--slotted-radius-xs, 2px);
283
+ color: var(--slotted-tone-warning-text, MarkText);
284
+ padding-inline: var(--slotted-prose-mark-inset, 0.2em);
285
+ }
286
+
287
+ [data-ui='prose']
288
+ :where(abbr[title]):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
289
+ text-decoration-line: underline;
290
+ text-decoration-style: dotted;
291
+ text-underline-offset: 0.2em;
292
+ }
293
+
294
+ /**
295
+ * A raised or lowered figure takes its own line height out of the line it
296
+ * sits in; zero is what keeps the paragraph's rhythm even where a footnote
297
+ * reference lands.
298
+ */
299
+ [data-ui='prose'] :where(sub, sup):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
300
+ font-size: 0.75em;
301
+ line-height: 0;
302
+ }
303
+
304
+ /* ── Links ──────────────────────────────────────────────────────────────
305
+ *
306
+ * A bare `a` from a Markdown renderer reads the `link` family's own tokens,
307
+ * so a rendered link and a `<Link>` on the same page are one theme decision
308
+ * rather than two colours for one idea. No selector here names another
309
+ * family's `data-ui`, which is the rule `accordion` and `collapsible` set: a
310
+ * `<Link>` placed inside this region wins on specificity and is left alone.
311
+ */
312
+
313
+ [data-ui='prose'] :where(a[href]):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
314
+ color: var(--slotted-link-color, var(--slotted-tone-accent-text, LinkText));
315
+ text-decoration-color: var(
316
+ --slotted-link-underline-color,
317
+ color-mix(in oklab, currentColor 55%, transparent)
318
+ );
319
+ text-decoration-line: underline;
320
+ text-decoration-thickness: var(--slotted-link-underline-thickness, from-font);
321
+ text-underline-offset: var(--slotted-link-underline-offset, 0.15em);
322
+ transition:
323
+ color var(--slotted-duration-short) var(--slotted-easing-standard),
324
+ text-decoration-color var(--slotted-duration-short) var(--slotted-easing-standard);
325
+ }
326
+
327
+ [data-ui='prose']
328
+ :where(a[href]):not(:where([data-part='exclude'], [data-part='exclude'] *)):not(
329
+ [data-disabled]
330
+ ):hover {
331
+ color: var(
332
+ --slotted-link-color-hover,
333
+ color-mix(
334
+ in oklab,
335
+ var(--slotted-link-color, var(--slotted-tone-accent-text, LinkText)) 65%,
336
+ var(--slotted-text, CanvasText)
337
+ )
338
+ );
339
+ text-decoration-color: currentColor;
340
+ }
341
+
342
+ [data-ui='prose']
343
+ :where(a[href]):not(:where([data-part='exclude'], [data-part='exclude'] *)):focus-visible {
344
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
345
+ outline-offset: var(--slotted-link-focus-ring-offset, 1px);
346
+ }
347
+
348
+ /* ── Lists ──────────────────────────────────────────────────────────────
349
+ *
350
+ * The native `::marker` is kept. `list-item` draws its own because its row is
351
+ * a grid and CSS has no `display` that is both `list-item` and a grid; an
352
+ * editorial `li` is not a grid, and removing the marker costs the list
353
+ * semantics Safari drops with it —
354
+ * <https://www.scottohara.me/blog/2019/01/12/lists-and-safari.html>.
355
+ */
356
+
357
+ [data-ui='prose'] :where(ul, ol):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
358
+ padding-inline-start: var(--slotted-prose-list-inset, 1.5em);
359
+ }
360
+
361
+ [data-ui='prose'] :where(li):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
362
+ margin-block-start: calc(var(--_flow) * 0.35);
363
+ padding-inline-start: var(--slotted-prose-marker-gap, 0.25em);
364
+ }
365
+
366
+ [data-ui='prose'] :where(li):not(:where([data-part='exclude'], [data-part='exclude'] *))::marker {
367
+ color: var(--_muted);
368
+ }
369
+
370
+ /**
371
+ * A nested list belongs to the row above it, so it takes the gap between two
372
+ * rows rather than the gap between two blocks.
373
+ */
374
+ [data-ui='prose']
375
+ :where(li)
376
+ > :where(ul, ol):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
377
+ margin-block-start: calc(var(--_flow) * 0.35);
378
+ }
379
+
380
+ [data-ui='prose'] :where(dt):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
381
+ font-weight: var(--slotted-font-weight-semibold, 600);
382
+ margin-block-start: calc(var(--_flow) * 0.5);
383
+ }
384
+
385
+ [data-ui='prose'] :where(dd):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
386
+ margin-inline-start: var(--slotted-prose-list-inset, 1.5em);
387
+ }
388
+
389
+ /* ── Quotation ──────────────────────────────────────────────────────── */
390
+
391
+ [data-ui='prose'] :where(blockquote):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
392
+ border-inline-start: var(
393
+ --slotted-prose-quote-thickness,
394
+ var(--slotted-border-width-thick, 2px)
395
+ )
396
+ solid var(--slotted-prose-quote-color, var(--slotted-border-strong, ButtonBorder));
397
+ color: var(--_muted);
398
+ /**
399
+ * The user agent indents a quotation by forty physical pixels of its own,
400
+ * and a family that never says otherwise inherits them: the rule of this
401
+ * blockquote stood a whole indent to the right of the paragraph above it
402
+ * in the first capture of this family, and the figure below it did the
403
+ * same. The reset is what makes the quotation's rule land on the text's
404
+ * own margin.
405
+ */
406
+ margin-inline: 0;
407
+ padding-inline-start: var(--slotted-prose-quote-inset, 1em);
408
+ }
409
+
410
+ /** The same forty pixels, on the element that holds an image. */
411
+ [data-ui='prose'] :where(figure):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
412
+ margin-inline: 0;
413
+ }
414
+
415
+ [data-ui='prose']
416
+ :where(figcaption, caption):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
417
+ color: var(--_muted);
418
+ font-size: var(--slotted-prose-caption-size, 0.875em);
419
+ margin-block-start: calc(var(--_flow) * 0.5);
420
+ text-align: start;
421
+ }
422
+
423
+ /* ── Media ──────────────────────────────────────────────────────────── */
424
+
425
+ [data-ui='prose']
426
+ :where(img, svg, video, canvas):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
427
+ block-size: auto;
428
+ border-radius: var(--slotted-prose-media-radius, var(--slotted-radius-md, 6px));
429
+ display: block;
430
+ max-inline-size: 100%;
431
+ }
432
+
433
+ /* ── Code ───────────────────────────────────────────────────────────────
434
+ *
435
+ * The type, the ground and the inset. Highlighting, a copy control, line
436
+ * numbers and a wrap toggle belong to `code-block` in wave 8; a Markdown
437
+ * fence needs none of them to be readable.
438
+ *
439
+ * The ground is a fill and the edge is a border, deliberately: under forced
440
+ * colours the fill is replaced and the border is what still says where the
441
+ * code starts.
442
+ */
443
+
444
+ [data-ui='prose']
445
+ :where(code, kbd, samp, var):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
446
+ font-family: var(--slotted-font-family-mono, ui-monospace, monospace);
447
+ /* The mono face runs large beside the sans at the same size. */
448
+ font-size: var(--slotted-prose-code-size, 0.9em);
449
+ }
450
+
451
+ [data-ui='prose'] :where(code):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
452
+ background-color: var(--_ground);
453
+ border: var(--slotted-border-width-thin, 1px) solid var(--_rule);
454
+ border-radius: var(--slotted-radius-sm, 4px);
455
+ padding-inline: var(--slotted-prose-code-inset, 0.3em);
456
+ }
457
+
458
+ [data-ui='prose'] :where(kbd):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
459
+ background-color: var(--slotted-surface-raised, Canvas);
460
+ border: var(--slotted-kbd-border-width, var(--slotted-border-width-thin, 1px)) solid
461
+ var(--slotted-border-strong, ButtonBorder);
462
+ border-radius: var(--slotted-kbd-radius, var(--slotted-radius-sm, 4px));
463
+ font-family: var(--slotted-kbd-font-family, var(--slotted-font-family-mono, monospace));
464
+ font-weight: var(--slotted-kbd-font-weight, var(--slotted-font-weight-medium, 500));
465
+ padding-inline: var(--slotted-prose-code-inset, 0.3em);
466
+ }
467
+
468
+ [data-ui='prose'] :where(pre):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
469
+ background-color: var(--_ground);
470
+ /**
471
+ * A fence reads left to right in a right-to-left document: the order of
472
+ * the characters is what the code means, and the first RTL capture of this
473
+ * family showed the block aligned to the right with its check marks
474
+ * trailing. The rule is the block's own, so an Arabic sentence around it
475
+ * is untouched.
476
+ */
477
+ direction: ltr;
478
+ border: var(--slotted-border-width-thin, 1px) solid var(--_rule);
479
+ border-radius: var(--slotted-prose-media-radius, var(--slotted-radius-md, 6px));
480
+ overflow-x: auto;
481
+ padding-block: var(--slotted-space-5, 0.75rem);
482
+ padding-inline: var(--slotted-space-6, 1rem);
483
+ }
484
+
485
+ /** A fence is one box, not a box of boxes. */
486
+ [data-ui='prose']
487
+ :where(pre)
488
+ > :where(code):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
489
+ background-color: transparent;
490
+ border: 0;
491
+ border-radius: 0;
492
+ font-size: inherit;
493
+ padding-inline: 0;
494
+ }
495
+
496
+ /* ── Tables ─────────────────────────────────────────────────────────────
497
+ *
498
+ * The rhythm and the rules. Sorting, sticky headers, column resize and row
499
+ * selection are the `table` family of wave 6.
500
+ *
501
+ * Every separator sits on the row that arrives — `tr + tr` looks backwards —
502
+ * so a row appended to a streaming answer restyles nothing above it.
503
+ */
504
+
505
+ [data-ui='prose'] :where(table):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
506
+ border-collapse: collapse;
507
+ inline-size: 100%;
508
+ text-align: start;
509
+ }
510
+
511
+ /**
512
+ * A table the consumer handed to the `scroll` part takes the width its
513
+ * content asks for and overflows the wrapper, which is the whole point of
514
+ * having wrapped it. Left at `100%` it would instead be squeezed into the
515
+ * column, and the inherited `overflow-wrap: anywhere` would then break
516
+ * "Environment" across two lines rather than let one column be wide — the
517
+ * defect the first capture of this family showed.
518
+ *
519
+ * `min-inline-size` keeps a narrow table filling the column, so wrapping a
520
+ * table that happens to fit costs nothing.
521
+ */
522
+ [data-ui='prose']
523
+ [data-part='scroll']
524
+ > :where(table):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
525
+ inline-size: max-content;
526
+ min-inline-size: 100%;
527
+ }
528
+
529
+ [data-ui='prose'] :where(th, td):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
530
+ padding-block: var(--slotted-space-4, 0.5rem);
531
+ padding-inline: var(--slotted-space-5, 0.75rem);
532
+ text-align: start;
533
+ vertical-align: baseline;
534
+ }
535
+
536
+ [data-ui='prose'] :where(th):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
537
+ font-weight: var(--slotted-font-weight-semibold, 600);
538
+ }
539
+
540
+ [data-ui='prose']
541
+ :where(thead)
542
+ > :where(tr)
543
+ > :where(th, td):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
544
+ border-block-end: var(--slotted-border-width-thin, 1px) solid
545
+ var(--slotted-border-strong, ButtonBorder);
546
+ }
547
+
548
+ [data-ui='prose']
549
+ :where(tr + tr)
550
+ > :where(th, td):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
551
+ border-block-start: var(--slotted-border-width-thin, 1px) solid var(--_rule);
552
+ }
553
+
554
+ /* ── Rules and disclosure ───────────────────────────────────────────── */
555
+
556
+ [data-ui='prose'] :where(hr):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
557
+ border: 0;
558
+ border-block-start: var(--slotted-divider-thickness, var(--slotted-border-width-thin, 1px))
559
+ solid var(--slotted-divider-color, var(--slotted-border-subtle, ButtonBorder));
560
+ margin-block-start: calc(var(--_flow) * 1.75);
561
+ }
562
+
563
+ [data-ui='prose'] :where(summary):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
564
+ cursor: pointer;
565
+ font-weight: var(--slotted-font-weight-medium, 500);
566
+ }
567
+
568
+ [data-ui='prose']
569
+ :where(summary):not(:where([data-part='exclude'], [data-part='exclude'] *)):focus-visible {
570
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
571
+ outline-offset: var(--slotted-prose-focus-ring-offset, 2px);
572
+ }
573
+
574
+ /* ── The lead ───────────────────────────────────────────────────────── */
575
+
576
+ /**
577
+ * The block after the lead takes a wider gap than two ordinary paragraphs
578
+ * do, so the opening reads as its own movement rather than as the first of
579
+ * several. The selector looks backwards, which is what keeps it stable while
580
+ * the rest of the document is still arriving.
581
+ */
582
+ [data-ui='prose']
583
+ [data-part='lead']
584
+ + :not(:where([data-part='exclude'], [data-part='exclude'] *)) {
585
+ margin-block-start: calc(var(--_flow) * 1.35);
586
+ }
587
+
588
+ [data-ui='prose'] [data-part='lead'] {
589
+ color: var(--_muted);
590
+ font-size: var(--slotted-prose-lead-size, 1.125em);
591
+ line-height: var(--slotted-prose-lead-line-height, var(--slotted-line-height-lg, 1.5));
592
+ text-wrap: pretty;
593
+ }
594
+
595
+ /* ── The heading anchor ─────────────────────────────────────────────────
596
+ *
597
+ * Hidden with opacity, never with `display: none` or `visibility: hidden`:
598
+ * the anchor stays in the tab sequence and in the accessible tree, so a
599
+ * keyboard reader reaches it and a screen reader announces it. It appears
600
+ * when its heading is hovered *or* when it is itself focus-visible — a
601
+ * control that answered hover alone would be a control a keyboard cannot
602
+ * find.
603
+ *
604
+ * It sits on the heading's own line, after the words, and it holds its box
605
+ * whether it is visible or not — so revealing it moves nothing. Hanging it
606
+ * in a start gutter is the arrangement Primer uses and the first capture of
607
+ * this family showed why it cannot be borrowed: a region flush with its
608
+ * container has no gutter, and the focused anchor was clipped by the edge.
609
+ * A family cannot assume the page indented it.
610
+ *
611
+ * The binding writes a word joiner — U+2060, the zero-width character whose
612
+ * whole purpose is to forbid a break without occupying anything — before the
613
+ * anchor, so the last word of a title and its permalink wrap together. It is
614
+ * the same device `link` uses for its external marker, and for the same
615
+ * reason: a no-break space would carry a full word space with it.
616
+ */
617
+
618
+ [data-ui='prose'] [data-part='anchor'] {
619
+ align-items: center;
620
+ color: var(--_muted);
621
+ display: inline-flex;
622
+ justify-content: center;
623
+ margin-inline-start: var(--slotted-prose-anchor-gap, 0.35em);
624
+ /* WCAG 2.2 SC 2.5.8: a target is at least 24 by 24 CSS pixels. */
625
+ min-block-size: var(--slotted-target-min, 24px);
626
+ min-inline-size: var(--slotted-target-min, 24px);
627
+ opacity: 0;
628
+ text-decoration-line: none;
629
+ transition: opacity var(--slotted-duration-short) var(--slotted-easing-standard);
630
+ }
631
+
632
+ [data-ui='prose']
633
+ :where(h1, h2, h3, h4, h5, h6):hover
634
+ > [data-part='anchor']:not([data-disabled]),
635
+ [data-ui='prose'] [data-part='anchor']:focus-visible {
636
+ opacity: 1;
637
+ }
638
+
639
+ [data-ui='prose'] [data-part='anchor']:focus-visible {
640
+ border-radius: var(--slotted-radius-sm, 4px);
641
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
642
+ outline-offset: var(--slotted-prose-focus-ring-offset, 2px);
643
+ }
644
+
645
+ /* ── The scrolling block ────────────────────────────────────────────────
646
+ *
647
+ * A `pre` or a `table` wider than the column has to scroll sideways, and a
648
+ * reader with no pointer must be able to do it: the axe rule
649
+ * `scrollable-region-focusable` is WCAG 2.2 level A. Anything that takes
650
+ * focus then needs a name and a role, or it fails SC 4.1.2 — which is why
651
+ * the binding writes `role="region"`, `tabindex="0"` and a name *only while
652
+ * the block actually overflows*. A tab stop on a block that fits is a tab
653
+ * stop that does nothing.
654
+ *
655
+ * The ring is therefore painted on `[tabindex]` rather than on the part:
656
+ * Adrian Roselli's own trick, where the selector will not match markup that
657
+ * is not operable. He writes `:focus`; this writes `:focus-visible`, because
658
+ * a pointer press inside a `tabindex` box focuses it and a ring drawn then is
659
+ * a ring nobody asked for.
660
+ */
661
+
662
+ [data-ui='prose'] [data-part='scroll'] {
663
+ max-inline-size: 100%;
664
+ /* The page does not scroll sideways because one table is wide. */
665
+ overflow-x: auto;
666
+ /* A swipe that reaches the end of the table does not then move the page. */
667
+ overscroll-behavior-inline: contain;
668
+ }
669
+
670
+ [data-ui='prose'] [data-part='scroll'][tabindex]:focus-visible {
671
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
672
+ outline-offset: var(--slotted-prose-focus-ring-offset, 2px);
673
+ }
674
+
675
+ /* ── Footnotes ──────────────────────────────────────────────────────── */
676
+
677
+ [data-ui='prose'] [data-part='footnotes'] {
678
+ border-block-start: var(--slotted-border-width-thin, 1px) solid var(--_rule);
679
+ color: var(--_muted);
680
+ font-size: var(--slotted-prose-footnotes-size, 0.875em);
681
+ margin-block-start: calc(var(--_flow) * 2);
682
+ padding-block-start: var(--_flow);
683
+ }
684
+
685
+ /* ── The opt-out ────────────────────────────────────────────────────────
686
+ *
687
+ * The donut on every rule above stops this family reaching inside, and these
688
+ * four declarations undo what inheritance carried in on its own. Tailwind's
689
+ * `not-prose` and Typeset's `not-typeset` both leave the inherited type in
690
+ * place, so a card inside a `prose-xl` region is set in 20-pixel text.
691
+ * Returning the subtree to control type is what a component placed here
692
+ * expects, and a component that sets its own overrides all four.
693
+ */
694
+
695
+ [data-ui='prose'] [data-part='exclude'] {
696
+ font-family: var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif);
697
+ font-size: var(--slotted-font-size-md, 0.875rem);
698
+ line-height: var(--slotted-line-height-md, 1.5);
699
+ overflow-wrap: normal;
700
+ text-wrap: wrap;
701
+ }
702
+
703
+ /* ── Reflow ─────────────────────────────────────────────────────────────
704
+ *
705
+ * A container query cannot restyle its own container — `container-type`
706
+ * makes an element a query container for its descendants — and every rule
707
+ * here targets a descendant, which is why the family needs one element
708
+ * rather than two. The breakpoints are literals because CSS forbids a custom
709
+ * property in a container condition.
710
+ */
711
+
712
+ @container slotted-prose (max-width: 34rem) {
713
+ /* A 2em heading in a 400-pixel column is six words a line. */
714
+ [data-ui='prose'] :where(h1):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
715
+ font-size: var(--slotted-prose-h1-size-narrow, 1.6em);
716
+ }
717
+
718
+ [data-ui='prose'] :where(h2):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
719
+ font-size: var(--slotted-prose-h2-size-narrow, 1.35em);
720
+ }
721
+ }
722
+
723
+ @container slotted-prose (max-width: 22rem) {
724
+ [data-ui='prose']
725
+ :where(blockquote):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
726
+ padding-inline-start: calc(var(--slotted-prose-quote-inset, 1em) / 2);
727
+ }
728
+
729
+ [data-ui='prose'] :where(ul, ol):not(:where([data-part='exclude'], [data-part='exclude'] *)) {
730
+ padding-inline-start: var(--slotted-prose-list-inset-narrow, 1.15em);
731
+ }
732
+ }
733
+ }