@slotted/styles 0.0.0-stage → 0.1.0-beta.1

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,1473 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * A chart is a figure: a caption that names it, a toolbar of its own
4
+ * controls, a legend of toggles, and a plot the engine draws marks into and
5
+ * the family draws every interaction over. The table is a view of the plot,
6
+ * shown in the plot's own box.
7
+ *
8
+ * ┌ figure [data-ui=chart] ─────────────────────────────────────────┐
9
+ * │ header title (help) · description actions toolbar │
10
+ * │ legend ▬ Revenue ■ Cost ● Visits +3 │
11
+ * │ plot ┌ canvas (engine) · table-region (the table view) ───┐ │
12
+ * │ │ crosshair · markers · tooltip (family, over it) │ │
13
+ * │ └────────────────────────────────────────────────────┘ │
14
+ * └─────────────────────────────────────────────────────────────────┘
15
+ *
16
+ * One set of boxes for every state. The legend holds one line, the table
17
+ * opens inside the plot, the skeleton, the empty and the failed plot stand in
18
+ * the plot's box, so a card does not change height when its data arrives, its
19
+ * series change or its reader opens the table (the `loading-states` skill,
20
+ * section 3).
21
+ *
22
+ * The engine reads its look from this sheet: the root declares the private
23
+ * properties `--_chart-*`, and `readChartTheme` in `@slotted/core/chart`
24
+ * resolves them at the plot, so a scheme, a density, a palette or a token a
25
+ * consumer overrides on a wrapper reaches the marks through the cascade.
26
+ */
27
+ [data-ui='chart'] {
28
+ --_gap: var(--slotted-chart-gap, var(--slotted-space-5, 0.75rem));
29
+ --_plot-size: var(--slotted-chart-plot-block-size, calc(var(--slotted-space-12, 4rem) * 4));
30
+ --_radius: var(--slotted-chart-radius, var(--slotted-radius-md, 6px));
31
+
32
+ /**
33
+ * ── Colour ──────────────────────────────────────────────────────────
34
+ *
35
+ * Declared on the root so the legend, the tooltip, the markers and the
36
+ * engine read one palette. `--slotted-chart-color-1` … `-8` retune it for
37
+ * every chart under a wrapper, or for one chart; unset, it is the theme's
38
+ * data scale. A series names a step with `slot` and a meaning with
39
+ * `tone`; no series takes a colour value (`docs/component-features.md`
40
+ * §2.4).
41
+ */
42
+ --_chart-slot-1: var(--slotted-chart-color-1, var(--slotted-data-1));
43
+ --_chart-slot-2: var(--slotted-chart-color-2, var(--slotted-data-2));
44
+ --_chart-slot-3: var(--slotted-chart-color-3, var(--slotted-data-3));
45
+ --_chart-slot-4: var(--slotted-chart-color-4, var(--slotted-data-4));
46
+ --_chart-slot-5: var(--slotted-chart-color-5, var(--slotted-data-5));
47
+ --_chart-slot-6: var(--slotted-chart-color-6, var(--slotted-data-6));
48
+ --_chart-slot-7: var(--slotted-chart-color-7, var(--slotted-data-7));
49
+ --_chart-slot-8: var(--slotted-chart-color-8, var(--slotted-data-8));
50
+ --_chart-tone-neutral: var(--slotted-text-muted, GrayText);
51
+ --_chart-tone-accent: var(--slotted-tone-accent-text, CanvasText);
52
+ --_chart-tone-secondary: var(--slotted-tone-secondary-text, CanvasText);
53
+ --_chart-tone-success: var(--slotted-tone-success-text, CanvasText);
54
+ --_chart-tone-warning: var(--slotted-tone-warning-text, CanvasText);
55
+ --_chart-tone-danger: var(--slotted-tone-danger-text, CanvasText);
56
+ --_chart-overflow: var(--slotted-text-muted, GrayText);
57
+ --_chart-text: var(--slotted-text, CanvasText);
58
+ --_chart-label: var(--slotted-chart-label-color, var(--slotted-text-muted, GrayText));
59
+ /* The grid is the faintest line the theme has: a guide the eye uses and
60
+ does not read. The axis the marks stand on is one step stronger, and a
61
+ reference line one more — three lines, three weights. */
62
+ --_chart-grid: var(--slotted-chart-grid-color, var(--slotted-border-subtle, GrayText));
63
+ --_chart-axis: var(--slotted-chart-axis-color, var(--slotted-control-border-color, GrayText));
64
+ --_chart-reference: var(
65
+ --slotted-chart-reference-color,
66
+ var(--slotted-border-strong, GrayText)
67
+ );
68
+ /* The ground the marks sit on: the ring around a marker and the gap
69
+ between two slices are painted in it. A card lays its own. */
70
+ --_chart-surface: var(--slotted-chart-surface, var(--slotted-surface, Canvas));
71
+ --_chart-label-size: var(--slotted-chart-label-size, var(--slotted-font-size-xs, 0.75rem));
72
+ --_chart-line-width: var(--slotted-chart-line-width, var(--slotted-border-width-thick, 2px));
73
+ --_chart-marker-size: var(--slotted-chart-marker-size, var(--slotted-space-4, 0.5rem));
74
+ --_chart-bar-radius: var(--slotted-chart-bar-radius, var(--slotted-radius-sm, 4px));
75
+ /* The wash under a line, as a share of the series colour. A number and
76
+ not a token step, for the reason `sparkline` records beside its own:
77
+ no scale in the foundation holds an opacity for a fill read through. */
78
+ --_chart-area-opacity: var(--slotted-chart-area-opacity, 0.18);
79
+ /* The room between the plot's edge and its marks and labels: the gap a
80
+ control keeps inside itself, so a dense page draws a tighter chart. */
81
+ --_chart-inset: var(--slotted-chart-inset, var(--slotted-control-gap-md, 0.5rem));
82
+ --_chart-duration: var(--slotted-duration-long);
83
+ --_chart-easing: var(--slotted-easing-standard);
84
+
85
+ box-sizing: border-box;
86
+ color: var(--slotted-text, CanvasText);
87
+ container: slotted-chart / inline-size;
88
+ display: flex;
89
+ flex-direction: column;
90
+ font-family: var(--slotted-font-family-sans, system-ui, sans-serif);
91
+ font-size: var(--slotted-font-size-md, 0.875rem);
92
+ gap: var(--_gap);
93
+ line-height: var(--slotted-line-height-md, 1.5);
94
+ margin: 0;
95
+ min-inline-size: 0;
96
+ }
97
+
98
+ /* Three heights on the space scale's top step: 12, 16 and 24 rem. A plot
99
+ is content, not a control, so the height does not follow density; what
100
+ density moves is the inset around the marks and the type on the axes. */
101
+ [data-ui='chart'][data-size='sm'] {
102
+ --_plot-size: var(--slotted-chart-plot-block-size-sm, calc(var(--slotted-space-12, 4rem) * 3));
103
+ }
104
+
105
+ [data-ui='chart'][data-size='lg'] {
106
+ --_plot-size: var(--slotted-chart-plot-block-size-lg, calc(var(--slotted-space-12, 4rem) * 6));
107
+ }
108
+
109
+ /**
110
+ * ── Palettes ───────────────────────────────────────────────────────────
111
+ *
112
+ * `sequential` is one hue — the theme's accent — stepped toward the ground,
113
+ * for ordered data (a ranking, shares of a whole, low to high) and for up
114
+ * to four series read by identity; past four the steps stop separating.
115
+ * `focus` is one series in the accent read against the rest in muted steps:
116
+ * this year against the last ones, one product against the market. Both
117
+ * are mixed in CSS from tokens the theme already owns, so they follow every
118
+ * scheme and brand with no scale of their own.
119
+ */
120
+ [data-ui='chart'][data-palette='sequential'] {
121
+ --_hue: var(--slotted-chart-sequential-color, var(--slotted-tone-accent-text, CanvasText));
122
+ --_chart-slot-1: var(--_hue);
123
+ --_chart-slot-2: color-mix(in oklab, var(--_hue) 76%, var(--_chart-surface));
124
+ --_chart-slot-3: color-mix(in oklab, var(--_hue) 56%, var(--_chart-surface));
125
+ --_chart-slot-4: color-mix(in oklab, var(--_hue) 40%, var(--_chart-surface));
126
+ --_chart-slot-5: color-mix(in oklab, var(--_hue) 28%, var(--_chart-surface));
127
+ --_chart-slot-6: color-mix(in oklab, var(--_hue) 20%, var(--_chart-surface));
128
+ --_chart-slot-7: color-mix(in oklab, var(--_hue) 14%, var(--_chart-surface));
129
+ --_chart-slot-8: color-mix(in oklab, var(--_hue) 10%, var(--_chart-surface));
130
+ }
131
+
132
+ [data-ui='chart'][data-palette='focus'] {
133
+ --_muted: var(--slotted-text-muted, GrayText);
134
+ --_chart-slot-1: var(--slotted-chart-focus-color, var(--slotted-tone-accent-text, CanvasText));
135
+ --_chart-slot-2: color-mix(in oklab, var(--_muted) 70%, var(--_chart-surface));
136
+ --_chart-slot-3: color-mix(in oklab, var(--_muted) 52%, var(--_chart-surface));
137
+ --_chart-slot-4: color-mix(in oklab, var(--_muted) 38%, var(--_chart-surface));
138
+ --_chart-slot-5: color-mix(in oklab, var(--_muted) 30%, var(--_chart-surface));
139
+ --_chart-slot-6: color-mix(in oklab, var(--_muted) 24%, var(--_chart-surface));
140
+ --_chart-slot-7: color-mix(in oklab, var(--_muted) 20%, var(--_chart-surface));
141
+ --_chart-slot-8: color-mix(in oklab, var(--_muted) 16%, var(--_chart-surface));
142
+ }
143
+
144
+ /**
145
+ * ── The card ───────────────────────────────────────────────────────────
146
+ *
147
+ * The chart as a dashboard tile: the raised surface, edge, corner and inset
148
+ * `card` draws, read from the same semantic tokens, so a chart tile and a
149
+ * card beside it are one material. The tile takes the block size its grid
150
+ * cell gives it and the plot takes what the header and the legend leave —
151
+ * never less than its size step — so tiles in one row end on one line
152
+ * whatever their titles and legends hold.
153
+ */
154
+ [data-ui='chart'][data-variant='card'] {
155
+ --_chart-surface: var(--slotted-chart-surface, var(--slotted-surface-raised, Canvas));
156
+
157
+ background-color: var(--_chart-surface);
158
+ border: var(--slotted-border-width-thin, 1px) solid var(--slotted-border-subtle, CanvasText);
159
+ border-radius: var(--slotted-chart-card-radius, var(--slotted-radius-lg, 8px));
160
+ padding-block: var(--slotted-chart-card-padding-block, var(--slotted-space-6, 1rem));
161
+ padding-inline: var(--slotted-chart-card-padding-inline, var(--slotted-space-6, 1rem));
162
+ }
163
+
164
+ /* ── Header ───────────────────────────────────────────────────────────── */
165
+
166
+ /* The header's parts are selected through the header: `title`,
167
+ `description` and `actions` are also parts of the families a plot
168
+ composes — `result-state` in an empty or failed plot — and a bare
169
+ descendant selector restyled theirs. */
170
+ [data-ui='chart'] > [data-part='header'] {
171
+ align-items: start;
172
+ display: flex;
173
+ gap: var(--slotted-space-4, 0.5rem);
174
+ min-inline-size: 0;
175
+ }
176
+
177
+ /* The heading block: title and help on one line, the description under. */
178
+ [data-ui='chart'] > [data-part='header'] > :first-child {
179
+ align-content: start;
180
+ display: grid;
181
+ flex: 1 1 auto;
182
+ gap: var(--slotted-space-1, 0.125rem);
183
+ min-inline-size: 0;
184
+ }
185
+
186
+ [data-ui='chart'] > [data-part='header'] > :first-child > :first-child {
187
+ align-items: center;
188
+ display: flex;
189
+ gap: var(--slotted-space-2, 0.25rem);
190
+ min-inline-size: 0;
191
+ }
192
+
193
+ [data-ui='chart'] > [data-part='header'] [data-part='title'] {
194
+ color: var(--slotted-text, CanvasText);
195
+ font-family: var(
196
+ --slotted-font-family-heading,
197
+ var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif)
198
+ );
199
+ font-size: var(--slotted-font-size-lg, 1rem);
200
+ font-weight: var(--slotted-font-weight-semibold, 600);
201
+ line-height: var(--slotted-line-height-lg, 1.5);
202
+ min-inline-size: 0;
203
+ overflow-wrap: anywhere;
204
+ }
205
+
206
+ [data-ui='chart'] > [data-part='header'] [data-part='description'] {
207
+ color: var(--slotted-text-muted, GrayText);
208
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
209
+ line-height: var(--slotted-line-height-sm, 1.45);
210
+ overflow-wrap: anywhere;
211
+ }
212
+
213
+ /* A tile's heading is one line of title and one of description, cut with
214
+ an ellipsis and whole in the DOM, so tiles in a row keep one header
215
+ height. The full text stays the figure's name and description. */
216
+ [data-ui='chart'][data-variant='card']
217
+ > [data-part='header']
218
+ :is([data-part='title'], [data-part='description']) {
219
+ overflow: hidden;
220
+ text-overflow: ellipsis;
221
+ white-space: nowrap;
222
+ }
223
+
224
+ [data-ui='chart'][data-variant='card'] > [data-part='header'] [data-part='title'] {
225
+ font-size: var(--slotted-font-size-md, 0.875rem);
226
+ line-height: var(--slotted-line-height-md, 1.5);
227
+ }
228
+
229
+ /* A tile keeps the description's line whether it has one or not, so the
230
+ legends and the plots of a row start on one line too. */
231
+ [data-ui='chart'][data-variant='card'] > [data-part='header'] > :first-child {
232
+ min-block-size: calc(
233
+ var(--slotted-font-size-md, 0.875rem) * var(--slotted-line-height-md, 1.5) +
234
+ var(--slotted-space-1, 0.125rem) + var(--slotted-font-size-sm, 0.8125rem) *
235
+ var(--slotted-line-height-sm, 1.45)
236
+ );
237
+ }
238
+
239
+ [data-ui='chart'] > [data-part='header'] > [data-part='actions'] {
240
+ align-items: center;
241
+ display: flex;
242
+ flex: none;
243
+ gap: var(--slotted-space-2, 0.25rem);
244
+ }
245
+
246
+ /**
247
+ * ── The chart's own controls ───────────────────────────────────────────
248
+ *
249
+ * Icon buttons one control-height square, quiet at rest — a chart's
250
+ * toolbar is read far less often than its marks — with the hover wash every
251
+ * secondary control carries. The toolbar can step back until the tile is
252
+ * hovered or holds focus (`toolbar="hover"`), and never where the device
253
+ * cannot hover.
254
+ */
255
+ [data-ui='chart'] > [data-part='header'] > [data-part='toolbar'] {
256
+ align-items: center;
257
+ display: flex;
258
+ flex: none;
259
+ gap: var(--slotted-space-1, 0.125rem);
260
+ /* The buttons sit on the title's first line and hang past their box by
261
+ the difference, so the row does not grow the header. */
262
+ margin-block: calc(
263
+ (
264
+ var(--slotted-font-size-lg, 1rem) * var(--slotted-line-height-lg, 1.5) -
265
+ var(--slotted-control-height-sm, 1.75rem)
266
+ ) /
267
+ 2
268
+ );
269
+ transition: opacity var(--slotted-duration-short) var(--slotted-easing-standard);
270
+ }
271
+
272
+ [data-ui='chart'][data-toolbar='hover'] > [data-part='header'] > [data-part='toolbar'] {
273
+ opacity: 0;
274
+ }
275
+
276
+ /* While the plot waits, fails or has no data the toolbar keeps its width —
277
+ the title and the description wrap where they will wrap once it is ready —
278
+ and draws nothing: an action nobody can press yet is absent. */
279
+ [data-ui='chart'] > [data-part='header'] > [data-part='toolbar'][data-waiting] {
280
+ visibility: hidden;
281
+ }
282
+
283
+ /* A chart has no disabled state; the guard is the precedence rule every
284
+ hover in the library states (`packages/styles/src/states.test.mjs`). */
285
+ [data-ui='chart'][data-toolbar='hover']:is(:hover, :focus-within):not([data-disabled])
286
+ > [data-part='header']
287
+ > [data-part='toolbar'] {
288
+ opacity: 1;
289
+ }
290
+
291
+ @media (hover: none) {
292
+ [data-ui='chart'][data-toolbar='hover'] > [data-part='header'] > [data-part='toolbar'] {
293
+ opacity: 1;
294
+ }
295
+ }
296
+
297
+ [data-ui='chart']
298
+ :is(
299
+ [data-part='zoom-reset'],
300
+ [data-part='view-toggle'],
301
+ [data-part='fullscreen-toggle'],
302
+ [data-part='menu-trigger'],
303
+ [data-part='help']
304
+ ) {
305
+ --_box: var(--slotted-control-height-sm, 1.75rem);
306
+
307
+ align-items: center;
308
+ background: transparent;
309
+ block-size: var(--_box);
310
+ border: 0;
311
+ border-radius: var(--slotted-control-radius, var(--slotted-radius-md, 6px));
312
+ color: var(--slotted-text-muted, GrayText);
313
+ cursor: pointer;
314
+ display: inline-flex;
315
+ flex: none;
316
+ inline-size: var(--_box);
317
+ justify-content: center;
318
+ padding: 0;
319
+ transition:
320
+ background-color var(--slotted-duration-short) var(--slotted-easing-standard),
321
+ color var(--slotted-duration-short) var(--slotted-easing-standard);
322
+ }
323
+
324
+ /* Help sits beside the words it explains, a step smaller than the toolbar. */
325
+ [data-ui='chart'] [data-part='help'] {
326
+ --_box: var(--slotted-control-inner-size-sm, 1.25rem);
327
+
328
+ /* It hangs past the title's line by the difference rather than growing
329
+ it: a tile with help and a tile without start their plots on one line. */
330
+ margin-block: calc(
331
+ (var(--slotted-font-size-md, 0.875rem) * var(--slotted-line-height-md, 1.5) - var(--_box)) / 2
332
+ );
333
+ }
334
+
335
+ [data-ui='chart']
336
+ :is(
337
+ [data-part='zoom-reset'],
338
+ [data-part='view-toggle'],
339
+ [data-part='fullscreen-toggle'],
340
+ [data-part='menu-trigger'],
341
+ [data-part='help']
342
+ ):hover:not(:disabled) {
343
+ background-color: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
344
+ color: var(--slotted-text, CanvasText);
345
+ }
346
+
347
+ /* On: the table standing in the plot, the menu or the help open. */
348
+ [data-ui='chart']
349
+ :is([data-part='view-toggle'], [data-part='menu-trigger'], [data-part='help'])[data-pressed],
350
+ [data-ui='chart'] :is([data-part='menu-trigger'], [data-part='help'])[data-open] {
351
+ background-color: var(--slotted-tone-secondary-surface, ButtonFace);
352
+ color: var(--slotted-text, CanvasText);
353
+ }
354
+
355
+ [data-ui='chart']
356
+ :is(
357
+ [data-part='zoom-reset'],
358
+ [data-part='view-toggle'],
359
+ [data-part='fullscreen-toggle'],
360
+ [data-part='menu-trigger'],
361
+ [data-part='help'],
362
+ [data-part='legend-more'],
363
+ [data-part='menu-item']
364
+ ):focus-visible {
365
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
366
+ outline-offset: 0;
367
+ }
368
+
369
+ /**
370
+ * The menu and the help are layers over the page: the raised surface of
371
+ * every floating layer in the library. They are placed in the viewport's
372
+ * coordinates by the binding, through the chart's two runtime properties.
373
+ */
374
+ [data-ui='chart'] :is([data-part='menu'], [data-part='help-content']) {
375
+ background-color: var(--slotted-surface-raised, Canvas);
376
+ border: var(--slotted-border-width-thin, 1px) solid var(--slotted-border-subtle, CanvasText);
377
+ border-radius: var(--slotted-radius-md, 6px);
378
+ box-shadow: var(--slotted-shadow-md, none);
379
+ box-sizing: border-box;
380
+ color: var(--slotted-text, CanvasText);
381
+ font-family: var(--slotted-font-family-sans, system-ui, sans-serif);
382
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
383
+ inset: 0 auto auto 0;
384
+ line-height: var(--slotted-line-height-sm, 1.45);
385
+ margin: 0;
386
+ max-inline-size: min(20rem, calc(100vw - var(--slotted-space-8, 1.5rem)));
387
+ position: fixed;
388
+ transform: translate(var(--slotted-chart-x, 0px), var(--slotted-chart-y, 0px));
389
+ z-index: var(--slotted-z-index-popover, 1100);
390
+ }
391
+
392
+ [data-ui='chart'] [data-part='menu'] {
393
+ display: grid;
394
+ min-inline-size: 11rem;
395
+ padding: var(--slotted-space-2, 0.25rem);
396
+ }
397
+
398
+ [data-ui='chart'] [data-part='menu']:not(:popover-open, [data-open]) {
399
+ display: none;
400
+ }
401
+
402
+ [data-ui='chart'] [data-part='help-content'] {
403
+ padding-block: var(--slotted-space-4, 0.5rem);
404
+ padding-inline: var(--slotted-space-5, 0.75rem);
405
+ }
406
+
407
+ [data-ui='chart'] [data-part='help-content']:not(:popover-open, [data-open]) {
408
+ display: none;
409
+ }
410
+
411
+ [data-ui='chart'] [data-part='menu-item'] {
412
+ align-items: center;
413
+ background: transparent;
414
+ border: 0;
415
+ border-radius: var(--slotted-radius-sm, 4px);
416
+ color: inherit;
417
+ cursor: pointer;
418
+ display: flex;
419
+ font: inherit;
420
+ gap: var(--slotted-space-3, 0.375rem);
421
+ min-block-size: var(--slotted-control-height-sm, 1.75rem);
422
+ padding-inline: var(--slotted-space-4, 0.5rem);
423
+ text-align: start;
424
+ }
425
+
426
+ /* The table and full-screen controls are in the toolbar; the menu holds
427
+ them only where the toolbar gives them up (see Narrow). */
428
+ [data-ui='chart'] [data-part='menu-item']:is([data-action='view'], [data-action='fullscreen']) {
429
+ display: none;
430
+ }
431
+
432
+ [data-ui='chart'] [data-part='menu-item']:hover:not(:disabled) {
433
+ background-color: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
434
+ }
435
+
436
+ /* ── Legend ───────────────────────────────────────────────────────────── */
437
+
438
+ /* One line: what does not fit waits behind `legend-more`, so a legend of
439
+ three and a legend of twelve are the same height. `legendOverflow="wrap"`
440
+ lets a chart that owns its own page wrap instead. */
441
+ [data-ui='chart'] [data-part='legend'] {
442
+ align-items: center;
443
+ display: flex;
444
+ flex: none;
445
+ flex-wrap: nowrap;
446
+ gap: var(--slotted-space-1, 0.125rem) var(--slotted-space-2, 0.25rem);
447
+ list-style: none;
448
+ margin: 0;
449
+ /* The items carry their own inline padding so their hover wash has room;
450
+ the row gives it back so the first marker lines up with the title. */
451
+ margin-inline-start: calc(var(--slotted-space-3, 0.375rem) * -1);
452
+ min-block-size: var(--slotted-target-min, 1.5rem);
453
+ min-inline-size: 0;
454
+ overflow: hidden;
455
+ padding: 0;
456
+ }
457
+
458
+ [data-ui='chart'][data-legend-overflow='wrap'] [data-part='legend'] {
459
+ flex-wrap: wrap;
460
+ overflow: visible;
461
+ }
462
+
463
+ /**
464
+ * The colour of one series, resolved in the order the model resolves it:
465
+ * a tone says what the series means and wins, a slot says which one it is,
466
+ * and the ninth series and on — which the scale never cycles to — takes the
467
+ * muted step with a dash of its own. The legend, the markers and the
468
+ * tooltip read the palette the root declares, as the engine does.
469
+ */
470
+ [data-ui='chart'] [data-slot='1'] {
471
+ --_series: var(--_chart-slot-1);
472
+ }
473
+ [data-ui='chart'] [data-slot='2'] {
474
+ --_series: var(--_chart-slot-2);
475
+ }
476
+ [data-ui='chart'] [data-slot='3'] {
477
+ --_series: var(--_chart-slot-3);
478
+ }
479
+ [data-ui='chart'] [data-slot='4'] {
480
+ --_series: var(--_chart-slot-4);
481
+ }
482
+ [data-ui='chart'] [data-slot='5'] {
483
+ --_series: var(--_chart-slot-5);
484
+ }
485
+ [data-ui='chart'] [data-slot='6'] {
486
+ --_series: var(--_chart-slot-6);
487
+ }
488
+ [data-ui='chart'] [data-slot='7'] {
489
+ --_series: var(--_chart-slot-7);
490
+ }
491
+ [data-ui='chart'] [data-slot='8'] {
492
+ --_series: var(--_chart-slot-8);
493
+ }
494
+ [data-ui='chart'] [data-tone='neutral'] {
495
+ --_series: var(--_chart-tone-neutral);
496
+ }
497
+ [data-ui='chart'] [data-tone='accent'] {
498
+ --_series: var(--_chart-tone-accent);
499
+ }
500
+ [data-ui='chart'] [data-tone='secondary'] {
501
+ --_series: var(--_chart-tone-secondary);
502
+ }
503
+ [data-ui='chart'] [data-tone='success'] {
504
+ --_series: var(--_chart-tone-success);
505
+ }
506
+ [data-ui='chart'] [data-tone='warning'] {
507
+ --_series: var(--_chart-tone-warning);
508
+ }
509
+ [data-ui='chart'] [data-tone='danger'] {
510
+ --_series: var(--_chart-tone-danger);
511
+ }
512
+ [data-ui='chart'] [data-overflow] {
513
+ --_series: var(--_chart-overflow);
514
+ }
515
+
516
+ [data-ui='chart'] :is([data-part='legend-item'], [data-part='legend-more']) {
517
+ align-items: center;
518
+ background: transparent;
519
+ border: 0;
520
+ border-radius: var(--slotted-control-radius, var(--slotted-radius-md, 6px));
521
+ color: var(--slotted-text, CanvasText);
522
+ display: inline-flex;
523
+ flex: none;
524
+ font: inherit;
525
+ font-size: var(--slotted-control-font-size-sm, 0.75rem);
526
+ gap: var(--slotted-space-3, 0.375rem);
527
+ line-height: var(--slotted-line-height-sm, 1.45);
528
+ max-inline-size: 100%;
529
+ min-block-size: var(--slotted-target-min, 1.5rem);
530
+ min-inline-size: 0;
531
+ padding-inline: var(--slotted-space-3, 0.375rem);
532
+ text-align: start;
533
+ transition:
534
+ background-color var(--slotted-duration-short) var(--slotted-easing-standard),
535
+ color var(--slotted-duration-short) var(--slotted-easing-standard);
536
+ }
537
+
538
+ [data-ui='chart'] :is([data-part='legend-item'], [data-part='legend-more'])[hidden] {
539
+ display: none;
540
+ }
541
+
542
+ [data-ui='chart'] [data-part='legend-more'] {
543
+ color: var(--slotted-text-muted, GrayText);
544
+ cursor: pointer;
545
+ font-variant-numeric: tabular-nums;
546
+ font-weight: var(--slotted-font-weight-medium, 500);
547
+ }
548
+
549
+ /* An entry moved into the `+N` layer stands in a column there. */
550
+ [data-ui='chart'] [data-part='menu'] [data-part='legend-item'] {
551
+ inline-size: 100%;
552
+ }
553
+
554
+ [data-ui='chart'] :is(button[data-part='legend-item'], [data-part='legend-more']) {
555
+ cursor: pointer;
556
+ }
557
+
558
+ [data-ui='chart']
559
+ :is(button[data-part='legend-item'], [data-part='legend-more']):hover:not(:disabled) {
560
+ background-color: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
561
+ }
562
+
563
+ [data-ui='chart'] [data-part='legend-item']:focus-visible {
564
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
565
+ outline-offset: 0;
566
+ }
567
+
568
+ /**
569
+ * The marker is the shape of the mark it stands for, so a combined chart's
570
+ * legend reads without colour: a stroke for a line, a square for a bar, an
571
+ * area or a slice, a disc for a scatter.
572
+ */
573
+ [data-ui='chart'] :is([data-part='legend-marker'], [data-part='tooltip-marker']) {
574
+ background-color: var(--_series);
575
+ block-size: 0.625rem;
576
+ border-radius: var(--slotted-radius-xs, 2px);
577
+ flex: none;
578
+ inline-size: 0.625rem;
579
+ }
580
+
581
+ [data-ui='chart']
582
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'])[data-kind='line'] {
583
+ block-size: var(--slotted-border-width-thick, 2px);
584
+ border-radius: var(--slotted-radius-full, 9999px);
585
+ inline-size: 0.875rem;
586
+ }
587
+
588
+ [data-ui='chart']
589
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'])[data-kind='scatter'] {
590
+ border-radius: var(--slotted-radius-full, 9999px);
591
+ }
592
+
593
+ /* The line's own dash, drawn at the marker's scale, so three series that
594
+ share the muted colour past the eighth slot still read apart. */
595
+ [data-ui='chart']
596
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'])[data-stroke='dashed'] {
597
+ background: repeating-linear-gradient(to right, var(--_series) 0 3px, transparent 3px 5px);
598
+ }
599
+
600
+ [data-ui='chart']
601
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'])[data-stroke='dotted'] {
602
+ background: repeating-linear-gradient(to right, var(--_series) 0 2px, transparent 2px 4px);
603
+ }
604
+
605
+ [data-ui='chart']
606
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'])[data-stroke='dash-dot'] {
607
+ background: repeating-linear-gradient(
608
+ to right,
609
+ var(--_series) 0 5px,
610
+ transparent 5px 7px,
611
+ var(--_series) 7px 9px,
612
+ transparent 9px 11px
613
+ );
614
+ }
615
+
616
+ [data-ui='chart'] [data-part='legend-label'] {
617
+ min-inline-size: 0;
618
+ overflow: hidden;
619
+ text-overflow: ellipsis;
620
+ white-space: nowrap;
621
+ }
622
+
623
+ [data-ui='chart'] [data-part='legend-value'] {
624
+ color: var(--slotted-text-muted, GrayText);
625
+ font-variant-numeric: tabular-nums;
626
+ white-space: nowrap;
627
+ }
628
+
629
+ [data-ui='chart'] [data-part='legend-item'][data-current] [data-part='legend-value'] {
630
+ color: var(--slotted-text, CanvasText);
631
+ }
632
+
633
+ /**
634
+ * A hidden series keeps its place in the row — a legend that reflowed on
635
+ * every toggle would move the next item from under the pointer — and reads
636
+ * as off: the marker empties to its outline and the label mutes. The
637
+ * outline is the series colour, so the item still says which series it
638
+ * would bring back.
639
+ */
640
+ [data-ui='chart'] button[data-part='legend-item']:not([data-pressed]) {
641
+ color: var(--slotted-text-muted, GrayText);
642
+ }
643
+
644
+ [data-ui='chart']
645
+ button[data-part='legend-item']:not([data-pressed])
646
+ [data-part='legend-marker'] {
647
+ background: transparent;
648
+ box-shadow: inset 0 0 0 var(--slotted-border-width-medium, 1.5px) var(--_series);
649
+ }
650
+
651
+ [data-ui='chart']
652
+ button[data-part='legend-item']:not([data-pressed])
653
+ [data-part='legend-marker'][data-kind='line'] {
654
+ background: var(--_series);
655
+ box-shadow: none;
656
+ opacity: 0.4;
657
+ }
658
+
659
+ [data-ui='chart'] button[data-part='legend-item']:not([data-pressed]) [data-part='legend-label'] {
660
+ text-decoration: line-through;
661
+ text-decoration-color: color-mix(in oklab, currentColor 55%, transparent);
662
+ }
663
+
664
+ /* ── Plot ─────────────────────────────────────────────────────────────── */
665
+
666
+ [data-ui='chart'] [data-part='plot'] {
667
+ border-radius: var(--_radius);
668
+ /* Its size step, and whatever more a tile or the full screen gives it. */
669
+ flex: 1 0 var(--_plot-size);
670
+ min-block-size: var(--_plot-size);
671
+ /* The plot does not mirror: axes, time and bars read left to right in
672
+ every document (Material Design, Bidirectionality, "Charts and
673
+ graphs"). Its overlay is positioned in the engine's coordinates, which
674
+ are the same in both directions; the text laid over it takes the
675
+ document's direction back below. */
676
+ direction: ltr;
677
+ min-inline-size: 0;
678
+ position: relative;
679
+ }
680
+
681
+ [data-ui='chart'] [data-part='plot']:focus-visible {
682
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
683
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
684
+ }
685
+
686
+ [data-ui='chart'] [data-part='canvas'] {
687
+ inset: 0;
688
+ position: absolute;
689
+ z-index: 1;
690
+ }
691
+
692
+ /* The engine keeps its size and its state behind the table, so the chart
693
+ comes back where the reader left it. */
694
+ [data-ui='chart']
695
+ [data-part='plot']:has(> [data-part='table-region']:not([hidden]))
696
+ > :is(
697
+ [data-part='canvas'],
698
+ [data-part='crosshair'],
699
+ [data-part='marker'],
700
+ [data-part='tooltip'],
701
+ [data-part='center']
702
+ ) {
703
+ visibility: hidden;
704
+ }
705
+
706
+ /**
707
+ * ── The overlay ───────────────────────────────────────────────────────
708
+ *
709
+ * Drawn by the family at the pixel the engine reports, for a pointer and a
710
+ * keyboard alike, through runtime properties the script writes:
711
+ * `--slotted-chart-x` and `--slotted-chart-y` for a point,
712
+ * `--slotted-chart-band-start` and `--slotted-chart-band-size` for the
713
+ * category a point sits in, and `--slotted-chart-frame-start` and
714
+ * `--slotted-chart-frame-size` for the grid across it. None of them is a
715
+ * design token.
716
+ */
717
+ [data-ui='chart'] :is([data-part='crosshair'], [data-part='marker'], [data-part='tooltip']) {
718
+ inset-block-start: 0;
719
+ inset-inline-start: 0;
720
+ pointer-events: none;
721
+ position: absolute;
722
+ }
723
+
724
+ /* A line under the marks for a line or an area, where the eye needs the
725
+ exact x; a band for bars, where the category is the whole slot. */
726
+ [data-ui='chart'] [data-part='crosshair'] {
727
+ background-color: var(--slotted-chart-crosshair-color, var(--slotted-border-strong, GrayText));
728
+ block-size: var(--slotted-chart-frame-size, 100%);
729
+ inline-size: 1px;
730
+ transform: translate(
731
+ calc(var(--slotted-chart-x, 0px) - 0.5px),
732
+ var(--slotted-chart-frame-start, 0px)
733
+ );
734
+ z-index: 0;
735
+ }
736
+
737
+ [data-ui='chart'] [data-part='crosshair'][data-band] {
738
+ background-color: var(
739
+ --slotted-chart-band-color,
740
+ color-mix(in oklab, var(--slotted-text, CanvasText) 6%, transparent)
741
+ );
742
+ border-radius: var(--slotted-radius-sm, 4px);
743
+ inline-size: var(--slotted-chart-band-size, 0px);
744
+ transform: translate(
745
+ var(--slotted-chart-band-start, 0px),
746
+ var(--slotted-chart-frame-start, 0px)
747
+ );
748
+ }
749
+
750
+ [data-ui='chart'] [data-part='crosshair'][data-orientation='horizontal'] {
751
+ block-size: 1px;
752
+ inline-size: var(--slotted-chart-frame-size, 100%);
753
+ transform: translate(
754
+ var(--slotted-chart-frame-start, 0px),
755
+ calc(var(--slotted-chart-y, 0px) - 0.5px)
756
+ );
757
+ }
758
+
759
+ [data-ui='chart'] [data-part='crosshair'][data-band][data-orientation='horizontal'] {
760
+ block-size: var(--slotted-chart-band-size, 0px);
761
+ transform: translate(
762
+ var(--slotted-chart-frame-start, 0px),
763
+ var(--slotted-chart-band-start, 0px)
764
+ );
765
+ }
766
+
767
+ /**
768
+ * The marker on the point the reader is on: the series colour with a ring
769
+ * of the ground around it, so it separates from the line it sits on and
770
+ * from a neighbouring series crossing at the same place.
771
+ */
772
+ [data-ui='chart'] [data-part='marker'] {
773
+ --_size: calc(var(--_chart-marker-size) + var(--slotted-space-2, 0.25rem));
774
+
775
+ background-color: var(--_series, var(--_chart-slot-1));
776
+ block-size: var(--_size);
777
+ border-radius: var(--slotted-radius-full, 9999px);
778
+ box-shadow: 0 0 0 var(--slotted-border-width-thick, 2px) var(--_chart-surface);
779
+ inline-size: var(--_size);
780
+ transform: translate(
781
+ calc(var(--slotted-chart-x, 0px) - var(--_size) / 2),
782
+ calc(var(--slotted-chart-y, 0px) - var(--_size) / 2)
783
+ );
784
+ z-index: 2;
785
+ }
786
+
787
+ /* The point the reader chose stays marked after the pointer leaves: a ring
788
+ in the series colour around the ground, larger than the hover marker so
789
+ the two read as two states when they meet. */
790
+ [data-ui='chart'] [data-part='marker'][data-selected] {
791
+ --_size: calc(var(--_chart-marker-size) * 2 + var(--slotted-space-2, 0.25rem));
792
+
793
+ background-color: transparent;
794
+ box-shadow:
795
+ inset 0 0 0 var(--slotted-border-width-thick, 2px) var(--_series, CanvasText),
796
+ 0 0 0 var(--slotted-border-width-thick, 2px) var(--_chart-surface);
797
+ }
798
+
799
+ /* ── Tooltip ──────────────────────────────────────────────────────────── */
800
+
801
+ /**
802
+ * The raised surface every floating layer in the library uses, and the
803
+ * reading order a tooltip is read in: what the point is, then each series
804
+ * with its value aligned on the right, then the total. The rows are a
805
+ * subgrid of one three-column grid, so the values line up whatever the
806
+ * labels' lengths.
807
+ */
808
+ [data-ui='chart'] [data-part='tooltip'] {
809
+ background-color: var(--slotted-chart-tooltip-surface, var(--slotted-surface-raised, Canvas));
810
+ border: var(--slotted-border-width-thin, 1px) solid var(--slotted-border-subtle, CanvasText);
811
+ border-radius: var(--slotted-radius-md, 6px);
812
+ box-shadow: var(--slotted-shadow-md, none);
813
+ box-sizing: border-box;
814
+ color: var(--slotted-text, CanvasText);
815
+ column-gap: var(--slotted-space-4, 0.5rem);
816
+ display: grid;
817
+ font-size: var(--slotted-control-font-size-sm, 0.75rem);
818
+ grid-template-columns: auto minmax(0, 1fr) auto;
819
+ line-height: var(--slotted-line-height-sm, 1.45);
820
+ max-inline-size: min(18rem, 100%);
821
+ min-inline-size: 8rem;
822
+ opacity: 0;
823
+ padding-block: var(--slotted-space-4, 0.5rem);
824
+ padding-inline: var(--slotted-space-5, 0.75rem);
825
+ row-gap: var(--slotted-space-2, 0.25rem);
826
+ transform: translate(var(--slotted-chart-x, 0px), var(--slotted-chart-y, 0px));
827
+ transition:
828
+ opacity var(--slotted-duration-short) var(--slotted-easing-standard),
829
+ transform var(--slotted-duration-short) var(--slotted-easing-standard);
830
+ visibility: hidden;
831
+ z-index: 3;
832
+ }
833
+
834
+ /**
835
+ * Docked: on a plot too narrow for a box beside the point — a phone, a
836
+ * narrow tile — the tooltip is a strip across the plot's top edge that the
837
+ * point never hides under, and the crosshair shows which point it is about.
838
+ * The binding docks it; `placeTooltip` says when.
839
+ */
840
+ [data-ui='chart'] [data-part='tooltip'][data-docked] {
841
+ inline-size: 100%;
842
+ max-inline-size: 100%;
843
+ min-inline-size: 0;
844
+ }
845
+
846
+ /* The tooltip's text runs in the document's direction. Its box stays in the
847
+ plot's coordinates: an inset resolves against the element's own
848
+ direction, so the right-to-left box anchors at its inline end, which is
849
+ the same left edge the translation is measured from. */
850
+ [data-ui='chart']:dir(rtl) :is([data-part='tooltip'], [data-part='center']) {
851
+ direction: rtl;
852
+ }
853
+
854
+ [data-ui='chart']:dir(rtl) [data-part='tooltip'] {
855
+ inset-inline-end: 0;
856
+ inset-inline-start: auto;
857
+ }
858
+
859
+ [data-ui='chart'] [data-part='tooltip'][data-open] {
860
+ opacity: 1;
861
+ visibility: visible;
862
+ }
863
+
864
+ /* A tooltip that appears slides into place from where it opened; one that
865
+ follows the pointer from point to point moves with it. Opening snaps the
866
+ position so the first frame is not a flight from the corner. */
867
+ [data-ui='chart'] [data-part='tooltip']:not([data-open]) {
868
+ transition:
869
+ opacity var(--slotted-duration-short) var(--slotted-easing-standard),
870
+ visibility var(--slotted-duration-instant) linear var(--slotted-duration-short);
871
+ }
872
+
873
+ [data-ui='chart'] [data-part='tooltip-title'] {
874
+ color: var(--slotted-text, CanvasText);
875
+ font-weight: var(--slotted-font-weight-semibold, 600);
876
+ grid-column: 1 / -1;
877
+ overflow-wrap: anywhere;
878
+ }
879
+
880
+ [data-ui='chart'] :is([data-part='tooltip-item'], [data-part='tooltip-total']) {
881
+ align-items: center;
882
+ display: grid;
883
+ grid-column: 1 / -1;
884
+ grid-template-columns: subgrid;
885
+ }
886
+
887
+ [data-ui='chart'] [data-part='tooltip-item'] {
888
+ color: var(--slotted-text-muted, GrayText);
889
+ }
890
+
891
+ [data-ui='chart'] [data-part='tooltip-item'][data-current] {
892
+ color: var(--slotted-text, CanvasText);
893
+ }
894
+
895
+ [data-ui='chart'] [data-part='tooltip-label'] {
896
+ min-inline-size: 0;
897
+ overflow: hidden;
898
+ text-overflow: ellipsis;
899
+ white-space: nowrap;
900
+ }
901
+
902
+ [data-ui='chart'] [data-part='tooltip-value'] {
903
+ color: var(--slotted-text, CanvasText);
904
+ font-variant-numeric: tabular-nums;
905
+ font-weight: var(--slotted-font-weight-medium, 500);
906
+ text-align: end;
907
+ white-space: nowrap;
908
+ }
909
+
910
+ [data-ui='chart'] [data-part='tooltip-total'] {
911
+ border-block-start: var(--slotted-border-width-thin, 1px) solid
912
+ var(--slotted-border-subtle, CanvasText);
913
+ font-weight: var(--slotted-font-weight-semibold, 600);
914
+ margin-block-start: var(--slotted-space-2, 0.25rem);
915
+ padding-block-start: var(--slotted-space-3, 0.375rem);
916
+ }
917
+
918
+ [data-ui='chart'] [data-part='tooltip-total'] > :first-child {
919
+ grid-column: 1 / 3;
920
+ }
921
+
922
+ /* ── The centre of a donut ────────────────────────────────────────────── */
923
+
924
+ [data-ui='chart'] [data-part='center'] {
925
+ align-content: center;
926
+ display: grid;
927
+ inset: 0;
928
+ justify-items: center;
929
+ pointer-events: none;
930
+ position: absolute;
931
+ text-align: center;
932
+ z-index: 2;
933
+ }
934
+
935
+ [data-ui='chart'] [data-part='center-value'] {
936
+ font-size: var(--slotted-font-size-2xl, 1.25rem);
937
+ font-variant-numeric: tabular-nums;
938
+ font-weight: var(--slotted-font-weight-semibold, 600);
939
+ line-height: var(--slotted-line-height-2xl, 1.4);
940
+ }
941
+
942
+ [data-ui='chart'] [data-part='center-label'] {
943
+ color: var(--slotted-text-muted, GrayText);
944
+ font-size: var(--slotted-font-size-xs, 0.75rem);
945
+ line-height: var(--slotted-line-height-xs, 1.4);
946
+ }
947
+
948
+ /* ── Waiting ──────────────────────────────────────────────────────────── */
949
+
950
+ /**
951
+ * The skeleton is the chart it stands in for, drawn in the skeleton
952
+ * family's fill at a lighter share of the ground: the value axis' labels in
953
+ * a column, the category axis' labels in a row, the grid the loaded chart
954
+ * draws, and the marks of its kind — bars of the heights data tends to
955
+ * have, a line and its wash, a pie's ring — under one shimmer. It fills the
956
+ * plot's box exactly, so nothing moves when the data lands.
957
+ */
958
+ [data-ui='chart'] [data-part='skeleton'] {
959
+ inset: var(--_chart-inset);
960
+ position: absolute;
961
+ }
962
+
963
+ [data-ui='chart'] [data-part='skeleton'] > [data-ui='skeleton'] {
964
+ /* A tenth of the text over the ground: a step lighter than the ground
965
+ in a dark scheme and a step darker in a light one, where the skeleton
966
+ family's own fill, made for a sunken field, sank into a dark tile. */
967
+ --slotted-skeleton-fill: color-mix(
968
+ in oklab,
969
+ var(--slotted-text, CanvasText) 9%,
970
+ var(--_chart-surface)
971
+ );
972
+
973
+ block-size: 100%;
974
+ box-sizing: border-box;
975
+ column-gap: var(--_chart-inset);
976
+ display: grid;
977
+ grid-template-areas:
978
+ 'y marks'
979
+ '. x';
980
+ grid-template-columns: 2.25rem minmax(0, 1fr);
981
+ grid-template-rows: minmax(0, 1fr) auto;
982
+ inline-size: 100%;
983
+ row-gap: var(--_chart-inset);
984
+ }
985
+
986
+ [data-ui='chart'] [data-part='skeleton'] [data-skeleton='y'] {
987
+ align-items: end;
988
+ display: flex;
989
+ flex-direction: column;
990
+ grid-area: y;
991
+ justify-content: space-between;
992
+ }
993
+
994
+ [data-ui='chart'] [data-part='skeleton'] [data-skeleton='x'] {
995
+ display: flex;
996
+ grid-area: x;
997
+ justify-content: space-around;
998
+ }
999
+
1000
+ /* An axis label is a short line at the axis type's height. */
1001
+ [data-ui='chart']
1002
+ [data-part='skeleton']
1003
+ :is([data-skeleton='y'], [data-skeleton='x'])
1004
+ > [data-ui='skeleton'] {
1005
+ block-size: 0.5rem;
1006
+ border-radius: var(--slotted-radius-full, 9999px);
1007
+ flex: none;
1008
+ inline-size: 1.5rem;
1009
+ min-block-size: 0;
1010
+ }
1011
+
1012
+ [data-ui='chart']
1013
+ [data-part='skeleton']
1014
+ [data-skeleton='y']
1015
+ > [data-ui='skeleton']:nth-child(odd) {
1016
+ inline-size: 2rem;
1017
+ }
1018
+
1019
+ /* Six category labels at their full width are 144 pixels, more than the
1020
+ marks column of a quarter-width tile holds; they shrink together with it,
1021
+ as the engine's labels thin out, rather than run past the plot. */
1022
+ [data-ui='chart'] [data-part='skeleton'] [data-skeleton='x'] > [data-ui='skeleton'] {
1023
+ flex: 0 1 auto;
1024
+ min-inline-size: 0;
1025
+ }
1026
+
1027
+ [data-ui='chart'] [data-part='skeleton'] [data-skeleton='marks'] {
1028
+ align-items: end;
1029
+ background-image: repeating-linear-gradient(
1030
+ to bottom,
1031
+ var(--_chart-grid) 0 1px,
1032
+ transparent 1px calc((100% - 1px) / 4)
1033
+ );
1034
+ display: flex;
1035
+ grid-area: marks;
1036
+ justify-content: space-around;
1037
+ min-block-size: 0;
1038
+ position: relative;
1039
+ }
1040
+
1041
+ /* The skeleton family sizes a block on its own; inside the plot a bar takes
1042
+ its share of the row and nothing more. */
1043
+ [data-ui='chart'] [data-part='skeleton'] [data-skeleton='marks'] > [data-ui='skeleton'] {
1044
+ border-radius: var(--_chart-bar-radius) var(--_chart-bar-radius) 0 0;
1045
+ flex: 0 1 9%;
1046
+ inline-size: auto;
1047
+ min-inline-size: 0;
1048
+ }
1049
+
1050
+ [data-ui='chart']
1051
+ [data-part='skeleton'][data-kind='bar']
1052
+ [data-skeleton='marks']
1053
+ > [data-ui='skeleton']:nth-child(7n + 1) {
1054
+ block-size: 38%;
1055
+ }
1056
+ [data-ui='chart']
1057
+ [data-part='skeleton'][data-kind='bar']
1058
+ [data-skeleton='marks']
1059
+ > [data-ui='skeleton']:nth-child(7n + 2) {
1060
+ block-size: 62%;
1061
+ }
1062
+ [data-ui='chart']
1063
+ [data-part='skeleton'][data-kind='bar']
1064
+ [data-skeleton='marks']
1065
+ > [data-ui='skeleton']:nth-child(7n + 3) {
1066
+ block-size: 50%;
1067
+ }
1068
+ [data-ui='chart']
1069
+ [data-part='skeleton'][data-kind='bar']
1070
+ [data-skeleton='marks']
1071
+ > [data-ui='skeleton']:nth-child(7n + 4) {
1072
+ block-size: 74%;
1073
+ }
1074
+ [data-ui='chart']
1075
+ [data-part='skeleton'][data-kind='bar']
1076
+ [data-skeleton='marks']
1077
+ > [data-ui='skeleton']:nth-child(7n + 5) {
1078
+ block-size: 56%;
1079
+ }
1080
+ [data-ui='chart']
1081
+ [data-part='skeleton'][data-kind='bar']
1082
+ [data-skeleton='marks']
1083
+ > [data-ui='skeleton']:nth-child(7n + 6) {
1084
+ block-size: 44%;
1085
+ }
1086
+ [data-ui='chart']
1087
+ [data-part='skeleton'][data-kind='bar']
1088
+ [data-skeleton='marks']
1089
+ > [data-ui='skeleton']:nth-child(7n + 7) {
1090
+ block-size: 68%;
1091
+ }
1092
+
1093
+ /* A line is its stroke and the wash under it: two blocks over the whole
1094
+ marks area, one cut to a band as thick as a line, one to the silhouette
1095
+ under it at a third of the fill. */
1096
+ [data-ui='chart']
1097
+ [data-part='skeleton'][data-kind='line']
1098
+ [data-skeleton='marks']
1099
+ > [data-ui='skeleton'] {
1100
+ block-size: 100%;
1101
+ border-radius: 0;
1102
+ inset: 0;
1103
+ position: absolute;
1104
+ }
1105
+
1106
+ [data-ui='chart']
1107
+ [data-part='skeleton'][data-kind='line']
1108
+ [data-skeleton='marks']
1109
+ > [data-ui='skeleton']:first-child {
1110
+ clip-path: polygon(
1111
+ 0% 60.5%,
1112
+ 14% 46.5%,
1113
+ 28% 54.5%,
1114
+ 42% 28.5%,
1115
+ 57% 38.5%,
1116
+ 71% 20.5%,
1117
+ 86% 32.5%,
1118
+ 100% 12.5%,
1119
+ 100% 15.5%,
1120
+ 86% 35.5%,
1121
+ 71% 23.5%,
1122
+ 57% 41.5%,
1123
+ 42% 31.5%,
1124
+ 28% 57.5%,
1125
+ 14% 49.5%,
1126
+ 0% 63.5%
1127
+ );
1128
+ }
1129
+
1130
+ [data-ui='chart']
1131
+ [data-part='skeleton'][data-kind='line']
1132
+ [data-skeleton='marks']
1133
+ > [data-ui='skeleton']:last-child {
1134
+ clip-path: polygon(
1135
+ 0% 62%,
1136
+ 14% 48%,
1137
+ 28% 56%,
1138
+ 42% 30%,
1139
+ 57% 40%,
1140
+ 71% 22%,
1141
+ 86% 34%,
1142
+ 100% 14%,
1143
+ 100% 100%,
1144
+ 0% 100%
1145
+ );
1146
+ opacity: 0.35;
1147
+ }
1148
+
1149
+ /* A pie has no axes: its ring, centred, at the size the engine draws it. */
1150
+ [data-ui='chart'] [data-part='skeleton'][data-kind='pie'] > [data-ui='skeleton'] {
1151
+ align-items: center;
1152
+ display: flex;
1153
+ justify-content: center;
1154
+ }
1155
+
1156
+ [data-ui='chart']
1157
+ [data-part='skeleton'][data-kind='pie']
1158
+ [data-ui='skeleton'][data-shape='circle'] {
1159
+ aspect-ratio: 1;
1160
+ block-size: 76%;
1161
+ flex: none;
1162
+ inline-size: auto;
1163
+ mask-image: radial-gradient(
1164
+ circle,
1165
+ transparent calc(var(--slotted-chart-skeleton-hole, 64%) * 0.5),
1166
+ #000 calc(var(--slotted-chart-skeleton-hole, 64%) * 0.5 + 0.5px)
1167
+ );
1168
+ }
1169
+
1170
+ /* A legend whose entries come with the data stands in as three short
1171
+ lines of the entries' type height. */
1172
+ [data-ui='chart'] [data-part='legend'] > [data-ui='skeleton'] {
1173
+ /* A tenth of the text over the ground: a step lighter than the ground
1174
+ in a dark scheme and a step darker in a light one, where the skeleton
1175
+ family's own fill, made for a sunken field, sank into a dark tile. */
1176
+ --slotted-skeleton-fill: color-mix(
1177
+ in oklab,
1178
+ var(--slotted-text, CanvasText) 9%,
1179
+ var(--_chart-surface)
1180
+ );
1181
+
1182
+ --slotted-skeleton-block-size: 0.5rem;
1183
+ --slotted-skeleton-min-block-size: 0;
1184
+
1185
+ align-self: center;
1186
+ block-size: 0.5rem;
1187
+ border-radius: var(--slotted-radius-full, 9999px);
1188
+ flex: none;
1189
+ inline-size: 4.5rem;
1190
+ margin-inline-start: var(--slotted-space-3, 0.375rem);
1191
+ min-block-size: 0;
1192
+ }
1193
+
1194
+ [data-ui='chart'] [data-part='legend'] > [data-ui='skeleton']:nth-child(2) {
1195
+ inline-size: 3.25rem;
1196
+ }
1197
+
1198
+ /* ── Empty and failed ─────────────────────────────────────────────────── */
1199
+
1200
+ [data-ui='chart'] :is([data-part='empty'], [data-part='error']) {
1201
+ /* A message about one chart, at the size of the chart's own words. */
1202
+ --slotted-result-state-title-font-size: var(--slotted-font-size-md, 0.875rem);
1203
+ --slotted-result-state-padding-block: var(--slotted-space-4, 0.5rem);
1204
+
1205
+ align-content: center;
1206
+ display: grid;
1207
+ inset: 0;
1208
+ justify-items: center;
1209
+ padding: var(--_chart-inset);
1210
+ position: absolute;
1211
+ z-index: 3;
1212
+ }
1213
+
1214
+ /* An empty or failed plot keeps the baseline it would have drawn, so the box
1215
+ reads as the chart's and not as a hole in the page. The baseline alone:
1216
+ the message stands on no surface of its own, and the bands the grid drew
1217
+ every quarter of the height crossed the empty title and ran between the
1218
+ failed title and its retry. */
1219
+ [data-ui='chart'] [data-part='plot']:has(> :is([data-part='empty'], [data-part='error'])) {
1220
+ background: linear-gradient(var(--_chart-grid), var(--_chart-grid)) 0 100% / 100% 1px no-repeat
1221
+ content-box;
1222
+ box-sizing: border-box;
1223
+ padding: var(--_chart-inset) var(--_chart-inset) calc(var(--_chart-inset) * 3);
1224
+ }
1225
+
1226
+ /* ── Text alternatives ────────────────────────────────────────────────── */
1227
+
1228
+ [data-ui='chart'] [data-part='summary'] {
1229
+ block-size: 1px;
1230
+ clip-path: inset(50%);
1231
+ inline-size: 1px;
1232
+ margin: -1px;
1233
+ overflow: hidden;
1234
+ position: absolute;
1235
+ white-space: nowrap;
1236
+ }
1237
+
1238
+ /* The table view: in the plot's box, scrolling inside it, in the document's
1239
+ direction, on the plot's ground. */
1240
+ [data-ui='chart'] [data-part='table-region'] {
1241
+ background-color: var(--_chart-surface);
1242
+ border-radius: var(--_radius);
1243
+ inset: 0;
1244
+ overflow: auto;
1245
+ overscroll-behavior: contain;
1246
+ position: absolute;
1247
+ z-index: 4;
1248
+ }
1249
+
1250
+ [data-ui='chart']:dir(rtl) [data-part='table-region'] {
1251
+ direction: rtl;
1252
+ }
1253
+
1254
+ /* The region scrolls, so it takes focus to be scrolled by keyboard. */
1255
+ [data-ui='chart'] [data-part='table-region']:focus-visible {
1256
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
1257
+ outline-offset: calc(var(--slotted-focus-ring-width, 2px) * -1);
1258
+ }
1259
+
1260
+ [data-ui='chart'] [data-part='table-region'][hidden] {
1261
+ display: none;
1262
+ }
1263
+
1264
+ [data-ui='chart'] [data-part='table'] {
1265
+ border-collapse: collapse;
1266
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
1267
+ inline-size: 100%;
1268
+ line-height: var(--slotted-line-height-sm, 1.45);
1269
+ }
1270
+
1271
+ [data-ui='chart'] [data-part='table'] caption {
1272
+ caption-side: bottom;
1273
+ color: var(--slotted-text-muted, GrayText);
1274
+ font-size: var(--slotted-font-size-xs, 0.75rem);
1275
+ padding-block: var(--slotted-space-3, 0.375rem);
1276
+ text-align: start;
1277
+ }
1278
+
1279
+ [data-ui='chart'] [data-part='table'] :is(th, td) {
1280
+ border-block-end: var(--slotted-border-width-thin, 1px) solid
1281
+ var(--slotted-border-subtle, CanvasText);
1282
+ padding-block: var(--slotted-control-gap-sm, 0.375rem);
1283
+ padding-inline: var(--slotted-space-4, 0.5rem);
1284
+ text-align: start;
1285
+ white-space: nowrap;
1286
+ }
1287
+
1288
+ [data-ui='chart'] [data-part='table'] tbody th {
1289
+ font-weight: var(--slotted-font-weight-medium, 500);
1290
+ }
1291
+
1292
+ [data-ui='chart'] [data-part='table'] thead th {
1293
+ background-color: var(--_chart-surface);
1294
+ color: var(--slotted-text-muted, GrayText);
1295
+ font-weight: var(--slotted-font-weight-medium, 500);
1296
+ inset-block-start: 0;
1297
+ position: sticky;
1298
+ }
1299
+
1300
+ [data-ui='chart'] [data-part='table'] [data-numeric] {
1301
+ font-variant-numeric: tabular-nums;
1302
+ text-align: end;
1303
+ }
1304
+
1305
+ [data-ui='chart'] [data-part='table'] tbody tr[data-current] {
1306
+ background-color: var(--slotted-tone-secondary-subtle-hover, Highlight);
1307
+ }
1308
+
1309
+ /* ── Full screen ──────────────────────────────────────────────────────── */
1310
+
1311
+ /**
1312
+ * The same chart, given the whole screen: by the Fullscreen API where the
1313
+ * page may use it, and as a layer fixed over the page where it may not —
1314
+ * an iframe without `allowfullscreen`, an embedded webview. Both carry
1315
+ * `data-fullscreen`; the plot takes the height the header and the legend
1316
+ * leave, and the engine redraws at the new size on its own.
1317
+ */
1318
+ [data-ui='chart'][data-fullscreen] {
1319
+ --_chart-surface: var(--slotted-chart-surface, var(--slotted-surface, Canvas));
1320
+
1321
+ background-color: var(--_chart-surface);
1322
+ block-size: 100%;
1323
+ border: 0;
1324
+ border-radius: 0;
1325
+ inset: 0;
1326
+ padding-block: var(--slotted-space-8, 1.5rem);
1327
+ padding-inline: var(--slotted-space-9, 2rem);
1328
+ position: fixed;
1329
+ z-index: var(--slotted-z-index-overlay, 1000);
1330
+ }
1331
+
1332
+ [data-ui='chart'][data-fullscreen] [data-part='title'] {
1333
+ font-size: var(--slotted-font-size-xl, 1.125rem);
1334
+ }
1335
+
1336
+ /* ── Narrow ───────────────────────────────────────────────────────────── */
1337
+
1338
+ /**
1339
+ * Responsiveness changes what a chart shows first, not only its size
1340
+ * (`docs/component-features.md` §2.7). Below 480 pixels — a phone, a third
1341
+ * of a dashboard — the toolbar keeps only the menu, which holds its other
1342
+ * controls, and the legend gives up its hover padding; below 360 the
1343
+ * card gives up half its inset. The tooltip docks at the binding's word
1344
+ * (`placeTooltip`), because it depends on the plot's width, not the
1345
+ * figure's. Literal, as a container condition has to be
1346
+ * (`docs/token-foundation.md`, rule 4).
1347
+ */
1348
+ @container slotted-chart (max-width: 480px) {
1349
+ [data-ui='chart']
1350
+ > [data-part='header']
1351
+ > [data-part='toolbar']
1352
+ > :is([data-part='view-toggle'], [data-part='fullscreen-toggle']) {
1353
+ display: none;
1354
+ }
1355
+
1356
+ [data-ui='chart'] [data-part='menu-item']:is([data-action='view'], [data-action='fullscreen']) {
1357
+ display: flex;
1358
+ }
1359
+
1360
+ [data-ui='chart'] :is([data-part='legend-item'], [data-part='legend-more']) {
1361
+ padding-inline: var(--slotted-space-2, 0.25rem);
1362
+ }
1363
+ }
1364
+
1365
+ @container slotted-chart (max-width: 360px) {
1366
+ [data-ui='chart'][data-variant='card'] {
1367
+ padding-block: var(--slotted-space-5, 0.75rem);
1368
+ padding-inline: var(--slotted-space-5, 0.75rem);
1369
+ }
1370
+ }
1371
+
1372
+ /**
1373
+ * A finger needs the comfortable target, not the minimum one.
1374
+ *
1375
+ * A row in the layer is as wide as the layer, so it grows. An entry in the
1376
+ * legend's own line keeps the ground a mouse sees — a `+1` grown to the
1377
+ * comfortable height stood 26 wide and 44 tall — and a transparent
1378
+ * `::after` centred on it reaches 44 pixels in both axes. The line is that
1379
+ * tall, so its clip does not cut the target, and wrapped lines stand that
1380
+ * far apart, so one line's targets do not reach into the next. `+N` follows
1381
+ * the last entry two pixels away and does not reach back across it.
1382
+ */
1383
+ @media (pointer: coarse) {
1384
+ [data-ui='chart'] [data-part='menu-item'] {
1385
+ min-block-size: var(--slotted-target-comfortable, 2.75rem);
1386
+ }
1387
+
1388
+ [data-ui='chart'] [data-part='menu'] [data-part='legend-item'] {
1389
+ min-block-size: var(--slotted-target-comfortable, 2.75rem);
1390
+ min-inline-size: var(--slotted-target-comfortable, 2.75rem);
1391
+ }
1392
+
1393
+ [data-ui='chart'] [data-part='legend'] {
1394
+ min-block-size: var(--slotted-target-comfortable, 2.75rem);
1395
+ row-gap: calc(var(--slotted-target-comfortable, 2.75rem) - var(--slotted-target-min, 1.5rem));
1396
+ }
1397
+
1398
+ [data-ui='chart']
1399
+ [data-part='legend']
1400
+ > :is([data-part='legend-item'], [data-part='legend-more']) {
1401
+ position: relative;
1402
+ }
1403
+
1404
+ [data-ui='chart']
1405
+ [data-part='legend']
1406
+ > :is([data-part='legend-item'], [data-part='legend-more'])::after {
1407
+ content: '';
1408
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 2.75rem)) / 2));
1409
+ position: absolute;
1410
+ }
1411
+
1412
+ [data-ui='chart'] [data-part='legend'] > [data-part='legend-more']::after {
1413
+ inset-inline-start: 0;
1414
+ }
1415
+
1416
+ [data-ui='chart']
1417
+ :is(
1418
+ [data-part='zoom-reset'],
1419
+ [data-part='view-toggle'],
1420
+ [data-part='fullscreen-toggle'],
1421
+ [data-part='menu-trigger']
1422
+ ) {
1423
+ --_box: var(--slotted-target-comfortable, 2.75rem);
1424
+ }
1425
+ }
1426
+
1427
+ /* ── Print ────────────────────────────────────────────────────────────── */
1428
+
1429
+ /* Paper holds the marks and the words: no controls, no hover, no layer. */
1430
+ @media print {
1431
+ [data-ui='chart']
1432
+ :is(
1433
+ [data-part='toolbar'],
1434
+ [data-part='help'],
1435
+ [data-part='legend-more'],
1436
+ [data-part='tooltip'],
1437
+ [data-part='crosshair'],
1438
+ [data-part='marker']:not([data-selected])
1439
+ ) {
1440
+ display: none;
1441
+ }
1442
+
1443
+ [data-ui='chart'] [data-part='legend'] {
1444
+ flex-wrap: wrap;
1445
+ overflow: visible;
1446
+ }
1447
+
1448
+ [data-ui='chart'] {
1449
+ break-inside: avoid;
1450
+ }
1451
+ }
1452
+
1453
+ /* ── Forced colours ───────────────────────────────────────────────────── */
1454
+
1455
+ /**
1456
+ * Every series is one system colour here and the engine draws its textures,
1457
+ * so the legend's filled markers would all read as one: they keep their
1458
+ * shape, and the hidden state keeps its strike-through, which colour could
1459
+ * not have carried anyway.
1460
+ */
1461
+ @media (forced-colors: active) {
1462
+ [data-ui='chart']
1463
+ :is([data-part='legend-marker'], [data-part='tooltip-marker'], [data-part='marker']) {
1464
+ forced-color-adjust: none;
1465
+ background-color: CanvasText;
1466
+ }
1467
+
1468
+ [data-ui='chart'] [data-part='crosshair'] {
1469
+ background-color: GrayText;
1470
+ forced-color-adjust: none;
1471
+ }
1472
+ }
1473
+ }