@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,843 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * ── A datetime field, a trigger, and two surfaces behind them ──────────
4
+ *
5
+ * ┌─ root ──────────────────────────────────────────────────────────┐
6
+ * │ ┌─ control ─────────────────────────────────────────────────┐ │
7
+ * │ │ datetime-field ┌ trigger ┐ │ │
8
+ * │ └───────────────────────────────────────────────────────────┘ │
9
+ * └─────────────────────────────────────────────────────────────────┘
10
+ * ┌─ positioner ─ the layer ────────────────────────────────┐
11
+ * │ ┌─ content ─ role="dialog" ────────────────────────┐ │
12
+ * │ │ head: now │ presets │ │
13
+ * │ │ ┌─ panels ────────────────────────────────────┐ │ │
14
+ * │ │ │ date-panel ─ calendar │ time-panel ─ list │ │ │
15
+ * │ │ └─────────────────────────────────────────────┘ │ │
16
+ * │ │ footer │ │
17
+ * │ └──────────────────────────────────────────────────┘ │
18
+ * └────────────────────────────────────────────────────────┘
19
+ *
20
+ * **The only family in the library holding two surfaces.** One layer, one
21
+ * dialog, and inside it a `grid` that `calendar` draws and a `listbox` that
22
+ * this family draws. Both are in the DOM at every width: a `tablist` that
23
+ * exists on a narrow container and not on a wide one tells assistive
24
+ * technology two different stories about the same component, and Kendo's tabs
25
+ * and MUI's mobile tabs are what that decline is against.
26
+ *
27
+ * `datetime-field` and `calendar` inside keep their own `data-ui`, so nothing
28
+ * here restyles a segment or a day cell. This stylesheet owns the box the
29
+ * positioner measures, the trigger inside the field, the layer, and the list.
30
+ */
31
+ [data-ui='datetime-picker'][data-part='root'] {
32
+ display: block;
33
+ /* The anchor the positioner measures is the control, and a block root lets
34
+ the frame take the width the form gave it. */
35
+ inline-size: 100%;
36
+ }
37
+
38
+ /**
39
+ * The box the positioner measures, and nothing else.
40
+ *
41
+ * It draws no frame: the `datetime-field` inside it draws its own, and the
42
+ * trigger is handed to that field's `end` slot by the binding.
43
+ */
44
+ [data-ui='datetime-picker'] [data-part='control'] {
45
+ --_icon-size: var(--slotted-control-icon-size-md, 16px);
46
+ --_height: var(--slotted-control-height-md, 34px);
47
+
48
+ align-items: center;
49
+ display: flex;
50
+ inline-size: 100%;
51
+ min-inline-size: 0;
52
+ position: relative;
53
+ }
54
+
55
+ [data-ui='datetime-picker'][data-part='root'][data-size='sm'] [data-part='control'] {
56
+ --_icon-size: var(--slotted-control-icon-size-sm, 14px);
57
+ --_height: var(--slotted-control-height-sm, 30px);
58
+ }
59
+
60
+ [data-ui='datetime-picker'][data-part='root'][data-size='lg'] [data-part='control'] {
61
+ --_icon-size: var(--slotted-control-icon-size-lg, 18px);
62
+ --_height: var(--slotted-control-height-lg, 38px);
63
+ }
64
+
65
+ /**
66
+ * The button that opens the panel.
67
+ *
68
+ * Its mark is a calendar, which is the mark `input[type=datetime-local]`
69
+ * draws for the same control and the one `date-picker` already uses. The
70
+ * panel holds two surfaces and each names itself inside; the trigger names
71
+ * the kind of value the control holds, which is the one thing about it that
72
+ * never changes — so it does not turn while the panel is open either. It is
73
+ * a `Glyph` the binding draws inside an `icon` box, at the field's icon step.
74
+ *
75
+ * It is always drawn. Angular Material records why: ChromeOS turns
76
+ * `Alt`+`ArrowDown` into `PageDown` before the browser sees it, so the chord
77
+ * cannot be the only way in.
78
+ */
79
+ [data-ui='datetime-picker'] [data-part='trigger'] {
80
+ --slotted-icon-size: var(--_icon-size);
81
+
82
+ align-items: center;
83
+ appearance: none;
84
+ background-color: transparent;
85
+ block-size: var(
86
+ --slotted-datetime-picker-trigger-size,
87
+ min(
88
+ calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)),
89
+ calc(
90
+ var(--_height) - var(--slotted-control-border-width, 1px) * 2 -
91
+ var(--slotted-space-2, 0.25rem)
92
+ )
93
+ )
94
+ );
95
+ border: 0;
96
+ border-radius: var(--slotted-datetime-picker-radius, var(--slotted-control-radius, 4px));
97
+ color: var(--slotted-datetime-picker-trigger-color, var(--slotted-text-muted, GrayText));
98
+ cursor: pointer;
99
+ display: inline-flex;
100
+ flex: 0 0 auto;
101
+ inline-size: var(
102
+ --slotted-datetime-picker-trigger-size,
103
+ min(
104
+ calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)),
105
+ calc(
106
+ var(--_height) - var(--slotted-control-border-width, 1px) * 2 -
107
+ var(--slotted-space-2, 0.25rem)
108
+ )
109
+ )
110
+ );
111
+ justify-content: center;
112
+ padding: 0;
113
+ position: relative;
114
+ touch-action: manipulation;
115
+ transition:
116
+ background-color var(--slotted-control-transition-duration)
117
+ var(--slotted-control-transition-easing),
118
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
119
+ -webkit-tap-highlight-color: transparent;
120
+ }
121
+
122
+ /* The hit area, recovered outside the paint, exactly as every other inner
123
+ control in the library recovers it. */
124
+ [data-ui='datetime-picker'] [data-part='trigger']::after {
125
+ content: '';
126
+ inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
127
+ position: absolute;
128
+ }
129
+
130
+ /* On a finger the target is the comfortable size in both axes and the box
131
+ is the one a mouse sees: the ground and the focus ring stay square, and
132
+ the hit area above grows to 44 pixels around them. Before the field's
133
+ clear it does not reach across it. */
134
+ @media (pointer: coarse) {
135
+ [data-ui='datetime-picker'] [data-part='trigger']::after {
136
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
137
+ }
138
+
139
+ [data-ui='datetime-picker']
140
+ [data-part='end']:has(+ [data-part='clear']:not([hidden]))
141
+ > [data-part='trigger']::after {
142
+ inset-inline-end: 0;
143
+ }
144
+ }
145
+
146
+ [data-ui='datetime-picker'] [data-part='trigger']:hover:not(:disabled):not([data-disabled]) {
147
+ background-color: var(
148
+ --slotted-datetime-picker-trigger-hover-background,
149
+ var(--slotted-tone-secondary-subtle-hover)
150
+ );
151
+ }
152
+
153
+ [data-ui='datetime-picker'] [data-part='trigger']:active:not(:disabled):not([data-disabled]) {
154
+ background-color: var(
155
+ --slotted-datetime-picker-trigger-active-background,
156
+ var(--slotted-tone-secondary-subtle-active)
157
+ );
158
+ }
159
+
160
+ /* Its own ring: tabbing from the last segment to the trigger has to move
161
+ something visible, and the frame's ring would sit still. */
162
+ [data-ui='datetime-picker'] [data-part='trigger']:focus-visible {
163
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
164
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
165
+ }
166
+
167
+ [data-ui='datetime-picker'][data-part='root'][data-invalid] {
168
+ --slotted-focus-ring-color: var(
169
+ --slotted-datetime-picker-invalid-focus-ring-color,
170
+ var(--slotted-focus-ring-color-invalid, Highlight)
171
+ );
172
+ }
173
+
174
+ [data-ui='datetime-picker'] [data-part='trigger']:disabled {
175
+ color: var(--slotted-disabled-foreground);
176
+ cursor: not-allowed;
177
+ }
178
+
179
+ /* ── The layer ────────────────────────────────────────────────────────
180
+ *
181
+ * What `packages/core/src/positioner` writes `position`, `left` and `top`
182
+ * onto. The painted surface is one element in, as every anchored family in
183
+ * the library is built.
184
+ */
185
+ [data-ui='datetime-picker'][data-part='positioner'] {
186
+ /* Only the block inset: the positioner writes `left` and never `right`,
187
+ and `inset-inline-start` would resolve to `right` in a right-to-left
188
+ document and win over the measured value. */
189
+ position: absolute;
190
+ inset-block-start: 0;
191
+
192
+ box-sizing: border-box;
193
+ isolation: isolate;
194
+ /* The layer is only a frame around the surface; the surface takes the
195
+ pointer, and the frame must not swallow a press meant for the page. */
196
+ pointer-events: none;
197
+ z-index: calc(var(--slotted-z-index-popover, 1100) + var(--slotted-layer-depth, 0));
198
+
199
+ /* The layer arrives along the axis it opens on and never along the inline
200
+ one, which is the rule `select` records. */
201
+ --_enter-distance: var(--slotted-space-2, 0.25rem);
202
+ opacity: 0;
203
+ translate: 0 calc(-1 * var(--_enter-distance));
204
+ transition:
205
+ opacity var(--slotted-duration-short) var(--slotted-easing-exit),
206
+ translate var(--slotted-duration-short) var(--slotted-easing-exit);
207
+ }
208
+
209
+ [data-ui='datetime-picker'][data-part='positioner'][data-side='top'] {
210
+ translate: 0 var(--_enter-distance);
211
+ }
212
+
213
+ /* A lateral side has no block direction to arrive from, so it only fades. */
214
+ [data-ui='datetime-picker'][data-part='positioner']:is([data-side='left'], [data-side='right']) {
215
+ translate: 0 0;
216
+ }
217
+
218
+ [data-ui='datetime-picker'][data-part='positioner'][data-open] {
219
+ opacity: 1;
220
+ translate: 0 0;
221
+ transition: none;
222
+ }
223
+
224
+ /**
225
+ * The entrance is a keyframe animation and not a transition, for the reason
226
+ * `select` records: a transition starts from the style the browser computed
227
+ * last, and the positioner writes `data-side` in the same style update as the
228
+ * family opens the layer. A layer written open in static markup — the
229
+ * harness, a docs snippet — is simply there, and is photographed where it
230
+ * stands.
231
+ */
232
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned] {
233
+ animation: slotted-datetime-picker-enter-down var(--slotted-duration-medium)
234
+ var(--slotted-easing-enter);
235
+ }
236
+
237
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned][data-side='top'] {
238
+ animation-name: slotted-datetime-picker-enter-up;
239
+ }
240
+
241
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned]:is(
242
+ [data-side='left'],
243
+ [data-side='right']
244
+ ) {
245
+ animation-name: slotted-datetime-picker-fade;
246
+ }
247
+
248
+ @keyframes slotted-datetime-picker-enter-down {
249
+ from {
250
+ opacity: 0;
251
+ translate: 0 calc(-1 * var(--_enter-distance));
252
+ }
253
+ }
254
+
255
+ @keyframes slotted-datetime-picker-enter-up {
256
+ from {
257
+ opacity: 0;
258
+ translate: 0 var(--_enter-distance);
259
+ }
260
+ }
261
+
262
+ @keyframes slotted-datetime-picker-fade {
263
+ from {
264
+ opacity: 0;
265
+ }
266
+ }
267
+
268
+ /* Stillness keeps the fade and drops the movement. */
269
+ @media (prefers-reduced-motion: reduce) {
270
+ [data-ui='datetime-picker'][data-part='positioner'],
271
+ [data-ui='datetime-picker'][data-part='positioner'][data-side='top'],
272
+ [data-ui='datetime-picker'][data-part='positioner'][data-side='left'],
273
+ [data-ui='datetime-picker'][data-part='positioner'][data-side='right'] {
274
+ translate: 0 0;
275
+ transition: opacity var(--slotted-duration-short) var(--slotted-easing-exit);
276
+ }
277
+
278
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned],
279
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned][data-side='top'],
280
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned][data-side='left'],
281
+ [data-ui='datetime-picker'][data-part='positioner'][data-open][data-positioned][data-side='right'] {
282
+ animation-name: slotted-datetime-picker-fade;
283
+ }
284
+ }
285
+
286
+ /* The anchor scrolled out of its own clipper. The panel is still open and
287
+ still belongs to a control the reader can no longer see. */
288
+ [data-ui='datetime-picker'][data-part='positioner'][data-detached] {
289
+ visibility: hidden;
290
+ }
291
+
292
+ /**
293
+ * The surface.
294
+ *
295
+ * It is shrink-wrapped from the two panels and capped by the room the
296
+ * positioner measured, rather than sized to the anchor: a calendar has a
297
+ * width of its own and a field narrower than one would squeeze the month
298
+ * rather than the panel. That is also why there is **no container query
299
+ * here**. `container-type: inline-size` would make the surface's inline size
300
+ * independent of its contents, which is the opposite of what a panel sized to
301
+ * a calendar needs; the two panels wrap instead, which needs no threshold to
302
+ * guess at and cannot be wrong at a width nobody tested.
303
+ */
304
+ [data-ui='datetime-picker'] [data-part='content'] {
305
+ background-color: var(--slotted-datetime-picker-surface, var(--slotted-surface-raised, Canvas));
306
+ border: var(--slotted-border-width-thin, 1px) solid
307
+ var(
308
+ --slotted-datetime-picker-content-border-color,
309
+ var(--slotted-border-subtle, ButtonBorder)
310
+ );
311
+ border-radius: var(--slotted-datetime-picker-content-radius, var(--slotted-radius-lg, 8px));
312
+ box-shadow: var(--slotted-datetime-picker-content-shadow, var(--slotted-shadow-md));
313
+ box-sizing: border-box;
314
+ color: var(--slotted-datetime-picker-content-color, var(--slotted-text, CanvasText));
315
+
316
+ /**
317
+ * One row's height, stated once, because the list's cap is counted in rows
318
+ * at every density. Read from the control scale rather than from the target
319
+ * floor alone, so a dense panel shrinks its rows and its cap together — the
320
+ * alternative shrinks only the cap and shows fewer options, which is
321
+ * density changing what a reader can see rather than how much room it
322
+ * takes.
323
+ */
324
+ --_row: max(var(--slotted-target-min, 24px), var(--slotted-control-height-sm, 30px));
325
+ --_row-pitch: calc(var(--_row) + var(--slotted-space-1, 0.125rem));
326
+
327
+ display: grid;
328
+ gap: var(--slotted-space-2, 0.25rem);
329
+ grid-template-areas: 'head' 'panels' 'footer';
330
+ grid-template-columns: minmax(0, 1fr);
331
+ inline-size: auto;
332
+ max-inline-size: min(34rem, var(--slotted-positioner-available-width, 34rem));
333
+ padding: var(--slotted-datetime-picker-content-padding, var(--slotted-space-3, 0.375rem));
334
+ /* The layer above gave up the pointer; the surface takes it back. */
335
+ pointer-events: auto;
336
+ }
337
+
338
+ /**
339
+ * The head band.
340
+ *
341
+ * It says what the reader has chosen **so far**, which is the one thing
342
+ * neither surface can show: a month grid says which day is chosen and a
343
+ * column of times says which time is, and a reader who chose a day and is now
344
+ * reading a column of times has nothing telling them which day those times
345
+ * belong to. No surveyed panel says it at all.
346
+ *
347
+ * It replaces a pair of labels — `Data` and `Hora`, each with a mark small
348
+ * enough to sit in eleven-pixel text — that were decoration twice over: a
349
+ * month grid is a date and a column of times is times, which is why none of
350
+ * the four surveyed panels labels either, and a mark that small is a mark
351
+ * nobody can read. The listbox's name is written in `aria-label` instead,
352
+ * where a name belongs when the thing it names says what it is.
353
+ *
354
+ * The rule under it is what makes this a band rather than a line of text
355
+ * floating over two columns.
356
+ */
357
+ [data-ui='datetime-picker'] [data-part='head'] {
358
+ /**
359
+ * The band renders at the panel's width and contributes nothing to it.
360
+ *
361
+ * A grid track sizes to the widest thing in it, so a row of the consumer's
362
+ * own shortcuts stretched the whole panel — and with it the column of
363
+ * times, which then ran the width of a page. `inline-size: 0` takes the
364
+ * band out of that measurement and `min-inline-size: 100%` puts it back at
365
+ * the track's own width, so the two surfaces decide how wide the panel is
366
+ * and the band wraps inside whatever they decide.
367
+ */
368
+ /* `border-box`, and it is load-bearing: under `content-box` the percentage
369
+ resolves to the content box and the padding is added on top, so the band
370
+ came out twelve pixels wider than the area it sits in and pushed the
371
+ control at its end six pixels past the panel's own edge. */
372
+ box-sizing: border-box;
373
+ inline-size: 0;
374
+ min-inline-size: 100%;
375
+
376
+ align-items: center;
377
+ border-block-end: var(--slotted-border-width-thin, 1px) solid
378
+ var(
379
+ --slotted-datetime-picker-content-border-color,
380
+ var(--slotted-border-subtle, ButtonBorder)
381
+ );
382
+ column-gap: var(--slotted-space-4, 0.5rem);
383
+ display: flex;
384
+ flex-wrap: wrap;
385
+ grid-area: head;
386
+ justify-content: space-between;
387
+ /**
388
+ * No inline padding of its own. The surface's own padding is the panel's
389
+ * one gutter, and every box under this band starts and ends on it: the
390
+ * month's column, the page trigger inside it, the list's column and the
391
+ * ground of every row in it. With six pixels more here the title stood six
392
+ * pixels inside the month below it and the control at the end stopped six
393
+ * pixels short of the rows below *it* — two edges that almost line up,
394
+ * which reads worse than two that plainly do not.
395
+ *
396
+ * Measured on the default theme at `comfortable`, 720 pixels: the surface's
397
+ * inner edges are 32 and 405.4, and the month's column, the list's column
398
+ * and this band now all begin and end there.
399
+ */
400
+ /**
401
+ * Air under the controls before the rule — the same step the footer keeps
402
+ * between its own rule and its buttons, so the two bands hold the surface
403
+ * symmetrically. With none, the rule read as an underline on `now` and on
404
+ * the consumer's shortcuts rather than as the bottom of the band they
405
+ * stand in.
406
+ */
407
+ padding-block-end: var(--slotted-space-3, 0.375rem);
408
+ row-gap: var(--slotted-space-2, 0.25rem);
409
+ }
410
+
411
+ /**
412
+ * The value as it stands. It is the panel's own title, so it takes the
413
+ * surface's ink and a step of weight, and its digits line up with the list's
414
+ * below it.
415
+ */
416
+ [data-ui='datetime-picker'] [data-part='head-value'] {
417
+ color: var(--slotted-datetime-picker-content-color, var(--slotted-text, CanvasText));
418
+ font-size: var(--slotted-font-size-sm, 13px);
419
+ font-variant-numeric: tabular-nums;
420
+ font-weight: var(--slotted-font-weight-medium, 500);
421
+ min-inline-size: 0;
422
+ /* A datetime in words is a mixed run — a month name beside two numbers — so
423
+ it is laid out by its own content rather than by the paragraph, which is
424
+ the rule the field's own preview records. */
425
+ unicode-bidi: plaintext;
426
+ }
427
+
428
+ /**
429
+ * The half the reader has not written yet, drawn as its placeholder beside
430
+ * the half they have. It is the family's own answer to a value that is not
431
+ * whole, said where the reader is looking rather than only in the field.
432
+ */
433
+ [data-ui='datetime-picker'] [data-part='head-value'] [data-placeholder] {
434
+ color: var(--slotted-datetime-picker-label-color, var(--slotted-text-muted, GrayText));
435
+ }
436
+
437
+ /**
438
+ * One press for the current datetime — what a reader who never discovers that
439
+ * `+` opens an expression still has.
440
+ *
441
+ * It is drawn as a control and not as a link. `time-picker` writes its own
442
+ * `now` as accent text, and alone at the head of a single list that reads
443
+ * correctly; here it stands at the end of a band opposite a title, where bare
444
+ * coloured text is a third register beside the panel's plain ink and its one
445
+ * solid accent block — it read as a stray link rather than as the shortcut it
446
+ * is. A quiet bordered control at the small step is the shape the library
447
+ * already gives an action of this weight, and the divergence from the sibling
448
+ * is the band around it.
449
+ *
450
+ * It carries the clock, which is the second of the family's two marks and the
451
+ * only place one earns its keep: this is the control that writes a time, so
452
+ * the mark names what it does, and at the control glyph size inside a control
453
+ * it is legible rather than a speck beside a word.
454
+ */
455
+ [data-ui='datetime-picker'] [data-part='now'] {
456
+ align-items: center;
457
+ appearance: none;
458
+ background-color: var(--slotted-datetime-picker-now-background, transparent);
459
+ /* The control's own border token rather than the surface's subtle one: this
460
+ button stands *on* the raised surface, where `--slotted-border-subtle` is
461
+ within a shade of the ground and the dark capture showed no edge at all. */
462
+ border: var(--slotted-control-border-width, 1px) solid
463
+ var(
464
+ --slotted-datetime-picker-now-border-color,
465
+ var(--slotted-control-border-color, ButtonBorder)
466
+ );
467
+ border-radius: var(--slotted-datetime-picker-radius, var(--slotted-control-radius, 4px));
468
+ color: var(--slotted-datetime-picker-now-color, var(--slotted-text, CanvasText));
469
+ cursor: pointer;
470
+ display: inline-flex;
471
+ flex: 0 0 auto;
472
+ font: inherit;
473
+ font-size: var(--slotted-control-font-size-sm, 12px);
474
+ gap: var(--slotted-space-2, 0.25rem);
475
+ justify-content: center;
476
+ min-block-size: var(--slotted-control-height-sm, 30px);
477
+ padding-block: 0;
478
+ padding-inline: var(--slotted-control-padding-inline-sm, 10px);
479
+ touch-action: manipulation;
480
+ transition:
481
+ background-color var(--slotted-control-transition-duration)
482
+ var(--slotted-control-transition-easing),
483
+ border-color var(--slotted-control-transition-duration)
484
+ var(--slotted-control-transition-easing);
485
+ white-space: nowrap;
486
+ -webkit-tap-highlight-color: transparent;
487
+ }
488
+
489
+ /**
490
+ * The mark — the clock `Glyph` the binding draws before the label, at the
491
+ * `sm` icon step — takes the muted ink the label does not, so the pair reads
492
+ * as one control with a glyph rather than as two things of equal weight.
493
+ */
494
+ [data-ui='datetime-picker'] [data-part='now'] > [data-ui='icon'] {
495
+ /* No system colour: a theme that never loaded should let the mark take the
496
+ label's ink rather than the operating system's own grey, which is the
497
+ rule `fallbacks.test.mjs` holds. */
498
+ color: var(--slotted-datetime-picker-now-icon-color, var(--slotted-text-muted));
499
+ }
500
+
501
+ [data-ui='datetime-picker'] [data-part='now']:hover:not(:disabled):not([data-disabled]) {
502
+ background-color: var(
503
+ --slotted-datetime-picker-now-hover-background,
504
+ var(--slotted-tone-secondary-subtle-hover)
505
+ );
506
+ border-color: var(
507
+ --slotted-datetime-picker-now-hover-border-color,
508
+ var(--slotted-tone-accent-border)
509
+ );
510
+ }
511
+
512
+ [data-ui='datetime-picker'] [data-part='now']:active:not(:disabled):not([data-disabled]) {
513
+ background-color: var(
514
+ --slotted-datetime-picker-now-active-background,
515
+ var(--slotted-tone-secondary-subtle-active)
516
+ );
517
+ }
518
+
519
+ [data-ui='datetime-picker'] [data-part='now']:focus-visible {
520
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
521
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
522
+ }
523
+
524
+ /**
525
+ * The consumer's own shortcuts. This family ships no list of them: "tomorrow
526
+ * at nine" is a business clock, and a library that guessed at one would be
527
+ * guessing at an industry. What it ships is the row they stand in, at the
528
+ * reading end of the head beside `now`.
529
+ */
530
+ [data-ui='datetime-picker'] [data-part='presets'] {
531
+ align-items: center;
532
+ display: flex;
533
+ flex-wrap: wrap;
534
+ gap: var(--slotted-space-2, 0.25rem);
535
+ }
536
+
537
+ /* ── The two panels ───────────────────────────────────────────────────
538
+ *
539
+ * A wrapping flex row of exactly two items, in the value's own order. Where
540
+ * the positioner measured room for both, they stand side by side; where it
541
+ * did not, the time panel wraps under the date panel and nothing is hidden.
542
+ *
543
+ * The reflow is the row's own, at every width. `openTo` does not reorder it:
544
+ * moving a whole calendar because focus starts elsewhere would make one
545
+ * setting look like a different component, and what answers the narrow case
546
+ * is `scrollIntoView` on the surface focus lands in.
547
+ */
548
+ [data-ui='datetime-picker'] [data-part='panels'] {
549
+ /**
550
+ * The two columns are told apart by the air between them and by what they
551
+ * hold, not by a rule. A rule would have to be on one inline edge, and the
552
+ * same declaration is a divider beside the month in one arrangement and a
553
+ * stray line under it in the other — the arrangement is the row's own and
554
+ * no selector can tell which one is on screen.
555
+ */
556
+ column-gap: var(--slotted-space-6, 1rem);
557
+ display: flex;
558
+ flex-wrap: wrap;
559
+ grid-area: panels;
560
+ min-inline-size: 0;
561
+ row-gap: var(--slotted-space-4, 0.5rem);
562
+ }
563
+
564
+ /**
565
+ * The month's column never shrinks below the month.
566
+ *
567
+ * A calendar has an intrinsic width — its cell is a share of its own
568
+ * container — and this column is that width. A flexible basis with
569
+ * `min-inline-size: 0` would let the grid be squeezed under it, and a squeezed
570
+ * month is the half of this panel a reader came for. When the room runs out it
571
+ * is the time panel that wraps instead, which is the arrangement this family
572
+ * already draws.
573
+ */
574
+ [data-ui='datetime-picker'] [data-part='date-panel'] {
575
+ flex: 0 0 auto;
576
+ }
577
+
578
+ /**
579
+ * The list's column.
580
+ *
581
+ * `flex-grow: 1` against a basis of seven rem does two things at once and
582
+ * needs no query to tell them apart. Beside the month, the surface is
583
+ * shrink-wrapped to the sum of the two bases, so there is no free space to
584
+ * grow into and the column stays the narrow one it should be — a column of
585
+ * times spread across half a panel is a column of numbers nobody chose that
586
+ * shape for. Wrapped onto a line of its own, the free space is the whole line
587
+ * and the column takes it, so the times read as a section rather than as a
588
+ * narrow strip under a wide month.
589
+ */
590
+ [data-ui='datetime-picker'] [data-part='time-panel'] {
591
+ display: flex;
592
+ flex: 1 1 var(--slotted-datetime-picker-time-panel-inline-size, 7rem);
593
+ flex-direction: column;
594
+ gap: var(--slotted-space-2, 0.25rem);
595
+ min-inline-size: var(--slotted-datetime-picker-time-panel-inline-size, 7rem);
596
+ }
597
+
598
+ /* ── The list ─────────────────────────────────────────────────────────
599
+ *
600
+ * One column of times on the day the reader is on, capped in control heights
601
+ * so the cap holds at every density and every type step, and scrolled rather
602
+ * than truncated: a day of quarter-hours is ninety-six rows and every one of
603
+ * them is choosable.
604
+ */
605
+ [data-ui='datetime-picker'] [data-part='list'] {
606
+ display: flex;
607
+ flex: 1 1 auto;
608
+ flex-direction: column;
609
+ /**
610
+ * One step of air between rows, so the chosen row's painted ground and the
611
+ * focused row's inset ring never share an edge. Touching, the two read as
612
+ * one band with a dark underline rather than as two states of two rows.
613
+ */
614
+ gap: var(--slotted-space-1, 0.125rem);
615
+ /**
616
+ * Seven rows and a half, which is deliberately *shorter* than a six-week
617
+ * month: the month is what governs the height of a panel holding both, and
618
+ * a list one row taller left the calendar's column with dead space under it
619
+ * and cut the list's last row against the panel's own border. Under the cap
620
+ * the list stretches to whatever the month leaves, so the two surfaces end
621
+ * on the same line at every density and in every month.
622
+ *
623
+ * The half is the point wherever the cap is what applies — the wrapped
624
+ * arrangement and the sheet: a list cut on a row boundary looks like the
625
+ * whole list, and a reader who cannot see that ninety-six times are
626
+ * available never scrolls for them.
627
+ */
628
+ max-block-size: var(--slotted-datetime-picker-list-block-size, calc(var(--_row-pitch) * 7.5));
629
+ /* Beside a month, the column is stretched to the month's height and the
630
+ list fills what the label leaves — so the list is as tall as the calendar
631
+ rather than a number of rows chosen against nothing. The cap above is
632
+ what holds when there is no month beside it, which is the wrapped
633
+ arrangement and the sheet. */
634
+ min-block-size: 0;
635
+ min-inline-size: 0;
636
+ overflow-y: auto;
637
+ /* A highlight moved by a key lands whole rather than half under the edge. */
638
+ scroll-padding-block: var(--slotted-space-2, 0.25rem);
639
+ }
640
+
641
+ /**
642
+ * One time on the day the reader is on.
643
+ *
644
+ * The row carries the time and nothing else. The day is the calendar's to
645
+ * say, and repeating it ninety-six times beside a month that already shows it
646
+ * would spend the whole column on one word.
647
+ */
648
+ [data-ui='datetime-picker'] [data-part='option'] {
649
+ align-items: center;
650
+ background-color: transparent;
651
+ border-radius: var(--slotted-datetime-picker-option-radius, var(--slotted-radius-sm, 4px));
652
+ color: inherit;
653
+ cursor: pointer;
654
+ display: flex;
655
+ flex: 0 0 auto;
656
+ font-variant-numeric: tabular-nums;
657
+ gap: var(--slotted-space-2, 0.25rem);
658
+ /* The row *is* `--_row`: no block padding on top of it, so eight rows are
659
+ eight rows and the cap that counts them is arithmetic rather than an
660
+ estimate. A time never wraps, so there is nothing for the padding to
661
+ protect. */
662
+ min-block-size: var(--_row);
663
+ padding-inline: var(--slotted-space-3, 0.375rem);
664
+ transition:
665
+ background-color var(--slotted-control-transition-duration)
666
+ var(--slotted-control-transition-easing),
667
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
668
+ user-select: none;
669
+ -webkit-tap-highlight-color: transparent;
670
+ }
671
+
672
+ /* ── Option states ────────────────────────────────────────────────────
673
+ *
674
+ * Written strongest last, and each weaker one guarded against every stronger
675
+ * one it can meet, which is the order `STATE_PRECEDENCE` sets: the chosen
676
+ * time outranks the highlight, and the highlight outranks the pointer.
677
+ *
678
+ * Specificity is what makes this a rule rather than an ordering: a hover
679
+ * selector carrying `:hover` and one `:not()` outweighs a plain
680
+ * `[data-selected]`, so a chosen row turns grey under the pointer however far
681
+ * down the file its own rule is written. Found by the reviewer at
682
+ * `time-picker`'s visual gate and inherited whole.
683
+ */
684
+ [data-ui='datetime-picker']
685
+ [data-part='option']:hover:not([data-disabled]):not([data-selected]):not([data-current]) {
686
+ background-color: var(
687
+ --slotted-datetime-picker-option-hover-background,
688
+ var(--slotted-tone-secondary-subtle-hover)
689
+ );
690
+ }
691
+
692
+ [data-ui='datetime-picker'] [data-part='option'][data-current]:not([data-selected]) {
693
+ background-color: var(
694
+ --slotted-datetime-picker-option-current-background,
695
+ var(--slotted-tone-secondary-subtle-active)
696
+ );
697
+ }
698
+
699
+ [data-ui='datetime-picker'] [data-part='option']:focus-visible {
700
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
701
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
702
+ }
703
+
704
+ [data-ui='datetime-picker'] [data-part='option'][data-selected] {
705
+ background-color: var(
706
+ --slotted-datetime-picker-option-selected-background,
707
+ var(--slotted-tone-accent-solid)
708
+ );
709
+ color: var(
710
+ --slotted-datetime-picker-option-selected-color,
711
+ var(--slotted-tone-accent-on-solid)
712
+ );
713
+ }
714
+
715
+ /* The chosen row still answers the pointer — one step along its own tone,
716
+ rather than the grey every other row takes. A row that swapped colour
717
+ family under the pointer read as a different row. */
718
+ [data-ui='datetime-picker'] [data-part='option'][data-selected]:hover:not([data-disabled]) {
719
+ background-color: var(
720
+ --slotted-datetime-picker-option-selected-hover-background,
721
+ var(--slotted-tone-accent-solid-hover)
722
+ );
723
+ }
724
+
725
+ /**
726
+ * A time a bound or a predicate refuses. It stays in the list by default,
727
+ * because a list that silently drops rows is a list whose step the reader
728
+ * cannot infer — and it is muted to the colour the theme measures rather than
729
+ * faded by opacity, so it stays readable.
730
+ */
731
+ [data-ui='datetime-picker'] [data-part='option'][data-disabled] {
732
+ background-color: transparent;
733
+ color: var(--slotted-disabled-foreground);
734
+ cursor: not-allowed;
735
+ }
736
+
737
+ /**
738
+ * The day the reader is on offers no time at all — a closed Saturday, a
739
+ * window `minTime` and `maxTime` leave empty, a predicate that refuses every
740
+ * step. It is a sentence rather than an empty box, and it is the state that
741
+ * makes the list worth recomputing as the reader moves through the month.
742
+ */
743
+ [data-ui='datetime-picker'] [data-part='empty'] {
744
+ align-items: center;
745
+ color: var(--slotted-datetime-picker-label-color, var(--slotted-text-muted, GrayText));
746
+ display: flex;
747
+ flex: 1 1 auto;
748
+ justify-content: center;
749
+ min-block-size: calc(var(--_row) * 2);
750
+ padding: var(--slotted-space-4, 0.5rem);
751
+ text-align: center;
752
+ text-wrap: balance;
753
+ }
754
+
755
+ [data-ui='datetime-picker'] [data-part='footer'] {
756
+ /* The band's rule, for the same reason: a consumer's two buttons are not
757
+ what decides how wide a month is drawn — and `border-box` with it, or the
758
+ padding pushes the last button past the panel's edge. */
759
+ box-sizing: border-box;
760
+ inline-size: 0;
761
+ min-inline-size: 100%;
762
+
763
+ align-items: center;
764
+ border-block-start: var(--slotted-border-width-thin, 1px) solid
765
+ var(
766
+ --slotted-datetime-picker-content-border-color,
767
+ var(--slotted-border-subtle, ButtonBorder)
768
+ );
769
+ display: flex;
770
+ gap: var(--slotted-space-2, 0.25rem);
771
+ grid-area: footer;
772
+ justify-content: flex-end;
773
+ /* The same one gutter: the last button ends where the rows above it end. */
774
+ padding-block-start: var(--slotted-space-3, 0.375rem);
775
+ }
776
+
777
+ /* ── Narrow, on a finger ──────────────────────────────────────────────
778
+ *
779
+ * §2.7 of `docs/component-features.md` asks for it by name: a popover on the
780
+ * desktop and a sheet in a narrow viewport. The DOM does not change, so the
781
+ * decision is testable without a device — and the query is on the viewport
782
+ * rather than on a container because a layer in a portal has no container to
783
+ * ask, and the question really is how much screen there is.
784
+ */
785
+ @media (max-width: 480px) and (pointer: coarse) {
786
+ [data-ui='datetime-picker'][data-part='positioner'][data-presentation='sheet'] {
787
+ /* The positioner's own measurement is overridden here on purpose: a sheet
788
+ is not placed against an anchor, it is placed against the screen. */
789
+ inset: auto 0 0;
790
+ position: fixed;
791
+ translate: 0 var(--slotted-space-9, 2rem);
792
+ }
793
+
794
+ [data-ui='datetime-picker'][data-part='positioner'][data-presentation='sheet'][data-open] {
795
+ translate: 0 0;
796
+ }
797
+
798
+ [data-ui='datetime-picker'][data-part='positioner'][data-presentation='sheet']
799
+ [data-part='content'] {
800
+ border-end-end-radius: 0;
801
+ border-end-start-radius: 0;
802
+ border-inline: 0;
803
+ border-block-end: 0;
804
+ inline-size: var(--slotted-datetime-picker-sheet-inline-size, 100%);
805
+ max-inline-size: none;
806
+ /* The two surfaces are stacked here and the sheet has the screen's height
807
+ to spend, so the whole panel scrolls rather than each surface scrolling
808
+ inside its own box. */
809
+ max-block-size: 85vh;
810
+ overflow-y: auto;
811
+ }
812
+
813
+ /* Stacked under a month, the list gets a shorter run: the reader scrolls
814
+ the sheet to reach it, and a full-height list would put the footer out of
815
+ reach behind ninety-six rows. */
816
+ [data-ui='datetime-picker'][data-part='positioner'][data-presentation='sheet']
817
+ [data-part='list'] {
818
+ max-block-size: calc(var(--_row-pitch) * 5.5);
819
+ }
820
+ }
821
+
822
+ @media (forced-colors: active) {
823
+ /* The chosen row and the highlighted row both lose their painted grounds,
824
+ so each says what it is with a system pair the operating system
825
+ guarantees legible together. */
826
+ [data-ui='datetime-picker'] [data-part='option'][data-selected] {
827
+ background-color: Highlight;
828
+ color: HighlightText;
829
+ forced-color-adjust: none;
830
+ }
831
+
832
+ [data-ui='datetime-picker'] [data-part='option'][data-current]:not([data-selected]) {
833
+ outline: var(--slotted-focus-ring-width, 2px) solid Highlight;
834
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
835
+ }
836
+
837
+ /* No rule between the two surfaces is added here. The gap between them is
838
+ only space, but each panel already carries a label with its own mark
839
+ above it, and a label is a boundary that reads in both arrangements — a
840
+ border on one inline edge would be a divider beside the month in one and
841
+ a stray rule under it in the other. */
842
+ }
843
+ }