material-plus-ui 0.0.1 → 1.0.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 (265) hide show
  1. package/README.md +39 -28
  2. package/dist/components/accordion/MPAccordion.d.ts +115 -0
  3. package/dist/components/accordion/MPAccordion.js +1 -0
  4. package/dist/components/accordion/index.d.ts +2 -0
  5. package/dist/components/accordion/index.js +1 -0
  6. package/dist/components/alert/MPAlert.d.ts +91 -0
  7. package/dist/components/alert/MPAlert.js +1 -0
  8. package/dist/components/alert/index.d.ts +2 -0
  9. package/dist/components/alert/index.js +1 -0
  10. package/dist/components/aspect-ratio/MPAspectRatio.d.ts +69 -0
  11. package/dist/components/aspect-ratio/MPAspectRatio.js +1 -0
  12. package/dist/components/aspect-ratio/index.d.ts +2 -0
  13. package/dist/components/aspect-ratio/index.js +1 -0
  14. package/dist/components/avatar/MPAvatar.d.ts +97 -0
  15. package/dist/components/avatar/MPAvatar.js +1 -0
  16. package/dist/components/avatar/index.d.ts +2 -0
  17. package/dist/components/avatar/index.js +1 -0
  18. package/dist/components/badge/MPBadge.d.ts +104 -0
  19. package/dist/components/badge/MPBadge.js +1 -0
  20. package/dist/components/badge/index.d.ts +2 -0
  21. package/dist/components/badge/index.js +1 -0
  22. package/dist/components/blockquote/MPBlockquote.d.ts +73 -0
  23. package/dist/components/blockquote/MPBlockquote.js +1 -0
  24. package/dist/components/blockquote/index.d.ts +2 -0
  25. package/dist/components/blockquote/index.js +1 -0
  26. package/dist/components/box/MPBox.d.ts +78 -0
  27. package/dist/components/box/MPBox.js +1 -0
  28. package/dist/components/box/index.d.ts +2 -0
  29. package/dist/components/box/index.js +1 -0
  30. package/dist/components/breadcrumb/MPBreadcrumb.d.ts +105 -0
  31. package/dist/components/breadcrumb/MPBreadcrumb.js +1 -0
  32. package/dist/components/breadcrumb/index.d.ts +2 -0
  33. package/dist/components/breadcrumb/index.js +1 -0
  34. package/dist/components/button/MPButton.d.ts +70 -0
  35. package/dist/components/button/MPButton.js +1 -0
  36. package/dist/components/button/index.d.ts +2 -0
  37. package/dist/components/button/index.js +1 -0
  38. package/dist/components/button-group/MPButtonGroup.d.ts +31 -0
  39. package/dist/components/button-group/MPButtonGroup.js +1 -0
  40. package/dist/components/button-group/index.d.ts +2 -0
  41. package/dist/components/button-group/index.js +1 -0
  42. package/dist/components/card/MPCard.d.ts +73 -0
  43. package/dist/components/card/MPCard.js +1 -0
  44. package/dist/components/card/index.d.ts +2 -0
  45. package/dist/components/card/index.js +1 -0
  46. package/dist/components/carousel/MPCarousel.d.ts +116 -0
  47. package/dist/components/carousel/MPCarousel.js +1 -0
  48. package/dist/components/carousel/index.d.ts +2 -0
  49. package/dist/components/carousel/index.js +1 -0
  50. package/dist/components/chat-bubble/MPChatBubble.d.ts +132 -0
  51. package/dist/components/chat-bubble/MPChatBubble.js +1 -0
  52. package/dist/components/chat-bubble/index.d.ts +2 -0
  53. package/dist/components/chat-bubble/index.js +1 -0
  54. package/dist/components/checkbox/MPCheckbox.d.ts +76 -0
  55. package/dist/components/checkbox/MPCheckbox.js +1 -0
  56. package/dist/components/checkbox/index.d.ts +2 -0
  57. package/dist/components/checkbox/index.js +1 -0
  58. package/dist/components/chip/MPChip.d.ts +64 -0
  59. package/dist/components/chip/MPChip.js +1 -0
  60. package/dist/components/chip/index.d.ts +2 -0
  61. package/dist/components/chip/index.js +1 -0
  62. package/dist/components/collapsible/MPCollapsible.d.ts +97 -0
  63. package/dist/components/collapsible/MPCollapsible.js +1 -0
  64. package/dist/components/collapsible/index.d.ts +2 -0
  65. package/dist/components/collapsible/index.js +1 -0
  66. package/dist/components/color-picker/MPColorPicker.d.ts +113 -0
  67. package/dist/components/color-picker/MPColorPicker.js +1 -0
  68. package/dist/components/color-picker/index.d.ts +2 -0
  69. package/dist/components/color-picker/index.js +1 -0
  70. package/dist/components/combobox/MPCombobox.d.ts +147 -0
  71. package/dist/components/combobox/MPCombobox.js +1 -0
  72. package/dist/components/combobox/index.d.ts +2 -0
  73. package/dist/components/combobox/index.js +1 -0
  74. package/dist/components/date-picker/MPDatePicker.d.ts +95 -0
  75. package/dist/components/date-picker/MPDatePicker.js +1 -0
  76. package/dist/components/date-picker/index.d.ts +2 -0
  77. package/dist/components/date-picker/index.js +1 -0
  78. package/dist/components/date-range-picker/MPDateRangePicker.d.ts +98 -0
  79. package/dist/components/date-range-picker/MPDateRangePicker.js +1 -0
  80. package/dist/components/date-range-picker/index.d.ts +2 -0
  81. package/dist/components/date-range-picker/index.js +1 -0
  82. package/dist/components/date-time-picker/MPDateTimePicker.d.ts +78 -0
  83. package/dist/components/date-time-picker/MPDateTimePicker.js +1 -0
  84. package/dist/components/date-time-picker/index.d.ts +2 -0
  85. package/dist/components/date-time-picker/index.js +1 -0
  86. package/dist/components/dialog/MPDialog.d.ts +145 -0
  87. package/dist/components/dialog/MPDialog.js +1 -0
  88. package/dist/components/dialog/index.d.ts +2 -0
  89. package/dist/components/dialog/index.js +1 -0
  90. package/dist/components/divider/MPDivider.d.ts +80 -0
  91. package/dist/components/divider/MPDivider.js +1 -0
  92. package/dist/components/divider/index.d.ts +2 -0
  93. package/dist/components/divider/index.js +1 -0
  94. package/dist/components/drawer/MPDrawer.d.ts +163 -0
  95. package/dist/components/drawer/MPDrawer.js +1 -0
  96. package/dist/components/drawer/index.d.ts +2 -0
  97. package/dist/components/drawer/index.js +1 -0
  98. package/dist/components/empty/MPEmpty.d.ts +64 -0
  99. package/dist/components/empty/MPEmpty.js +1 -0
  100. package/dist/components/empty/index.d.ts +2 -0
  101. package/dist/components/empty/index.js +1 -0
  102. package/dist/components/file-picker/MPFilePicker.d.ts +103 -0
  103. package/dist/components/file-picker/MPFilePicker.js +1 -0
  104. package/dist/components/file-picker/index.d.ts +2 -0
  105. package/dist/components/file-picker/index.js +1 -0
  106. package/dist/components/highlight/MPHighlight.d.ts +95 -0
  107. package/dist/components/highlight/MPHighlight.js +1 -0
  108. package/dist/components/highlight/index.d.ts +2 -0
  109. package/dist/components/highlight/index.js +1 -0
  110. package/dist/components/icon-button/MPIconButton.d.ts +59 -0
  111. package/dist/components/icon-button/MPIconButton.js +1 -0
  112. package/dist/components/icon-button/index.d.ts +2 -0
  113. package/dist/components/icon-button/index.js +1 -0
  114. package/dist/components/list/MPList.d.ts +96 -0
  115. package/dist/components/list/MPList.js +1 -0
  116. package/dist/components/list/index.d.ts +2 -0
  117. package/dist/components/list/index.js +1 -0
  118. package/dist/components/locale/MPLocaleProvider.d.ts +63 -0
  119. package/dist/components/locale/MPLocaleProvider.js +1 -0
  120. package/dist/components/locale/index.d.ts +2 -0
  121. package/dist/components/locale/index.js +1 -0
  122. package/dist/components/menu/MPMenu.d.ts +223 -0
  123. package/dist/components/menu/MPMenu.js +1 -0
  124. package/dist/components/menu/index.d.ts +2 -0
  125. package/dist/components/menu/index.js +1 -0
  126. package/dist/components/number-field/MPNumberField.d.ts +99 -0
  127. package/dist/components/number-field/MPNumberField.js +1 -0
  128. package/dist/components/number-field/index.d.ts +2 -0
  129. package/dist/components/number-field/index.js +1 -0
  130. package/dist/components/otp-field/MPOtpField.d.ts +89 -0
  131. package/dist/components/otp-field/MPOtpField.js +1 -0
  132. package/dist/components/otp-field/index.d.ts +2 -0
  133. package/dist/components/otp-field/index.js +1 -0
  134. package/dist/components/overlay/MPOverlay.d.ts +96 -0
  135. package/dist/components/overlay/MPOverlay.js +1 -0
  136. package/dist/components/overlay/index.d.ts +2 -0
  137. package/dist/components/overlay/index.js +1 -0
  138. package/dist/components/panes/MPPanes.d.ts +100 -0
  139. package/dist/components/panes/MPPanes.js +1 -0
  140. package/dist/components/panes/index.d.ts +2 -0
  141. package/dist/components/panes/index.js +1 -0
  142. package/dist/components/pill/MPPill.d.ts +117 -0
  143. package/dist/components/pill/MPPill.js +1 -0
  144. package/dist/components/pill/index.d.ts +2 -0
  145. package/dist/components/pill/index.js +1 -0
  146. package/dist/components/popover/MPPopover.d.ts +138 -0
  147. package/dist/components/popover/MPPopover.js +1 -0
  148. package/dist/components/popover/index.d.ts +2 -0
  149. package/dist/components/popover/index.js +1 -0
  150. package/dist/components/progress-box/MPProgressBox.d.ts +40 -0
  151. package/dist/components/progress-box/MPProgressBox.js +1 -0
  152. package/dist/components/progress-box/index.d.ts +2 -0
  153. package/dist/components/progress-box/index.js +1 -0
  154. package/dist/components/progress-circular/MPProgressCircular.d.ts +32 -0
  155. package/dist/components/progress-circular/MPProgressCircular.js +1 -0
  156. package/dist/components/progress-circular/index.d.ts +2 -0
  157. package/dist/components/progress-circular/index.js +1 -0
  158. package/dist/components/progress-linear/MPProgressLinear.d.ts +32 -0
  159. package/dist/components/progress-linear/MPProgressLinear.js +1 -0
  160. package/dist/components/progress-linear/index.d.ts +2 -0
  161. package/dist/components/progress-linear/index.js +1 -0
  162. package/dist/components/radio-group/MPRadioGroup.d.ts +81 -0
  163. package/dist/components/radio-group/MPRadioGroup.js +1 -0
  164. package/dist/components/radio-group/index.d.ts +2 -0
  165. package/dist/components/radio-group/index.js +1 -0
  166. package/dist/components/segmented-button/MPSegmentedButton.d.ts +75 -0
  167. package/dist/components/segmented-button/MPSegmentedButton.js +1 -0
  168. package/dist/components/segmented-button/index.d.ts +2 -0
  169. package/dist/components/segmented-button/index.js +1 -0
  170. package/dist/components/select/MPSelect.d.ts +86 -0
  171. package/dist/components/select/MPSelect.js +1 -0
  172. package/dist/components/select/index.d.ts +2 -0
  173. package/dist/components/select/index.js +1 -0
  174. package/dist/components/shortcut/MPShortcut.d.ts +67 -0
  175. package/dist/components/shortcut/MPShortcut.js +1 -0
  176. package/dist/components/shortcut/index.d.ts +2 -0
  177. package/dist/components/shortcut/index.js +1 -0
  178. package/dist/components/skeleton/MPSkeleton.d.ts +76 -0
  179. package/dist/components/skeleton/MPSkeleton.js +1 -0
  180. package/dist/components/skeleton/index.d.ts +2 -0
  181. package/dist/components/skeleton/index.js +1 -0
  182. package/dist/components/slider/MPSlider.d.ts +77 -0
  183. package/dist/components/slider/MPSlider.js +1 -0
  184. package/dist/components/slider/index.d.ts +2 -0
  185. package/dist/components/slider/index.js +1 -0
  186. package/dist/components/snackbar/MPSnackbar.d.ts +170 -0
  187. package/dist/components/snackbar/MPSnackbar.js +1 -0
  188. package/dist/components/snackbar/index.d.ts +2 -0
  189. package/dist/components/snackbar/index.js +1 -0
  190. package/dist/components/spoiler/MPSpoiler.d.ts +106 -0
  191. package/dist/components/spoiler/MPSpoiler.js +1 -0
  192. package/dist/components/spoiler/index.d.ts +2 -0
  193. package/dist/components/spoiler/index.js +1 -0
  194. package/dist/components/switch/MPSwitch.d.ts +75 -0
  195. package/dist/components/switch/MPSwitch.js +1 -0
  196. package/dist/components/switch/index.d.ts +2 -0
  197. package/dist/components/switch/index.js +1 -0
  198. package/dist/components/table/MPTable.d.ts +107 -0
  199. package/dist/components/table/MPTable.js +1 -0
  200. package/dist/components/table/index.d.ts +2 -0
  201. package/dist/components/table/index.js +1 -0
  202. package/dist/components/text-field/MPTextField.d.ts +17 -18
  203. package/dist/components/text-field/MPTextField.js +1 -1
  204. package/dist/components/text-link/MPTextLink.d.ts +88 -0
  205. package/dist/components/text-link/MPTextLink.js +1 -0
  206. package/dist/components/text-link/index.d.ts +2 -0
  207. package/dist/components/text-link/index.js +1 -0
  208. package/dist/components/time-picker/MPTimePicker.d.ts +108 -0
  209. package/dist/components/time-picker/MPTimePicker.js +1 -0
  210. package/dist/components/time-picker/index.d.ts +2 -0
  211. package/dist/components/time-picker/index.js +1 -0
  212. package/dist/components/timeline/MPTimeline.d.ts +96 -0
  213. package/dist/components/timeline/MPTimeline.js +1 -0
  214. package/dist/components/timeline/index.d.ts +2 -0
  215. package/dist/components/timeline/index.js +1 -0
  216. package/dist/components/tooltip/MPTooltip.d.ts +117 -0
  217. package/dist/components/tooltip/MPTooltip.js +1 -0
  218. package/dist/components/tooltip/index.d.ts +2 -0
  219. package/dist/components/tooltip/index.js +1 -0
  220. package/dist/components/typography/MPTypography.d.ts +94 -0
  221. package/dist/components/typography/MPTypography.js +1 -0
  222. package/dist/components/typography/index.d.ts +2 -0
  223. package/dist/components/typography/index.js +1 -0
  224. package/dist/constants/icons.d.ts +36 -0
  225. package/dist/constants/icons.js +1 -1
  226. package/dist/index.d.ts +55 -0
  227. package/dist/index.js +1 -1
  228. package/dist/internal/Calendar.d.ts +118 -0
  229. package/dist/internal/Calendar.js +1 -0
  230. package/dist/internal/FieldOutline.d.ts +38 -0
  231. package/dist/internal/FieldOutline.js +1 -0
  232. package/dist/internal/Picker.d.ts +110 -0
  233. package/dist/internal/Picker.js +1 -0
  234. package/dist/internal/StateLayer.d.ts +45 -0
  235. package/dist/internal/StateLayer.js +1 -0
  236. package/dist/internal/SupportingText.d.ts +23 -0
  237. package/dist/internal/SupportingText.js +1 -0
  238. package/dist/internal/WidthSizer.d.ts +31 -0
  239. package/dist/internal/WidthSizer.js +1 -0
  240. package/dist/internal/accent.d.ts +39 -0
  241. package/dist/internal/accent.js +1 -0
  242. package/dist/internal/button-group.d.ts +21 -0
  243. package/dist/internal/button-group.js +1 -0
  244. package/dist/internal/color.d.ts +125 -0
  245. package/dist/internal/color.js +1 -0
  246. package/dist/internal/date.d.ts +179 -0
  247. package/dist/internal/date.js +1 -0
  248. package/dist/internal/i18n.d.ts +131 -0
  249. package/dist/internal/i18n.js +1 -0
  250. package/dist/internal/locale.d.ts +43 -0
  251. package/dist/internal/locale.js +1 -0
  252. package/dist/internal/menu.d.ts +23 -0
  253. package/dist/internal/menu.js +1 -0
  254. package/dist/internal/progress.d.ts +126 -0
  255. package/dist/internal/progress.js +1 -0
  256. package/dist/internal/scale.d.ts +127 -0
  257. package/dist/internal/scale.js +1 -0
  258. package/dist/internal/surface.d.ts +76 -0
  259. package/dist/internal/surface.js +1 -0
  260. package/dist/internal/visually-hidden.d.ts +23 -0
  261. package/dist/internal/visually-hidden.js +1 -0
  262. package/dist/styles.css +1 -1
  263. package/dist/tailwind.css +1285 -20
  264. package/dist/types.d.ts +107 -16
  265. package/package.json +16 -21
package/dist/tailwind.css CHANGED
@@ -12,20 +12,31 @@
12
12
  * is this file plus the compiled utilities, built by `scripts/build-styles.mjs`
13
13
  * from `src/standalone.css`. The tokens below are the same in both.
14
14
  *
15
- * ## What is deliberately not here
15
+ * ## The vocabulary is Material Design 3's, not Material UI's
16
+ *
17
+ * This library implements the Material Design specification rather than wrapping
18
+ * an implementation of it, so the token names here are the ones the spec uses —
19
+ * `primary`, `on-surface-variant`, `outline`, `corner-extra-small`,
20
+ * `body-large`. They are not `main`/`light`/`dark`/`contrastText`, which is
21
+ * Material UI's own palette model and a different (earlier) colour system.
22
+ *
23
+ * ## Only what a component reads
16
24
  *
17
- * **Colour, typography and dark mode.** Material UI owns all three. A component
18
- * in this library takes its palette from the surrounding `ThemeProvider`, the
19
- * same as the `@mui/material` component beside it, so a token family here would
20
- * be a second theme that could disagree with the first. Anything a component
21
- * needs from the theme it reads through MUI, not from a custom property.
25
+ * A token nobody uses is a promise to keep supporting a name, so the roles below
26
+ * are exactly the ones the components actually resolve, and nothing else. MD3
27
+ * defines around fifty colour roles; an outlined text field reads five of them,
28
+ * and the components in this library between them read twenty-nine. The rest
29
+ * are absent on purpose and get added as components need them.
22
30
  *
23
- * **A reset.** MUI's `CssBaseline` is one, and every application using this
24
- * library already has it. See `src/standalone.css`.
31
+ * This is also why the library does not try to reproduce MD3 completely. It has
32
+ * to *coexist* with whatever Material implementation a page already runs, not
33
+ * replace it — so the surface it claims stays as small as the components make
34
+ * necessary.
35
+ *
36
+ * ## What is deliberately not here
25
37
  *
26
- * What Tailwind is for here is layout and the handful of structural utilities a
27
- * component needs that `sx` would express less clearly — so the tokens below
28
- * stay to that job, and the file is short on purpose.
38
+ * **A reset.** Material Plus adds no page-level styling of any kind. See
39
+ * `src/standalone.css` for why Tailwind's Preflight is left out too.
29
40
  */
30
41
 
31
42
  /*
@@ -48,16 +59,1270 @@
48
59
  @source '.';
49
60
 
50
61
  /* ---------------------------------------------------------------------------
51
- * Tokens
62
+ * System tokens
63
+ *
64
+ * Everything in this block is layered. A cascade layer loses to every unlayered
65
+ * rule, so a consumer's plain `:root { --mp-source-color: … }` wins over these
66
+ * defaults *regardless of source order* — they do not have to reason about
67
+ * whether their override sits before or after the `@import`.
68
+ *
69
+ * Note that the *public* names are `--mp-sys-*`, not `--md-sys-*`. The spec's
70
+ * names are what a role is *called*, but the `--md-sys-*` namespace belongs to
71
+ * the page: a project running Material Web Components already defines those, and
72
+ * writing to them would overwrite a theme this library has no business touching.
73
+ * So each role *reads* `--md-sys-color-*` and falls back to its own derivation,
74
+ * which gives three levels of control without a single conflict:
75
+ *
76
+ * --mp-sys-color-primary set by the consumer → wins outright
77
+ * --md-sys-color-primary already on the page → picked up, zero config
78
+ * neither → derived from the source colour
79
+ *
80
+ * ## Why the derived colours are declared on `*` and not on `:root`
81
+ *
82
+ * A custom property's value is not *parsed* until it is used, but its `var()`
83
+ * references are substituted at the element the property is **declared on**, and
84
+ * descendants inherit the already-substituted result. A role declared once on
85
+ * `:root` therefore freezes there: setting `--mp-source-color` further down the
86
+ * tree — on a section, on a wrapper, from an inline style at runtime — could not
87
+ * reach back and change it, and neither could a `.dark` on `<body>` rather than
88
+ * on `<html>`.
52
89
  *
53
- * Only what a component actually reads. A token nobody uses is a promise to
54
- * keep supporting a name, so they are added here as components need them
55
- * rather than in anticipation.
90
+ * Declaring them on every element instead makes each one re-substitute against
91
+ * whatever is in scope where it sits, which is what actually makes scoped and
92
+ * runtime theming work. This is the same technique Tailwind uses for its own
93
+ * composed variables.
94
+ *
95
+ * Only the *derived* colours need it. Everything else here is a literal value
96
+ * with no `var()` to freeze, so plain inheritance from `:root` is enough.
97
+ *
98
+ * The computed results are `--_mp-*`: private, read by the components, and not
99
+ * a name to set. Material Web marks its own internal tokens the same way. The
100
+ * indirection is load-bearing — it is what keeps a consumer's
101
+ * `--mp-sys-color-primary` on a wrapper from being clobbered by the `*` rule on
102
+ * the wrapper's own children.
56
103
  * ------------------------------------------------------------------------- */
57
104
 
58
- :root {
59
- /* How long a Material Plus transition runs. Matches MUI's own `short`
60
- duration so a control from this library and one from `@mui/material`
61
- settle together rather than a frame apart. */
62
- --mp-duration: 250ms;
105
+ @layer theme {
106
+ :root {
107
+ /*
108
+ * The one value most consumers ever set. MD3 calls it the source colour: a
109
+ * single seed that the tonal palettes — and therefore every role below —
110
+ * are generated from.
111
+ *
112
+ * ## Why this blue rather than MD3's baseline purple
113
+ *
114
+ * The specification's own baseline source is `#6750a4`, and a library that
115
+ * defaults to it is making a louder statement than it looks: purple is the
116
+ * one hue nobody arrives at by accident, so an application that has not
117
+ * chosen a colour yet ends up looking like it chose that one.
118
+ *
119
+ * A deep azure is the quieter default. It is also picked for its *chroma*
120
+ * rather than only its hue — 0.118, close to the baseline's 0.130 — because
121
+ * every role derives its saturation from here. A more vivid blue (Google's
122
+ * `#0b57d0` sits at 0.199) pulls the whole scheme brighter than any
123
+ * reference Material palette, which reads as a brand rather than as
124
+ * Material.
125
+ *
126
+ * The one thing a source colour must not be is near-grey. At a chroma below
127
+ * roughly 0.05 the derived `primary` stops being distinguishable from
128
+ * `outline`, and a focus ring then reads as no change at all.
129
+ */
130
+ --mp-source-color: #00639b;
131
+
132
+ /*
133
+ * Tone stops.
134
+ *
135
+ * MD3's light and dark schemes are not two palettes. They are the *same*
136
+ * tonal palettes read at different tones — light `primary` is tone 40, dark
137
+ * `primary` is tone 80, light `outline` is neutral-variant 50, dark is 60.
138
+ * Keeping them in variables is what lets the dark scheme below be a
139
+ * reassignment rather than a second copy of every colour, and it is why
140
+ * overriding `--mp-source-color` moves both schemes at once.
141
+ *
142
+ * These are private. The supported way to disagree with a colour is to set
143
+ * the role — `--mp-sys-color-outline` — not to retune the ramp. They are also
144
+ * specific to *this* approximation of MD3's palette generation, and would go
145
+ * away if that were ever replaced with real HCT.
146
+ *
147
+ * ## Where the numbers come from
148
+ *
149
+ * Read off MD3's own baseline ref palette, converted to OKLCh, rather than
150
+ * chosen by eye: light is (primary40, neutral10, neutral-variant30,
151
+ * neutral-variant50, error40) and dark is (primary80, neutral90,
152
+ * neutral-variant80, neutral-variant60, error80).
153
+ *
154
+ * The check that fixed these numbers is therefore run against `#6750a4`, not
155
+ * against the default above: fed the baseline source, the derivation lands on
156
+ * the baseline scheme — `primary` and `error` on its exact hex in both
157
+ * schemes, the near-grey roles within a ΔE of 0.008. What the default source
158
+ * changes is the hue and chroma the ramp is applied *to*, never the ramp.
159
+ *
160
+ * The lightnesses are OKLCh L, not MD3 tone numbers — tone is CIE L*, which
161
+ * OKLCh's L does not equal. Chroma is absolute for the near-grey roles, which
162
+ * are near-grey whatever the source is, and a multiplier of the source's own
163
+ * chroma for `primary`, so a deliberately muted brand colour stays muted.
164
+ *
165
+ * One known and accepted divergence: every derived role keeps the source
166
+ * colour's hue, while MD3's neutral palettes sit 10–20° off it. At a chroma
167
+ * of 0.01–0.02 that is a difference of a couple of thousandths in a/b — below
168
+ * anything visible, and chasing it would be fitting to noise, since hue is
169
+ * barely determined at all that close to grey.
170
+ *
171
+ * ## The accent tones are shared, the chroma is not
172
+ *
173
+ * `primary`, `secondary` and `tertiary` are one palette generation read three
174
+ * times: MD3 takes all three at the *same* tones and differs only in how much
175
+ * chroma the palette carries and, for `tertiary`, in its hue. So there is one
176
+ * `--_mp-tone-accent` rather than three, and a `--_mp-chroma-*` per family.
177
+ */
178
+ --_mp-tone-accent: 0.496;
179
+ --_mp-tone-on-accent: 1;
180
+ --_mp-tone-accent-container: 0.918;
181
+ --_mp-tone-on-accent-container: 0.242;
182
+
183
+ --_mp-chroma-primary: 1;
184
+ --_mp-chroma-secondary: 0.274;
185
+ --_mp-chroma-tertiary: 0.464;
186
+ /* MD3 puts `tertiary` 60° round the wheel in HCT, which lands at about 65°
187
+ in OKLCh near the default source. Measured rather than converted, because
188
+ the two spaces do not agree on where a hue is by a constant. */
189
+ --_mp-hue-tertiary: 64.7;
190
+
191
+ --_mp-tone-on-surface: 0.227;
192
+ --_mp-chroma-on-surface: 0.01;
193
+ --_mp-tone-on-surface-variant: 0.398;
194
+ --_mp-chroma-on-surface-variant: 0.0174;
195
+ --_mp-tone-outline: 0.567;
196
+ --_mp-chroma-outline: 0.0163;
197
+ --_mp-tone-outline-variant: 0.829;
198
+ --_mp-chroma-outline-variant: 0.0178;
199
+
200
+ /* The page's own surface — neutral 98 in the light scheme and neutral 6 in
201
+ the dark one. Read by exactly one thing, `MPOverlay`'s `solid` tone,
202
+ whose job is to put the page's own background over the page. */
203
+ --_mp-tone-surface: 0.984;
204
+ --_mp-chroma-surface: 0.0128;
205
+
206
+ /* The four surface containers, which are one neutral palette read at four
207
+ tones. MD3 has five; a menu (`surface-container`), an elevated button
208
+ (`-low`), a dialog (`-high`) and a switch's track (`-highest`) are the
209
+ four anything here actually asks for. */
210
+ --_mp-tone-surface-container-low: 0.967;
211
+ --_mp-chroma-surface-container-low: 0.0118;
212
+ --_mp-tone-surface-container: 0.954;
213
+ --_mp-chroma-surface-container: 0.0147;
214
+ --_mp-tone-surface-container-high: 0.933;
215
+ --_mp-chroma-surface-container-high: 0.0148;
216
+ --_mp-tone-surface-container-highest: 0.914;
217
+ --_mp-chroma-surface-container-highest: 0.0137;
218
+
219
+ /* `inverse-primary`, which is the accent palette read at the *other*
220
+ scheme's tone — light takes the dark scheme's stop and vice versa. That
221
+ is not an approximation of MD3's role, it is the definition of it, which
222
+ is why these two numbers are the accent stops above and below swapped.
223
+ One thing reads it: a snackbar's action label, which sits on the inverse
224
+ surface and would be unreadable in the accent proper. */
225
+ --_mp-tone-inverse-accent: 0.835;
226
+ --_mp-chroma-inverse-primary: 0.725;
227
+
228
+ /* The inverted pair, which is the same neutral palette read at the *other*
229
+ end: neutral 20 under neutral 95 in the light scheme, and the two swapped
230
+ in the dark one. MD3 gives it to exactly one thing, and so does this
231
+ library — a plain tooltip, whose whole job is to be legible over content
232
+ it was not designed against. A surface that inverts with the scheme is
233
+ readable on either. */
234
+ --_mp-tone-inverse-surface: 0.313;
235
+ --_mp-chroma-inverse-surface: 0.0118;
236
+ --_mp-tone-inverse-on-surface: 0.96;
237
+ --_mp-chroma-inverse-on-surface: 0.0118;
238
+
239
+ /* `error` carries its own hue as well, because it is not derived from the
240
+ source colour at all — see the role below. */
241
+ --_mp-tone-error: 0.501;
242
+ --_mp-chroma-error: 0.1783;
243
+ --_mp-hue-error: 28.7;
244
+
245
+ /*
246
+ * The chroma a whole palette carries, as opposed to the chroma one role of it
247
+ * came out at. Deliberately *not* reassigned for the dark scheme below, and
248
+ * the only stops here that are not.
249
+ *
250
+ * MD3 holds a palette's chroma constant across its tones and lets the sRGB
251
+ * boundary take back whatever will not fit — which is why `primary` at tone 40
252
+ * is vivid and `primary-container` at tone 90 is a pale wash, from one number.
253
+ * The container and `on-` roles are written the same way: the palette's chroma
254
+ * goes in unmodified and the browser's own gamut mapping does the clipping, at
255
+ * constant lightness and hue, exactly as HCT's does.
256
+ *
257
+ * Fed the baseline source, that lands the twelve container and `on-` roles
258
+ * within 0.01 of MD3's own — bar the two `error` containers, which come out up
259
+ * to 0.025 more chromatic because sRGB's boundary is a blunter clip than HCT's
260
+ * and the error palette is the only one saturated enough to notice.
261
+ *
262
+ * `error` is an absolute chroma rather than a multiplier, because it is not
263
+ * derived from the source colour at all.
264
+ */
265
+ --_mp-palette-primary: 1;
266
+ --_mp-palette-secondary: 0.274;
267
+ --_mp-palette-tertiary: 0.464;
268
+ --_mp-palette-error: 0.1783;
269
+ }
270
+
271
+ /* The dark scheme, by tone reassignment. Two ways in: the page's own signal
272
+ (`prefers-color-scheme`), and an explicit attribute or class for a project
273
+ that switches schemes itself. `.dark` is included because it is what
274
+ Tailwind's own `dark:` variant keys on by default.
275
+ Declared twice rather than pulled into a shared rule: a media query and a
276
+ selector cannot be combined without either nesting the selector list twice
277
+ over or inventing a third indirection for values that are read off a table
278
+ anyway. */
279
+ @media (prefers-color-scheme: dark) {
280
+ :root:not([data-mp-scheme='light']) {
281
+ --_mp-tone-accent: 0.835;
282
+ --_mp-tone-on-accent: 0.325;
283
+ --_mp-tone-accent-container: 0.41;
284
+ --_mp-tone-on-accent-container: 0.918;
285
+ --_mp-chroma-primary: 0.725;
286
+ --_mp-chroma-secondary: 0.287;
287
+ --_mp-chroma-tertiary: 0.51;
288
+ --_mp-hue-tertiary: 65.7;
289
+ --_mp-tone-on-surface: 0.914;
290
+ --_mp-chroma-on-surface: 0.0137;
291
+ --_mp-tone-on-surface-variant: 0.829;
292
+ --_mp-chroma-on-surface-variant: 0.0178;
293
+ --_mp-tone-outline: 0.657;
294
+ --_mp-chroma-outline: 0.0153;
295
+ --_mp-tone-outline-variant: 0.398;
296
+ --_mp-chroma-outline-variant: 0.0174;
297
+ --_mp-tone-surface: 0.187;
298
+ --_mp-chroma-surface: 0.0124;
299
+ --_mp-tone-surface-container-low: 0.227;
300
+ --_mp-chroma-surface-container-low: 0.01;
301
+ --_mp-tone-surface-container: 0.245;
302
+ --_mp-chroma-surface-container: 0.0134;
303
+ --_mp-tone-surface-container-high: 0.286;
304
+ --_mp-chroma-surface-container-high: 0.0129;
305
+ --_mp-tone-surface-container-highest: 0.33;
306
+ --_mp-chroma-surface-container-highest: 0.0125;
307
+ --_mp-tone-inverse-accent: 0.496;
308
+ --_mp-chroma-inverse-primary: 1;
309
+ --_mp-tone-inverse-surface: 0.914;
310
+ --_mp-chroma-inverse-surface: 0.0137;
311
+ --_mp-tone-inverse-on-surface: 0.313;
312
+ --_mp-chroma-inverse-on-surface: 0.0118;
313
+ --_mp-tone-error: 0.834;
314
+ --_mp-chroma-error: 0.0677;
315
+ --_mp-hue-error: 22;
316
+ }
317
+ }
318
+
319
+ [data-mp-scheme='dark'],
320
+ .dark {
321
+ --_mp-tone-accent: 0.835;
322
+ --_mp-tone-on-accent: 0.325;
323
+ --_mp-tone-accent-container: 0.41;
324
+ --_mp-tone-on-accent-container: 0.918;
325
+ --_mp-chroma-primary: 0.725;
326
+ --_mp-chroma-secondary: 0.287;
327
+ --_mp-chroma-tertiary: 0.51;
328
+ --_mp-hue-tertiary: 65.7;
329
+ --_mp-tone-on-surface: 0.914;
330
+ --_mp-chroma-on-surface: 0.0137;
331
+ --_mp-tone-on-surface-variant: 0.829;
332
+ --_mp-chroma-on-surface-variant: 0.0178;
333
+ --_mp-tone-outline: 0.657;
334
+ --_mp-chroma-outline: 0.0153;
335
+ --_mp-tone-outline-variant: 0.398;
336
+ --_mp-chroma-outline-variant: 0.0174;
337
+ --_mp-tone-surface: 0.187;
338
+ --_mp-chroma-surface: 0.0124;
339
+ --_mp-tone-surface-container-low: 0.227;
340
+ --_mp-chroma-surface-container-low: 0.01;
341
+ --_mp-tone-surface-container: 0.245;
342
+ --_mp-chroma-surface-container: 0.0134;
343
+ --_mp-tone-surface-container-high: 0.286;
344
+ --_mp-chroma-surface-container-high: 0.0129;
345
+ --_mp-tone-surface-container-highest: 0.33;
346
+ --_mp-chroma-surface-container-highest: 0.0125;
347
+ --_mp-tone-inverse-accent: 0.496;
348
+ --_mp-chroma-inverse-primary: 1;
349
+ --_mp-tone-inverse-surface: 0.914;
350
+ --_mp-chroma-inverse-surface: 0.0137;
351
+ --_mp-tone-inverse-on-surface: 0.313;
352
+ --_mp-chroma-inverse-on-surface: 0.0118;
353
+ --_mp-tone-error: 0.834;
354
+ --_mp-chroma-error: 0.0677;
355
+ --_mp-hue-error: 22;
356
+ }
357
+
358
+ /*
359
+ * Colour roles.
360
+ *
361
+ * Twenty-five, and every one of them is resolved by a component in this
362
+ * library. Checked against the spec's own component token maps rather than
363
+ * assumed — an outlined text field reads five, a filled button four, a switch
364
+ * six, a plain tooltip two nothing else touches.
365
+ *
366
+ * The three source-derived families are written out rather than generated. CSS
367
+ * has no way to build a custom property's *name* from another one, so a family
368
+ * is four declarations wherever it appears; what is shared between them lives
369
+ * in the tone stops above, which is the part that would otherwise drift.
370
+ *
371
+ * `oklch(from … h)` keeps the source colour's hue and replaces lightness and
372
+ * chroma. See the note above for why this is on `*` rather than `:root`.
373
+ */
374
+ *,
375
+ ::before,
376
+ ::after,
377
+ ::backdrop {
378
+ --_mp-color-primary: var(
379
+ --mp-sys-color-primary,
380
+ var(
381
+ --md-sys-color-primary,
382
+ oklch(
383
+ from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-primary)) h
384
+ )
385
+ )
386
+ );
387
+ --_mp-color-on-primary: var(
388
+ --mp-sys-color-on-primary,
389
+ var(
390
+ --md-sys-color-on-primary,
391
+ oklch(
392
+ from var(--mp-source-color) var(--_mp-tone-on-accent) calc(c * var(--_mp-palette-primary))
393
+ h
394
+ )
395
+ )
396
+ );
397
+ --_mp-color-primary-container: var(
398
+ --mp-sys-color-primary-container,
399
+ var(
400
+ --md-sys-color-primary-container,
401
+ oklch(
402
+ from var(--mp-source-color) var(--_mp-tone-accent-container)
403
+ calc(c * var(--_mp-palette-primary)) h
404
+ )
405
+ )
406
+ );
407
+ --_mp-color-on-primary-container: var(
408
+ --mp-sys-color-on-primary-container,
409
+ var(
410
+ --md-sys-color-on-primary-container,
411
+ oklch(
412
+ from var(--mp-source-color) var(--_mp-tone-on-accent-container)
413
+ calc(c * var(--_mp-palette-primary)) h
414
+ )
415
+ )
416
+ );
417
+
418
+ --_mp-color-secondary: var(
419
+ --mp-sys-color-secondary,
420
+ var(
421
+ --md-sys-color-secondary,
422
+ oklch(
423
+ from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-secondary)) h
424
+ )
425
+ )
426
+ );
427
+ --_mp-color-on-secondary: var(
428
+ --mp-sys-color-on-secondary,
429
+ var(
430
+ --md-sys-color-on-secondary,
431
+ oklch(
432
+ from var(--mp-source-color) var(--_mp-tone-on-accent)
433
+ calc(c * var(--_mp-palette-secondary)) h
434
+ )
435
+ )
436
+ );
437
+ --_mp-color-secondary-container: var(
438
+ --mp-sys-color-secondary-container,
439
+ var(
440
+ --md-sys-color-secondary-container,
441
+ oklch(
442
+ from var(--mp-source-color) var(--_mp-tone-accent-container)
443
+ calc(c * var(--_mp-palette-secondary)) h
444
+ )
445
+ )
446
+ );
447
+ --_mp-color-on-secondary-container: var(
448
+ --mp-sys-color-on-secondary-container,
449
+ var(
450
+ --md-sys-color-on-secondary-container,
451
+ oklch(
452
+ from var(--mp-source-color) var(--_mp-tone-on-accent-container)
453
+ calc(c * var(--_mp-palette-secondary)) h
454
+ )
455
+ )
456
+ );
457
+
458
+ /* The one family that moves off the source colour's hue. */
459
+ --_mp-color-tertiary: var(
460
+ --mp-sys-color-tertiary,
461
+ var(
462
+ --md-sys-color-tertiary,
463
+ oklch(
464
+ from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-tertiary))
465
+ calc(h + var(--_mp-hue-tertiary))
466
+ )
467
+ )
468
+ );
469
+ --_mp-color-on-tertiary: var(
470
+ --mp-sys-color-on-tertiary,
471
+ var(
472
+ --md-sys-color-on-tertiary,
473
+ oklch(
474
+ from var(--mp-source-color) var(--_mp-tone-on-accent)
475
+ calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
476
+ )
477
+ )
478
+ );
479
+ --_mp-color-tertiary-container: var(
480
+ --mp-sys-color-tertiary-container,
481
+ var(
482
+ --md-sys-color-tertiary-container,
483
+ oklch(
484
+ from var(--mp-source-color) var(--_mp-tone-accent-container)
485
+ calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
486
+ )
487
+ )
488
+ );
489
+ --_mp-color-on-tertiary-container: var(
490
+ --mp-sys-color-on-tertiary-container,
491
+ var(
492
+ --md-sys-color-on-tertiary-container,
493
+ oklch(
494
+ from var(--mp-source-color) var(--_mp-tone-on-accent-container)
495
+ calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
496
+ )
497
+ )
498
+ );
499
+
500
+ /* The page's own surface. Only `MPOverlay`'s `solid` tone reads it — a sheet
501
+ that hides the page by being the page. */
502
+ --_mp-color-surface: var(
503
+ --mp-sys-color-surface,
504
+ var(
505
+ --md-sys-color-surface,
506
+ oklch(from var(--mp-source-color) var(--_mp-tone-surface) var(--_mp-chroma-surface) h)
507
+ )
508
+ );
509
+
510
+ --_mp-color-surface-container-low: var(
511
+ --mp-sys-color-surface-container-low,
512
+ var(
513
+ --md-sys-color-surface-container-low,
514
+ oklch(
515
+ from var(--mp-source-color) var(--_mp-tone-surface-container-low)
516
+ var(--_mp-chroma-surface-container-low) h
517
+ )
518
+ )
519
+ );
520
+ --_mp-color-surface-container: var(
521
+ --mp-sys-color-surface-container,
522
+ var(
523
+ --md-sys-color-surface-container,
524
+ oklch(
525
+ from var(--mp-source-color) var(--_mp-tone-surface-container)
526
+ var(--_mp-chroma-surface-container) h
527
+ )
528
+ )
529
+ );
530
+ /* One step above `surface-container`, and the tone MD3 puts a dialog on: a
531
+ sheet that has taken the page has to sit above the menus that did not. */
532
+ --_mp-color-surface-container-high: var(
533
+ --mp-sys-color-surface-container-high,
534
+ var(
535
+ --md-sys-color-surface-container-high,
536
+ oklch(
537
+ from var(--mp-source-color) var(--_mp-tone-surface-container-high)
538
+ var(--_mp-chroma-surface-container-high) h
539
+ )
540
+ )
541
+ );
542
+ --_mp-color-surface-container-highest: var(
543
+ --mp-sys-color-surface-container-highest,
544
+ var(
545
+ --md-sys-color-surface-container-highest,
546
+ oklch(
547
+ from var(--mp-source-color) var(--_mp-tone-surface-container-highest)
548
+ var(--_mp-chroma-surface-container-highest) h
549
+ )
550
+ )
551
+ );
552
+
553
+ /* The two inverted roles, read by a plain tooltip and by nothing else. */
554
+ --_mp-color-inverse-surface: var(
555
+ --mp-sys-color-inverse-surface,
556
+ var(
557
+ --md-sys-color-inverse-surface,
558
+ oklch(
559
+ from var(--mp-source-color) var(--_mp-tone-inverse-surface)
560
+ var(--_mp-chroma-inverse-surface) h
561
+ )
562
+ )
563
+ );
564
+ --_mp-color-inverse-on-surface: var(
565
+ --mp-sys-color-inverse-on-surface,
566
+ var(
567
+ --md-sys-color-inverse-on-surface,
568
+ oklch(
569
+ from var(--mp-source-color) var(--_mp-tone-inverse-on-surface)
570
+ var(--_mp-chroma-inverse-on-surface) h
571
+ )
572
+ )
573
+ );
574
+ /* The accent read at the other scheme's tone, for the one label that sits on
575
+ the inverse surface: a snackbar's action. `primary` proper is derived to
576
+ contrast with the *page*, so on a plate that inverts the page it is the
577
+ one colour guaranteed not to read. */
578
+ --_mp-color-inverse-primary: var(
579
+ --mp-sys-color-inverse-primary,
580
+ var(
581
+ --md-sys-color-inverse-primary,
582
+ oklch(
583
+ from var(--mp-source-color) var(--_mp-tone-inverse-accent)
584
+ calc(c * var(--_mp-chroma-inverse-primary)) h
585
+ )
586
+ )
587
+ );
588
+
589
+ --_mp-color-on-surface: var(
590
+ --mp-sys-color-on-surface,
591
+ var(
592
+ --md-sys-color-on-surface,
593
+ oklch(from var(--mp-source-color) var(--_mp-tone-on-surface) var(--_mp-chroma-on-surface) h)
594
+ )
595
+ );
596
+ --_mp-color-on-surface-variant: var(
597
+ --mp-sys-color-on-surface-variant,
598
+ var(
599
+ --md-sys-color-on-surface-variant,
600
+ oklch(
601
+ from var(--mp-source-color) var(--_mp-tone-on-surface-variant)
602
+ var(--_mp-chroma-on-surface-variant) h
603
+ )
604
+ )
605
+ );
606
+ --_mp-color-outline: var(
607
+ --mp-sys-color-outline,
608
+ var(
609
+ --md-sys-color-outline,
610
+ oklch(from var(--mp-source-color) var(--_mp-tone-outline) var(--_mp-chroma-outline) h)
611
+ )
612
+ );
613
+ /* The quieter of the two outlines: a divider, or a line that is not the edge
614
+ of a control. A slider's inactive track and a dropzone's dashed rectangle
615
+ are both this rather than `outline`. */
616
+ --_mp-color-outline-variant: var(
617
+ --mp-sys-color-outline-variant,
618
+ var(
619
+ --md-sys-color-outline-variant,
620
+ oklch(
621
+ from var(--mp-source-color) var(--_mp-tone-outline-variant)
622
+ var(--_mp-chroma-outline-variant) h
623
+ )
624
+ )
625
+ );
626
+
627
+ /*
628
+ * The scrim, and the one colour in the sheet that is the same in both
629
+ * schemes.
630
+ *
631
+ * MD3 puts it at neutral tone 0 — black — and it stays black in the dark
632
+ * scheme, because a scrim is not a surface that has to be legible against
633
+ * the page: it is the absence of the page. A scrim that lightened with the
634
+ * scheme would fail to dim anything on the theme that needs dimming most.
635
+ * The alpha is the component's, not the token's: MD3 draws it at 32%.
636
+ */
637
+ --_mp-color-scrim: var(--mp-sys-color-scrim, var(--md-sys-color-scrim, #000000));
638
+
639
+ /* Not derived from the source colour. MD3's error palette is a fixed red
640
+ regardless of the seed — an error that shifted hue with the brand would
641
+ stop reading as an error. It still tracks the scheme, so it belongs here
642
+ rather than with the literals below. */
643
+ --_mp-color-error: var(
644
+ --mp-sys-color-error,
645
+ var(
646
+ --md-sys-color-error,
647
+ oklch(var(--_mp-tone-error) var(--_mp-chroma-error) var(--_mp-hue-error))
648
+ )
649
+ );
650
+ --_mp-color-on-error: var(
651
+ --mp-sys-color-on-error,
652
+ var(
653
+ --md-sys-color-on-error,
654
+ oklch(var(--_mp-tone-on-accent) var(--_mp-palette-error) var(--_mp-hue-error))
655
+ )
656
+ );
657
+ --_mp-color-error-container: var(
658
+ --mp-sys-color-error-container,
659
+ var(
660
+ --md-sys-color-error-container,
661
+ oklch(var(--_mp-tone-accent-container) var(--_mp-palette-error) var(--_mp-hue-error))
662
+ )
663
+ );
664
+ --_mp-color-on-error-container: var(
665
+ --mp-sys-color-on-error-container,
666
+ var(
667
+ --md-sys-color-on-error-container,
668
+ oklch(var(--_mp-tone-on-accent-container) var(--_mp-palette-error) var(--_mp-hue-error))
669
+ )
670
+ );
671
+
672
+ /*
673
+ * The names Tailwind's utilities actually read, aliased here as well as in
674
+ * the `@theme` block at the end of the file.
675
+ *
676
+ * Both are needed, and for different reasons. `@theme` is the *registration*:
677
+ * Tailwind only emits `border-mp-outline` for a name declared there. But what
678
+ * it emits alongside is a `:root` declaration, and a `:root` declaration
679
+ * freezes its `var()` references at the document root — which would put the
680
+ * whole cascade back where it started, one level up. A field inside a section
681
+ * with its own source colour would read the root's colour and quietly ignore
682
+ * its own.
683
+ *
684
+ * So the aliases are repeated here, where `*` re-resolves them per element.
685
+ * Only the alias is duplicated: the derivation above it lives in one place.
686
+ */
687
+ --color-mp-primary: var(--_mp-color-primary);
688
+ --color-mp-on-primary: var(--_mp-color-on-primary);
689
+ --color-mp-primary-container: var(--_mp-color-primary-container);
690
+ --color-mp-on-primary-container: var(--_mp-color-on-primary-container);
691
+ --color-mp-secondary: var(--_mp-color-secondary);
692
+ --color-mp-on-secondary: var(--_mp-color-on-secondary);
693
+ --color-mp-secondary-container: var(--_mp-color-secondary-container);
694
+ --color-mp-on-secondary-container: var(--_mp-color-on-secondary-container);
695
+ --color-mp-tertiary: var(--_mp-color-tertiary);
696
+ --color-mp-on-tertiary: var(--_mp-color-on-tertiary);
697
+ --color-mp-tertiary-container: var(--_mp-color-tertiary-container);
698
+ --color-mp-on-tertiary-container: var(--_mp-color-on-tertiary-container);
699
+ --color-mp-surface: var(--_mp-color-surface);
700
+ --color-mp-surface-container-low: var(--_mp-color-surface-container-low);
701
+ --color-mp-surface-container: var(--_mp-color-surface-container);
702
+ --color-mp-surface-container-high: var(--_mp-color-surface-container-high);
703
+ --color-mp-surface-container-highest: var(--_mp-color-surface-container-highest);
704
+ --color-mp-inverse-surface: var(--_mp-color-inverse-surface);
705
+ --color-mp-inverse-on-surface: var(--_mp-color-inverse-on-surface);
706
+ --color-mp-inverse-primary: var(--_mp-color-inverse-primary);
707
+ --color-mp-scrim: var(--_mp-color-scrim);
708
+ --color-mp-on-surface: var(--_mp-color-on-surface);
709
+ --color-mp-on-surface-variant: var(--_mp-color-on-surface-variant);
710
+ --color-mp-outline: var(--_mp-color-outline);
711
+ --color-mp-outline-variant: var(--_mp-color-outline-variant);
712
+ --color-mp-error: var(--_mp-color-error);
713
+ --color-mp-on-error: var(--_mp-color-on-error);
714
+ --color-mp-error-container: var(--_mp-color-error-container);
715
+ --color-mp-on-error-container: var(--_mp-color-on-error-container);
716
+
717
+ /* Literals rather than derivations, but resolved through a variable all the
718
+ same, so they freeze at `:root` in exactly the same way. A consumer setting
719
+ a typescale on a wrapper should see it apply inside that wrapper. */
720
+ --text-mp-display-small: var(--mp-sys-typescale-display-small-size);
721
+ --text-mp-display-small--line-height: var(--mp-sys-typescale-display-small-line-height);
722
+ --text-mp-display-small--letter-spacing: var(--mp-sys-typescale-display-small-tracking);
723
+ --text-mp-display-small--font-weight: var(--mp-sys-typescale-display-small-weight);
724
+
725
+ --text-mp-headline-large: var(--mp-sys-typescale-headline-large-size);
726
+ --text-mp-headline-large--line-height: var(--mp-sys-typescale-headline-large-line-height);
727
+ --text-mp-headline-large--letter-spacing: var(--mp-sys-typescale-headline-large-tracking);
728
+ --text-mp-headline-large--font-weight: var(--mp-sys-typescale-headline-large-weight);
729
+
730
+ --text-mp-headline-medium: var(--mp-sys-typescale-headline-medium-size);
731
+ --text-mp-headline-medium--line-height: var(--mp-sys-typescale-headline-medium-line-height);
732
+ --text-mp-headline-medium--letter-spacing: var(--mp-sys-typescale-headline-medium-tracking);
733
+ --text-mp-headline-medium--font-weight: var(--mp-sys-typescale-headline-medium-weight);
734
+
735
+ --text-mp-headline-small: var(--mp-sys-typescale-headline-small-size);
736
+ --text-mp-headline-small--line-height: var(--mp-sys-typescale-headline-small-line-height);
737
+ --text-mp-headline-small--letter-spacing: var(--mp-sys-typescale-headline-small-tracking);
738
+ --text-mp-headline-small--font-weight: var(--mp-sys-typescale-headline-small-weight);
739
+
740
+ --text-mp-title-large: var(--mp-sys-typescale-title-large-size);
741
+ --text-mp-title-large--line-height: var(--mp-sys-typescale-title-large-line-height);
742
+ --text-mp-title-large--letter-spacing: var(--mp-sys-typescale-title-large-tracking);
743
+ --text-mp-title-large--font-weight: var(--mp-sys-typescale-title-large-weight);
744
+
745
+ --text-mp-title-small: var(--mp-sys-typescale-title-small-size);
746
+ --text-mp-title-small--line-height: var(--mp-sys-typescale-title-small-line-height);
747
+ --text-mp-title-small--letter-spacing: var(--mp-sys-typescale-title-small-tracking);
748
+ --text-mp-title-small--font-weight: var(--mp-sys-typescale-title-small-weight);
749
+
750
+ --text-mp-label-medium: var(--mp-sys-typescale-label-medium-size);
751
+ --text-mp-label-medium--line-height: var(--mp-sys-typescale-label-medium-line-height);
752
+ --text-mp-label-medium--letter-spacing: var(--mp-sys-typescale-label-medium-tracking);
753
+ --text-mp-label-medium--font-weight: var(--mp-sys-typescale-label-medium-weight);
754
+
755
+ --text-mp-label-small: var(--mp-sys-typescale-label-small-size);
756
+ --text-mp-label-small--line-height: var(--mp-sys-typescale-label-small-line-height);
757
+ --text-mp-label-small--letter-spacing: var(--mp-sys-typescale-label-small-tracking);
758
+ --text-mp-label-small--font-weight: var(--mp-sys-typescale-label-small-weight);
759
+
760
+ --text-mp-body-large: var(--mp-sys-typescale-body-large-size);
761
+ --text-mp-body-large--line-height: var(--mp-sys-typescale-body-large-line-height);
762
+ --text-mp-body-large--letter-spacing: var(--mp-sys-typescale-body-large-tracking);
763
+ --text-mp-body-large--font-weight: var(--mp-sys-typescale-body-large-weight);
764
+
765
+ --text-mp-body-medium: var(--mp-sys-typescale-body-medium-size);
766
+ --text-mp-body-medium--line-height: var(--mp-sys-typescale-body-medium-line-height);
767
+ --text-mp-body-medium--letter-spacing: var(--mp-sys-typescale-body-medium-tracking);
768
+ --text-mp-body-medium--font-weight: var(--mp-sys-typescale-body-medium-weight);
769
+
770
+ --text-mp-body-small: var(--mp-sys-typescale-body-small-size);
771
+ --text-mp-body-small--line-height: var(--mp-sys-typescale-body-small-line-height);
772
+ --text-mp-body-small--letter-spacing: var(--mp-sys-typescale-body-small-tracking);
773
+ --text-mp-body-small--font-weight: var(--mp-sys-typescale-body-small-weight);
774
+
775
+ --text-mp-label-large: var(--mp-sys-typescale-label-large-size);
776
+ --text-mp-label-large--line-height: var(--mp-sys-typescale-label-large-line-height);
777
+ --text-mp-label-large--letter-spacing: var(--mp-sys-typescale-label-large-tracking);
778
+ --text-mp-label-large--font-weight: var(--mp-sys-typescale-label-large-weight);
779
+
780
+ --text-mp-title-medium: var(--mp-sys-typescale-title-medium-size);
781
+ --text-mp-title-medium--line-height: var(--mp-sys-typescale-title-medium-line-height);
782
+ --text-mp-title-medium--letter-spacing: var(--mp-sys-typescale-title-medium-tracking);
783
+ --text-mp-title-medium--font-weight: var(--mp-sys-typescale-title-medium-weight);
784
+
785
+ --radius-mp-xs: var(--mp-sys-shape-corner-extra-small);
786
+ --radius-mp-sm: var(--mp-sys-shape-corner-small);
787
+ --radius-mp-md: var(--mp-sys-shape-corner-medium);
788
+ --radius-mp-lg: var(--mp-sys-shape-corner-large);
789
+ --radius-mp-xl: var(--mp-sys-shape-corner-extra-large);
790
+ --radius-mp-full: var(--mp-sys-shape-corner-full);
791
+
792
+ --shadow-mp-1: var(--mp-sys-elevation-level1);
793
+ --shadow-mp-2: var(--mp-sys-elevation-level2);
794
+ --shadow-mp-3: var(--mp-sys-elevation-level3);
795
+
796
+ --ease-mp-standard: var(--mp-sys-motion-easing-standard);
797
+ }
798
+
799
+ :root {
800
+ /*
801
+ * No state opacities here. The spec's disabled treatment — content at 38%,
802
+ * an outline at 12% — is expressed where it is used, as `/38` and `/12` on
803
+ * the colour a component was already naming. A token would be a third name
804
+ * for a number nothing would read.
805
+ */
806
+
807
+ /*
808
+ * Typescale. Thirteen of MD3's fifteen roles, and each one is read by
809
+ * something: a text field's input is `body-large` at `md` and above and
810
+ * `body-medium` at `sm` and `xs`, its notched label and supporting text are
811
+ * `body-small`. A button's label is `label-large` at `xs` and `sm` and
812
+ * `title-medium` from `md` up, which is what MD3 sets its own small and
813
+ * medium buttons in.
814
+ *
815
+ * The display and headline half of the scale arrived with `MPTypography`,
816
+ * which is the component whose whole subject is the ladder — before it, a
817
+ * heading role was a token nothing read. `display-large` and
818
+ * `display-medium` are still absent for exactly that reason: at 57px and
819
+ * 45px they are hero type, and nothing in the library sets any.
820
+ *
821
+ * All three values are the spec's. The size ladder is ours — see `MPSize` in
822
+ * `src/types.ts` — but what it selects between is not: a smaller control
823
+ * moves *down the Material type scale* rather than to some interpolated size
824
+ * of the library's own invention.
825
+ *
826
+ * `--mp-sys-typescale-*-font` is left pointing at whatever the page uses
827
+ * rather than naming a typeface. Shipping a font stack would be a page-level
828
+ * decision, and this library does not make those.
829
+ */
830
+ /* The five roles above body, at MD3's own sizes and — this is the part that
831
+ looks like a mistake and is not — at MD3's own **weight 400**. Material
832
+ headings are not bold. A 32px line at regular weight is what the
833
+ specification draws, and the single fastest way to make a Material page
834
+ look like a Bootstrap one is to set its headings in 600. */
835
+ --mp-sys-typescale-display-small-font: inherit;
836
+ --mp-sys-typescale-display-small-size: 2.25rem;
837
+ --mp-sys-typescale-display-small-line-height: 2.75rem;
838
+ --mp-sys-typescale-display-small-tracking: 0rem;
839
+ --mp-sys-typescale-display-small-weight: 400;
840
+
841
+ --mp-sys-typescale-headline-large-font: inherit;
842
+ --mp-sys-typescale-headline-large-size: 2rem;
843
+ --mp-sys-typescale-headline-large-line-height: 2.5rem;
844
+ --mp-sys-typescale-headline-large-tracking: 0rem;
845
+ --mp-sys-typescale-headline-large-weight: 400;
846
+
847
+ --mp-sys-typescale-headline-medium-font: inherit;
848
+ --mp-sys-typescale-headline-medium-size: 1.75rem;
849
+ --mp-sys-typescale-headline-medium-line-height: 2.25rem;
850
+ --mp-sys-typescale-headline-medium-tracking: 0rem;
851
+ --mp-sys-typescale-headline-medium-weight: 400;
852
+
853
+ --mp-sys-typescale-headline-small-font: inherit;
854
+ --mp-sys-typescale-headline-small-size: 1.5rem;
855
+ --mp-sys-typescale-headline-small-line-height: 2rem;
856
+ --mp-sys-typescale-headline-small-tracking: 0rem;
857
+ --mp-sys-typescale-headline-small-weight: 400;
858
+
859
+ --mp-sys-typescale-title-large-font: inherit;
860
+ --mp-sys-typescale-title-large-size: 1.375rem;
861
+ --mp-sys-typescale-title-large-line-height: 1.75rem;
862
+ --mp-sys-typescale-title-large-tracking: 0rem;
863
+ --mp-sys-typescale-title-large-weight: 400;
864
+
865
+ --mp-sys-typescale-body-large-font: inherit;
866
+ --mp-sys-typescale-body-large-size: 1rem;
867
+ --mp-sys-typescale-body-large-line-height: 1.5rem;
868
+ --mp-sys-typescale-body-large-tracking: 0.03125rem;
869
+ --mp-sys-typescale-body-large-weight: 400;
870
+
871
+ --mp-sys-typescale-body-medium-font: inherit;
872
+ --mp-sys-typescale-body-medium-size: 0.875rem;
873
+ --mp-sys-typescale-body-medium-line-height: 1.25rem;
874
+ --mp-sys-typescale-body-medium-tracking: 0.015625rem;
875
+ --mp-sys-typescale-body-medium-weight: 400;
876
+
877
+ --mp-sys-typescale-body-small-font: inherit;
878
+ --mp-sys-typescale-body-small-size: 0.75rem;
879
+ --mp-sys-typescale-body-small-line-height: 1rem;
880
+ --mp-sys-typescale-body-small-tracking: 0.025rem;
881
+ --mp-sys-typescale-body-small-weight: 400;
882
+
883
+ /* The label and small-title roles. All of them are 500 rather than 400: MD3
884
+ sets a control's own text one weight up from prose, which is what keeps a
885
+ button's label from reading as a paragraph that happens to be inside a
886
+ box. `label-small` at 11px is the smallest type in the specification and
887
+ is why a badge's count is legible at all. */
888
+ --mp-sys-typescale-label-large-font: inherit;
889
+ --mp-sys-typescale-label-large-size: 0.875rem;
890
+ --mp-sys-typescale-label-large-line-height: 1.25rem;
891
+ --mp-sys-typescale-label-large-tracking: 0.00625rem;
892
+ --mp-sys-typescale-label-large-weight: 500;
893
+
894
+ --mp-sys-typescale-label-medium-font: inherit;
895
+ --mp-sys-typescale-label-medium-size: 0.75rem;
896
+ --mp-sys-typescale-label-medium-line-height: 1rem;
897
+ --mp-sys-typescale-label-medium-tracking: 0.03125rem;
898
+ --mp-sys-typescale-label-medium-weight: 500;
899
+
900
+ --mp-sys-typescale-label-small-font: inherit;
901
+ --mp-sys-typescale-label-small-size: 0.6875rem;
902
+ --mp-sys-typescale-label-small-line-height: 1rem;
903
+ --mp-sys-typescale-label-small-tracking: 0.03125rem;
904
+ --mp-sys-typescale-label-small-weight: 500;
905
+
906
+ --mp-sys-typescale-title-small-font: inherit;
907
+ --mp-sys-typescale-title-small-size: 0.875rem;
908
+ --mp-sys-typescale-title-small-line-height: 1.25rem;
909
+ --mp-sys-typescale-title-small-tracking: 0.00625rem;
910
+ --mp-sys-typescale-title-small-weight: 500;
911
+
912
+ --mp-sys-typescale-title-medium-font: inherit;
913
+ --mp-sys-typescale-title-medium-size: 1rem;
914
+ --mp-sys-typescale-title-medium-line-height: 1.5rem;
915
+ --mp-sys-typescale-title-medium-tracking: 0.009375rem;
916
+ --mp-sys-typescale-title-medium-weight: 500;
917
+
918
+ /*
919
+ * Shape. Four corner sizes, and which one a component takes is a statement
920
+ * about what kind of object it is rather than a size to taste: a text field
921
+ * is a well (`extra-small`), a button is a pill (`full`), a dropzone is a
922
+ * sheet (`medium`), and the tiles inside one are `small`.
923
+ *
924
+ * `full` is a length rather than `50%` deliberately. A percentage radius on a
925
+ * box whose width and height differ draws an ellipse, so a wide button would
926
+ * bow along its top edge instead of ending in two half-circles.
927
+ */
928
+ --mp-sys-shape-corner-extra-small: 4px;
929
+ --mp-sys-shape-corner-small: 8px;
930
+ --mp-sys-shape-corner-medium: 12px;
931
+ /* `large` is read by exactly one thing, and it arrived with it: a drawer's
932
+ free edge. MD3 gives the navigation drawer `corner-large` on the side that
933
+ faces the page and leaves the side against the window square, and neither
934
+ neighbour is a substitute — 12px on a 360dp panel is barely a corner, and
935
+ 28px is the bottom sheet's, which is a different object. */
936
+ --mp-sys-shape-corner-large: 16px;
937
+ /* `extra-large` is here for the dialog, which is the spec's own corner for
938
+ it and the loudest radius in the system: a sheet that has taken the page
939
+ is allowed to look like an object rather than like a panel. It is also the
940
+ bottom sheet's, which is the same claim made along one edge. */
941
+ --mp-sys-shape-corner-extra-large: 28px;
942
+ --mp-sys-shape-corner-full: 9999px;
943
+
944
+ /*
945
+ * Elevation. Three of MD3's six levels, because three are what gets read: an
946
+ * elevated button rests at level 1 and rises to 2 under the pointer, a menu
947
+ * floats at level 2, and a dialog — which has taken the page rather than
948
+ * merely covered part of it — sits at level 3.
949
+ *
950
+ * Both are the spec's own two-shadow recipe — a tight key shadow plus a wider
951
+ * ambient one — rather than one blurred box shadow. The pair is what makes a
952
+ * raised surface read as lit from above instead of as a sticker with a halo.
953
+ */
954
+ --mp-sys-elevation-level1: 0 1px 2px 0 rgb(0 0 0 / 0.3), 0 1px 3px 1px rgb(0 0 0 / 0.15);
955
+ --mp-sys-elevation-level2: 0 1px 2px 0 rgb(0 0 0 / 0.3), 0 2px 6px 2px rgb(0 0 0 / 0.15);
956
+ --mp-sys-elevation-level3: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 4px 8px 3px rgb(0 0 0 / 0.15);
957
+
958
+ /* Motion. MD3's `short4`, which is what a text field's label and outline
959
+ transition on. Worth knowing if these controls sit beside another
960
+ library's: 250ms is a common default elsewhere, and a field from here
961
+ will settle slightly sooner unless this is set to match. */
962
+ --mp-sys-motion-duration-short4: 200ms;
963
+ /* The spec's `standard` curve: quick to leave, slow to arrive. Read by the
964
+ one thing in the library that actually travels, a switch's thumb. */
965
+ --mp-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
966
+ }
967
+
968
+ /*
969
+ * Two shape presets, on the same model as `data-mp-scheme`: say nothing and
970
+ * you get the specification's corners, name one and the whole subtree moves.
971
+ *
972
+ * <html data-mp-shape="rounded">
973
+ * <section data-mp-shape="sharp"> <!-- a subtree, same as the scheme -->
974
+ *
975
+ * These only set the four tokens above, so anything a consumer sets themselves
976
+ * still wins: the block is inside `@layer theme`, and unlayered CSS beats a
977
+ * layered rule whatever order the two are imported in.
978
+ *
979
+ * Named presets rather than a `--mp-shape-scale` multiplier, because the corner
980
+ * ladder is not linear and should not be scaled as if it were. Going rounder,
981
+ * `extra-small` wants to double and `extra-large` wants to move by a sixth — a
982
+ * dialog whose corner has doubled to 56px is not a rounder dialog, it is a
983
+ * lozenge. The numbers below are chosen per rung for that reason.
984
+ */
985
+ [data-mp-shape='rounded'] {
986
+ --mp-sys-shape-corner-extra-small: 8px;
987
+ --mp-sys-shape-corner-small: 12px;
988
+ --mp-sys-shape-corner-medium: 20px;
989
+ --mp-sys-shape-corner-large: 24px;
990
+ --mp-sys-shape-corner-extra-large: 32px;
991
+ /* `full` is not here, and cannot be: a button is already a pill at 9999px,
992
+ so there is no rounder to go. This preset moves the four rungs that have
993
+ somewhere to move, which is why it reads on fields, chips, sheets and
994
+ dialogs and is invisible on buttons and sliders. */
995
+ }
996
+
997
+ [data-mp-shape='sharp'] {
998
+ --mp-sys-shape-corner-extra-small: 0;
999
+ --mp-sys-shape-corner-small: 0;
1000
+ --mp-sys-shape-corner-medium: 0;
1001
+ --mp-sys-shape-corner-large: 0;
1002
+ --mp-sys-shape-corner-extra-large: 0;
1003
+ /* `full` *is* here, unlike above, and for the same reason: this is the one
1004
+ direction a pill can travel. Leaving it round would make `sharp` a theme
1005
+ where every corner is square except the buttons, which is not a theme. */
1006
+ --mp-sys-shape-corner-full: 0;
1007
+ }
1008
+ }
1009
+
1010
+ /* ---------------------------------------------------------------------------
1011
+ * Utility generation
1012
+ *
1013
+ * The block above is the input side: values a consumer sets, in a plain `:root`,
1014
+ * where Tailwind will not touch them. This block is the output side — Tailwind
1015
+ * only generates `bg-mp-primary`, `text-mp-body-large` and friends for names
1016
+ * declared in `@theme`, and it prunes the ones no utility ends up using.
1017
+ *
1018
+ * The split is what keeps the input side safe from that pruning: a variable only
1019
+ * ever referenced from inside another custom property's value has no utility
1020
+ * pointing at it, and would be a candidate for removal if it lived here.
1021
+ *
1022
+ * Every name is prefixed. `@theme` registers globally, so an unprefixed
1023
+ * `--color-primary` would generate a `bg-primary` that collides with the
1024
+ * consumer's own.
1025
+ *
1026
+ * What this block does *not* do is supply the values the utilities end up using.
1027
+ * It registers the names; the `*` rule above resolves them, and has to, because a
1028
+ * `:root` declaration would freeze the cascade at the document root. Every name
1029
+ * here is therefore also declared there — deliberately, not by oversight.
1030
+ * ------------------------------------------------------------------------- */
1031
+
1032
+ @theme {
1033
+ --color-mp-primary: var(--_mp-color-primary);
1034
+ --color-mp-on-primary: var(--_mp-color-on-primary);
1035
+ --color-mp-primary-container: var(--_mp-color-primary-container);
1036
+ --color-mp-on-primary-container: var(--_mp-color-on-primary-container);
1037
+ --color-mp-secondary: var(--_mp-color-secondary);
1038
+ --color-mp-on-secondary: var(--_mp-color-on-secondary);
1039
+ --color-mp-secondary-container: var(--_mp-color-secondary-container);
1040
+ --color-mp-on-secondary-container: var(--_mp-color-on-secondary-container);
1041
+ --color-mp-tertiary: var(--_mp-color-tertiary);
1042
+ --color-mp-on-tertiary: var(--_mp-color-on-tertiary);
1043
+ --color-mp-tertiary-container: var(--_mp-color-tertiary-container);
1044
+ --color-mp-on-tertiary-container: var(--_mp-color-on-tertiary-container);
1045
+ --color-mp-surface: var(--_mp-color-surface);
1046
+ --color-mp-surface-container-low: var(--_mp-color-surface-container-low);
1047
+ --color-mp-surface-container: var(--_mp-color-surface-container);
1048
+ --color-mp-surface-container-high: var(--_mp-color-surface-container-high);
1049
+ --color-mp-surface-container-highest: var(--_mp-color-surface-container-highest);
1050
+ --color-mp-inverse-surface: var(--_mp-color-inverse-surface);
1051
+ --color-mp-inverse-on-surface: var(--_mp-color-inverse-on-surface);
1052
+ --color-mp-inverse-primary: var(--_mp-color-inverse-primary);
1053
+ --color-mp-scrim: var(--_mp-color-scrim);
1054
+ --color-mp-on-surface: var(--_mp-color-on-surface);
1055
+ --color-mp-on-surface-variant: var(--_mp-color-on-surface-variant);
1056
+ --color-mp-outline: var(--_mp-color-outline);
1057
+ --color-mp-outline-variant: var(--_mp-color-outline-variant);
1058
+ --color-mp-error: var(--_mp-color-error);
1059
+ --color-mp-on-error: var(--_mp-color-on-error);
1060
+ --color-mp-error-container: var(--_mp-color-error-container);
1061
+ --color-mp-on-error-container: var(--_mp-color-on-error-container);
1062
+
1063
+ --text-mp-display-small: var(--mp-sys-typescale-display-small-size);
1064
+ --text-mp-display-small--line-height: var(--mp-sys-typescale-display-small-line-height);
1065
+ --text-mp-display-small--letter-spacing: var(--mp-sys-typescale-display-small-tracking);
1066
+ --text-mp-display-small--font-weight: var(--mp-sys-typescale-display-small-weight);
1067
+
1068
+ --text-mp-headline-large: var(--mp-sys-typescale-headline-large-size);
1069
+ --text-mp-headline-large--line-height: var(--mp-sys-typescale-headline-large-line-height);
1070
+ --text-mp-headline-large--letter-spacing: var(--mp-sys-typescale-headline-large-tracking);
1071
+ --text-mp-headline-large--font-weight: var(--mp-sys-typescale-headline-large-weight);
1072
+
1073
+ --text-mp-headline-medium: var(--mp-sys-typescale-headline-medium-size);
1074
+ --text-mp-headline-medium--line-height: var(--mp-sys-typescale-headline-medium-line-height);
1075
+ --text-mp-headline-medium--letter-spacing: var(--mp-sys-typescale-headline-medium-tracking);
1076
+ --text-mp-headline-medium--font-weight: var(--mp-sys-typescale-headline-medium-weight);
1077
+
1078
+ --text-mp-headline-small: var(--mp-sys-typescale-headline-small-size);
1079
+ --text-mp-headline-small--line-height: var(--mp-sys-typescale-headline-small-line-height);
1080
+ --text-mp-headline-small--letter-spacing: var(--mp-sys-typescale-headline-small-tracking);
1081
+ --text-mp-headline-small--font-weight: var(--mp-sys-typescale-headline-small-weight);
1082
+
1083
+ --text-mp-title-large: var(--mp-sys-typescale-title-large-size);
1084
+ --text-mp-title-large--line-height: var(--mp-sys-typescale-title-large-line-height);
1085
+ --text-mp-title-large--letter-spacing: var(--mp-sys-typescale-title-large-tracking);
1086
+ --text-mp-title-large--font-weight: var(--mp-sys-typescale-title-large-weight);
1087
+
1088
+ --text-mp-title-small: var(--mp-sys-typescale-title-small-size);
1089
+ --text-mp-title-small--line-height: var(--mp-sys-typescale-title-small-line-height);
1090
+ --text-mp-title-small--letter-spacing: var(--mp-sys-typescale-title-small-tracking);
1091
+ --text-mp-title-small--font-weight: var(--mp-sys-typescale-title-small-weight);
1092
+
1093
+ --text-mp-label-medium: var(--mp-sys-typescale-label-medium-size);
1094
+ --text-mp-label-medium--line-height: var(--mp-sys-typescale-label-medium-line-height);
1095
+ --text-mp-label-medium--letter-spacing: var(--mp-sys-typescale-label-medium-tracking);
1096
+ --text-mp-label-medium--font-weight: var(--mp-sys-typescale-label-medium-weight);
1097
+
1098
+ --text-mp-label-small: var(--mp-sys-typescale-label-small-size);
1099
+ --text-mp-label-small--line-height: var(--mp-sys-typescale-label-small-line-height);
1100
+ --text-mp-label-small--letter-spacing: var(--mp-sys-typescale-label-small-tracking);
1101
+ --text-mp-label-small--font-weight: var(--mp-sys-typescale-label-small-weight);
1102
+
1103
+ --text-mp-body-large: var(--mp-sys-typescale-body-large-size);
1104
+ --text-mp-body-large--line-height: var(--mp-sys-typescale-body-large-line-height);
1105
+ --text-mp-body-large--letter-spacing: var(--mp-sys-typescale-body-large-tracking);
1106
+ --text-mp-body-large--font-weight: var(--mp-sys-typescale-body-large-weight);
1107
+
1108
+ --text-mp-body-medium: var(--mp-sys-typescale-body-medium-size);
1109
+ --text-mp-body-medium--line-height: var(--mp-sys-typescale-body-medium-line-height);
1110
+ --text-mp-body-medium--letter-spacing: var(--mp-sys-typescale-body-medium-tracking);
1111
+ --text-mp-body-medium--font-weight: var(--mp-sys-typescale-body-medium-weight);
1112
+
1113
+ --text-mp-body-small: var(--mp-sys-typescale-body-small-size);
1114
+ --text-mp-body-small--line-height: var(--mp-sys-typescale-body-small-line-height);
1115
+ --text-mp-body-small--letter-spacing: var(--mp-sys-typescale-body-small-tracking);
1116
+ --text-mp-body-small--font-weight: var(--mp-sys-typescale-body-small-weight);
1117
+
1118
+ --text-mp-label-large: var(--mp-sys-typescale-label-large-size);
1119
+ --text-mp-label-large--line-height: var(--mp-sys-typescale-label-large-line-height);
1120
+ --text-mp-label-large--letter-spacing: var(--mp-sys-typescale-label-large-tracking);
1121
+ --text-mp-label-large--font-weight: var(--mp-sys-typescale-label-large-weight);
1122
+
1123
+ --text-mp-title-medium: var(--mp-sys-typescale-title-medium-size);
1124
+ --text-mp-title-medium--line-height: var(--mp-sys-typescale-title-medium-line-height);
1125
+ --text-mp-title-medium--letter-spacing: var(--mp-sys-typescale-title-medium-tracking);
1126
+ --text-mp-title-medium--font-weight: var(--mp-sys-typescale-title-medium-weight);
1127
+
1128
+ --radius-mp-xs: var(--mp-sys-shape-corner-extra-small);
1129
+ --radius-mp-sm: var(--mp-sys-shape-corner-small);
1130
+ --radius-mp-md: var(--mp-sys-shape-corner-medium);
1131
+ --radius-mp-lg: var(--mp-sys-shape-corner-large);
1132
+ --radius-mp-xl: var(--mp-sys-shape-corner-extra-large);
1133
+ --radius-mp-full: var(--mp-sys-shape-corner-full);
1134
+
1135
+ --shadow-mp-1: var(--mp-sys-elevation-level1);
1136
+ --shadow-mp-2: var(--mp-sys-elevation-level2);
1137
+ --shadow-mp-3: var(--mp-sys-elevation-level3);
1138
+
1139
+ --ease-mp-standard: var(--mp-sys-motion-easing-standard);
1140
+ }
1141
+
1142
+ /* ---------------------------------------------------------------------------
1143
+ * Keyframes
1144
+ *
1145
+ * The one part of the library that cannot be written as a utility, and the only
1146
+ * CSS here that draws rather than declares.
1147
+ *
1148
+ * Four of them belong to the progress indicators and the fifth is shared with
1149
+ * `MPChatBubble`'s typing dots, and they exist for a reason Tailwind cannot
1150
+ * answer: an indeterminate indicator is a *loop*, and a loop is a `@keyframes`
1151
+ * rule. Everything else about those components — their colours, their ladders,
1152
+ * their shapes — is classes and inline slots, exactly as it is everywhere else.
1153
+ *
1154
+ * Unlayered on purpose. `@keyframes` does not take part in the cascade, but the
1155
+ * two classes below do, and a layered class would lose to any unlayered rule a
1156
+ * consumer's own stylesheet happens to have.
1157
+ *
1158
+ * `prefers-reduced-motion` stops all of them. An indeterminate indicator that has
1159
+ * stopped moving still says "something is happening" — it is on screen, and it
1160
+ * was not before — and for a reader who asked for less motion that is the whole
1161
+ * of the message. The determinate transitions are left alone: they are a value
1162
+ * changing, not decoration.
1163
+ * ------------------------------------------------------------------------- */
1164
+
1165
+ /*
1166
+ * The linear indicator, which is two bars rather than one.
1167
+ *
1168
+ * MD3's indeterminate bar is a long sweep followed by a short one that catches
1169
+ * up — the second is what keeps the track from being empty for most of the
1170
+ * cycle. Both are written as `inset-inline-*` rather than as a translate so
1171
+ * that the whole thing runs the other way under RTL without a second rule.
1172
+ */
1173
+ @keyframes mp-progress-linear-lead {
1174
+ 0% {
1175
+ inset-inline-start: -35%;
1176
+ inset-inline-end: 100%;
1177
+ }
1178
+
1179
+ 60% {
1180
+ inset-inline-start: 100%;
1181
+ inset-inline-end: -90%;
1182
+ }
1183
+
1184
+ 100% {
1185
+ inset-inline-start: 100%;
1186
+ inset-inline-end: -90%;
1187
+ }
1188
+ }
1189
+
1190
+ @keyframes mp-progress-linear-trail {
1191
+ 0% {
1192
+ inset-inline-start: -200%;
1193
+ inset-inline-end: 100%;
1194
+ }
1195
+
1196
+ 60% {
1197
+ inset-inline-start: 107%;
1198
+ inset-inline-end: -8%;
1199
+ }
1200
+
1201
+ 100% {
1202
+ inset-inline-start: 107%;
1203
+ inset-inline-end: -8%;
1204
+ }
1205
+ }
1206
+
1207
+ /*
1208
+ * The circular indicator: the ring turns while the arc it draws grows and
1209
+ * shrinks. Two animations rather than one, on two elements, because the turn is
1210
+ * linear and the arc is eased — a single timing function cannot be both, and a
1211
+ * spinner whose arc pulses on the same curve it rotates on reads as a stutter.
1212
+ *
1213
+ * The dash values are in the circle's own `pathLength` units, which the
1214
+ * component pins to 100. That is what lets one keyframe rule serve every
1215
+ * diameter on the size ladder: without it each rung would need its own
1216
+ * arithmetic in a stylesheet that cannot do arithmetic.
1217
+ */
1218
+ @keyframes mp-progress-circular-turn {
1219
+ to {
1220
+ transform: rotate(360deg);
1221
+ }
1222
+ }
1223
+
1224
+ @keyframes mp-progress-circular-arc {
1225
+ 0% {
1226
+ stroke-dasharray: 1 100;
1227
+ stroke-dashoffset: 0;
1228
+ }
1229
+
1230
+ 50% {
1231
+ stroke-dasharray: 70 100;
1232
+ stroke-dashoffset: -8;
1233
+ }
1234
+
1235
+ 100% {
1236
+ stroke-dasharray: 1 100;
1237
+ stroke-dashoffset: -70;
1238
+ }
1239
+ }
1240
+
1241
+ /*
1242
+ * A wave of light running along a row of marks, and the one loop two components
1243
+ * turned out to want.
1244
+ *
1245
+ * `MPProgressBox` runs it along its segments and `MPChatBubble` runs it along
1246
+ * the three dots that say somebody is writing. The two differ only in how fast
1247
+ * and how far apart, which is what the classes below set — a second keyframe
1248
+ * saying the same thing is a second chance for the two to drift apart.
1249
+ *
1250
+ * Opacity rather than colour, so one rule covers all four accent families, and
1251
+ * each mark reads its own index out of `--_mp-index` for its delay — which is
1252
+ * what makes a row one class and one custom property instead of N generated
1253
+ * keyframe names.
1254
+ */
1255
+ @keyframes mp-wave {
1256
+ 0%,
1257
+ 100% {
1258
+ opacity: 0.24;
1259
+ }
1260
+
1261
+ 40% {
1262
+ opacity: 1;
1263
+ }
1264
+ }
1265
+
1266
+ .mp-progress-linear-lead {
1267
+ animation: mp-progress-linear-lead 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
1268
+ }
1269
+
1270
+ .mp-progress-linear-trail {
1271
+ animation: mp-progress-linear-trail 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
1272
+ animation-delay: 1.15s;
1273
+ }
1274
+
1275
+ .mp-progress-circular-turn {
1276
+ animation: mp-progress-circular-turn 1.4s linear infinite;
1277
+ }
1278
+
1279
+ .mp-progress-circular-arc {
1280
+ animation: mp-progress-circular-arc 1.4s ease-in-out infinite;
1281
+ }
1282
+
1283
+ .mp-progress-segment-wave {
1284
+ animation: mp-wave 1.2s ease-in-out infinite;
1285
+ animation-delay: calc(var(--_mp-index, 0) * 120ms);
1286
+ }
1287
+
1288
+ /* Faster and tighter than the progress row: three dots at conversational pace,
1289
+ which is roughly a beat a second. The dots never move — a bubble that bounced
1290
+ while somebody typed would bounce in a thread another reader is scrolling. */
1291
+ .mp-chat-typing {
1292
+ animation: mp-wave 1s ease-in-out infinite;
1293
+ animation-delay: calc(var(--_mp-index, 0) * 160ms);
1294
+ }
1295
+
1296
+ @media (prefers-reduced-motion: reduce) {
1297
+ .mp-progress-linear-lead,
1298
+ .mp-progress-linear-trail,
1299
+ .mp-progress-circular-turn,
1300
+ .mp-progress-circular-arc,
1301
+ .mp-progress-segment-wave,
1302
+ .mp-chat-typing {
1303
+ animation: none;
1304
+ }
1305
+
1306
+ /* Stopping the animation is not enough on its own: three of the five draw
1307
+ nothing at all outside a keyframe, so each is given the frame it should
1308
+ rest on. A partial bar and a partial arc, never a full one — an indicator
1309
+ that has stopped must not read as an indicator that has finished. */
1310
+ .mp-progress-linear-lead {
1311
+ inset-inline-start: 0;
1312
+ inset-inline-end: 65%;
1313
+ }
1314
+
1315
+ .mp-progress-linear-trail {
1316
+ display: none;
1317
+ }
1318
+
1319
+ .mp-progress-circular-arc {
1320
+ stroke-dasharray: 25 100;
1321
+ stroke-dashoffset: 0;
1322
+ }
1323
+
1324
+ .mp-progress-segment-wave,
1325
+ .mp-chat-typing {
1326
+ opacity: 0.6;
1327
+ }
63
1328
  }