@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,1320 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * ── A control that picks one place in a hierarchy ───────────────────────
4
+ *
5
+ * Two subtrees, as `select` is built: the **control** where the consumer
6
+ * wrote it, and the **popup** portalled to the end of the document. Both
7
+ * carry `data-ui='cascader'` and every rule states which one it is about
8
+ * through its own `data-part`.
9
+ *
10
+ * ┌─ root ─ the control ───────────────────────────────────────────┐
11
+ * │ ┌─ trigger ─ role="combobox" ────────────────────────────────┐ │
12
+ * │ │ value ▸ segment / segment / segment │ │
13
+ * │ └────────────────────────────────────────────────────────────┘ │
14
+ * │ clear ✕ arrow ⌄ │
15
+ * └────────────────────────────────────────────────────────────────┘
16
+ *
17
+ * ┌─ positioner ─ data-layout ──────────────────────────────────────┐
18
+ * │ ┌─ content ─────────────────────────────────────────────────┐ │
19
+ * │ │ search ▸ search-input (search only) │ │
20
+ * │ │ breadcrumb ▸ crumb › crumb › crumb (drill only) │ │
21
+ * │ │ ┌─ panel ─ role="tree" ─────────────────────────────────┐ │ │
22
+ * │ │ │ column │ column │ column (one in drill/tree) │ │ │
23
+ * │ │ │ node ▸ indicator icon label meta end │ │ │
24
+ * │ │ └──────────────────────────────────────────────────────┘ │ │
25
+ * │ └───────────────────────────────────────────────────────────┘ │
26
+ * └────────────────────────────────────────────────────────────────┘
27
+ *
28
+ * The control is `select`'s control, rule for rule and on the same control
29
+ * tokens: a form holding a select and a cascader is one row of controls.
30
+ *
31
+ * The panel also stands alone, without a control or a layer, as a settings
32
+ * screen or a sidebar holds it. It then carries `data-ui='cascader'` itself,
33
+ * paints its own surface, and reads the same scale the layer states.
34
+ *
35
+ * ── Why each column is a grid and a node a subgrid ────────────────────
36
+ *
37
+ * The same architecture `select` and `menu` use. A column owns five tracks —
38
+ * the box, the icon, the label, the meta, the end — and every node passes
39
+ * through them, so labels line up down a column however many nodes carry
40
+ * artwork, and every count ends on one edge. No track carries a gap; each
41
+ * cell carries its own margin, so a column of plain labels has no gutter.
42
+ *
43
+ * The end track holds the check of a single selection or the chevron of a
44
+ * branch, never both: a branch is opened rather than chosen by default, and
45
+ * a branch that may be chosen says so with its ink.
46
+ */
47
+
48
+ /* ── The control ──────────────────────────────────────────────────────── */
49
+
50
+ [data-ui='cascader'][data-part='root'] {
51
+ --_font-size: var(--slotted-control-font-size-md, 13px);
52
+ --_height: var(--slotted-control-height-md, 34px);
53
+ --_padding-inline: var(--slotted-control-padding-inline-md, 13px);
54
+ --_gap: var(--slotted-control-gap-md, 8px);
55
+ --_icon-floor: var(--slotted-cascader-icon-size-min, 14px);
56
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-md, 16px));
57
+ --_inner-size: var(--slotted-control-inner-size-md, 24px);
58
+ --_action-size: min(
59
+ calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)),
60
+ var(--_inner-size)
61
+ );
62
+
63
+ align-items: center;
64
+ background-color: var(--slotted-cascader-background, var(--slotted-control-surface, Field));
65
+ border: var(--slotted-control-border-width, 1px) solid
66
+ var(--slotted-cascader-border-color, var(--slotted-control-border-color, ButtonBorder));
67
+ border-radius: var(--slotted-cascader-radius, var(--slotted-control-radius, 4px));
68
+ box-shadow: var(--slotted-control-shadow, none);
69
+ box-sizing: border-box;
70
+ color: var(--slotted-text, CanvasText);
71
+ column-gap: var(--_gap);
72
+ display: grid;
73
+ font-family: var(--slotted-control-font-family, system-ui, sans-serif);
74
+ font-size: var(--_font-size);
75
+ grid-template-columns: minmax(0, 1fr) auto;
76
+ inline-size: 100%;
77
+ min-block-size: var(--_height);
78
+ min-inline-size: 0;
79
+ position: relative;
80
+ transition:
81
+ background-color var(--slotted-control-transition-duration)
82
+ var(--slotted-control-transition-easing),
83
+ border-color var(--slotted-control-transition-duration)
84
+ var(--slotted-control-transition-easing),
85
+ box-shadow var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
86
+ }
87
+
88
+ [data-ui='cascader'][data-part='root']:has(> [data-part='clear']) {
89
+ grid-template-columns: minmax(0, 1fr) auto auto;
90
+ }
91
+
92
+ [data-ui='cascader'][data-part='root']:not([data-full-width]) {
93
+ inline-size: auto;
94
+ }
95
+
96
+ /* The trigger fills the frame and the two marks sit over it, for the reason
97
+ `select` writes above its own trigger: the chevron ends the control, and
98
+ the clear button is a sibling of the button rather than a widget in it. */
99
+ [data-ui='cascader'] > [data-part='trigger'] {
100
+ align-items: center;
101
+ appearance: none;
102
+ background-color: transparent;
103
+ border: 0;
104
+ box-sizing: border-box;
105
+ color: inherit;
106
+ cursor: pointer;
107
+ display: flex;
108
+ font: inherit;
109
+ gap: var(--_gap);
110
+ grid-area: 1 / 1 / 2 / -1;
111
+ margin-block: calc(var(--slotted-control-border-width, 1px) * -1);
112
+ min-block-size: var(--_height);
113
+ min-inline-size: 0;
114
+ outline: none;
115
+ padding-block: 0;
116
+ padding-inline-start: var(--_padding-inline);
117
+ padding-inline-end: calc(var(--_padding-inline) + var(--_icon-size) + var(--_gap));
118
+ text-align: start;
119
+ touch-action: manipulation;
120
+ -webkit-tap-highlight-color: transparent;
121
+ }
122
+
123
+ [data-ui='cascader'][data-part='root']:has(> [data-part='clear']) > [data-part='trigger'] {
124
+ padding-inline-end: calc(
125
+ var(--_padding-inline) + var(--_icon-size) + var(--_gap) + var(--_action-size) + var(--_gap)
126
+ );
127
+ }
128
+
129
+ /**
130
+ * The path, on one line. A path that wrapped would change the control's
131
+ * height as the reader chose. The segments give way before the last one: a
132
+ * long path reads "Portugal / Lis… / Alfama", keeping the place itself whole
133
+ * and eliding the middle of the road to it. The whole path stays in the DOM,
134
+ * so the trigger's name is never the ellipsis.
135
+ */
136
+ [data-ui='cascader'] [data-part='value'] {
137
+ align-items: baseline;
138
+ display: flex;
139
+ flex: 1 1 auto;
140
+ min-inline-size: 0;
141
+ overflow: hidden;
142
+ white-space: nowrap;
143
+ }
144
+
145
+ [data-ui='cascader'] [data-part='value-segment'] {
146
+ flex: 0 1 auto;
147
+ /* Two characters and the ellipsis, the least a segment can say. */
148
+ min-inline-size: 2.5ch;
149
+ overflow: hidden;
150
+ text-overflow: ellipsis;
151
+ }
152
+
153
+ /**
154
+ * The segments give way in order: the middle ones first, then the first,
155
+ * and the place itself last — it shrinks only once every other segment is at
156
+ * its floor. Flex freezes a segment at its minimum and hands the rest of the
157
+ * shortfall to the ones still free, so the weights order the giving way. The
158
+ * smallest weight is 1 and not a fraction: once the others are frozen, a
159
+ * free set whose weights sum below one receives only that share of the
160
+ * shortfall, and the last segment overflowed the value unclipped by its own
161
+ * ellipsis at a weight of 0.001.
162
+ */
163
+ [data-ui='cascader'] [data-part='value-segment'] {
164
+ flex-shrink: 100;
165
+ }
166
+
167
+ [data-ui='cascader'] [data-part='value-segment']:first-child {
168
+ flex-shrink: 50;
169
+ }
170
+
171
+ [data-ui='cascader'] [data-part='value-segment']:last-child {
172
+ flex-shrink: 1;
173
+ }
174
+
175
+ [data-ui='cascader'] [data-part='value-separator'] {
176
+ color: var(--slotted-cascader-separator-color, var(--slotted-text-muted, GrayText));
177
+ flex: none;
178
+ padding-inline: var(--slotted-space-2, 0.25rem);
179
+ }
180
+
181
+ /* Nothing chosen yet: the same weight, one step quieter. */
182
+ [data-ui='cascader'] [data-part='placeholder'] {
183
+ color: var(--slotted-cascader-placeholder-color, var(--slotted-text-muted, GrayText));
184
+ flex: 1 1 auto;
185
+ min-inline-size: 0;
186
+ overflow: hidden;
187
+ text-overflow: ellipsis;
188
+ white-space: nowrap;
189
+ }
190
+
191
+ /* A multiple selection shows its chips in the content lane, as `select`'s. */
192
+ [data-ui='cascader'][data-part='root'] > [data-part='tags'] {
193
+ align-items: center;
194
+ display: flex;
195
+ gap: var(--slotted-space-2, 0.25rem);
196
+ grid-area: 1 / 1 / 2 / 2;
197
+ margin-inline-start: var(--_padding-inline);
198
+ min-block-size: var(--slotted-target-min, 24px);
199
+ min-inline-size: 0;
200
+ overflow: hidden;
201
+ pointer-events: none;
202
+ }
203
+
204
+ [data-ui='cascader'] > [data-part='tags'] > * {
205
+ pointer-events: auto;
206
+ position: relative;
207
+ }
208
+
209
+ [data-ui='cascader'] [data-part='summary'] {
210
+ display: block;
211
+ overflow: hidden;
212
+ text-overflow: ellipsis;
213
+ unicode-bidi: plaintext;
214
+ white-space: nowrap;
215
+ }
216
+
217
+ [data-ui='cascader'][data-part='root']:not([data-narrow]) [data-part='summary'] {
218
+ block-size: 1px;
219
+ clip-path: inset(50%);
220
+ inline-size: 1px;
221
+ overflow: hidden;
222
+ white-space: nowrap;
223
+ }
224
+
225
+ [data-ui='cascader'][data-part='root'][data-narrow] > [data-part='tags'] {
226
+ display: none;
227
+ }
228
+
229
+ [data-ui='cascader'] > [data-part='arrow'] {
230
+ --slotted-icon-size: var(--_icon-size);
231
+
232
+ align-items: center;
233
+ block-size: var(--_icon-size);
234
+ color: var(--slotted-cascader-arrow-color, var(--slotted-text-muted, GrayText));
235
+ display: flex;
236
+ grid-area: 1 / -2 / 2 / -1;
237
+ inline-size: var(--_icon-size);
238
+ justify-content: center;
239
+ margin-inline-end: var(--_padding-inline);
240
+ pointer-events: none;
241
+ }
242
+
243
+ [data-ui='cascader'] > [data-part='arrow'] > [data-ui='icon'] {
244
+ transition: rotate var(--slotted-control-transition-duration)
245
+ var(--slotted-control-transition-easing);
246
+ }
247
+
248
+ [data-ui='cascader'][data-open] > [data-part='arrow'] > [data-ui='icon'] {
249
+ rotate: 180deg;
250
+ }
251
+
252
+ /* The ring where the chevron stands, while the value's path is resolving. */
253
+ [data-ui='cascader'] > [data-part='busy'] {
254
+ --slotted-spinner-size: var(--_icon-size);
255
+
256
+ color: var(--slotted-cascader-arrow-color, var(--slotted-text-muted, GrayText));
257
+ grid-area: 1 / -2 / 2 / -1;
258
+ margin-inline-end: var(--_padding-inline);
259
+ pointer-events: none;
260
+ }
261
+
262
+ [data-ui='cascader'] > [data-part='clear'] {
263
+ --slotted-icon-size: var(--_icon-size);
264
+
265
+ align-items: center;
266
+ appearance: none;
267
+ background-color: transparent;
268
+ block-size: var(--_action-size);
269
+ border: 0;
270
+ border-radius: var(--slotted-cascader-radius, var(--slotted-control-radius, 4px));
271
+ color: var(--slotted-text-muted, GrayText);
272
+ cursor: pointer;
273
+ display: inline-flex;
274
+ grid-area: 1 / 2 / 2 / 3;
275
+ inline-size: var(--_action-size);
276
+ justify-content: center;
277
+ margin-inline: calc((var(--_icon-size) - var(--_action-size)) / 2);
278
+ padding: 0;
279
+ position: relative;
280
+ touch-action: manipulation;
281
+ transition:
282
+ background-color var(--slotted-control-transition-duration)
283
+ var(--slotted-control-transition-easing),
284
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
285
+ -webkit-tap-highlight-color: transparent;
286
+ }
287
+
288
+ /* The hit area recovered outside the paint, as `select`'s. */
289
+ [data-ui='cascader'] > [data-part='clear']::after {
290
+ content: '';
291
+ inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
292
+ position: absolute;
293
+ }
294
+
295
+ @media (pointer: coarse) {
296
+ [data-ui='cascader'] > [data-part='clear']::after {
297
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
298
+ inset-inline-end: 0;
299
+ }
300
+ }
301
+
302
+ /* ── Size ─────────────────────────────────────────────────────────────── */
303
+
304
+ [data-ui='cascader'][data-part='root'][data-size='sm'] {
305
+ --_font-size: var(--slotted-control-font-size-sm, 12px);
306
+ --_height: var(--slotted-control-height-sm, 30px);
307
+ --_padding-inline: var(--slotted-control-padding-inline-sm, 10px);
308
+ --_gap: var(--slotted-control-gap-sm, 6px);
309
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-sm, 14px));
310
+ --_inner-size: var(--slotted-control-inner-size-sm, 22px);
311
+ }
312
+
313
+ [data-ui='cascader'][data-part='root'][data-size='lg'] {
314
+ --_font-size: var(--slotted-control-font-size-lg, 14px);
315
+ --_height: var(--slotted-control-height-lg, 38px);
316
+ --_padding-inline: var(--slotted-control-padding-inline-lg, 16px);
317
+ --_gap: var(--slotted-control-gap-lg, 8px);
318
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-lg, 18px));
319
+ --_inner-size: var(--slotted-control-inner-size-lg, 28px);
320
+ }
321
+
322
+ /* ── Variant ──────────────────────────────────────────────────────────── */
323
+
324
+ [data-ui='cascader'][data-part='root'][data-variant='subtle'] {
325
+ background-color: var(--slotted-surface-sunken, Canvas);
326
+ border-color: var(--slotted-border-subtle, ButtonBorder);
327
+ }
328
+
329
+ [data-ui='cascader'][data-part='root'][data-variant='plain'] {
330
+ background-color: transparent;
331
+ border-color: transparent;
332
+ border-radius: var(--slotted-radius-none, 0px);
333
+ box-shadow: none;
334
+ }
335
+
336
+ @media (forced-colors: active) {
337
+ [data-ui='cascader'][data-part='root'][data-variant='plain'] {
338
+ border-color: ButtonBorder;
339
+ }
340
+ }
341
+
342
+ /* ── States on the control ────────────────────────────────────────────── */
343
+
344
+ [data-ui='cascader'][data-part='root']:hover:not([data-disabled]):not([data-readonly]):not(
345
+ [data-invalid]
346
+ ) {
347
+ border-color: var(--slotted-cascader-hover-border-color, var(--slotted-tone-accent-border));
348
+ }
349
+
350
+ [data-ui='cascader'][data-part='root'][data-variant='subtle']:hover:not([data-disabled]):not(
351
+ [data-readonly]
352
+ ):not([data-invalid]) {
353
+ background-color: var(--slotted-tone-secondary-subtle-hover);
354
+ }
355
+
356
+ [data-ui='cascader'][data-part='root'][data-variant='plain']:hover:not([data-disabled]):not(
357
+ [data-readonly]
358
+ ):not([data-invalid]) {
359
+ background-color: var(--slotted-tone-secondary-subtle-hover);
360
+ border-color: transparent;
361
+ }
362
+
363
+ [data-ui='cascader'][data-part='root']:has(> [data-part='trigger']:focus-visible) {
364
+ box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
365
+ var(--slotted-focus-ring-color, Highlight);
366
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
367
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
368
+ }
369
+
370
+ [data-ui='cascader'][data-part='root'][data-variant='plain']:has(
371
+ > [data-part='trigger']:focus-visible
372
+ ) {
373
+ box-shadow: none;
374
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
375
+ }
376
+
377
+ [data-ui='cascader'][data-part='root'][data-open]:not([data-disabled]) {
378
+ border-color: var(--slotted-cascader-open-border-color, var(--slotted-tone-accent-border));
379
+ }
380
+
381
+ [data-ui='cascader'][data-part='root'][data-invalid] {
382
+ --slotted-focus-ring-color: var(--slotted-focus-ring-color-invalid, Highlight);
383
+ --_invalid-edge-width: var(
384
+ --slotted-cascader-invalid-edge-width,
385
+ var(--slotted-control-invalid-edge-width, 1px)
386
+ );
387
+ --_invalid-edge-color: var(
388
+ --slotted-cascader-invalid-border-color,
389
+ var(--slotted-tone-danger-border)
390
+ );
391
+ --_invalid-edge: inset 0 0 0 var(--_invalid-edge-width) var(--_invalid-edge-color);
392
+
393
+ border-color: var(--slotted-cascader-invalid-border-color, var(--slotted-tone-danger-border));
394
+ /*
395
+ * Width as well as colour (WCAG 1.4.1), the edge `text-field` draws: in
396
+ * `high-contrast` the danger border is the resting edge's black. The line
397
+ * is a shadow inside the border, so neither box nor text moves, and it
398
+ * takes the resting lift's place.
399
+ */
400
+ box-shadow: var(--_invalid-edge);
401
+ }
402
+
403
+ [data-ui='cascader'][data-part='root'][data-invalid]:has(> [data-part='trigger']:focus-visible) {
404
+ box-shadow:
405
+ var(--_invalid-edge),
406
+ var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
407
+ var(--slotted-focus-ring-color, Highlight);
408
+ }
409
+
410
+ [data-ui='cascader'][data-part='root'][data-variant='plain'][data-invalid]:has(
411
+ > [data-part='trigger']:focus-visible
412
+ ) {
413
+ /* The ring lies inside the box here, over the border and an edge as wide as
414
+ it; the edge reaches past the ring. */
415
+ box-shadow: inset 0 0 0
416
+ calc(
417
+ var(--slotted-focus-ring-offset, 2px) - var(--slotted-control-border-width, 1px) +
418
+ var(--_invalid-edge-width)
419
+ )
420
+ var(--_invalid-edge-color);
421
+ }
422
+
423
+ /*
424
+ * Forced colours remove every box shadow, and the edge with them. The
425
+ * width comes back as an outline inside the border, and a focused invalid
426
+ * control draws its ring double, which a valid ring is not.
427
+ */
428
+ @media (forced-colors: active) {
429
+ [data-ui='cascader'][data-part='root'][data-invalid] {
430
+ outline: var(--_invalid-edge-width) solid CanvasText;
431
+ outline-offset: calc(
432
+ -1 * (var(--slotted-control-border-width, 1px) + var(--_invalid-edge-width))
433
+ );
434
+ }
435
+
436
+ [data-ui='cascader'][data-part='root'][data-invalid]:has(
437
+ > [data-part='trigger']:focus-visible
438
+ ) {
439
+ outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
440
+ var(--slotted-focus-ring-color, Highlight);
441
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
442
+ }
443
+
444
+ [data-ui='cascader'][data-part='root'][data-variant='plain'][data-invalid]:has(
445
+ > [data-part='trigger']:focus-visible
446
+ ) {
447
+ outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
448
+ var(--slotted-focus-ring-color, Highlight);
449
+ outline-offset: calc(
450
+ -1 * (var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width))
451
+ );
452
+ }
453
+ }
454
+
455
+ [data-ui='cascader'][data-part='root'][data-readonly] {
456
+ background-color: var(--slotted-tone-secondary-subtle-hover);
457
+ }
458
+
459
+ /* The chevron of a control nobody may open steps down to the muted ink it
460
+ already has plus the disabled one, rather than fading by opacity. */
461
+ [data-ui='cascader'][data-part='root'][data-readonly] > [data-part='arrow'] {
462
+ color: var(--slotted-disabled-foreground);
463
+ }
464
+
465
+ [data-ui='cascader'][data-part='root'][data-disabled],
466
+ [data-ui='cascader'][data-part='root']:has(> [data-part='trigger']:disabled) {
467
+ background-color: var(--slotted-disabled-background);
468
+ border-color: var(--slotted-disabled-border);
469
+ box-shadow: none;
470
+ color: var(--slotted-disabled-foreground);
471
+ }
472
+
473
+ [data-ui='cascader'][data-part='root'][data-disabled] > [data-part='trigger'],
474
+ [data-ui='cascader'][data-part='root'] > [data-part='trigger']:disabled {
475
+ cursor: not-allowed;
476
+ }
477
+
478
+ [data-ui='cascader'] > [data-part='clear']:hover:not(:disabled):not([data-disabled]) {
479
+ background-color: var(--slotted-tone-secondary-subtle-hover);
480
+ color: var(--slotted-text, CanvasText);
481
+ }
482
+
483
+ [data-ui='cascader'] > [data-part='clear']:active:not(:disabled):not([data-disabled]) {
484
+ background-color: var(--slotted-tone-secondary-subtle-active);
485
+ }
486
+
487
+ [data-ui='cascader'] > [data-part='clear']:focus-visible {
488
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
489
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
490
+ }
491
+
492
+ /* ── The layer ────────────────────────────────────────────────────────── */
493
+
494
+ [data-ui='cascader']:is([data-part='positioner'], [data-part='content']) {
495
+ --_surface: var(--slotted-cascader-surface, var(--slotted-surface-raised, #ffffff));
496
+ --_text: var(--slotted-text, #0f172a);
497
+ --_muted: var(--slotted-text-muted, #5b6b7f);
498
+ --_border-color: var(--slotted-cascader-border-subtle, var(--slotted-border-subtle, #e2e8f0));
499
+ --_border-width: var(--slotted-border-width-thin, 1px);
500
+ --_radius: var(--slotted-cascader-content-radius, var(--slotted-radius-lg, 8px));
501
+ --_shadow: var(--slotted-cascader-content-shadow, var(--slotted-shadow-md));
502
+
503
+ /**
504
+ * The cursor, the path and the press. The cursor is `select`'s stronger
505
+ * neutral step, which lifts in all three schemes where the weaker one sank
506
+ * in the dark (the measurement `select` records). The path — the nodes whose
507
+ * columns are open — takes the weaker step of the same pair only in the
508
+ * light schemes; in the dark it would sink, so the path is carried by the
509
+ * ink and the chevron as well, never by the ground alone.
510
+ */
511
+ --_highlight: var(--slotted-cascader-highlight, var(--slotted-tone-secondary-subtle-active));
512
+ --_highlight-active: var(
513
+ --slotted-cascader-highlight-active,
514
+ var(--slotted-tone-accent-surface)
515
+ );
516
+ --_path: var(--slotted-cascader-path, var(--slotted-tone-secondary-surface));
517
+ --_selected-color: var(--slotted-cascader-selected-color, var(--slotted-tone-accent-text));
518
+
519
+ --_inset-block: var(--slotted-space-2, 0.25rem);
520
+ --_inset-inline: var(--slotted-space-2, 0.25rem);
521
+ --_item-inset: calc(var(--slotted-control-padding-inline-md, 0.8125rem) - var(--_inset-inline));
522
+ --_item-height: var(--slotted-control-height-md, 34px);
523
+ --_item-radius: var(--slotted-control-radius);
524
+ --_content-font-size: var(--slotted-control-font-size-md, 13px);
525
+ --_secondary-font-size: var(--slotted-control-font-size-sm, 12px);
526
+ --_content-icon-size: var(--slotted-control-icon-size-md, 16px);
527
+ --_check-size: var(--slotted-selection-size-md, 16px);
528
+ --_column-gap: var(--slotted-control-gap-md, 0.5rem);
529
+ --_column-measure: var(--slotted-cascader-column-measure, 12rem);
530
+ --_indent: var(--slotted-cascader-indent, var(--slotted-space-6, 1rem));
531
+
532
+ /**
533
+ * Line boxes on whole pixels, so a column of nodes with descriptions sums
534
+ * to a whole number and the surface's bottom border sits on a pixel row.
535
+ * The same rounding `menu` and `attachment` apply to the same ratios.
536
+ */
537
+ --_leading: round(
538
+ up,
539
+ calc(var(--_content-font-size) * var(--slotted-line-height-md, 1.5)),
540
+ 1px
541
+ );
542
+ --_secondary-leading: round(
543
+ up,
544
+ calc(var(--_secondary-font-size) * var(--slotted-line-height-sm, 1.45)),
545
+ 1px
546
+ );
547
+ }
548
+
549
+ [data-ui='cascader'][data-part='positioner'] {
550
+ position: absolute;
551
+ inset-block-start: 0;
552
+ z-index: calc(var(--slotted-z-index-popover, 1100) + var(--slotted-layer-depth, 0));
553
+ isolation: isolate;
554
+ box-sizing: border-box;
555
+ pointer-events: none;
556
+
557
+ opacity: 0;
558
+ --_enter-distance: var(--slotted-space-2, 0.25rem);
559
+ translate: 0 calc(-1 * var(--_enter-distance));
560
+ transition:
561
+ opacity var(--slotted-duration-short) var(--slotted-easing-exit),
562
+ translate var(--slotted-duration-short) var(--slotted-easing-exit);
563
+ }
564
+
565
+ [data-ui='cascader'][data-part='positioner'][data-side='top'] {
566
+ translate: 0 var(--_enter-distance);
567
+ }
568
+
569
+ [data-ui='cascader'][data-part='positioner']:is([data-side='left'], [data-side='right']) {
570
+ translate: 0 0;
571
+ }
572
+
573
+ /* The entrance is a keyframe, the exit a transition: `select`'s reasoning. */
574
+ [data-ui='cascader'][data-part='positioner'][data-open] {
575
+ opacity: 1;
576
+ translate: 0 0;
577
+ transition: none;
578
+ }
579
+
580
+ [data-ui='cascader'][data-part='positioner'][data-open][data-positioned] {
581
+ animation: slotted-cascader-enter-down var(--slotted-duration-medium)
582
+ var(--slotted-easing-enter);
583
+ }
584
+
585
+ [data-ui='cascader'][data-part='positioner'][data-open][data-positioned][data-side='top'] {
586
+ animation-name: slotted-cascader-enter-up;
587
+ }
588
+
589
+ @keyframes slotted-cascader-enter-down {
590
+ from {
591
+ opacity: 0;
592
+ translate: 0 calc(-1 * var(--_enter-distance));
593
+ }
594
+ }
595
+
596
+ @keyframes slotted-cascader-enter-up {
597
+ from {
598
+ opacity: 0;
599
+ translate: 0 var(--_enter-distance);
600
+ }
601
+ }
602
+
603
+ @keyframes slotted-cascader-fade {
604
+ from {
605
+ opacity: 0;
606
+ }
607
+ }
608
+
609
+ @media (prefers-reduced-motion: reduce) {
610
+ [data-ui='cascader'][data-part='positioner'],
611
+ [data-ui='cascader'][data-part='positioner'][data-side='top'] {
612
+ translate: 0 0;
613
+ transition: opacity var(--slotted-duration-short) var(--slotted-easing-exit);
614
+ }
615
+
616
+ [data-ui='cascader'][data-part='positioner'][data-open][data-positioned],
617
+ [data-ui='cascader'][data-part='positioner'][data-open][data-positioned][data-side='top'] {
618
+ animation-name: slotted-cascader-fade;
619
+ }
620
+ }
621
+
622
+ [data-ui='cascader'][data-part='positioner'][data-detached] {
623
+ visibility: hidden;
624
+ }
625
+
626
+ /**
627
+ * The width follows the layout. Columns take their own sum, as wide as the
628
+ * path is deep, up to the room the positioner reports; one level at a time
629
+ * takes the control's width, and never less than one column.
630
+ */
631
+ [data-ui='cascader'][data-part='positioner'][data-layout='columns'] {
632
+ inline-size: max-content;
633
+ max-inline-size: var(--slotted-positioner-available-width, 100vw);
634
+ min-inline-size: var(--slotted-positioner-anchor-width, auto);
635
+ }
636
+
637
+ /**
638
+ * The layer reserves the widest width the window can reach and the surface
639
+ * inside it is only as wide as the columns on show, never narrower than the
640
+ * control it hangs from. The reserved strip beside it is the layer's, which
641
+ * takes no pointer.
642
+ */
643
+ [data-ui='cascader'][data-part='positioner'][data-layout='columns'] > [data-part='content'] {
644
+ inline-size: max-content;
645
+ max-inline-size: 100%;
646
+ min-inline-size: min(var(--slotted-positioner-anchor-width, 0px), 100%);
647
+ }
648
+
649
+ [data-ui='cascader'][data-part='positioner']:is([data-layout='drill'], [data-layout='tree']) {
650
+ inline-size: max(var(--slotted-positioner-anchor-width, 0px), var(--_column-measure));
651
+ max-inline-size: var(--slotted-positioner-available-width, 100vw);
652
+ }
653
+
654
+ [data-ui='cascader']:is([data-part='positioner'], [data-part='content'])[data-size='sm'] {
655
+ --_item-inset: calc(var(--slotted-control-padding-inline-sm, 0.625rem) - var(--_inset-inline));
656
+ --_item-height: var(--slotted-control-height-sm, 30px);
657
+ --_content-font-size: var(--slotted-control-font-size-sm, 12px);
658
+ --_secondary-font-size: var(--slotted-font-size-xs, 0.75rem);
659
+ --_content-icon-size: var(--slotted-control-icon-size-sm, 14px);
660
+ --_check-size: var(--slotted-selection-size-sm, 14px);
661
+ --_column-gap: var(--slotted-control-gap-sm, 0.375rem);
662
+ }
663
+
664
+ [data-ui='cascader']:is([data-part='positioner'], [data-part='content'])[data-size='lg'] {
665
+ --_item-inset: calc(var(--slotted-control-padding-inline-lg, 1rem) - var(--_inset-inline));
666
+ --_item-height: var(--slotted-control-height-lg, 38px);
667
+ --_content-font-size: var(--slotted-control-font-size-lg, 14px);
668
+ --_secondary-font-size: var(--slotted-control-font-size-sm, 12px);
669
+ --_content-icon-size: var(--slotted-control-icon-size-lg, 18px);
670
+ --_check-size: var(--slotted-selection-size-lg, 18px);
671
+ --_column-gap: var(--slotted-control-gap-lg, 0.5rem);
672
+ }
673
+
674
+ /* ── The surface ──────────────────────────────────────────────────────── */
675
+
676
+ /**
677
+ * A column of up to three rows — the search field, the breadcrumb, the
678
+ * panel — bounded by the height the positioner reports. The panel is the one
679
+ * that gives, and inside it each column scrolls on its own.
680
+ */
681
+ [data-ui='cascader'] > [data-part='content'] {
682
+ background: var(--_surface);
683
+ border: var(--_border-width) solid var(--_border-color);
684
+ border-radius: var(--_radius);
685
+ box-shadow: var(--_shadow);
686
+ box-sizing: border-box;
687
+ color: var(--_text);
688
+ display: flex;
689
+ flex-direction: column;
690
+ font-family: var(--slotted-font-family-sans);
691
+ font-size: var(--_content-font-size);
692
+ line-height: var(--_leading);
693
+ max-block-size: calc(
694
+ var(--slotted-positioner-available-height, 100vh) - var(--slotted-space-5, 0.75rem)
695
+ );
696
+ /* The columns' own rules meet the rounded edge rather than crossing it. */
697
+ overflow: hidden;
698
+ outline: none;
699
+ pointer-events: auto;
700
+ }
701
+
702
+ [data-ui='cascader'] > [data-part='content']:focus-visible {
703
+ outline: none;
704
+ }
705
+
706
+ /**
707
+ * The surface on its own, without a control or a layer — a settings screen,
708
+ * a sidebar. It carries `data-ui` itself, paints what the layer's surface
709
+ * paints minus the shadow, because it lies on the page rather than over it,
710
+ * and is as wide as its columns up to its container. The tree inside it
711
+ * takes focus here, and the surface draws the ring for it.
712
+ */
713
+ [data-ui='cascader'][data-part='content'] {
714
+ background: var(--_surface);
715
+ border: var(--_border-width) solid var(--_border-color);
716
+ border-radius: var(--_radius);
717
+ box-sizing: border-box;
718
+ color: var(--_text);
719
+ display: flex;
720
+ flex-direction: column;
721
+ font-family: var(--slotted-font-family-sans);
722
+ font-size: var(--_content-font-size);
723
+ inline-size: fit-content;
724
+ line-height: var(--_leading);
725
+ max-inline-size: 100%;
726
+ overflow: hidden;
727
+ }
728
+
729
+ [data-ui='cascader'][data-part='content']:has(> [data-part='panel']:focus-visible) {
730
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
731
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
732
+ }
733
+
734
+ /* ── The search field ─────────────────────────────────────────────────── */
735
+
736
+ [data-ui='cascader'] [data-part='search'] {
737
+ align-items: center;
738
+ border-block-end: var(--_border-width) solid var(--_border-color);
739
+ box-sizing: border-box;
740
+ display: flex;
741
+ flex: 0 0 auto;
742
+ gap: var(--_column-gap);
743
+ min-block-size: var(--_item-height);
744
+ padding-block: var(--slotted-space-2, 0.25rem);
745
+ padding-inline: calc(var(--_inset-inline) + var(--_item-inset));
746
+ }
747
+
748
+ [data-ui='cascader'] [data-part='search'] > [data-ui='icon'] {
749
+ --slotted-icon-size: var(--_content-icon-size);
750
+
751
+ color: var(--_muted);
752
+ flex: none;
753
+ }
754
+
755
+ /* No ring: the field holds focus for as long as the popup is open, so a
756
+ ring would be a border, not a state. The caret says where focus is. */
757
+ [data-ui='cascader'] [data-part='search-input'] {
758
+ background-color: transparent;
759
+ border: 0;
760
+ color: inherit;
761
+ flex: 1 1 auto;
762
+ font: inherit;
763
+ min-inline-size: 0;
764
+ outline: none;
765
+ padding: 0;
766
+ text-overflow: ellipsis;
767
+ }
768
+
769
+ [data-ui='cascader'] [data-part='search-input']::placeholder {
770
+ color: var(--_muted);
771
+ text-overflow: ellipsis;
772
+ }
773
+
774
+ /* ── The breadcrumb ───────────────────────────────────────────────────── */
775
+
776
+ /**
777
+ * Where the levels on show sit: the ones before them, each a press away. It
778
+ * is the way back by pointer in `drill`, which shows one level, and in
779
+ * `columns` once the window has slid past a level. Each crumb is a real
780
+ * control with the target minimum, and the row shares the column's inset so
781
+ * the first crumb starts where the labels under it start.
782
+ *
783
+ * One line, never wrapped: a deep trail folds its middle into one crumb
784
+ * (`cascaderCrumbs`), so the row is as tall at the tenth level as at the
785
+ * second and the list under it does not move down as the reader drills.
786
+ */
787
+ [data-ui='cascader'] [data-part='breadcrumb'] {
788
+ align-items: center;
789
+ border-block-end: var(--_border-width) solid var(--_border-color);
790
+ color: var(--_muted);
791
+ display: flex;
792
+ flex: 0 0 auto;
793
+ font-size: var(--_secondary-font-size);
794
+ gap: var(--slotted-space-1, 0.125rem);
795
+ line-height: var(--_secondary-leading);
796
+ min-inline-size: 0;
797
+ overflow: hidden;
798
+ padding-block: var(--slotted-space-2, 0.25rem);
799
+ padding-inline: calc(
800
+ var(--_inset-inline) + var(--_item-inset) - var(--slotted-space-2, 0.25rem)
801
+ );
802
+ white-space: nowrap;
803
+ }
804
+
805
+ [data-ui='cascader'] [data-part='breadcrumb'] > [data-ui='icon'] {
806
+ --slotted-icon-size: var(--_secondary-font-size);
807
+
808
+ flex: none;
809
+ }
810
+
811
+ [data-ui='cascader'] [data-part='crumb'] {
812
+ appearance: none;
813
+ background-color: transparent;
814
+ border: 0;
815
+ border-radius: var(--slotted-radius-sm, 4px);
816
+ color: inherit;
817
+ cursor: pointer;
818
+ font: inherit;
819
+ /* The crumbs before the current one give way first; weights rather than a
820
+ zero, for the reason the value's segments state. */
821
+ flex: 0 100 auto;
822
+ max-inline-size: 12ch;
823
+ min-block-size: var(--slotted-target-min, 24px);
824
+ min-inline-size: 3ch;
825
+ overflow: hidden;
826
+ padding-block: 0;
827
+ padding-inline: var(--slotted-space-2, 0.25rem);
828
+ text-overflow: ellipsis;
829
+ white-space: nowrap;
830
+ transition:
831
+ background-color var(--slotted-control-transition-duration)
832
+ var(--slotted-control-transition-easing),
833
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
834
+ }
835
+
836
+ [data-ui='cascader'] [data-part='crumb']:hover:not([aria-current]):not(:disabled) {
837
+ background-color: var(--_highlight);
838
+ color: var(--_text);
839
+ }
840
+
841
+ [data-ui='cascader'] [data-part='crumb']:active:not([aria-current]):not(:disabled) {
842
+ background-color: var(--_highlight-active);
843
+ }
844
+
845
+ /* Outside the crumb: an inset ring sat on the first letter of a label the
846
+ crumb's own padding barely clears. The row's block padding holds it. */
847
+ [data-ui='cascader'] [data-part='crumb']:focus-visible {
848
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
849
+ outline-offset: 0;
850
+ }
851
+
852
+ /* The level on show: where the reader is, and not a place to go. */
853
+ [data-ui='cascader'] [data-part='crumb'][aria-current] {
854
+ color: var(--_text);
855
+ cursor: default;
856
+ flex-shrink: 1;
857
+ font-weight: var(--slotted-font-weight-semibold, 600);
858
+ max-inline-size: none;
859
+ }
860
+
861
+ /* The fold: the middle of a deep trail as one crumb, its ellipsis whole. */
862
+ [data-ui='cascader'] [data-part='crumb'][data-collapsed] {
863
+ flex: none;
864
+ min-inline-size: var(--slotted-target-min, 24px);
865
+ }
866
+
867
+ /* ── The panel and its columns ────────────────────────────────────────── */
868
+
869
+ /**
870
+ * The panel never scrolls sideways. A path deeper than the room holds
871
+ * slides the window of columns the binding renders (`cascaderWindow`), and
872
+ * the levels left behind go to the breadcrumb above. The first capture
873
+ * scrolled them instead, and at 420 pixels the third column sat under the
874
+ * rounded edge with nothing on a touch screen saying there was more.
875
+ */
876
+ [data-ui='cascader'] [data-part='panel'] {
877
+ display: flex;
878
+ flex: 1 1 auto;
879
+ min-block-size: 0;
880
+ min-inline-size: 0;
881
+ outline: none;
882
+ }
883
+
884
+ /**
885
+ * One level. A grid of five tracks every node passes through, one measure
886
+ * wide, scrolling on its own. Columns after the first are ruled off from the
887
+ * one before by a hairline from the border scale — the edge a reader follows
888
+ * from a branch to its children.
889
+ */
890
+ [data-ui='cascader'] [data-part='column'] {
891
+ align-content: start;
892
+ box-sizing: border-box;
893
+ display: grid;
894
+ /**
895
+ * One measure each, and they give way together rather than spilling past
896
+ * the surface: the binding sizes the window to what fits, and this is the
897
+ * floor under it for the frames between a resize and the next measurement,
898
+ * when the room has shrunk and the window has not yet slid.
899
+ */
900
+ flex: 0 1 auto;
901
+ grid-template-columns: auto auto minmax(0, 1fr) auto auto;
902
+ /* A size and not a basis: the layer is `max-content`, and a flex basis
903
+ does not enter an item's max-content contribution, so with a basis alone
904
+ every column measured its longest label and broke words inside it. */
905
+ inline-size: var(--_column-measure);
906
+ min-inline-size: 0;
907
+ max-block-size: 100%;
908
+ overflow-y: auto;
909
+ overscroll-behavior: contain;
910
+ padding-block: var(--_inset-block);
911
+ padding-inline: var(--_inset-inline);
912
+ }
913
+
914
+ [data-ui='cascader'] [data-part='column'] + [data-part='column'] {
915
+ border-inline-start: var(--_border-width) solid var(--_border-color);
916
+ }
917
+
918
+ /* One level at a time, or every level in one run: the column is the panel. */
919
+ [data-ui='cascader']:is([data-layout='drill'], [data-layout='tree']) [data-part='column'] {
920
+ flex: 1 1 auto;
921
+ inline-size: auto;
922
+ }
923
+
924
+ /* A level still loading says so to a reader while its rows wait. */
925
+ [data-ui='cascader'] [data-part='column'][aria-busy='true'] {
926
+ cursor: progress;
927
+ }
928
+
929
+ /* ── Nodes ────────────────────────────────────────────────────────────── */
930
+
931
+ /**
932
+ * `role="treeitem"` on a `div`: DOM focus stays on the control and the
933
+ * cursor is `aria-activedescendant`, so a node is neither focusable nor a
934
+ * button, as `select`'s option is not.
935
+ */
936
+ [data-ui='cascader'] [data-part='node'] {
937
+ align-content: center;
938
+ border-radius: var(--_item-radius);
939
+ box-sizing: border-box;
940
+ cursor: pointer;
941
+ display: grid;
942
+ grid-column: 1 / -1;
943
+ grid-template-columns: subgrid;
944
+ line-height: var(--_leading);
945
+ min-block-size: var(--_item-height);
946
+ padding-block: var(--slotted-space-2, 0.25rem);
947
+ padding-inline: var(--_item-inset);
948
+ row-gap: var(--slotted-space-1, 0.125rem);
949
+ user-select: none;
950
+ transition:
951
+ background-color var(--slotted-control-transition-duration, var(--slotted-duration-short))
952
+ var(--slotted-control-transition-easing, var(--slotted-easing-standard)),
953
+ box-shadow var(--slotted-control-transition-duration, var(--slotted-duration-short))
954
+ var(--slotted-control-transition-easing, var(--slotted-easing-standard)),
955
+ color var(--slotted-control-transition-duration, var(--slotted-duration-short))
956
+ var(--slotted-control-transition-easing, var(--slotted-easing-standard));
957
+ }
958
+
959
+ /**
960
+ * The tree layout indents each node by its depth, which the binding writes
961
+ * as a runtime property: the visible nodes are one flat run of treeitems
962
+ * carrying `aria-level`, because a node that held its children would paint
963
+ * its highlight over them.
964
+ */
965
+ [data-ui='cascader'][data-layout='tree'] [data-part='node'] {
966
+ /* Its own tracks rather than the column's: a subgrid gives every row the
967
+ widest padding among them, so the first capture drew every level at the
968
+ deepest indent. The end tracks still line up, because every node ends in
969
+ a cell of the same width. */
970
+ grid-template-columns: auto auto minmax(0, 1fr) auto auto;
971
+ padding-inline-start: calc(
972
+ var(--_item-inset) + var(--slotted-cascader-depth, 0) * var(--_indent)
973
+ );
974
+ }
975
+
976
+ /**
977
+ * On the path: a branch whose level is open to its inline end. The ground is
978
+ * the quieter neutral step, and the chevron takes the label's ink, so the
979
+ * road from the first column to the cursor reads as one line — and in the
980
+ * dark scheme, where no neutral ground below the cursor lifts, the ink
981
+ * carries it alone.
982
+ */
983
+ [data-ui='cascader'] [data-part='node'][data-expanded] {
984
+ background-color: var(--_path);
985
+ }
986
+
987
+ /* And a weight, which is what carries the road where no ground does: the
988
+ high-contrast scheme draws the path ground as its own surface. */
989
+ [data-ui='cascader'] [data-part='node'][data-expanded] > [data-part='label'] {
990
+ font-weight: var(--slotted-font-weight-semibold, 600);
991
+ }
992
+
993
+ [data-ui='cascader'][data-layout='tree'] [data-part='node'][data-expanded] {
994
+ background-color: transparent;
995
+ }
996
+
997
+ /* The cursor, a ground and a one-pixel ring, for the reason `select` gives. */
998
+ [data-ui='cascader'] [data-part='node'][data-current] {
999
+ background-color: var(--_highlight);
1000
+ box-shadow: inset 0 0 0 var(--slotted-border-width-thin, 1px)
1001
+ var(--slotted-cascader-highlight-ring, var(--slotted-tone-accent-border));
1002
+ }
1003
+
1004
+ [data-ui='cascader'] [data-part='node']:not([data-disabled]):active {
1005
+ background-color: var(--_highlight-active);
1006
+ }
1007
+
1008
+ [data-ui='cascader'] [data-part='node'][data-selected] {
1009
+ color: var(--_selected-color);
1010
+ }
1011
+
1012
+ [data-ui='cascader'] [data-part='node'][data-selected] > [data-part='label'] {
1013
+ font-weight: var(--slotted-font-weight-medium, 500);
1014
+ }
1015
+
1016
+ [data-ui='cascader'] [data-part='node'][data-disabled] {
1017
+ color: var(--slotted-disabled-foreground, #64748b);
1018
+ cursor: not-allowed;
1019
+ }
1020
+
1021
+ /* The cursor lifts on a disabled node too; the ink and the ring step down. */
1022
+ [data-ui='cascader'] [data-part='node'][data-disabled][data-current] {
1023
+ box-shadow: inset 0 0 0 var(--slotted-border-width-thin, 1px)
1024
+ var(--slotted-disabled-border, #cbd5e1);
1025
+ }
1026
+
1027
+ /* ── The cells ────────────────────────────────────────────────────────── */
1028
+
1029
+ [data-ui='cascader']
1030
+ [data-part='node']
1031
+ > :is([data-part='indicator'], [data-part='icon'], [data-part='expander']) {
1032
+ block-size: 1lh;
1033
+ }
1034
+
1035
+ /**
1036
+ * Track two: the node's own picture, content the consumer supplies and the
1037
+ * column sizes. No stylesheet fills it.
1038
+ */
1039
+ [data-ui='cascader'] [data-part='node'] > [data-part='icon'] {
1040
+ --slotted-icon-size: var(--_content-icon-size);
1041
+
1042
+ align-items: center;
1043
+ display: flex;
1044
+ grid-column: 2;
1045
+ grid-row: 1;
1046
+ inline-size: var(--_content-icon-size);
1047
+ justify-content: center;
1048
+ margin-inline-end: var(--_column-gap);
1049
+ }
1050
+
1051
+ [data-ui='cascader'] [data-part='node'] > [data-part='icon'] > * {
1052
+ font-size: var(--_content-icon-size);
1053
+ }
1054
+
1055
+ /* Track three, the only one that gives way: two lines, then an ellipsis. */
1056
+ [data-ui='cascader'] [data-part='node'] > [data-part='label'] {
1057
+ display: -webkit-box;
1058
+ grid-column: 3;
1059
+ grid-row: 1;
1060
+ min-inline-size: 0;
1061
+ overflow: hidden;
1062
+ overflow-wrap: anywhere;
1063
+ -webkit-box-orient: vertical;
1064
+ -webkit-line-clamp: 2;
1065
+ }
1066
+
1067
+ /**
1068
+ * The path of a search hit, or the line under a label. Quieter by the
1069
+ * secondary step and never in the way of the label above it.
1070
+ */
1071
+ [data-ui='cascader'] [data-part='node'] > [data-part='description'] {
1072
+ color: var(--_muted);
1073
+ font-size: var(--_secondary-font-size);
1074
+ grid-column: 3;
1075
+ grid-row: 2;
1076
+ line-height: var(--_secondary-leading);
1077
+ min-inline-size: 0;
1078
+ overflow: hidden;
1079
+ text-overflow: ellipsis;
1080
+ white-space: nowrap;
1081
+ }
1082
+
1083
+ [data-ui='cascader'] [data-part='node'][data-disabled] > [data-part='description'] {
1084
+ color: inherit;
1085
+ }
1086
+
1087
+ /* Track four: the count of a branch, or how many inside it are chosen. */
1088
+ [data-ui='cascader'] [data-part='node'] > [data-part='meta'] {
1089
+ color: var(--_muted);
1090
+ font-size: var(--_secondary-font-size);
1091
+ font-variant-numeric: tabular-nums;
1092
+ grid-column: 4;
1093
+ grid-row: 1;
1094
+ justify-self: end;
1095
+ margin-inline-start: var(--_column-gap);
1096
+ white-space: nowrap;
1097
+ }
1098
+
1099
+ [data-ui='cascader'] [data-part='node'][data-selected] > [data-part='meta'],
1100
+ [data-ui='cascader'] [data-part='node'][data-indeterminate] > [data-part='meta'] {
1101
+ color: var(--_selected-color);
1102
+ }
1103
+
1104
+ /**
1105
+ * Track five: the chevron of a branch. It points along the reading
1106
+ * direction, from the `directional` icon box the binding draws, and takes
1107
+ * the label's ink on the path.
1108
+ */
1109
+ [data-ui='cascader'] [data-part='node'] > [data-part='expander'] {
1110
+ --slotted-icon-size: var(--_content-icon-size);
1111
+
1112
+ align-items: center;
1113
+ color: var(--_muted);
1114
+ display: flex;
1115
+ grid-column: 5;
1116
+ grid-row: 1;
1117
+ inline-size: var(--_content-icon-size);
1118
+ justify-content: center;
1119
+ justify-self: end;
1120
+ margin-inline-start: var(--_column-gap);
1121
+ transition: color var(--slotted-control-transition-duration)
1122
+ var(--slotted-control-transition-easing);
1123
+ }
1124
+
1125
+ [data-ui='cascader']
1126
+ [data-part='node']:is([data-expanded], [data-current])
1127
+ > [data-part='expander'] {
1128
+ color: inherit;
1129
+ }
1130
+
1131
+ [data-ui='cascader'] [data-part='node'] > [data-part='expander'] > [data-ui='icon'] {
1132
+ transition: rotate var(--slotted-control-transition-duration)
1133
+ var(--slotted-control-transition-easing);
1134
+ }
1135
+
1136
+ /* In the tree the level opens under the node, so the chevron turns down. */
1137
+ [data-ui='cascader'][data-layout='tree']
1138
+ [data-part='node'][data-expanded]
1139
+ > [data-part='expander']
1140
+ > [data-ui='icon'] {
1141
+ rotate: 90deg;
1142
+ }
1143
+
1144
+ /* A branch whose level is on its way: the ring stands where the chevron stood. */
1145
+ [data-ui='cascader'] [data-part='expander'] > [data-ui='spinner'] {
1146
+ --slotted-spinner-size: var(--_content-icon-size);
1147
+ }
1148
+
1149
+ /**
1150
+ * The mark of a single selection: the check at the end, in the chevron's
1151
+ * track, because only a node that is not a branch — or a branch the consumer
1152
+ * made selectable — carries it.
1153
+ */
1154
+ [data-ui='cascader'] [data-part='node'] > [data-part='indicator'] {
1155
+ --slotted-icon-size: var(--_content-icon-size);
1156
+
1157
+ align-items: center;
1158
+ display: flex;
1159
+ grid-column: 5;
1160
+ grid-row: 1;
1161
+ inline-size: var(--_content-icon-size);
1162
+ justify-content: center;
1163
+ justify-self: end;
1164
+ margin-inline-start: var(--_column-gap);
1165
+ opacity: 0;
1166
+ scale: 0.8;
1167
+ transition:
1168
+ opacity var(--slotted-duration-short) var(--slotted-easing-exit),
1169
+ scale var(--slotted-duration-short) var(--slotted-easing-exit);
1170
+ }
1171
+
1172
+ [data-ui='cascader'] [data-part='node'][data-selected] > [data-part='indicator'] {
1173
+ opacity: 1;
1174
+ scale: 1;
1175
+ transition:
1176
+ opacity var(--slotted-duration-short) var(--slotted-easing-enter),
1177
+ scale var(--slotted-duration-short) var(--slotted-easing-enter);
1178
+ }
1179
+
1180
+ /**
1181
+ * A multiple selection draws `checkbox`'s box in track one, as `tree` draws
1182
+ * it: the same square from the selection scale, the same medium edge, the
1183
+ * same solid ground when chosen, and the mark — a check, or the dash while
1184
+ * part of the branch is chosen — revealed along its stroke.
1185
+ */
1186
+ [data-ui='cascader'][data-selection='multiple'] [data-part='node'] > [data-part='indicator'] {
1187
+ --_mark-inset: var(--slotted-cascader-mark-inset, 2px);
1188
+ --_check-border: var(--slotted-border-width-medium, 1.5px);
1189
+ --slotted-icon-size: calc(var(--_check-size) - 2 * var(--_mark-inset));
1190
+
1191
+ align-self: center;
1192
+ background-color: var(--_surface);
1193
+ block-size: var(--_check-size);
1194
+ border: var(--_check-border) solid var(--slotted-border-strong);
1195
+ border-radius: var(--slotted-radius-xs, 2px);
1196
+ box-sizing: border-box;
1197
+ grid-column: 1;
1198
+ inline-size: var(--_check-size);
1199
+ justify-self: start;
1200
+ margin-inline-end: var(--_column-gap);
1201
+ margin-inline-start: 0;
1202
+ opacity: 1;
1203
+ position: relative;
1204
+ scale: 1;
1205
+ transition:
1206
+ background-color var(--slotted-control-transition-duration)
1207
+ var(--slotted-control-transition-easing),
1208
+ border-color var(--slotted-control-transition-duration)
1209
+ var(--slotted-control-transition-easing);
1210
+ }
1211
+
1212
+ [data-ui='cascader'][data-selection='multiple']
1213
+ [data-part='node']
1214
+ > [data-part='indicator']
1215
+ > [data-ui='icon'] {
1216
+ clip-path: inset(0% 100% 0% 0%);
1217
+ color: var(--slotted-tone-accent-on-solid);
1218
+ inset-block-start: calc(var(--_mark-inset) - var(--_check-border));
1219
+ inset-inline-start: calc(var(--_mark-inset) - var(--_check-border));
1220
+ opacity: 0;
1221
+ pointer-events: none;
1222
+ position: absolute;
1223
+ transition:
1224
+ clip-path var(--slotted-duration-medium) var(--slotted-control-transition-easing),
1225
+ opacity var(--slotted-duration-medium) var(--slotted-control-transition-easing);
1226
+ }
1227
+
1228
+ [data-ui='cascader'][data-selection='multiple']
1229
+ [data-part='node']:is([data-selected], [data-indeterminate])
1230
+ > [data-part='indicator'] {
1231
+ background-color: var(--slotted-tone-accent-solid);
1232
+ border-color: var(--slotted-tone-accent-solid);
1233
+ }
1234
+
1235
+ [data-ui='cascader'][data-selection='multiple']
1236
+ [data-part='node']:is([data-selected], [data-indeterminate])
1237
+ > [data-part='indicator']
1238
+ > [data-ui='icon'] {
1239
+ clip-path: inset(0% 0% 0% 0%);
1240
+ opacity: 1;
1241
+ }
1242
+
1243
+ [data-ui='cascader'][data-selection='multiple']
1244
+ [data-part='node'][data-disabled]
1245
+ > [data-part='indicator'] {
1246
+ background-color: var(--slotted-disabled-background, Canvas);
1247
+ border-color: var(--slotted-disabled-border, GrayText);
1248
+ }
1249
+
1250
+ /* ── Waiting, empty, status ───────────────────────────────────────────── */
1251
+
1252
+ /**
1253
+ * A level on its way, as the shape of the rows that are coming: three bars
1254
+ * the height of a node, descending in width, from `skeleton`'s sheet. The
1255
+ * column's `aria-busy` is what a reader hears.
1256
+ */
1257
+ [data-ui='cascader'] [data-part='loader'] {
1258
+ align-items: center;
1259
+ display: flex;
1260
+ grid-column: 1 / -1;
1261
+ min-block-size: var(--_item-height);
1262
+ padding-inline: var(--_item-inset);
1263
+ }
1264
+
1265
+ [data-ui='cascader'] [data-part='loader'] > [data-ui='skeleton'] {
1266
+ flex: 1 1 auto;
1267
+ }
1268
+
1269
+ [data-ui='cascader'] [data-part='loader']:nth-child(3n + 2) > [data-ui='skeleton'] {
1270
+ flex: 0 1 78%;
1271
+ }
1272
+
1273
+ [data-ui='cascader'] [data-part='loader']:nth-child(3n) > [data-ui='skeleton'] {
1274
+ flex: 0 1 56%;
1275
+ }
1276
+
1277
+ /**
1278
+ * A level with nothing in it, a query with no answer, and a level that failed
1279
+ * with its retry. Centred sentences in their own bidi run, as `select`'s are,
1280
+ * and never narrower than a word.
1281
+ */
1282
+ [data-ui='cascader'] :is([data-part='empty'], [data-part='status']) {
1283
+ align-items: center;
1284
+ color: var(--_muted);
1285
+ display: flex;
1286
+ flex-direction: column;
1287
+ gap: var(--slotted-space-2, 0.25rem);
1288
+ grid-column: 1 / -1;
1289
+ min-inline-size: min(10rem, 100%);
1290
+ padding-block: var(--slotted-space-5, 0.75rem);
1291
+ padding-inline: var(--_item-inset);
1292
+ text-align: center;
1293
+ unicode-bidi: plaintext;
1294
+ }
1295
+
1296
+ [data-ui='cascader'] [data-part='status']:empty {
1297
+ display: none;
1298
+ }
1299
+
1300
+ /* ── Forced colours ───────────────────────────────────────────────────── */
1301
+
1302
+ @media (forced-colors: active) {
1303
+ [data-ui='cascader'] [data-part='node'][data-current] {
1304
+ background-color: Highlight;
1305
+ color: HighlightText;
1306
+ forced-color-adjust: none;
1307
+ }
1308
+
1309
+ [data-ui='cascader'] [data-part='node'][data-disabled][data-current] {
1310
+ background-color: Highlight;
1311
+ color: GrayText;
1312
+ }
1313
+
1314
+ /* The path would lose its ground to Canvas: an outline keeps the road. */
1315
+ [data-ui='cascader'] [data-part='node'][data-expanded]:not([data-current]) {
1316
+ outline: 1px solid CanvasText;
1317
+ outline-offset: -1px;
1318
+ }
1319
+ }
1320
+ }