zabi-components 8.1.0 → 9.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 (273) hide show
  1. package/CHANGELOG.md +1011 -0
  2. package/README.md +1 -1
  3. package/THEME.md +18 -5
  4. package/THEMING.md +308 -74
  5. package/dist/atoms/ActionPanel.svelte +1 -1
  6. package/dist/atoms/Avatar.svelte +19 -3
  7. package/dist/atoms/Avatar.svelte.d.ts +12 -0
  8. package/dist/atoms/Badge.svelte +37 -8
  9. package/dist/atoms/Badge.svelte.d.ts +6 -0
  10. package/dist/atoms/Block.svelte +74 -0
  11. package/dist/atoms/Block.svelte.d.ts +29 -0
  12. package/dist/atoms/Button.svelte +52 -15
  13. package/dist/atoms/Button.svelte.d.ts +3 -2
  14. package/dist/atoms/Card.svelte +181 -25
  15. package/dist/atoms/Card.svelte.d.ts +55 -3
  16. package/dist/atoms/Checkbox.svelte +33 -0
  17. package/dist/atoms/Checkbox.svelte.d.ts +27 -0
  18. package/dist/atoms/Chip.svelte +351 -0
  19. package/dist/atoms/Chip.svelte.d.ts +57 -0
  20. package/dist/atoms/CodeField.svelte +385 -0
  21. package/dist/atoms/CodeField.svelte.d.ts +61 -0
  22. package/dist/atoms/ColorPicker.svelte +1 -0
  23. package/dist/atoms/DateField.svelte +41 -3
  24. package/dist/atoms/DateField.svelte.d.ts +31 -3
  25. package/dist/atoms/FloatingActionButton.svelte +5 -3
  26. package/dist/atoms/FloatingActionButton.svelte.d.ts +1 -1
  27. package/dist/atoms/Heading.svelte +27 -1
  28. package/dist/atoms/Heading.svelte.d.ts +7 -0
  29. package/dist/atoms/IconButton.svelte +81 -9
  30. package/dist/atoms/IconButton.svelte.d.ts +13 -0
  31. package/dist/atoms/Input.svelte +10 -5
  32. package/dist/atoms/Input.svelte.d.ts +3 -2
  33. package/dist/atoms/List.svelte +3 -2
  34. package/dist/atoms/ListItem.svelte +31 -7
  35. package/dist/atoms/ListItem.svelte.d.ts +6 -0
  36. package/dist/atoms/PickerField.svelte +239 -0
  37. package/dist/atoms/PickerField.svelte.d.ts +67 -0
  38. package/dist/atoms/Progress.svelte +78 -17
  39. package/dist/atoms/Progress.svelte.d.ts +11 -1
  40. package/dist/atoms/Radio.svelte +32 -0
  41. package/dist/atoms/Radio.svelte.d.ts +26 -0
  42. package/dist/atoms/Rating.svelte +132 -6
  43. package/dist/atoms/Rating.svelte.d.ts +24 -3
  44. package/dist/atoms/Select.svelte +24 -26
  45. package/dist/atoms/Select.svelte.d.ts +12 -0
  46. package/dist/atoms/SelectionControl.svelte +99 -6
  47. package/dist/atoms/SelectionControl.svelte.d.ts +25 -0
  48. package/dist/atoms/Skeleton.svelte +114 -18
  49. package/dist/atoms/Skeleton.svelte.d.ts +30 -3
  50. package/dist/atoms/SkeletonGroup.svelte +43 -0
  51. package/dist/atoms/SkeletonGroup.svelte.d.ts +20 -0
  52. package/dist/atoms/Slider.svelte +35 -0
  53. package/dist/atoms/Sparkline.svelte +109 -0
  54. package/dist/atoms/Sparkline.svelte.d.ts +27 -0
  55. package/dist/atoms/SpeechBubble.svelte +187 -0
  56. package/dist/atoms/SpeechBubble.svelte.d.ts +33 -0
  57. package/dist/atoms/Stat.svelte +72 -0
  58. package/dist/atoms/Stat.svelte.d.ts +19 -0
  59. package/dist/atoms/TemporalField.svelte +342 -10
  60. package/dist/atoms/TemporalField.svelte.d.ts +20 -4
  61. package/dist/atoms/Textarea.svelte +100 -5
  62. package/dist/atoms/Textarea.svelte.d.ts +21 -0
  63. package/dist/atoms/TimeColumn.svelte +150 -0
  64. package/dist/atoms/TimeColumn.svelte.d.ts +25 -0
  65. package/dist/atoms/TimeField.svelte +46 -3
  66. package/dist/atoms/TimeField.svelte.d.ts +34 -3
  67. package/dist/atoms/Toast.svelte +6 -5
  68. package/dist/atoms/Toggle.svelte +61 -10
  69. package/dist/atoms/Toggle.svelte.d.ts +15 -0
  70. package/dist/atoms/Tooltip.svelte +20 -1
  71. package/dist/atoms/Tooltip.svelte.d.ts +7 -0
  72. package/dist/atoms/index.d.ts +21 -0
  73. package/dist/atoms/index.js +17 -0
  74. package/dist/atoms/selection-control.styles.d.ts +15 -4
  75. package/dist/atoms/selection-control.styles.js +16 -5
  76. package/dist/components/atoms/index.d.ts +21 -0
  77. package/dist/components/atoms/index.d.ts.map +1 -1
  78. package/dist/components/atoms/selection-control.styles.d.ts +15 -4
  79. package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
  80. package/dist/components/index.d.ts +27 -3
  81. package/dist/components/index.d.ts.map +1 -1
  82. package/dist/components/map.d.ts +11 -0
  83. package/dist/components/map.d.ts.map +1 -0
  84. package/dist/components/molecules/index.d.ts +7 -2
  85. package/dist/components/molecules/index.d.ts.map +1 -1
  86. package/dist/components/molecules/toast-store.d.ts +30 -0
  87. package/dist/components/molecules/toast-store.d.ts.map +1 -1
  88. package/dist/components/organisms/index.d.ts +6 -1
  89. package/dist/components/organisms/index.d.ts.map +1 -1
  90. package/dist/components/types/variants.d.ts +12 -3
  91. package/dist/components/types/variants.d.ts.map +1 -1
  92. package/dist/components/util/app-shell.d.ts +55 -4
  93. package/dist/components/util/app-shell.d.ts.map +1 -1
  94. package/dist/components/util/avatar.d.ts +3 -0
  95. package/dist/components/util/avatar.d.ts.map +1 -1
  96. package/dist/components/util/bottom-tab-bar.d.ts +6 -0
  97. package/dist/components/util/bottom-tab-bar.d.ts.map +1 -1
  98. package/dist/components/util/chart.d.ts +140 -0
  99. package/dist/components/util/chart.d.ts.map +1 -0
  100. package/dist/components/util/chip.d.ts +66 -0
  101. package/dist/components/util/chip.d.ts.map +1 -0
  102. package/dist/components/util/cn.d.ts.map +1 -1
  103. package/dist/components/util/code-field.d.ts +63 -0
  104. package/dist/components/util/code-field.d.ts.map +1 -0
  105. package/dist/components/util/collapsible.d.ts +6 -0
  106. package/dist/components/util/collapsible.d.ts.map +1 -1
  107. package/dist/components/util/display-voice.d.ts +10 -0
  108. package/dist/components/util/display-voice.d.ts.map +1 -0
  109. package/dist/components/util/field-control.d.ts +30 -0
  110. package/dist/components/util/field-control.d.ts.map +1 -0
  111. package/dist/components/util/field.d.ts +6 -0
  112. package/dist/components/util/field.d.ts.map +1 -1
  113. package/dist/components/util/focus-utils.d.ts +2 -0
  114. package/dist/components/util/focus-utils.d.ts.map +1 -1
  115. package/dist/components/util/map-view.d.ts +144 -0
  116. package/dist/components/util/map-view.d.ts.map +1 -0
  117. package/dist/components/util/photo.d.ts +19 -0
  118. package/dist/components/util/photo.d.ts.map +1 -1
  119. package/dist/components/util/progress.d.ts +19 -0
  120. package/dist/components/util/progress.d.ts.map +1 -0
  121. package/dist/components/util/scroll-edge.d.ts +33 -0
  122. package/dist/components/util/scroll-edge.d.ts.map +1 -0
  123. package/dist/components/util/sheet-drag.d.ts +25 -1
  124. package/dist/components/util/sheet-drag.d.ts.map +1 -1
  125. package/dist/components/util/skeleton.d.ts +15 -0
  126. package/dist/components/util/skeleton.d.ts.map +1 -0
  127. package/dist/components/util/sliding-indicator.d.ts +25 -0
  128. package/dist/components/util/sliding-indicator.d.ts.map +1 -0
  129. package/dist/components/util/temporal-field.d.ts +89 -0
  130. package/dist/components/util/temporal-field.d.ts.map +1 -0
  131. package/dist/components/util/toaster.d.ts +40 -0
  132. package/dist/components/util/toaster.d.ts.map +1 -1
  133. package/dist/components/util/tone-surface.d.ts +34 -0
  134. package/dist/components/util/tone-surface.d.ts.map +1 -0
  135. package/dist/components/util/top-navbar.d.ts +26 -2
  136. package/dist/components/util/top-navbar.d.ts.map +1 -1
  137. package/dist/components/util/zabi-strings.d.ts +9 -0
  138. package/dist/components/util/zabi-strings.d.ts.map +1 -1
  139. package/dist/create-theme/cli.js +6 -2
  140. package/dist/create-theme/index.d.ts +17 -3
  141. package/dist/create-theme/index.js +252 -35
  142. package/dist/create-theme/lib/resolve.js +97 -0
  143. package/dist/create-theme/theme-data.js +1618 -90
  144. package/dist/index.d.ts +27 -3
  145. package/dist/index.js +18 -0
  146. package/dist/map.d.ts +10 -0
  147. package/dist/map.js +9 -0
  148. package/dist/molecules/Alert.svelte +31 -12
  149. package/dist/molecules/Alert.svelte.d.ts +12 -1
  150. package/dist/molecules/AppBar.svelte +287 -28
  151. package/dist/molecules/AppBar.svelte.d.ts +62 -0
  152. package/dist/molecules/AvatarGroup.svelte +1 -1
  153. package/dist/molecules/BarChart.svelte +381 -0
  154. package/dist/molecules/BarChart.svelte.d.ts +45 -0
  155. package/dist/molecules/BottomSheet.svelte +88 -20
  156. package/dist/molecules/BottomSheet.svelte.d.ts +17 -1
  157. package/dist/molecules/BottomTabBar.svelte +134 -28
  158. package/dist/molecules/BottomTabBar.svelte.d.ts +36 -2
  159. package/dist/molecules/Calendar.svelte.d.ts +1 -1
  160. package/dist/molecules/ChipGroup.svelte +325 -0
  161. package/dist/molecules/ChipGroup.svelte.d.ts +41 -0
  162. package/dist/molecules/Collapsible.svelte +158 -54
  163. package/dist/molecules/Collapsible.svelte.d.ts +23 -6
  164. package/dist/molecules/CollapsibleGroup.svelte +16 -6
  165. package/dist/molecules/ConfirmDialog.svelte +5 -1
  166. package/dist/molecules/ConfirmDialog.svelte.d.ts +3 -0
  167. package/dist/molecules/Drawer.svelte +33 -12
  168. package/dist/molecules/Dropdown.svelte +9 -1
  169. package/dist/molecules/Dropdown.svelte.d.ts +2 -0
  170. package/dist/molecules/DropdownItem.svelte +1 -1
  171. package/dist/molecules/ImageUpload.svelte +230 -120
  172. package/dist/molecules/ImageUpload.svelte.d.ts +38 -3
  173. package/dist/molecules/LineChart.svelte +459 -0
  174. package/dist/molecules/LineChart.svelte.d.ts +53 -0
  175. package/dist/molecules/MapView.svelte +565 -0
  176. package/dist/molecules/MapView.svelte.d.ts +88 -0
  177. package/dist/molecules/Modal.svelte +11 -6
  178. package/dist/molecules/PhotoGrid.svelte +100 -10
  179. package/dist/molecules/PhotoGrid.svelte.d.ts +11 -0
  180. package/dist/molecules/PhotoViewer.svelte +121 -24
  181. package/dist/molecules/PhotoViewer.svelte.d.ts +18 -0
  182. package/dist/molecules/PieChart.svelte +421 -0
  183. package/dist/molecules/PieChart.svelte.d.ts +51 -0
  184. package/dist/molecules/RadioGroup.svelte +20 -4
  185. package/dist/molecules/RadioGroup.svelte.d.ts +5 -0
  186. package/dist/molecules/SegmentedControl.svelte +136 -3
  187. package/dist/molecules/SegmentedControl.svelte.d.ts +6 -0
  188. package/dist/molecules/SidebarFooter.svelte +1 -1
  189. package/dist/molecules/SidebarNavSection.svelte +1 -1
  190. package/dist/molecules/SortableList.svelte +1 -0
  191. package/dist/molecules/Stepper.svelte +21 -7
  192. package/dist/molecules/StickyActionBar.svelte +67 -8
  193. package/dist/molecules/StickyActionBar.svelte.d.ts +14 -1
  194. package/dist/molecules/Tabs.svelte +79 -2
  195. package/dist/molecules/Toaster.svelte +171 -7
  196. package/dist/molecules/Toaster.svelte.d.ts +60 -2
  197. package/dist/molecules/ToasterToast.svelte +292 -60
  198. package/dist/molecules/ToasterToast.svelte.d.ts +6 -0
  199. package/dist/molecules/UnsavedChangesBar.svelte +13 -2
  200. package/dist/molecules/index.d.ts +7 -2
  201. package/dist/molecules/index.js +4 -0
  202. package/dist/molecules/toast-store.d.ts +30 -0
  203. package/dist/molecules/toast-store.js +4 -1
  204. package/dist/organisms/AppNavigation.svelte +440 -0
  205. package/dist/organisms/AppNavigation.svelte.d.ts +72 -0
  206. package/dist/organisms/AppShell.svelte +539 -39
  207. package/dist/organisms/AppShell.svelte.d.ts +102 -6
  208. package/dist/organisms/AppShellHeaderPart.svelte +163 -0
  209. package/dist/organisms/AppShellHeaderPart.svelte.d.ts +57 -0
  210. package/dist/organisms/SidebarNavigation.svelte +23 -36
  211. package/dist/organisms/SidebarPanel.svelte +10 -14
  212. package/dist/organisms/SidebarPanel.svelte.d.ts +1 -0
  213. package/dist/organisms/SidebarShell.svelte +2 -3
  214. package/dist/organisms/TopNavbar.svelte +117 -28
  215. package/dist/organisms/TopNavbar.svelte.d.ts +22 -1
  216. package/dist/organisms/TopNavbarSheetContent.svelte +145 -0
  217. package/dist/organisms/TopNavbarSheetContent.svelte.d.ts +24 -0
  218. package/dist/organisms/index.d.ts +6 -1
  219. package/dist/organisms/index.js +4 -0
  220. package/dist/types/components.d.ts +17 -1
  221. package/dist/types/components.d.ts.map +1 -1
  222. package/dist/types/index.d.ts +497 -10
  223. package/dist/types/index.d.ts.map +1 -1
  224. package/dist/types/variants.ts +14 -3
  225. package/dist/util/app-shell.d.ts +55 -4
  226. package/dist/util/app-shell.js +32 -7
  227. package/dist/util/avatar.d.ts +3 -0
  228. package/dist/util/bottom-tab-bar.d.ts +6 -0
  229. package/dist/util/chart.d.ts +139 -0
  230. package/dist/util/chart.js +305 -0
  231. package/dist/util/chip.d.ts +65 -0
  232. package/dist/util/chip.js +58 -0
  233. package/dist/util/cn.js +28 -2
  234. package/dist/util/code-field.d.ts +62 -0
  235. package/dist/util/code-field.js +112 -0
  236. package/dist/util/collapsible.d.ts +6 -0
  237. package/dist/util/display-voice.d.ts +9 -0
  238. package/dist/util/display-voice.js +9 -0
  239. package/dist/util/field-control.d.ts +29 -0
  240. package/dist/util/field-control.js +32 -0
  241. package/dist/util/field.d.ts +6 -0
  242. package/dist/util/focus-utils.d.ts +2 -0
  243. package/dist/util/focus-utils.js +4 -0
  244. package/dist/util/map-view.d.ts +143 -0
  245. package/dist/util/map-view.js +121 -0
  246. package/dist/util/photo.d.ts +19 -0
  247. package/dist/util/photo.js +3 -0
  248. package/dist/util/progress.d.ts +18 -0
  249. package/dist/util/progress.js +17 -0
  250. package/dist/util/scroll-edge.d.ts +32 -0
  251. package/dist/util/scroll-edge.js +87 -0
  252. package/dist/util/sheet-drag.d.ts +25 -1
  253. package/dist/util/sheet-drag.js +71 -1
  254. package/dist/util/skeleton.d.ts +14 -0
  255. package/dist/util/skeleton.js +22 -0
  256. package/dist/util/sliding-indicator.d.ts +24 -0
  257. package/dist/util/sliding-indicator.js +44 -0
  258. package/dist/util/temporal-field.d.ts +88 -0
  259. package/dist/util/temporal-field.js +136 -0
  260. package/dist/util/toaster.d.ts +40 -0
  261. package/dist/util/toaster.js +55 -0
  262. package/dist/util/tone-surface.d.ts +33 -0
  263. package/dist/util/tone-surface.js +35 -0
  264. package/dist/util/top-navbar.d.ts +26 -2
  265. package/dist/util/top-navbar.js +23 -0
  266. package/dist/util/zabi-strings.d.ts +9 -0
  267. package/dist/zabi-components-colors.css +9 -3
  268. package/dist/zabi-components-theme-dark-only.css +474 -164
  269. package/dist/zabi-components-theme-dark.css +474 -164
  270. package/dist/zabi-components-theme-only.css +933 -99
  271. package/dist/zabi-components-theme.css +933 -99
  272. package/dist/zabi-components.css +2275 -321
  273. package/package.json +11 -1
@@ -29,14 +29,18 @@
29
29
  --zabi-base-900: #18181b;
30
30
  --zabi-base-925: #101013;
31
31
  --zabi-base-950: #09090b;
32
- /* Typography - Nunito Sans font family */
33
- --font-family-sans: 'Nunito Sans', ui-sans-serif, system-ui, sans-serif;
32
+ /* Typography - the platform UI face, no font is downloaded */
33
+ --font-family-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
34
34
  /* Headings follow the body face until an app sets this to a display font
35
35
  * on :root. Applied to h1–h6 in the base layer below and by the Heading
36
36
  * component. */
37
37
  --font-family-heading: var(--font-family-sans);
38
- /* Code. The stack CodeBlock has always used, now a token. */
39
- --font-family-mono: "Monaco", "Menlo", "Ubuntu Mono", monospace;
38
+ /* A second face for a display line (Heading variant="display", `font-display`):
39
+ * a hero, a score, a big number. Follows the heading face until an app sets
40
+ * it, so a second typeface is one token and not a CSS rule. */
41
+ --font-family-display: var(--font-family-heading);
42
+ /* Code. CodeBlock reads it. */
43
+ --font-family-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
40
44
  /* Tailwind's own names for the same three faces. Its `font-sans` and
41
45
  * `font-mono` utilities read --font-sans and --font-mono, which were its
42
46
  * system stacks: `class="font-sans"` on a heading left the brand face, and
@@ -46,6 +50,7 @@
46
50
  --font-sans: var(--font-family-sans);
47
51
  --font-mono: var(--font-family-mono);
48
52
  --font-heading: var(--font-family-heading);
53
+ --font-display: var(--font-family-display);
49
54
  /* Font weights. These are the variables Tailwind's `font-normal`,
50
55
  * `font-medium`, `font-semibold` and `font-bold` read, so every component
51
56
  * weight follows an override here. `regular` is the name a brand uses for
@@ -79,17 +84,17 @@
79
84
  --color-brand-900: var(--zabi-brand-900);
80
85
  --color-brand-950: var(--zabi-brand-950);
81
86
  /* Citron Color Scale — physical ramp + semantic aliases (same mirror pattern as pine / base) */
82
- --zabi-citron-50: #f6f7ef;
83
- --zabi-citron-100: #edefdf;
84
- --zabi-citron-200: #dcdfbf;
85
- --zabi-citron-300: #c5ca95;
86
- --zabi-citron-400: #aab063;
87
- --zabi-citron-500: #8c9027;
88
- --zabi-citron-600: #707400;
89
- --zabi-citron-700: #5a5d00;
90
- --zabi-citron-800: #454700;
91
- --zabi-citron-900: #313200;
92
- --zabi-citron-950: #202100;
87
+ --zabi-citron-50: #f4f8ee;
88
+ --zabi-citron-100: #e9f0de;
89
+ --zabi-citron-200: #d4e2bd;
90
+ --zabi-citron-300: #b9ce92;
91
+ --zabi-citron-400: #99b55e;
92
+ --zabi-citron-500: #769619;
93
+ --zabi-citron-600: #5d7900;
94
+ --zabi-citron-700: #4a6100;
95
+ --zabi-citron-800: #384a00;
96
+ --zabi-citron-900: #273500;
97
+ --zabi-citron-950: #192300;
93
98
  --color-citron-50: var(--zabi-citron-50);
94
99
  --color-citron-100: var(--zabi-citron-100);
95
100
  --color-citron-200: var(--zabi-citron-200);
@@ -127,17 +132,17 @@
127
132
  --color-accent-900: var(--zabi-accent-900);
128
133
  --color-accent-950: var(--zabi-accent-950);
129
134
  /* Pine Color Scale — physical ramp + semantic aliases (mirror pattern matches --zabi-base-* / --color-base-*) */
130
- --zabi-pine-50: #f0f8f5;
131
- --zabi-pine-100: #e2f1eb;
132
- --zabi-pine-200: #c5e4d7;
133
- --zabi-pine-300: #9fd1bd;
134
- --zabi-pine-400: #70ba9e;
135
- --zabi-pine-500: #399c7a;
136
- --zabi-pine-600: #00805e;
137
- --zabi-pine-700: #00674a;
138
- --zabi-pine-800: #004f37;
139
- --zabi-pine-900: #003826;
140
- --zabi-pine-950: #002518;
135
+ --zabi-pine-50: #f0f9f3;
136
+ --zabi-pine-100: #e1f2e8;
137
+ --zabi-pine-200: #c3e5d0;
138
+ --zabi-pine-300: #9cd3b2;
139
+ --zabi-pine-400: #6cbb8e;
140
+ --zabi-pine-500: #319e67;
141
+ --zabi-pine-600: #00804b;
142
+ --zabi-pine-700: #00683b;
143
+ --zabi-pine-800: #00502b;
144
+ --zabi-pine-900: #00391c;
145
+ --zabi-pine-950: #002610;
141
146
  --color-pine-50: var(--zabi-pine-50);
142
147
  --color-pine-100: var(--zabi-pine-100);
143
148
  --color-pine-200: var(--zabi-pine-200);
@@ -173,17 +178,17 @@
173
178
  --color-iris-900: var(--zabi-iris-900);
174
179
  --color-iris-950: var(--zabi-iris-950);
175
180
  /* Warning Color Scale — physical ramp + semantic aliases (Tailwind amber) */
176
- --zabi-warning-50: #fbf6ed;
177
- --zabi-warning-100: #f7ecda;
178
- --zabi-warning-200: #f1d9b6;
179
- --zabi-warning-300: #e8bf87;
180
- --zabi-warning-400: #db9e4c;
181
- --zabi-warning-500: #c17b00;
182
- --zabi-warning-600: #9e6000;
183
- --zabi-warning-700: #824c00;
181
+ --zabi-warning-50: #fdf5ec;
182
+ --zabi-warning-100: #fbebda;
183
+ --zabi-warning-200: #f6d7b4;
184
+ --zabi-warning-300: #efbc84;
185
+ --zabi-warning-400: #e49a44;
186
+ --zabi-warning-500: #c67800;
187
+ --zabi-warning-600: #a05f00;
188
+ --zabi-warning-700: #834b00;
184
189
  --zabi-warning-800: #663800;
185
- --zabi-warning-900: #4b2600;
186
- --zabi-warning-950: #341800;
190
+ --zabi-warning-900: #4b2700;
191
+ --zabi-warning-950: #331800;
187
192
  --color-warning-50: var(--zabi-warning-50);
188
193
  --color-warning-100: var(--zabi-warning-100);
189
194
  --color-warning-200: var(--zabi-warning-200);
@@ -246,17 +251,33 @@
246
251
  * overlay: modals, sheets, menus, popovers, toasts. Light mode keeps white surfaces + shadows;
247
252
  * dark mode (see .dark) steps each level up in OKLCH lightness because shadows don't read on dark.
248
253
  *
249
- * Light cannot go lighter than white, so its ladder runs the other way below
250
- * the card: page (base-150) → elevated (base-100) → raised and overlay (white).
251
- * Each grey sits a visible step from its neighbour; the page used to be
252
- * base-100 with elevated at base-50, which left 1.04:1 between a card and the
253
- * card nested in it. Enforced by scripts/check-surface-elevation.js.
254
+ * Light cannot go lighter than white, so the page is a near-white (base-50)
255
+ * and the card, white, is told apart from it by its 1px --color-border edge,
256
+ * not by lightness or a shadow. Nested surfaces step down from the card:
257
+ * elevated and inset (base-100). Enforced by scripts/check-surface-elevation.js:
258
+ * raised and overlay no darker than the page, elevated and inset at least 2
259
+ * points below raised, and the card edge at least 1.2:1 on the page and the card.
260
+ * (Until 8.1 the page was base-150 and the card carried a shadow.)
254
261
  * Keep this block BELOW the "Background Colors" marker: scripts/sync-theme-tokens.js regenerates
255
262
  * everything between the base-scale aliases and that marker. */
256
- --color-surface-base: var(--color-base-150);
263
+ --color-surface-base: var(--color-base-50);
257
264
  --color-surface-raised: #ffffff;
258
265
  --color-surface-elevated: var(--color-base-100);
259
266
  --color-surface-overlay: #ffffff;
267
+ /* Chrome — the surface of bars and sidebars (AppBar, TopNavbar, BottomTabBar,
268
+ * the sidebars). One token so a theme can retint all of them at once. Equal to
269
+ * the page colour in both themes (D108): a bar is flush with the page at
270
+ * rest and takes the material over it once content scrolls under it. Point it
271
+ * at --color-surface-raised for a raised bar fill. */
272
+ --color-surface-chrome: var(--color-surface-base);
273
+ /* Bars (D124), read by .material-bar. The fill at rest, the hairline shown
274
+ * once content is under the bar (decorative, not a guarded edge: the same
275
+ * idea as the material rim), the fill of an on-brand AppBar, and the active
276
+ * tab's pill in the BottomTabBar. */
277
+ --color-bar: var(--color-surface-chrome);
278
+ --color-bar-border: color-mix(in srgb, var(--color-headline) 10%, transparent);
279
+ --color-bar-brand: var(--color-action-primary);
280
+ --color-tabbar-active: var(--color-nav-menu-active);
260
281
  /* Inset — a recessed area ON a raised surface (a well, a code sample, a stat
261
282
  * strip inside a card). It is the ramp step between the page and the raised
262
283
  * surface in both themes, so it always reads as cut into the card, never as
@@ -270,18 +291,31 @@
270
291
  * card still has an outline where its shadow is thinnest; a solid step in dark. */
271
292
  --color-border-overlay: rgba(9, 9, 11, 0.1);
272
293
  --color-background: var(--color-surface-base);
273
- --color-background-secondary: var(--color-base-50);
294
+ --color-background-secondary: var(--color-base-100);
295
+ /* was base-50, which is now the page itself */
274
296
  --color-background-tertiary: var(--color-base-150);
275
297
  /* Page Colors */
276
- --color-page: var(--color-base-150);
298
+ --color-page: var(--color-surface-base);
277
299
  --color-page-secondary: var(--color-base-200);
278
300
  /* Card Colors — aliases of the surface levels (kept for compatibility) */
279
301
  --color-card: var(--color-surface-raised);
280
- /* Hover stays one step off the white card and is no longer the page colour
281
- * (a hovered card used to turn exactly into the page). Active goes one further. */
282
- --color-card-hover: var(--color-base-100);
283
- --color-card-active: var(--color-base-150);
302
+ /* Hover must not read as the page: the page is base-50 now, so base-100 was
303
+ * only ΔE 2.1 from it (the guard wants 2.5). Hover is base-150 (1.18:1 on the
304
+ * white card, ΔE 4.6 from the page), active one step further. */
305
+ --color-card-hover: var(--color-base-150);
306
+ --color-card-active: var(--color-base-200);
284
307
  --color-card-elevated: var(--color-surface-overlay);
308
+ /* Card tint — the brand tint as a surface for content (Card tone="tint"): the
309
+ * subtle fill's own step (brand-100), as its own token so an app can move one
310
+ * and not the other. Headline, body, label, description, caption and link
311
+ * hold 4.5:1 on it, and the ring, the field edge and the outline Button's
312
+ * edge 3:1 (a form can sit on it): 15.30, 12.87, 9.02, 6.68, 5.29 and 5.84:1;
313
+ * ring 4.19, field edge 4.17. */
314
+ --color-card-tint: var(--color-brand-100);
315
+ /* Card variant="flat": today's flat fill (the card), opaque. Dark restates it as a translucent step. */
316
+ --color-card-flat: var(--color-card);
317
+ --color-card-flat-hover: var(--color-card-hover);
318
+ --color-card-flat-active: var(--color-card-active);
285
319
  /* Surfaces — numbered aliases (kept for compatibility; prefer surface-base/raised/elevated/overlay) */
286
320
  --color-surface-1: var(--color-surface-raised);
287
321
  --color-surface-2: var(--color-surface-elevated);
@@ -293,10 +327,33 @@
293
327
  --color-control-track: var(--color-base-400);
294
328
  --color-control-track-hover: var(--color-base-450);
295
329
  --color-control-track-active: var(--color-base-500);
330
+ /* Toggle track — the off switch. The shared control track above is a mid
331
+ * grey (base-400) that reads as disabled, so the switch has its own: a light
332
+ * tint, with its edge doing the 3:1 work (WCAG 1.4.11), which a fill this
333
+ * light cannot. The edge is the field edge, 4.63:1 on the page and 4.83:1 on
334
+ * a card. Slider and Progress keep the shared track. */
335
+ --color-toggle-track: var(--color-base-200);
336
+ --color-toggle-track-hover: var(--color-base-250);
337
+ --color-toggle-track-active: var(--color-base-300);
338
+ --color-toggle-track-border: var(--color-input-border);
339
+ /* Toggle knob, by default 3:1 or more on every track fill it sits on (WCAG
340
+ * 1.4.11). Off, a dark knob on the light track: base-500 is 3.81:1 on the
341
+ * resting track, 3.53:1 hovered and 3.27:1 pressed. On, the label colour of
342
+ * the primary fill: 4.86:1 at rest, 6.76:1 hovered and 9.44:1 pressed. The consumer's
343
+ * own `--color-toggle-thumb` and `--color-toggle-thumb-checked` (declared
344
+ * nowhere) come first; see `.bg-toggle-thumb`. */
345
+ --color-toggle-knob: var(--color-base-500);
346
+ --color-toggle-knob-checked: var(--color-action-primary-text);
296
347
  /* Progress — the bar of Progress. The fill is the primary action, so it
297
348
  * follows a pinned primary; the track is the field fill it always was. */
298
349
  --color-progress-fill: var(--color-action-primary);
299
350
  --color-progress-track: var(--color-input);
351
+ /* The edge of the track. The default track is the field fill (white on the
352
+ * white card), 1.00:1 on the card and 1.04:1 on the page, so its edge is the
353
+ * field edge, 3:1 on both (the guard holds it). An app whose own track
354
+ * already reaches 3:1 sets this to `transparent`; createTheme does that when
355
+ * it overrides the track. */
356
+ --color-progress-track-border: var(--color-input-border);
300
357
  /* Interaction fills — surface-relative on purpose.
301
358
  * A hard-coded ramp step (e.g. base-100) can coincide exactly with the
302
359
  * surface it sits on, which is how ghost hover became invisible: in dark
@@ -318,19 +375,31 @@
318
375
  * border, not by greying the fill; dark keeps its fill step and leaves this
319
376
  * equal to the resting border. One step past the resting edge. */
320
377
  --color-input-border-hover: var(--color-base-550);
321
- /* One step off white. It was base-150, which is now the page itself, and was
322
- * already greyer than the disabled fill. */
378
+ /* One step off white, and the same step the card hover uses. */
323
379
  --color-input-hover: var(--color-base-100);
324
380
  /* Pressed, for a field that is pressed rather than typed in: the Select
325
381
  * trigger. It borrowed the hover step, 1.10:1 against the resting field,
326
- * when every other pressed fill is 1.26:1 or more. base-200 is 1.27:1 on the
327
- * white field and a visible step past hover (1.15:1); body text is 11.7:1
328
- * on it. */
329
- --color-input-active: var(--color-base-200);
382
+ * when every other pressed fill is 1.26:1 or more. Derived from the field,
383
+ * not a fixed ramp step: an app that sets the card (and so the field) to
384
+ * another colour through createTheme overrides would otherwise land its
385
+ * field on top of a fixed step (base-200 was 1.21:1 against a base-50 field
386
+ * of #f8faff, below the 1.25 the generator holds). 12% of the ink into the
387
+ * field is the smallest whole percent that keeps the three pairs: 1.25:1
388
+ * against the field (11% is the floor), body and placeholder 4.5:1 on it.
389
+ * Default theme: #e3e3e4 (was #e4e4e7); on a #f8faff field with the
390
+ * ink at 12%: 1.28:1 against it. */
391
+ --color-input-active: color-mix(in srgb, var(--zabi-base-900) 12%, var(--color-input));
330
392
  --color-input-focus: var(--color-surface-raised);
331
- /* The page colour: a disabled field stops being a raised surface. Dark does
332
- * the same (base-100 is the dark page). */
333
- --color-input-disabled: var(--color-surface-base);
393
+ /* The only grey field. It was the page colour; the page is now near white
394
+ * (1.04:1 against the white field), so it takes base-150, 1.18:1 on the field
395
+ * as before. Dark still uses the dark page (base-100). */
396
+ --color-input-disabled: var(--color-base-150);
397
+ /* Light fields are opaque already: inside a colour block they stay as they are. The dark
398
+ * theme restates these as opaque steps (see there). */
399
+ --color-input-solid: var(--color-input);
400
+ --color-input-solid-hover: var(--color-input-hover);
401
+ --color-input-solid-focus: var(--color-input-focus);
402
+ --color-input-solid-active: var(--color-input-active);
334
403
  /* Text Colors */
335
404
  --color-headline: var(--color-base-900);
336
405
  --color-body: var(--color-base-800);
@@ -380,6 +449,14 @@
380
449
  * elevated surface and 1.98:1 on the dark overlay. .dark pins this one step
381
450
  * lighter for that reason. */
382
451
  --color-control-border: var(--color-base-500);
452
+ /* Segmented control thumb (tone neutral): the selected segment, a card-coloured
453
+ * piece on the tinted track. The edge is what identifies it (WCAG 1.4.11), as
454
+ * the 1.1:1 fill step alone would not. It is the control boundary, which dark
455
+ * lifts a step (base-600) because the input edge is only 2.4:1 on this track; it is held to 3:1 against the track
456
+ * over the page and over a card (scripts/contrast-pairs.js). */
457
+ --color-segment-thumb: var(--color-surface-raised);
458
+ --color-segment-thumb-text: var(--color-headline);
459
+ --color-segment-thumb-border: var(--color-control-border);
383
460
  /* Focus Colors
384
461
  * brand-600, not brand-500: a focus indicator needs 3:1 against what is
385
462
  * around it, and brand-500 was 2.99:1 on the page. brand-600 is also the
@@ -424,8 +501,8 @@
424
501
  * <family>-weak step 700 pressed / emphasis
425
502
  * <family>-medium step 800 strongest fill
426
503
  * <family>-strong step 900 darkest
427
- * <family>-subtle step 200 tinted fill (badges, alerts); .dark pins step 100
428
- * <family>-border step 300 tinted edge; .dark pins step 200
504
+ * <family>-subtle step 100 tinted fill (badges, alerts); .dark restates step 100
505
+ * <family>-border step 200 tinted edge; .dark restates step 200
429
506
  * <family>-text step 700 text on a subtle fill or a page surface
430
507
  *
431
508
  * Warning, error and energetic previously sat at step 500 — the mirror's
@@ -438,29 +515,29 @@
438
515
  --color-success-weak: var(--color-pine-700);
439
516
  --color-success-medium: var(--color-pine-800);
440
517
  --color-success-strong: var(--color-pine-900);
441
- --color-success-subtle: var(--color-pine-200);
442
- --color-success-border: var(--color-pine-300);
518
+ --color-success-subtle: var(--color-pine-100);
519
+ --color-success-border: var(--color-pine-200);
443
520
  /* Warning Colors */
444
521
  --color-warning: var(--color-warning-600);
445
522
  --color-warning-weak: var(--color-warning-700);
446
523
  --color-warning-medium: var(--color-warning-800);
447
524
  --color-warning-strong: var(--color-warning-900);
448
- --color-warning-subtle: var(--color-warning-200);
449
- --color-warning-border: var(--color-warning-300);
525
+ --color-warning-subtle: var(--color-warning-100);
526
+ --color-warning-border: var(--color-warning-200);
450
527
  /* Error Colors */
451
528
  --color-error: var(--color-error-600);
452
529
  --color-error-weak: var(--color-error-700);
453
530
  --color-error-medium: var(--color-error-800);
454
531
  --color-error-strong: var(--color-error-900);
455
- --color-error-subtle: var(--color-error-200);
456
- --color-error-border: var(--color-error-300);
532
+ --color-error-subtle: var(--color-error-100);
533
+ --color-error-border: var(--color-error-200);
457
534
  /* Energetic Colors (Citron) */
458
535
  --color-energetic: var(--color-citron-600);
459
536
  --color-energetic-weak: var(--color-citron-700);
460
537
  --color-energetic-medium: var(--color-citron-800);
461
538
  --color-energetic-strong: var(--color-citron-900);
462
- --color-energetic-subtle: var(--color-citron-200);
463
- --color-energetic-border: var(--color-citron-300);
539
+ --color-energetic-subtle: var(--color-citron-100);
540
+ --color-energetic-border: var(--color-citron-200);
464
541
  /* Accent Colors — the second brand colour, on --zabi-accent-* (citron by
465
542
  * default). The same recipe as the primary action: fill at 600, hover 700,
466
543
  * active 800, so "more pressed" is "more contrast" in both themes; tint,
@@ -469,8 +546,8 @@
469
546
  --color-accent: var(--color-accent-600);
470
547
  --color-accent-hover: var(--color-accent-700);
471
548
  --color-accent-active: var(--color-accent-800);
472
- --color-accent-subtle: var(--color-accent-200);
473
- --color-accent-border: var(--color-accent-300);
549
+ --color-accent-subtle: var(--color-accent-100);
550
+ --color-accent-border: var(--color-accent-200);
474
551
  --color-accent-text: var(--color-accent-700);
475
552
  /* Label on a solid accent fill — see "on brand" below for the two knobs. */
476
553
  --zabi-on-accent: #ffffff;
@@ -486,20 +563,20 @@
486
563
  --color-neutral-weak: var(--color-base-600);
487
564
  --color-neutral-medium: var(--color-base-700);
488
565
  --color-neutral-strong: var(--color-base-900);
489
- /* One visible step past the page (base-150) and two past a card. It was
566
+ /* Visibly past the page (base-50, 1.20:1) and the card (1.27:1). It was
490
567
  * base-100 once, which IS the dark page and made a neutral badge measure
491
- * 1.00:1 and read as bare text. The border is a step darker than the fill,
492
- * like every other family. */
493
- --color-neutral-subtle: var(--color-base-250);
494
- --color-neutral-border: var(--color-base-300);
568
+ * 1.00:1 and read as bare text; base-150 is only 1.13:1 on the page. The
569
+ * border is a step darker than the fill, like every other family. */
570
+ --color-neutral-subtle: var(--color-base-200);
571
+ --color-neutral-border: var(--color-base-250);
495
572
  /* Info Colors */
496
573
  --color-info: var(--color-iris-600);
497
574
  --color-info-weak: var(--color-iris-700);
498
575
  --color-info-medium: var(--color-iris-800);
499
576
  --color-info-strong: var(--color-iris-900);
500
577
  --color-info-active: var(--color-iris-400);
501
- --color-info-subtle: var(--color-iris-200);
502
- --color-info-border: var(--color-iris-300);
578
+ --color-info-subtle: var(--color-iris-100);
579
+ --color-info-border: var(--color-iris-200);
503
580
  /* Text alias */
504
581
  --color-info-text: var(--color-iris-700);
505
582
  /* ========================================
@@ -517,27 +594,32 @@
517
594
  --color-action-primary: var(--color-brand-600);
518
595
  --color-action-primary-hover: var(--color-brand-700);
519
596
  --color-action-primary-active: var(--color-brand-800);
520
- --color-action-primary-subtle: var(--color-brand-200);
521
- --color-action-primary-subtle-hover: var(--color-brand-300);
597
+ --color-action-primary-subtle: var(--color-brand-100);
598
+ --color-action-primary-subtle-hover: var(--color-brand-200);
599
+ /* Edge of a subtle brand badge when `bordered`; the tint's own darker step. */
600
+ --color-action-primary-border: var(--color-brand-200);
522
601
  /* Held down, on a control whose resting fill is the subtle one: a toggled-on
523
602
  * ghost IconButton. It used the hover step, which is 1.24:1 against the
524
603
  * resting fill and, with a mouse, is what the button already shows. Half a
525
604
  * step past hover is 1.42:1 against resting, and the icon (--color-link)
526
605
  * keeps 3.50:1 on it; a whole step would leave the icon at 3.01:1. */
527
- --color-action-primary-subtle-active: color-mix(in srgb, var(--color-brand-400) 50%, var(--color-brand-300));
606
+ --color-action-primary-subtle-active: color-mix(in srgb, var(--color-brand-300) 50%, var(--color-brand-200));
528
607
  /* "On brand" — the label on a primary fill.
529
608
  * White rather than brand-50: the ramp's lightest tint lands at exactly
530
609
  * 4.50:1 on brand-600 — passing, but with no margin. Pure white gives 4.86:1.
531
- * Dark uses the dark end of the ramp on the light fill (7.21:1).
610
+ * Dark has the same fill (step 600, physical) and the same label: white on
611
+ * it is 4.76:1 on any ramp, since every ramp is on one lightness curve.
532
612
  *
533
613
  * A light brand (amber, yellow) cannot carry white text, so both values are
534
614
  * knobs an app sets once on :root, like the ramps:
535
615
  * --zabi-on-brand label in light mode
536
- * --zabi-on-brand-dark label in dark mode
616
+ * --zabi-on-brand-dark label in dark mode: follows the light label (white),
617
+ * since the dark fill is the same step; set it to a dark
618
+ * one for a pale dark primary
537
619
  * --color-on-brand is the role, remapped by .dark; components keep using
538
620
  * --color-action-primary-text, which follows it. */
539
621
  --zabi-on-brand: #ffffff;
540
- --zabi-on-brand-dark: var(--zabi-brand-950);
622
+ --zabi-on-brand-dark: var(--zabi-on-brand);
541
623
  --color-on-brand: var(--zabi-on-brand);
542
624
  --color-action-primary-text: var(--color-on-brand);
543
625
  /* Secondary Actions - Used by bg-action-secondary utility class
@@ -550,6 +632,40 @@
550
632
  --color-action-secondary-subtle: var(--color-base-100);
551
633
  --color-action-secondary-subtle-hover: var(--color-base-200);
552
634
  --color-action-secondary-text: var(--color-headline);
635
+ /* Tonal Actions - Used by bg-action-tonal utility class.
636
+ * A brand-tinted fill with the brand as its label: the quieter action beside
637
+ * a primary, and a chosen answer. It is the subtle tint (brand-100) and its
638
+ * own hover (brand-200) and pressed steps (halfway to brand-300, like the
639
+ * toggled-on ghost button; 1.30:1 against the resting fill). The label is
640
+ * brand-800, the lightest step that holds 4.5:1 on all three fills for any
641
+ * brand, not only the default: step 700 does on the default brand (5.84,
642
+ * 4.97, 4.48:1) but fails the pressed fill by 0.02, and by more on a
643
+ * saturated blue (4.39:1 for #0026EA). 800 gives 8.15, 6.94 and 6.25:1. */
644
+ --color-action-tonal: var(--color-action-primary-subtle);
645
+ --color-action-tonal-hover: var(--color-action-primary-subtle-hover);
646
+ --color-action-tonal-active: color-mix(in srgb, var(--color-brand-300) 50%, var(--color-brand-200));
647
+ --color-action-tonal-text: var(--color-brand-800);
648
+ /* Chip - the filter and choice pill (Chip). At rest a quiet neutral fill that
649
+ * shows on the page and on a card without an edge: base-200 is 1.22:1 on the
650
+ * page and 1.27:1 on the card, hover base-300 and pressed base-350 (1.42 and
651
+ * 1.85 on the page). The label is the headline, 4.5:1 or more on all three
652
+ * (13.96, 11.99 and 9.18:1). */
653
+ --color-chip: var(--color-base-200);
654
+ --color-chip-hover: var(--color-base-300);
655
+ --color-chip-active: var(--color-base-350);
656
+ --color-chip-text: var(--color-headline);
657
+ /* A selected chip is tonal, in both modes (never solid): its own tokens,
658
+ * pointing at the tonal role, so an app that themes tonal gets matching chips
659
+ * and one that wants another selected look sets these. */
660
+ --color-chip-selected: var(--color-action-tonal);
661
+ --color-chip-selected-hover: var(--color-action-tonal-hover);
662
+ --color-chip-selected-active: var(--color-action-tonal-active);
663
+ --color-chip-selected-text: var(--color-action-tonal-text);
664
+ /* Outline Actions - the edge of an outline Button. The border role was the
665
+ * card edge, 1.25:1 on the page: a label in a ghost box. This is the field
666
+ * edge (base-500), already held to 3:1 on the field, the page and a card. */
667
+ --color-action-outline-border: var(--color-input-border);
668
+ --color-action-outline-border-hover: var(--color-input-border-hover);
553
669
  /* Disabled Actions - shared by every variant.
554
670
  * Disabled must be the QUIETEST state, never a brighter colour than the
555
671
  * enabled secondary. It used to be brand-500 plus opacity-50, which made a
@@ -574,13 +690,128 @@
574
690
  --color-action-danger-text: var(--color-error-50);
575
691
  /* Shadow Colors
576
692
  * Light elevation is carried by the shadow, so it is the ramp's own ink
577
- * (base-900) at a strength that still reads on the top and side edges. */
693
+ * (base-900). Every step is two layers: a tight contact shadow
694
+ * (--shadow-opacity-contact) that grounds the edge and a wider, softer
695
+ * ambient one (--shadow-opacity) that carries the distance. Until 8.1 both
696
+ * layers shared one flat 14%; the 8.1 values are in CHANGELOG.md. */
578
697
  --shadow-color: 24 24 27;
579
- --shadow-opacity: 0.14;
580
- --shadow-sm: 0 1px 3px 0 rgb(var(--shadow-color) / var(--shadow-opacity)), 0 1px 2px -1px rgb(var(--shadow-color) / var(--shadow-opacity));
581
- --shadow-md: 0 4px 6px -1px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 2px 4px -2px rgb(var(--shadow-color) / var(--shadow-opacity));
582
- --shadow-lg: 0 10px 15px -3px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 4px 6px -4px rgb(var(--shadow-color) / var(--shadow-opacity));
583
- --shadow-xl: 0 20px 25px -5px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 8px 10px -6px rgb(var(--shadow-color) / var(--shadow-opacity));
698
+ --shadow-opacity: 0.1;
699
+ --shadow-opacity-contact: 0.06;
700
+ --shadow-sm: 0 1px 2px 0 rgb(var(--shadow-color) / var(--shadow-opacity-contact)), 0 2px 6px -1px rgb(var(--shadow-color) / var(--shadow-opacity));
701
+ --shadow-md: 0 1px 3px 0 rgb(var(--shadow-color) / var(--shadow-opacity-contact)), 0 6px 14px -2px rgb(var(--shadow-color) / var(--shadow-opacity));
702
+ --shadow-lg: 0 1px 2px 0 rgb(var(--shadow-color) / var(--shadow-opacity-contact)), 0 10px 30px 0 rgb(var(--shadow-color) / var(--shadow-opacity));
703
+ --shadow-xl: 0 2px 4px 0 rgb(var(--shadow-color) / var(--shadow-opacity-contact)), 0 20px 50px -8px rgb(var(--shadow-color) / var(--shadow-opacity));
704
+ /* What a material (glass) casts: the lg step. Its own name so a theme can
705
+ * retune glass without moving every floating surface. */
706
+ --shadow-material: 0 1px 2px 0 rgb(var(--shadow-color) / var(--shadow-opacity-contact)), 0 10px 30px 0 rgb(var(--shadow-color) / var(--shadow-opacity));
707
+ /* Motion
708
+ * Four durations and three curves. Tailwind's default transition reads
709
+ * --duration-base and --ease-standard, so every `transition-*` class that
710
+ * sets no duration of its own follows them (150ms, as before; the curve is
711
+ * new). `ease-standard`, `ease-out` and `ease-spring` are utilities;
712
+ * durations are used as `duration-(--duration-moderate)`. --ease-out is
713
+ * Tailwind's own name and value. --ease-spring is a lightly damped spring
714
+ * (one overshoot of about 5%, settled by the end): the cubic-bezier is the
715
+ * fallback, and the @supports block after @theme upgrades it to linear().
716
+ * prefers-reduced-motion re-points all of them (see @motion-reduced). */
717
+ --duration-fast: 100ms;
718
+ --duration-base: 150ms;
719
+ --duration-moderate: 200ms;
720
+ --duration-slow: 300ms;
721
+ --ease-standard: cubic-bezier(0.2, 0, 0, 1);
722
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
723
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
724
+ --default-transition-duration: var(--duration-base);
725
+ --default-transition-timing-function: var(--ease-standard);
726
+ /* Materials — the frosted layer for what floats over content (bars, sheets,
727
+ * menus). Used through .material-thin|regular|thick (below), never a raw
728
+ * backdrop-blur. A material is a surface at partial alpha, so it is judged
729
+ * over the worst backdrop of the mode, not alone: the alpha floors are
730
+ * enforced by scripts/check-contrast.js (see scripts/contrast-pairs.js,
731
+ * MATERIALS) and by createTheme for an app's own theme. Each alpha is the
732
+ * smallest whole 2% that passes every pair its level carries, plus a little
733
+ * margin (floors against the page-colour chrome: thin 50 / 30, regular 82 / 47,
734
+ * thick 84 / 68, light / dark; light thick has 4 points because a tinted neutral (neutralChroma 0.08) needs 87; dark is judged on the dimmed backdrop, below):
735
+ * thin headline (a control on a bar: an icon, a short label;
736
+ * its focus ring is drawn outside it)
737
+ * regular + body, label, focus ring (bars, the tab bar, a floating sidebar)
738
+ * thick + description, caption (sheets, menus, modals, toasts, tooltips)
739
+ * Dark's worst backdrop is near-white, which its surfaces are close to. The
740
+ * dark filter therefore also dims the backdrop (--material-backdrop-brightness,
741
+ * 0.6: brightness() multiplies the sRGB channels), so the brightest thing
742
+ * that can be behind dark glass is near-white times 0.6, and the guard measures
743
+ * that. It is true to the rendering because the dimming and the translucent
744
+ * fill are switched together: every fallback below drops the filter and makes
745
+ * the fill opaque. Light is brightness(1), an identity.
746
+ * The fallbacks (reduced transparency, more contrast, forced colors, no
747
+ * backdrop-filter, data-materials="opaque") are below the .dark rule. */
748
+ --material-alpha-thin: 58%;
749
+ --material-alpha-regular: 84%;
750
+ --material-alpha-thick: 88%;
751
+ --color-material-thin: color-mix(in srgb, var(--color-surface-chrome) var(--material-alpha-thin), transparent);
752
+ --color-material-regular: color-mix(in srgb, var(--color-surface-chrome) var(--material-alpha-regular), transparent);
753
+ --color-material-thick: color-mix(in srgb, var(--color-surface-overlay) var(--material-alpha-thick), transparent);
754
+ --material-blur-thin: 16px;
755
+ --material-blur-regular: 24px;
756
+ --material-blur-thick: 32px;
757
+ --material-saturate: 180%;
758
+ /* What the filter does to the backdrop's brightness (a number): 1 in light,
759
+ * where it is an identity; below 1 in dark, which dims what shows through the
760
+ * glass. The alpha floors are measured on the dimmed backdrop. */
761
+ --material-backdrop-brightness: 1;
762
+ --material-filter-thin: blur(var(--material-blur-thin)) saturate(var(--material-saturate)) brightness(var(--material-backdrop-brightness));
763
+ --material-filter-regular: blur(var(--material-blur-regular)) saturate(var(--material-saturate)) brightness(var(--material-backdrop-brightness));
764
+ --material-filter-thick: blur(var(--material-blur-thick)) saturate(var(--material-saturate)) brightness(var(--material-backdrop-brightness));
765
+ /* The light top edge and the 1px outline, from the neutral ramp so a
766
+ * neutral override tints them. */
767
+ --color-material-highlight: color-mix(in srgb, var(--zabi-base-50) 60%, transparent);
768
+ --color-material-rim: color-mix(in srgb, var(--zabi-base-900) 9%, transparent);
769
+ /* Gradients (D99). Contrast is never measured against a gradient: each one
770
+ * is built from named stops, and scripts/contrast-pairs.js holds the worst
771
+ * stop of each to the pairs that sit on it. The strengths are the strongest
772
+ * whole 5% (canvas) and whole percent (control veils) at which every pair
773
+ * passes, capped at the prototype (canvas 85 / 45, top veil 22, bottom 14).
774
+ * Light canvas 55 (caption and link on the wash), dark canvas 25 (field edge
775
+ * on the wash).
776
+ *
777
+ * Control veils, light: darken-only. The top is 0%, so the fill at the top
778
+ * is the control's own colour: the label keeps its full contrast and an
779
+ * app's brand colour is not altered. Lightening the top of the brand-600
780
+ * fill took the white label (about 4.6:1) under 4.5:1, which is why it was
781
+ * 4% before. The bottom is 14% of base-950, the strongest whole percent that
782
+ * passes every pair (the label only gains from a darker fill); it is the
783
+ * depth. Dark is the same darken-only veil (the fill is a mid step with a white
784
+ * label, as in light); only the accent, whose dark fill is light under a dark
785
+ * label, keeps the lighter top, 22 / 6, in its own strengths.
786
+ *
787
+ * Canvas: two soft radial washes from brand 300 and accent 300 for glass to
788
+ * show something. A background-image only; .bg-canvas adds the page colour.
789
+ * The library does not paint it on body. */
790
+ --gradient-canvas-strength: 55%;
791
+ --color-canvas-wash-brand: color-mix(in srgb, var(--color-brand-300) var(--gradient-canvas-strength), transparent);
792
+ --color-canvas-wash-accent: color-mix(in srgb, var(--color-accent-300) var(--gradient-canvas-strength), transparent);
793
+ --gradient-canvas:
794
+ radial-gradient(90% 46% at 8% 0%, var(--color-canvas-wash-brand), transparent 70%),
795
+ radial-gradient(80% 40% at 100% 4%, var(--color-canvas-wash-accent), transparent 70%);
796
+ /* Solid controls: a veil laid over the control's own background-color, so
797
+ * hover and pressed fills keep working. The start and end tokens are the veil
798
+ * colours (translucent neutral, from the ramp so a neutral override tints
799
+ * them): a light one on top, a slight dark one at the bottom. It serves the
800
+ * three solid fills: primary, accent and danger (the veil is neutral, so
801
+ * `bg-control-gradient` is the danger one too). The accent has strengths of
802
+ * its own, which follow the shared ones, so an app whose accent carries a
803
+ * dark label can differ (createTheme does that when the pairs need it). */
804
+ --gradient-control-top-strength: 0%;
805
+ --gradient-control-bottom-strength: 14%;
806
+ --gradient-control-accent-top-strength: var(--gradient-control-top-strength);
807
+ --gradient-control-accent-bottom-strength: var(--gradient-control-bottom-strength);
808
+ --color-control-gradient-start: color-mix(in srgb, var(--zabi-base-50) var(--gradient-control-top-strength), transparent);
809
+ --color-control-gradient-end: color-mix(in srgb, var(--zabi-base-950) var(--gradient-control-bottom-strength), transparent);
810
+ --gradient-control: linear-gradient(to bottom, var(--color-control-gradient-start), var(--color-control-gradient-end));
811
+ --color-control-gradient-accent-start: color-mix(in srgb, var(--zabi-base-50) var(--gradient-control-accent-top-strength), transparent);
812
+ --color-control-gradient-accent-end: color-mix(in srgb, var(--zabi-base-950) var(--gradient-control-accent-bottom-strength), transparent);
813
+ --gradient-control-accent: linear-gradient(to bottom, var(--color-control-gradient-accent-start), var(--color-control-gradient-accent-end));
814
+ --shadow-control-highlight: inset 0 1px 0 color-mix(in srgb, var(--zabi-base-50) 40%, transparent);
584
815
  /* Spacing */
585
816
  --spacing-xs: 0.25rem;
586
817
  --spacing-sm: 0.5rem;
@@ -691,6 +922,248 @@ body {
691
922
  color-scheme: light;
692
923
  }
693
924
 
925
+ @media (prefers-reduced-transparency: reduce), (prefers-contrast: more), (forced-colors: active) {
926
+ :root:root {
927
+ --color-material-thin: var(--color-surface-chrome);
928
+ --color-material-regular: var(--color-surface-chrome);
929
+ --color-material-thick: var(--color-surface-overlay);
930
+ --material-filter-thin: none;
931
+ --material-filter-regular: none;
932
+ --material-filter-thick: none;
933
+ }
934
+ }
935
+
936
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
937
+ :root:root {
938
+ --color-material-thin: var(--color-surface-chrome);
939
+ --color-material-regular: var(--color-surface-chrome);
940
+ --color-material-thick: var(--color-surface-overlay);
941
+ --material-filter-thin: none;
942
+ --material-filter-regular: none;
943
+ --material-filter-thick: none;
944
+ }
945
+ }
946
+
947
+ [data-materials="opaque"][data-materials="opaque"] {
948
+ --color-material-thin: var(--color-surface-chrome);
949
+ --color-material-regular: var(--color-surface-chrome);
950
+ --color-material-thick: var(--color-surface-overlay);
951
+ --material-filter-thin: none;
952
+ --material-filter-regular: none;
953
+ --material-filter-thick: none;
954
+ }
955
+
956
+ @supports (transition-timing-function: linear(0, 1)) {
957
+ :root {
958
+ --ease-spring: linear(0, 0.14, 0.409, 0.668, 0.859, 0.974, 1.029, 1.046, 1.041, 1.03, 1.017, 1.008, 1.002, 0.999, 0.998, 0.998, 1);
959
+ }
960
+ }
961
+
962
+ @media (prefers-reduced-motion: reduce) {
963
+ :root:root {
964
+ --duration-fast: 0s;
965
+ --duration-base: 0s;
966
+ --duration-moderate: 0s;
967
+ --duration-slow: 0s;
968
+ --ease-spring: var(--ease-standard);
969
+ }
970
+ }
971
+
972
+ .material-thin,
973
+ .material-regular,
974
+ .material-thick {
975
+ --tw-shadow:
976
+ inset 0 1px 0 var(--color-material-highlight),
977
+ inset 0 0 0 1px var(--color-material-rim),
978
+ var(--shadow-material);
979
+ box-shadow:
980
+ var(--tw-inset-shadow, 0 0 #0000),
981
+ var(--tw-inset-ring-shadow, 0 0 #0000),
982
+ var(--tw-ring-offset-shadow, 0 0 #0000),
983
+ var(--tw-ring-shadow, 0 0 #0000),
984
+ var(--tw-shadow);
985
+ }
986
+
987
+ .material-thin {
988
+ background-color: var(--color-material-thin);
989
+ -webkit-backdrop-filter: var(--material-filter-thin);
990
+ backdrop-filter: var(--material-filter-thin);
991
+ }
992
+
993
+ .material-regular {
994
+ background-color: var(--color-material-regular);
995
+ -webkit-backdrop-filter: var(--material-filter-regular);
996
+ backdrop-filter: var(--material-filter-regular);
997
+ }
998
+
999
+ .material-thick {
1000
+ background-color: var(--color-material-thick);
1001
+ -webkit-backdrop-filter: var(--material-filter-thick);
1002
+ backdrop-filter: var(--material-filter-thick);
1003
+ }
1004
+
1005
+ @media (forced-colors: active) {
1006
+ .material-thin,
1007
+ .material-regular,
1008
+ .material-thick {
1009
+ outline: 1px solid CanvasText;
1010
+ outline-offset: -1px;
1011
+ }
1012
+ }
1013
+
1014
+ .material-layer-thick {
1015
+ isolation: isolate;
1016
+ background-color: transparent;
1017
+ --tw-shadow: var(--shadow-material);
1018
+ box-shadow:
1019
+ var(--tw-inset-shadow, 0 0 #0000),
1020
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1021
+ var(--tw-ring-offset-shadow, 0 0 #0000),
1022
+ var(--tw-ring-shadow, 0 0 #0000),
1023
+ var(--tw-shadow);
1024
+ }
1025
+
1026
+ .material-layer-thick::before {
1027
+ content: "";
1028
+ position: absolute;
1029
+ inset: 0;
1030
+ z-index: -1;
1031
+ border-radius: inherit;
1032
+ pointer-events: none;
1033
+ background-color: var(--color-material-thick);
1034
+ -webkit-backdrop-filter: var(--material-filter-thick);
1035
+ backdrop-filter: var(--material-filter-thick);
1036
+ box-shadow:
1037
+ inset 0 1px 0 var(--color-material-highlight),
1038
+ inset 0 0 0 1px var(--color-material-rim);
1039
+ }
1040
+
1041
+ @media (forced-colors: active) {
1042
+ .material-layer-thick {
1043
+ outline: 1px solid CanvasText;
1044
+ outline-offset: -1px;
1045
+ }
1046
+ }
1047
+
1048
+ .material-layer-regular {
1049
+ isolation: isolate;
1050
+ background-color: transparent;
1051
+ --tw-shadow: var(--shadow-material);
1052
+ box-shadow:
1053
+ var(--tw-inset-shadow, 0 0 #0000),
1054
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1055
+ var(--tw-ring-offset-shadow, 0 0 #0000),
1056
+ var(--tw-ring-shadow, 0 0 #0000),
1057
+ var(--tw-shadow);
1058
+ }
1059
+
1060
+ .material-layer-regular::before {
1061
+ content: "";
1062
+ position: absolute;
1063
+ inset: 0;
1064
+ z-index: -1;
1065
+ border-radius: inherit;
1066
+ pointer-events: none;
1067
+ background-color: var(--color-material-regular);
1068
+ -webkit-backdrop-filter: var(--material-filter-regular);
1069
+ backdrop-filter: var(--material-filter-regular);
1070
+ box-shadow:
1071
+ inset 0 1px 0 var(--color-material-highlight),
1072
+ inset 0 0 0 1px var(--color-material-rim);
1073
+ }
1074
+
1075
+ @media (forced-colors: active) {
1076
+ .material-layer-regular {
1077
+ outline: 1px solid CanvasText;
1078
+ outline-offset: -1px;
1079
+ }
1080
+ }
1081
+
1082
+ .material-bar {
1083
+ isolation: isolate;
1084
+ background-color: transparent;
1085
+ }
1086
+
1087
+ .material-bar::before {
1088
+ content: "";
1089
+ position: absolute;
1090
+ inset: 0;
1091
+ z-index: -1;
1092
+ box-sizing: border-box;
1093
+ pointer-events: none;
1094
+ background-color: var(--color-bar);
1095
+ border: 0 solid transparent;
1096
+ border-bottom-width: 1px;
1097
+ transition-property: background-color, border-color;
1098
+ transition-duration: var(--duration-moderate);
1099
+ transition-timing-function: var(--ease-standard);
1100
+ }
1101
+
1102
+ .material-bar[data-bar-edge="bottom"]::before {
1103
+ border-bottom-width: 0;
1104
+ border-top-width: 1px;
1105
+ }
1106
+
1107
+ .material-bar[data-scrolled-under="true"]::before {
1108
+ background-color: var(--color-material-regular);
1109
+ -webkit-backdrop-filter: var(--material-filter-regular);
1110
+ backdrop-filter: var(--material-filter-regular);
1111
+ border-color: var(--color-bar-border);
1112
+ }
1113
+
1114
+ @media (forced-colors: active) {
1115
+ .material-bar[data-scrolled-under="true"]::before {
1116
+ border-color: CanvasText;
1117
+ }
1118
+ }
1119
+
1120
+ .bg-canvas {
1121
+ background-color: var(--color-surface-base);
1122
+ background-image: var(--gradient-canvas);
1123
+ background-repeat: no-repeat;
1124
+ }
1125
+
1126
+ .bg-control-gradient,
1127
+ .bg-control-gradient-accent {
1128
+ --tw-inset-shadow: var(--shadow-control-highlight);
1129
+ box-shadow:
1130
+ var(--tw-inset-shadow, 0 0 #0000),
1131
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1132
+ var(--tw-ring-offset-shadow, 0 0 #0000),
1133
+ var(--tw-ring-shadow, 0 0 #0000),
1134
+ var(--tw-shadow, 0 0 #0000);
1135
+ }
1136
+
1137
+ .bg-control-gradient {
1138
+ background-image: var(--gradient-control);
1139
+ }
1140
+
1141
+ .bg-control-gradient-accent {
1142
+ background-image: var(--gradient-control-accent);
1143
+ }
1144
+
1145
+ .ring-toggle-track {
1146
+ --tw-inset-ring-shadow: inset 0 0 0 1px var(--color-toggle-track-border);
1147
+ box-shadow:
1148
+ var(--tw-inset-shadow, 0 0 #0000),
1149
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1150
+ var(--tw-ring-offset-shadow, 0 0 #0000),
1151
+ var(--tw-ring-shadow, 0 0 #0000),
1152
+ var(--tw-shadow, 0 0 #0000);
1153
+ }
1154
+
1155
+ .rounded-button {
1156
+ border-radius: var(--zabi-button-radius, var(--radius-control));
1157
+ }
1158
+
1159
+ .font-button {
1160
+ font-weight: var(--zabi-button-font-weight, 500);
1161
+ }
1162
+
1163
+ .font-button-strong {
1164
+ font-weight: var(--zabi-button-font-weight, 600);
1165
+ }
1166
+
694
1167
  .bg-base-50 {
695
1168
  background-color: var(--color-base-50);
696
1169
  }
@@ -865,10 +1338,26 @@ body {
865
1338
  background-color: var(--color-card);
866
1339
  }
867
1340
 
1341
+ .bg-toggle-thumb {
1342
+ background-color: var(--color-toggle-thumb, var(--color-toggle-knob));
1343
+ }
1344
+
1345
+ .bg-toggle-thumb-checked {
1346
+ background-color: var(--color-toggle-thumb-checked, var(--color-toggle-thumb, var(--color-toggle-knob-checked)));
1347
+ }
1348
+
1349
+ .bg-card-flat {
1350
+ background-color: var(--color-card-flat);
1351
+ }
1352
+
868
1353
  @media (hover: hover) {
869
1354
  .hover\:bg-card-hover:hover {
870
1355
  background-color: var(--color-card-hover);
871
1356
  }
1357
+
1358
+ .hover\:bg-card-flat-hover:hover {
1359
+ background-color: var(--color-card-flat-hover);
1360
+ }
872
1361
  }
873
1362
 
874
1363
  .bg-surface-1 {
@@ -921,6 +1410,10 @@ body {
921
1410
  background-color: var(--color-card-active);
922
1411
  }
923
1412
 
1413
+ .active\:bg-card-flat-active:active {
1414
+ background-color: var(--color-card-flat-active);
1415
+ }
1416
+
924
1417
  .disabled\:bg-input-disabled:disabled {
925
1418
  background-color: var(--color-input-disabled);
926
1419
  }
@@ -1119,6 +1612,18 @@ body {
1119
1612
  background-color: var(--color-nav-menu-item-active);
1120
1613
  }
1121
1614
 
1615
+ .bg-tabbar-active {
1616
+ background-color: var(--color-tabbar-active);
1617
+ }
1618
+
1619
+ .bg-bar-brand {
1620
+ background-color: var(--color-bar-brand);
1621
+ }
1622
+
1623
+ .border-bar {
1624
+ border-color: var(--color-bar-border);
1625
+ }
1626
+
1122
1627
  .text-success {
1123
1628
  color: var(--color-success-text);
1124
1629
  }
@@ -1273,7 +1778,7 @@ body {
1273
1778
  .focus-ring--muted {
1274
1779
  --zabi-focus-ring-color: var(--color-focus-ring-muted, var(--color-base-500));
1275
1780
  }
1276
- :where(:has(> .on-brand, > .on-accent):not(.on-brand, .on-accent, .on-brand *, .on-accent *)) {
1781
+ :where(:has(> .on-brand, > .on-accent, > .on-fill):not(.on-brand, .on-accent, .on-fill, .on-brand *, .on-accent *, .on-fill *)) {
1277
1782
  --zabi-theme-headline: var(--color-headline);
1278
1783
  --zabi-theme-body: var(--color-body);
1279
1784
  --zabi-theme-label: var(--color-label);
@@ -1285,6 +1790,8 @@ body {
1285
1790
  --zabi-theme-border-medium: var(--color-border-medium);
1286
1791
  --zabi-theme-border-strong: var(--color-border-strong);
1287
1792
  --zabi-theme-control-border: var(--color-control-border);
1793
+ --zabi-theme-action-outline-border: var(--color-action-outline-border);
1794
+ --zabi-theme-action-outline-border-hover: var(--color-action-outline-border-hover);
1288
1795
  --zabi-theme-focus-ring: var(--color-focus-ring);
1289
1796
  --zabi-theme-focus-ring-muted: var(--color-focus-ring-muted);
1290
1797
  --zabi-theme-nav-menu-focus: var(--color-nav-menu-focus);
@@ -1310,6 +1817,8 @@ body {
1310
1817
  --color-border-medium: var(--color-on-brand);
1311
1818
  --color-border-strong: var(--color-on-brand);
1312
1819
  --color-control-border: var(--color-on-brand);
1820
+ --color-action-outline-border: var(--color-on-brand);
1821
+ --color-action-outline-border-hover: var(--color-on-brand);
1313
1822
  }
1314
1823
 
1315
1824
  .on-accent {
@@ -1330,15 +1839,98 @@ body {
1330
1839
  --color-border-medium: var(--color-on-accent);
1331
1840
  --color-border-strong: var(--color-on-accent);
1332
1841
  --color-control-border: var(--color-on-accent);
1842
+ --color-action-outline-border: var(--color-on-accent);
1843
+ --color-action-outline-border-hover: var(--color-on-accent);
1333
1844
  }
1334
- :where(.on-brand, .on-accent)
1845
+ .on-fill {
1846
+ color: var(--zabi-on-fill, currentColor);
1847
+ --color-focus-ring: var(--zabi-on-fill, currentColor);
1848
+ --color-focus-ring-muted: var(--zabi-on-fill, currentColor);
1849
+ --color-nav-menu-focus: var(--zabi-on-fill, currentColor);
1850
+ --color-focus-ring-offset: transparent;
1851
+ --color-focus-ring-danger: var(--zabi-on-fill, currentColor);
1852
+ --color-headline: var(--zabi-on-fill, currentColor);
1853
+ --color-body: var(--zabi-on-fill, currentColor);
1854
+ --color-label: var(--zabi-on-fill, currentColor);
1855
+ --color-description: var(--zabi-on-fill, currentColor);
1856
+ --color-caption: var(--zabi-on-fill, currentColor);
1857
+ --color-link: var(--zabi-on-fill, currentColor);
1858
+ --color-link-hover: var(--zabi-on-fill, currentColor);
1859
+ --color-border: var(--zabi-on-fill, currentColor);
1860
+ --color-border-medium: var(--zabi-on-fill, currentColor);
1861
+ --color-border-strong: var(--zabi-on-fill, currentColor);
1862
+ --color-control-border: var(--zabi-on-fill, currentColor);
1863
+ --color-action-outline-border: var(--zabi-on-fill, currentColor);
1864
+ --color-action-outline-border-hover: var(--zabi-on-fill, currentColor);
1865
+ }
1866
+ :where(.on-brand, .on-accent, .on-fill) {
1867
+ --zabi-inv-primary: var(--color-action-primary);
1868
+ --zabi-inv-primary-hover: var(--color-action-primary-hover);
1869
+ --zabi-inv-primary-active: var(--color-action-primary-active);
1870
+ --zabi-inv-primary-text: var(--color-action-primary-text);
1871
+ --zabi-inv-accent: var(--color-accent);
1872
+ --zabi-inv-accent-hover: var(--color-accent-hover);
1873
+ --zabi-inv-accent-active: var(--color-accent-active);
1874
+ --zabi-inv-accent-text: var(--color-on-accent);
1875
+ --zabi-inv-secondary: var(--color-action-secondary);
1876
+ --zabi-inv-secondary-hover: var(--color-action-secondary-hover);
1877
+ --zabi-inv-secondary-active: var(--color-action-secondary-active);
1878
+ }
1879
+ :where(.on-brand) {
1880
+ --zabi-inv-secondary: rgba(9, 9, 11, 0.1);
1881
+ --zabi-inv-secondary-hover: rgba(9, 9, 11, 0.15);
1882
+ --zabi-inv-secondary-active: rgba(9, 9, 11, 0.2);
1883
+ }
1884
+ :where(.on-brand) {
1885
+ --zabi-inv-primary: var(--color-on-brand);
1886
+ --zabi-inv-primary-hover: color-mix(in srgb, var(--color-on-brand) 88%, var(--color-action-primary));
1887
+ --zabi-inv-primary-active: color-mix(in srgb, var(--color-on-brand) 76%, var(--color-action-primary));
1888
+ --zabi-inv-primary-text: var(--color-action-primary);
1889
+ --zabi-inv-star: var(--color-on-brand);
1890
+ }
1891
+ :where(.on-accent) {
1892
+ --zabi-inv-accent: var(--color-on-accent);
1893
+ --zabi-inv-accent-hover: color-mix(in srgb, var(--color-on-accent) 88%, var(--color-accent));
1894
+ --zabi-inv-accent-active: color-mix(in srgb, var(--color-on-accent) 76%, var(--color-accent));
1895
+ --zabi-inv-accent-text: var(--color-accent);
1896
+ --zabi-inv-star: var(--color-on-accent);
1897
+ }
1898
+ :where(.on-fill) {
1899
+ --zabi-inv-primary: var(--zabi-on-fill, currentColor);
1900
+ --zabi-inv-primary-hover: color-mix(in srgb, var(--zabi-on-fill, currentColor) 88%, var(--zabi-fill, var(--color-card)));
1901
+ --zabi-inv-primary-active: color-mix(in srgb, var(--zabi-on-fill, currentColor) 76%, var(--zabi-fill, var(--color-card)));
1902
+ --zabi-inv-primary-text: var(--zabi-fill, var(--color-card));
1903
+ --zabi-inv-star: var(--zabi-on-fill, currentColor);
1904
+ }
1905
+ :where(.bg-action-primary:not(.on-brand, .on-accent, .on-fill)):where(.on-brand *, .on-accent *, .on-fill *) {
1906
+ --color-action-primary: var(--zabi-inv-primary);
1907
+ --color-action-primary-hover: var(--zabi-inv-primary-hover);
1908
+ --color-action-primary-active: var(--zabi-inv-primary-active);
1909
+ --color-action-primary-text: var(--zabi-inv-primary-text);
1910
+ }
1911
+ :where(.bg-action-secondary, .bg-action-secondary-active):where(.on-brand *, .on-accent *, .on-fill *) {
1912
+ --color-action-secondary: var(--zabi-inv-secondary);
1913
+ --color-action-secondary-hover: var(--zabi-inv-secondary-hover);
1914
+ --color-action-secondary-active: var(--zabi-inv-secondary-active);
1915
+ }
1916
+ :where(.bg-accent:not(.on-brand, .on-accent, .on-fill)):where(.on-brand *, .on-accent *, .on-fill *) {
1917
+ --color-accent: var(--zabi-inv-accent);
1918
+ --color-accent-hover: var(--zabi-inv-accent-hover);
1919
+ --color-accent-active: var(--zabi-inv-accent-active);
1920
+ --color-on-accent: var(--zabi-inv-accent-text);
1921
+ }
1922
+ :where(.rating):where(.on-brand *, .on-accent *, .on-fill *) {
1923
+ --zabi-rating-on: var(--zabi-inv-star);
1924
+ }
1925
+ :where(.on-brand, .on-accent, .on-fill)
1335
1926
  :where(
1336
- .bg-card, .bg-card-elevated, .bg-background, .bg-surface-base,
1927
+ .bg-card, .bg-card-flat, .bg-card-elevated, .bg-background, .bg-surface-base,
1337
1928
  .bg-surface-raised, .bg-surface-elevated, .bg-surface-overlay, .bg-surface-overlay-hover,
1338
- .bg-surface-inset, .bg-surface-1, .bg-surface-2, .bg-surface-3,
1929
+ .bg-surface-chrome, .bg-surface-inset, .bg-surface-1, .bg-surface-2, .bg-surface-3,
1339
1930
  .bg-surface-4, .bg-input, .bg-input-disabled, .bg-accent-subtle,
1340
- .bg-action-danger-subtle, .bg-action-primary-subtle, .bg-energetic-subtle, .bg-error-subtle,
1341
- .bg-info-subtle, .bg-neutral-subtle, .bg-success-subtle, .bg-warning-subtle,
1931
+ .bg-action-danger-subtle, .bg-action-primary-subtle, .bg-action-tonal, .bg-card-tint, .bg-chip, .bg-chip-selected,
1932
+ .bg-energetic-subtle, .bg-error-subtle,
1933
+ .bg-info-subtle, .bg-neutral-subtle, .bg-badge-neutral, .bg-toggle-thumb, .bg-toggle-thumb-checked, .bg-success-subtle, .bg-warning-subtle,
1342
1934
  .bg-nav-menu-active, .bg-action-disabled, .list-group, .on-surface
1343
1935
  ) {
1344
1936
  color: var(--zabi-theme-body);
@@ -1353,15 +1945,41 @@ body {
1353
1945
  --color-border-medium: var(--zabi-theme-border-medium);
1354
1946
  --color-border-strong: var(--zabi-theme-border-strong);
1355
1947
  --color-control-border: var(--zabi-theme-control-border);
1948
+ --color-action-outline-border: var(--zabi-theme-action-outline-border);
1949
+ --color-action-outline-border-hover: var(--zabi-theme-action-outline-border-hover);
1950
+ --zabi-inv-primary: var(--color-action-primary);
1951
+ --zabi-inv-primary-hover: var(--color-action-primary-hover);
1952
+ --zabi-inv-primary-active: var(--color-action-primary-active);
1953
+ --zabi-inv-primary-text: var(--color-action-primary-text);
1954
+ --zabi-inv-accent: var(--color-accent);
1955
+ --zabi-inv-accent-hover: var(--color-accent-hover);
1956
+ --zabi-inv-accent-active: var(--color-accent-active);
1957
+ --zabi-inv-accent-text: var(--color-on-accent);
1958
+ --zabi-inv-secondary: var(--color-action-secondary);
1959
+ --zabi-inv-secondary-hover: var(--color-action-secondary-hover);
1960
+ --zabi-inv-secondary-active: var(--color-action-secondary-active);
1961
+ --zabi-inv-star: initial;
1962
+ }
1963
+ :where(.on-brand, .on-accent, .on-fill) :where(.bg-card-flat) {
1964
+ --color-card-flat: var(--color-card);
1965
+ --color-card-flat-hover: var(--color-card-hover);
1966
+ --color-card-flat-active: var(--color-card-active);
1967
+ }
1968
+ :where(.on-brand, .on-accent, .on-fill) :where(.bg-input) {
1969
+ --color-input: var(--color-input-solid);
1970
+ --color-input-hover: var(--color-input-solid-hover);
1971
+ --color-input-focus: var(--color-input-solid-focus);
1972
+ --color-input-active: var(--color-input-solid-active);
1356
1973
  }
1357
- :where(.on-brand, .on-accent)
1974
+ :where(.on-brand, .on-accent, .on-fill)
1358
1975
  :where(
1359
- .bg-card, .bg-card-elevated, .bg-background, .bg-surface-base,
1976
+ .bg-card, .bg-card-flat, .bg-card-elevated, .bg-background, .bg-surface-base,
1360
1977
  .bg-surface-raised, .bg-surface-elevated, .bg-surface-overlay, .bg-surface-overlay-hover,
1361
- .bg-surface-inset, .bg-surface-1, .bg-surface-2, .bg-surface-3,
1978
+ .bg-surface-chrome, .bg-surface-inset, .bg-surface-1, .bg-surface-2, .bg-surface-3,
1362
1979
  .bg-surface-4, .bg-input, .bg-input-disabled, .bg-accent-subtle,
1363
- .bg-action-danger-subtle, .bg-action-primary-subtle, .bg-energetic-subtle, .bg-error-subtle,
1364
- .bg-info-subtle, .bg-neutral-subtle, .bg-success-subtle, .bg-warning-subtle,
1980
+ .bg-action-danger-subtle, .bg-action-primary-subtle, .bg-action-tonal, .bg-card-tint, .bg-chip, .bg-chip-selected,
1981
+ .bg-energetic-subtle, .bg-error-subtle,
1982
+ .bg-info-subtle, .bg-neutral-subtle, .bg-badge-neutral, .bg-toggle-thumb, .bg-toggle-thumb-checked, .bg-success-subtle, .bg-warning-subtle,
1365
1983
  .bg-nav-menu-active, .bg-action-disabled, .list-group, .on-surface
1366
1984
  )
1367
1985
  > :where(*) {
@@ -1371,6 +1989,24 @@ body {
1371
1989
  --color-focus-ring-offset: var(--zabi-theme-focus-ring-offset);
1372
1990
  --color-focus-ring-danger: var(--zabi-theme-focus-ring-danger);
1373
1991
  }
1992
+ .list-dividers > li + li,
1993
+ .list-group > li + li {
1994
+ position: relative;
1995
+ }
1996
+ .list-dividers > li + li::before,
1997
+ .list-group > li + li::before {
1998
+ content: "";
1999
+ position: absolute;
2000
+ inset-inline: 1rem;
2001
+ top: calc(-0.125rem - 0.5px);
2002
+ height: 1px;
2003
+ background-color: var(--zabi-list-divider-color, var(--color-border));
2004
+ pointer-events: none;
2005
+ }
2006
+ :is(.list-dividers, .list-group) > li:has(> [data-selected="true"])::before,
2007
+ :is(.list-dividers, .list-group) > li:has(> [data-selected="true"]) + li::before {
2008
+ display: none;
2009
+ }
1374
2010
  .list-group {
1375
2011
  @apply space-y-1 overflow-hidden rounded-xl border border-border p-1;
1376
2012
  background-color: var(--color-surface-1);
@@ -1423,6 +2059,9 @@ body {
1423
2059
  0 0 0 2px var(--color-focus-ring-offset),
1424
2060
  0 0 0 4px var(--color-focus-ring);
1425
2061
  }
2062
+ .select-container {
2063
+ max-width: 100%;
2064
+ }
1426
2065
  .selection-control-option-row {
1427
2066
  box-shadow: none;
1428
2067
  }
@@ -1432,6 +2071,9 @@ body {
1432
2071
  0 0 0 2px var(--color-focus-ring-offset),
1433
2072
  0 0 0 4px var(--color-focus-ring);
1434
2073
  }
2074
+ .selection-control-option-row-quiet:has(:checked):not(:has(:focus-visible)) {
2075
+ box-shadow: none;
2076
+ }
1435
2077
  }
1436
2078
 
1437
2079
  @media (forced-colors: active) {
@@ -1444,6 +2086,71 @@ body {
1444
2086
  }
1445
2087
  }
1446
2088
 
2089
+ @media (forced-colors: active) {
2090
+ .toggle-switch {
2091
+ border: 1px solid ButtonText;
2092
+ background-color: Canvas;
2093
+ background-image: none;
2094
+ }
2095
+ .toggle-switch-thumb {
2096
+ top: 1px;
2097
+ left: 1px;
2098
+ background-color: ButtonText;
2099
+ }
2100
+ .toggle-switch[aria-checked="true"] {
2101
+ border-color: Highlight;
2102
+ background-color: Highlight;
2103
+ }
2104
+ .toggle-switch[aria-checked="true"] .toggle-switch-thumb {
2105
+ background-color: HighlightText;
2106
+ }
2107
+ .toggle-switch:disabled {
2108
+ border-color: GrayText;
2109
+ opacity: 1;
2110
+ }
2111
+ .toggle-switch:disabled[aria-checked="true"] {
2112
+ background-color: GrayText;
2113
+ }
2114
+ .toggle-switch:disabled .toggle-switch-thumb {
2115
+ background-color: GrayText;
2116
+ }
2117
+ .toggle-switch:disabled[aria-checked="true"] .toggle-switch-thumb,
2118
+ .toggle-switch:disabled[aria-busy="true"] .toggle-switch-thumb {
2119
+ background-color: Canvas;
2120
+ }
2121
+
2122
+ .selection-control-shell {
2123
+ border-color: ButtonText;
2124
+ }
2125
+ .selection-control-shell:has(:checked) {
2126
+ border-color: Highlight;
2127
+ background-color: Highlight;
2128
+ }
2129
+ .selection-control-shell:has(:checked) > svg {
2130
+ color: HighlightText;
2131
+ }
2132
+ .selection-control-shell:has(:checked) > .selection-control-dot {
2133
+ background-color: HighlightText;
2134
+ }
2135
+ .selection-control-shell:has(:disabled) {
2136
+ border-color: GrayText;
2137
+ opacity: 1;
2138
+ }
2139
+ .selection-control-shell:has(:checked):has(:disabled) {
2140
+ background-color: GrayText;
2141
+ }
2142
+ .selection-control-shell:has(:checked):has(:disabled) > svg {
2143
+ color: Canvas;
2144
+ }
2145
+ .selection-control-shell:has(:checked):has(:disabled) > .selection-control-dot {
2146
+ background-color: Canvas;
2147
+ }
2148
+ .selection-control-label-row-interaction:has(:disabled) {
2149
+ opacity: 1;
2150
+ color: GrayText;
2151
+ }
2152
+ }
2153
+
1447
2154
  .bg-action-primary {
1448
2155
  background-color: var(--color-action-primary);
1449
2156
  }
@@ -1506,6 +2213,129 @@ body {
1506
2213
  }
1507
2214
  }
1508
2215
 
2216
+ .bg-action-tonal {
2217
+ background-color: var(--color-action-tonal);
2218
+ }
2219
+
2220
+ @media (hover: hover) {
2221
+ .bg-action-tonal:hover {
2222
+ background-color: var(--color-action-tonal-hover);
2223
+ }
2224
+ }
2225
+
2226
+ .bg-action-tonal:active {
2227
+ background-color: var(--color-action-tonal-active);
2228
+ }
2229
+
2230
+ .bg-action-tonal:disabled {
2231
+ background-color: var(--color-action-disabled);
2232
+ color: var(--color-action-disabled-text);
2233
+ }
2234
+
2235
+ .text-action-tonal {
2236
+ color: var(--color-action-tonal-text);
2237
+ }
2238
+
2239
+ @layer utilities {
2240
+ .bg-badge-neutral {
2241
+ background-color: var(--zabi-badge-neutral-fill, var(--color-neutral-subtle));
2242
+ }
2243
+ .text-badge-neutral {
2244
+ color: var(--zabi-badge-neutral-text, var(--color-neutral-text));
2245
+ }
2246
+ }
2247
+
2248
+ @layer utilities {
2249
+ .bg-skeleton-on-color {
2250
+ background-color: var(--zabi-skeleton-fill, color-mix(in srgb, currentColor 24%, transparent));
2251
+ }
2252
+ }
2253
+
2254
+ .bg-chip {
2255
+ background-color: var(--color-chip);
2256
+ }
2257
+
2258
+ .bg-chip-hover {
2259
+ background-color: var(--color-chip-hover);
2260
+ }
2261
+
2262
+ .bg-chip-active {
2263
+ background-color: var(--color-chip-active);
2264
+ }
2265
+
2266
+ @media (hover: hover) {
2267
+ .hover\:bg-chip-hover:hover {
2268
+ background-color: var(--color-chip-hover);
2269
+ }
2270
+ }
2271
+
2272
+ .active\:bg-chip-active:active {
2273
+ background-color: var(--color-chip-active);
2274
+ }
2275
+
2276
+ .text-chip-text {
2277
+ color: var(--color-chip-text);
2278
+ }
2279
+
2280
+ .bg-chip-selected {
2281
+ background-color: var(--color-chip-selected);
2282
+ }
2283
+
2284
+ .bg-chip-selected-hover {
2285
+ background-color: var(--color-chip-selected-hover);
2286
+ }
2287
+
2288
+ .bg-chip-selected-active {
2289
+ background-color: var(--color-chip-selected-active);
2290
+ }
2291
+
2292
+ @media (hover: hover) {
2293
+ .hover\:bg-chip-selected-hover:hover {
2294
+ background-color: var(--color-chip-selected-hover);
2295
+ }
2296
+ }
2297
+
2298
+ .active\:bg-chip-selected-active:active {
2299
+ background-color: var(--color-chip-selected-active);
2300
+ }
2301
+
2302
+ .text-chip-selected-text {
2303
+ color: var(--color-chip-selected-text);
2304
+ }
2305
+
2306
+ .bg-card-tint {
2307
+ background-color: var(--color-card-tint);
2308
+ }
2309
+
2310
+ .border-progress-track-border {
2311
+ border-color: var(--color-progress-track-border);
2312
+ }
2313
+
2314
+ .bg-toggle-track {
2315
+ background-color: var(--color-toggle-track);
2316
+ }
2317
+
2318
+ @media (hover: hover) {
2319
+ .bg-toggle-track:hover {
2320
+ background-color: var(--color-toggle-track-hover);
2321
+ }
2322
+ }
2323
+
2324
+ .bg-toggle-track:active {
2325
+ background-color: var(--color-toggle-track-active);
2326
+ }
2327
+
2328
+ .border-action-outline {
2329
+ border-color: var(--color-action-outline-border);
2330
+ }
2331
+
2332
+ @media (hover: hover) {
2333
+ .border-action-outline:hover,
2334
+ .hover\:border-action-outline-hover:hover {
2335
+ border-color: var(--color-action-outline-border-hover);
2336
+ }
2337
+ }
2338
+
1509
2339
  .bg-action-danger {
1510
2340
  background-color: var(--color-action-danger);
1511
2341
  }
@@ -1657,6 +2487,10 @@ body {
1657
2487
  z-index: var(--z-sticky);
1658
2488
  }
1659
2489
 
2490
+ .z-fixed {
2491
+ z-index: var(--z-fixed);
2492
+ }
2493
+
1660
2494
  .z-dropdown {
1661
2495
  z-index: var(--z-dropdown);
1662
2496
  }