zabi-components 8.0.0 → 8.1.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 (364) hide show
  1. package/CHANGELOG.md +1924 -0
  2. package/README.md +243 -10
  3. package/THEME.md +149 -332
  4. package/THEMING.md +1192 -266
  5. package/dist/atoms/ActionPanel.svelte +15 -5
  6. package/dist/atoms/Avatar.svelte +104 -0
  7. package/dist/atoms/Avatar.svelte.d.ts +34 -0
  8. package/dist/atoms/Badge.svelte +36 -7
  9. package/dist/atoms/Badge.svelte.d.ts +2 -2
  10. package/dist/atoms/Button.svelte +177 -27
  11. package/dist/atoms/Button.svelte.d.ts +30 -2
  12. package/dist/atoms/Card.svelte +4 -4
  13. package/dist/atoms/CardHeader.svelte +16 -4
  14. package/dist/atoms/Checkbox.svelte +48 -21
  15. package/dist/atoms/Checkbox.svelte.d.ts +4 -2
  16. package/dist/atoms/CodeBlock.svelte +20 -2
  17. package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
  18. package/dist/atoms/ColorPicker.svelte +259 -49
  19. package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
  20. package/dist/atoms/Container.svelte +16 -8
  21. package/dist/atoms/DateField.svelte +107 -0
  22. package/dist/atoms/DateField.svelte.d.ts +53 -0
  23. package/dist/atoms/FieldMessages.svelte +69 -0
  24. package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
  25. package/dist/atoms/FloatingActionButton.svelte +174 -0
  26. package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
  27. package/dist/atoms/Heading.svelte +37 -5
  28. package/dist/atoms/Heading.svelte.d.ts +7 -0
  29. package/dist/atoms/IconButton.svelte +220 -24
  30. package/dist/atoms/IconButton.svelte.d.ts +49 -4
  31. package/dist/atoms/Input.svelte +253 -52
  32. package/dist/atoms/Input.svelte.d.ts +32 -2
  33. package/dist/atoms/List.svelte +4 -1
  34. package/dist/atoms/ListItem.svelte +44 -11
  35. package/dist/atoms/ListItem.svelte.d.ts +5 -0
  36. package/dist/atoms/Progress.svelte +27 -8
  37. package/dist/atoms/Progress.svelte.d.ts +4 -0
  38. package/dist/atoms/Radio.svelte +19 -3
  39. package/dist/atoms/Radio.svelte.d.ts +4 -2
  40. package/dist/atoms/Rating.svelte +494 -0
  41. package/dist/atoms/Rating.svelte.d.ts +56 -0
  42. package/dist/atoms/Select.svelte +433 -91
  43. package/dist/atoms/Select.svelte.d.ts +49 -3
  44. package/dist/atoms/SelectionControl.svelte +94 -17
  45. package/dist/atoms/SelectionControl.svelte.d.ts +4 -3
  46. package/dist/atoms/Skeleton.svelte +1 -1
  47. package/dist/atoms/Slider.svelte +309 -0
  48. package/dist/atoms/Slider.svelte.d.ts +40 -0
  49. package/dist/atoms/Spinner.svelte +57 -0
  50. package/dist/atoms/Spinner.svelte.d.ts +19 -0
  51. package/dist/atoms/Table.svelte +151 -6
  52. package/dist/atoms/Table.svelte.d.ts +15 -3
  53. package/dist/atoms/TemporalField.svelte +140 -0
  54. package/dist/atoms/TemporalField.svelte.d.ts +32 -0
  55. package/dist/atoms/Text.svelte +23 -11
  56. package/dist/atoms/Text.svelte.d.ts +6 -3
  57. package/dist/atoms/Textarea.svelte +55 -44
  58. package/dist/atoms/Textarea.svelte.d.ts +14 -2
  59. package/dist/atoms/ThemeToggle.svelte +223 -44
  60. package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
  61. package/dist/atoms/TimeField.svelte +108 -0
  62. package/dist/atoms/TimeField.svelte.d.ts +54 -0
  63. package/dist/atoms/Toast.svelte +17 -4
  64. package/dist/atoms/Toast.svelte.d.ts +2 -0
  65. package/dist/atoms/Toggle.svelte +41 -8
  66. package/dist/atoms/Toggle.svelte.d.ts +11 -2
  67. package/dist/atoms/Tooltip.svelte +508 -23
  68. package/dist/atoms/Tooltip.svelte.d.ts +11 -0
  69. package/dist/atoms/ZabiStringsProvider.svelte +45 -0
  70. package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
  71. package/dist/atoms/index.d.ts +17 -0
  72. package/dist/atoms/index.js +12 -0
  73. package/dist/atoms/selection-control.styles.d.ts +36 -5
  74. package/dist/atoms/selection-control.styles.js +40 -9
  75. package/dist/components/atoms/index.d.ts +17 -0
  76. package/dist/components/atoms/index.d.ts.map +1 -1
  77. package/dist/components/atoms/selection-control.styles.d.ts +36 -5
  78. package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
  79. package/dist/components/index.d.ts +80 -2
  80. package/dist/components/index.d.ts.map +1 -1
  81. package/dist/components/molecules/index.d.ts +46 -0
  82. package/dist/components/molecules/index.d.ts.map +1 -1
  83. package/dist/components/molecules/toast-store.d.ts +53 -7
  84. package/dist/components/molecules/toast-store.d.ts.map +1 -1
  85. package/dist/components/organisms/index.d.ts +5 -0
  86. package/dist/components/organisms/index.d.ts.map +1 -1
  87. package/dist/components/types/variants.d.ts +15 -1
  88. package/dist/components/types/variants.d.ts.map +1 -1
  89. package/dist/components/util/app-shell.d.ts +28 -0
  90. package/dist/components/util/app-shell.d.ts.map +1 -0
  91. package/dist/components/util/avatar.d.ts +36 -0
  92. package/dist/components/util/avatar.d.ts.map +1 -0
  93. package/dist/components/util/bottom-sheet.d.ts +30 -0
  94. package/dist/components/util/bottom-sheet.d.ts.map +1 -0
  95. package/dist/components/util/bottom-tab-bar.d.ts +35 -0
  96. package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
  97. package/dist/components/util/calendar.d.ts +56 -0
  98. package/dist/components/util/calendar.d.ts.map +1 -0
  99. package/dist/components/util/collapsible.d.ts +58 -0
  100. package/dist/components/util/collapsible.d.ts.map +1 -0
  101. package/dist/components/util/confirm-dialog.d.ts +12 -0
  102. package/dist/components/util/confirm-dialog.d.ts.map +1 -0
  103. package/dist/components/util/date.d.ts +96 -0
  104. package/dist/components/util/date.d.ts.map +1 -0
  105. package/dist/components/util/drawer.d.ts +13 -0
  106. package/dist/components/util/drawer.d.ts.map +1 -0
  107. package/dist/components/util/dropdown.d.ts +47 -0
  108. package/dist/components/util/dropdown.d.ts.map +1 -0
  109. package/dist/components/util/field.d.ts +39 -0
  110. package/dist/components/util/field.d.ts.map +1 -0
  111. package/dist/components/util/fit-in-viewport.d.ts +201 -0
  112. package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
  113. package/dist/components/util/focus-utils.d.ts +75 -2
  114. package/dist/components/util/focus-utils.d.ts.map +1 -1
  115. package/dist/components/util/hydration.d.ts +45 -0
  116. package/dist/components/util/hydration.d.ts.map +1 -0
  117. package/dist/components/util/keyboard-inset.d.ts +18 -0
  118. package/dist/components/util/keyboard-inset.d.ts.map +1 -0
  119. package/dist/components/util/media-grid.d.ts +51 -0
  120. package/dist/components/util/media-grid.d.ts.map +1 -0
  121. package/dist/components/util/media.d.ts +6 -0
  122. package/dist/components/util/media.d.ts.map +1 -0
  123. package/dist/components/util/overlay-chrome.d.ts +53 -0
  124. package/dist/components/util/overlay-chrome.d.ts.map +1 -0
  125. package/dist/components/util/overlay.d.ts +72 -0
  126. package/dist/components/util/overlay.d.ts.map +1 -0
  127. package/dist/components/util/photo.d.ts +215 -0
  128. package/dist/components/util/photo.d.ts.map +1 -0
  129. package/dist/components/util/portal.d.ts +23 -0
  130. package/dist/components/util/portal.d.ts.map +1 -0
  131. package/dist/components/util/pull-to-refresh.d.ts +27 -0
  132. package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
  133. package/dist/components/util/radio-keys.d.ts +25 -0
  134. package/dist/components/util/radio-keys.d.ts.map +1 -0
  135. package/dist/components/util/rating.d.ts +23 -0
  136. package/dist/components/util/rating.d.ts.map +1 -0
  137. package/dist/components/util/ready-made-strings.d.ts +77 -0
  138. package/dist/components/util/ready-made-strings.d.ts.map +1 -0
  139. package/dist/components/util/scroll-padding.d.ts +20 -0
  140. package/dist/components/util/scroll-padding.d.ts.map +1 -0
  141. package/dist/components/util/segmented-control.d.ts +16 -0
  142. package/dist/components/util/segmented-control.d.ts.map +1 -0
  143. package/dist/components/util/select.d.ts +41 -0
  144. package/dist/components/util/select.d.ts.map +1 -0
  145. package/dist/components/util/sheet-drag.d.ts +60 -0
  146. package/dist/components/util/sheet-drag.d.ts.map +1 -0
  147. package/dist/components/util/sidebar.d.ts +63 -0
  148. package/dist/components/util/sidebar.d.ts.map +1 -0
  149. package/dist/components/util/sortable-list.d.ts +65 -0
  150. package/dist/components/util/sortable-list.d.ts.map +1 -0
  151. package/dist/components/util/stepper.d.ts +40 -0
  152. package/dist/components/util/stepper.d.ts.map +1 -0
  153. package/dist/components/util/swipeable-list-item.d.ts +36 -0
  154. package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
  155. package/dist/components/util/theme-mode.d.ts +80 -0
  156. package/dist/components/util/theme-mode.d.ts.map +1 -0
  157. package/dist/components/util/toaster.d.ts +93 -0
  158. package/dist/components/util/toaster.d.ts.map +1 -0
  159. package/dist/components/util/tooltip.d.ts +10 -0
  160. package/dist/components/util/tooltip.d.ts.map +1 -0
  161. package/dist/components/util/top-navbar.d.ts +11 -0
  162. package/dist/components/util/top-navbar.d.ts.map +1 -0
  163. package/dist/components/util/touch-target.d.ts +31 -0
  164. package/dist/components/util/touch-target.d.ts.map +1 -0
  165. package/dist/components/util/zabi-strings.d.ts +133 -0
  166. package/dist/components/util/zabi-strings.d.ts.map +1 -0
  167. package/dist/create-theme/cli.js +169 -0
  168. package/dist/create-theme/index.d.ts +176 -0
  169. package/dist/create-theme/index.js +817 -0
  170. package/dist/create-theme/lib/ramp-math.js +128 -0
  171. package/dist/create-theme/lib/resolve.js +141 -0
  172. package/dist/create-theme/theme-data.js +1116 -0
  173. package/dist/index.d.ts +80 -2
  174. package/dist/index.js +57 -2
  175. package/dist/molecules/Alert.svelte +33 -5
  176. package/dist/molecules/Alert.svelte.d.ts +2 -0
  177. package/dist/molecules/AppBar.svelte +415 -0
  178. package/dist/molecules/AppBar.svelte.d.ts +69 -0
  179. package/dist/molecules/AvatarGroup.svelte +116 -0
  180. package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
  181. package/dist/molecules/BottomSheet.svelte +540 -0
  182. package/dist/molecules/BottomSheet.svelte.d.ts +93 -0
  183. package/dist/molecules/BottomTabBar.svelte +297 -0
  184. package/dist/molecules/BottomTabBar.svelte.d.ts +64 -0
  185. package/dist/molecules/Calendar.svelte +597 -0
  186. package/dist/molecules/Calendar.svelte.d.ts +72 -0
  187. package/dist/molecules/Collapsible.svelte +243 -0
  188. package/dist/molecules/Collapsible.svelte.d.ts +44 -0
  189. package/dist/molecules/CollapsibleGroup.svelte +126 -0
  190. package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
  191. package/dist/molecules/ComponentDemo.svelte +16 -4
  192. package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
  193. package/dist/molecules/ConfirmDialog.svelte +253 -0
  194. package/dist/molecules/ConfirmDialog.svelte.d.ts +55 -0
  195. package/dist/molecules/ContactForm.svelte +34 -17
  196. package/dist/molecules/ContactForm.svelte.d.ts +8 -0
  197. package/dist/molecules/Drawer.svelte +394 -0
  198. package/dist/molecules/Drawer.svelte.d.ts +55 -0
  199. package/dist/molecules/Dropdown.svelte +509 -48
  200. package/dist/molecules/Dropdown.svelte.d.ts +45 -6
  201. package/dist/molecules/DropdownItem.svelte +122 -0
  202. package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
  203. package/dist/molecules/EmptyState.svelte +55 -10
  204. package/dist/molecules/EmptyState.svelte.d.ts +8 -0
  205. package/dist/molecules/FormField.svelte +9 -1
  206. package/dist/molecules/FormField.svelte.d.ts +2 -0
  207. package/dist/molecules/Header.svelte +1 -1
  208. package/dist/molecules/ImageUpload.svelte +383 -70
  209. package/dist/molecules/ImageUpload.svelte.d.ts +47 -2
  210. package/dist/molecules/MediaGrid.svelte +527 -0
  211. package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
  212. package/dist/molecules/Modal.svelte +288 -72
  213. package/dist/molecules/Modal.svelte.d.ts +51 -2
  214. package/dist/molecules/NavigationMenuContent.svelte +58 -1
  215. package/dist/molecules/NavigationMenuItem.svelte +0 -1
  216. package/dist/molecules/NavigationMenuLink.svelte +1 -1
  217. package/dist/molecules/NavigationMenuList.svelte +10 -3
  218. package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
  219. package/dist/molecules/Page.svelte +32 -2
  220. package/dist/molecules/Page.svelte.d.ts +11 -0
  221. package/dist/molecules/PhotoGrid.svelte +433 -0
  222. package/dist/molecules/PhotoGrid.svelte.d.ts +62 -0
  223. package/dist/molecules/PhotoViewer.svelte +1116 -0
  224. package/dist/molecules/PhotoViewer.svelte.d.ts +56 -0
  225. package/dist/molecules/PropsTable.svelte +22 -10
  226. package/dist/molecules/PropsTable.svelte.d.ts +3 -0
  227. package/dist/molecules/PullToRefresh.svelte +263 -0
  228. package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
  229. package/dist/molecules/RadioGroup.svelte +52 -14
  230. package/dist/molecules/RadioGroup.svelte.d.ts +14 -3
  231. package/dist/molecules/Section.svelte +1 -1
  232. package/dist/molecules/SegmentedControl.svelte +323 -0
  233. package/dist/molecules/SegmentedControl.svelte.d.ts +34 -0
  234. package/dist/molecules/SidebarBrandHeader.svelte +11 -1
  235. package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
  236. package/dist/molecules/SidebarFooter.svelte +29 -6
  237. package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
  238. package/dist/molecules/SlideUp.svelte +220 -61
  239. package/dist/molecules/SlideUp.svelte.d.ts +26 -0
  240. package/dist/molecules/SortableList.svelte +632 -0
  241. package/dist/molecules/SortableList.svelte.d.ts +69 -0
  242. package/dist/molecules/Stepper.svelte +548 -0
  243. package/dist/molecules/Stepper.svelte.d.ts +39 -0
  244. package/dist/molecules/StickyActionBar.svelte +191 -0
  245. package/dist/molecules/StickyActionBar.svelte.d.ts +65 -0
  246. package/dist/molecules/SwipeableListItem.svelte +334 -0
  247. package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
  248. package/dist/molecules/Tabs.svelte +233 -9
  249. package/dist/molecules/Tabs.svelte.d.ts +7 -0
  250. package/dist/molecules/Toaster.svelte +350 -5
  251. package/dist/molecules/Toaster.svelte.d.ts +95 -2
  252. package/dist/molecules/ToasterToast.svelte +253 -67
  253. package/dist/molecules/ToasterToast.svelte.d.ts +9 -0
  254. package/dist/molecules/UnsavedChangesBar.svelte +212 -0
  255. package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
  256. package/dist/molecules/index.d.ts +46 -0
  257. package/dist/molecules/index.js +27 -0
  258. package/dist/molecules/toast-store.d.ts +53 -7
  259. package/dist/molecules/toast-store.js +21 -0
  260. package/dist/organisms/AppShell.svelte +196 -0
  261. package/dist/organisms/AppShell.svelte.d.ts +61 -0
  262. package/dist/organisms/SidebarAccountPanel.svelte +107 -12
  263. package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
  264. package/dist/organisms/SidebarNavigation.svelte +96 -15
  265. package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
  266. package/dist/organisms/SidebarPanel.svelte +31 -10
  267. package/dist/organisms/SidebarShell.svelte +162 -11
  268. package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
  269. package/dist/organisms/TopNavbar.svelte +256 -31
  270. package/dist/organisms/TopNavbar.svelte.d.ts +26 -0
  271. package/dist/organisms/index.d.ts +5 -0
  272. package/dist/organisms/index.js +3 -0
  273. package/dist/types/components.d.ts +4 -0
  274. package/dist/types/components.d.ts.map +1 -1
  275. package/dist/types/index.d.ts +605 -25
  276. package/dist/types/index.d.ts.map +1 -1
  277. package/dist/types/variants.ts +17 -1
  278. package/dist/util/app-shell.d.ts +27 -0
  279. package/dist/util/app-shell.js +72 -0
  280. package/dist/util/avatar.d.ts +35 -0
  281. package/dist/util/avatar.js +52 -0
  282. package/dist/util/bottom-sheet.d.ts +29 -0
  283. package/dist/util/bottom-sheet.js +43 -0
  284. package/dist/util/bottom-tab-bar.d.ts +34 -0
  285. package/dist/util/bottom-tab-bar.js +54 -0
  286. package/dist/util/calendar.d.ts +55 -0
  287. package/dist/util/calendar.js +74 -0
  288. package/dist/util/collapsible.d.ts +57 -0
  289. package/dist/util/collapsible.js +23 -0
  290. package/dist/util/confirm-dialog.d.ts +11 -0
  291. package/dist/util/confirm-dialog.js +2 -0
  292. package/dist/util/date.d.ts +95 -0
  293. package/dist/util/date.js +237 -0
  294. package/dist/util/drawer.d.ts +12 -0
  295. package/dist/util/drawer.js +7 -0
  296. package/dist/util/dropdown.d.ts +46 -0
  297. package/dist/util/dropdown.js +21 -0
  298. package/dist/util/field.d.ts +38 -0
  299. package/dist/util/field.js +38 -0
  300. package/dist/util/fit-in-viewport.d.ts +200 -0
  301. package/dist/util/fit-in-viewport.js +399 -0
  302. package/dist/util/focus-utils.d.ts +75 -2
  303. package/dist/util/focus-utils.js +182 -9
  304. package/dist/util/hydration.d.ts +44 -0
  305. package/dist/util/hydration.js +58 -0
  306. package/dist/util/keyboard-inset.d.ts +17 -0
  307. package/dist/util/keyboard-inset.js +53 -0
  308. package/dist/util/media-grid.d.ts +50 -0
  309. package/dist/util/media-grid.js +81 -0
  310. package/dist/util/media.d.ts +5 -0
  311. package/dist/util/media.js +10 -0
  312. package/dist/util/overlay-chrome.d.ts +52 -0
  313. package/dist/util/overlay-chrome.js +56 -0
  314. package/dist/util/overlay.d.ts +71 -0
  315. package/dist/util/overlay.js +240 -0
  316. package/dist/util/photo.d.ts +214 -0
  317. package/dist/util/photo.js +206 -0
  318. package/dist/util/portal.d.ts +22 -0
  319. package/dist/util/portal.js +50 -0
  320. package/dist/util/pull-to-refresh.d.ts +26 -0
  321. package/dist/util/pull-to-refresh.js +30 -0
  322. package/dist/util/radio-keys.d.ts +24 -0
  323. package/dist/util/radio-keys.js +49 -0
  324. package/dist/util/rating.d.ts +22 -0
  325. package/dist/util/rating.js +26 -0
  326. package/dist/util/ready-made-strings.d.ts +76 -0
  327. package/dist/util/ready-made-strings.js +67 -0
  328. package/dist/util/scroll-padding.d.ts +19 -0
  329. package/dist/util/scroll-padding.js +44 -0
  330. package/dist/util/segmented-control.d.ts +15 -0
  331. package/dist/util/segmented-control.js +1 -0
  332. package/dist/util/select.d.ts +40 -0
  333. package/dist/util/select.js +63 -0
  334. package/dist/util/sheet-drag.d.ts +59 -0
  335. package/dist/util/sheet-drag.js +241 -0
  336. package/dist/util/sidebar.d.ts +62 -0
  337. package/dist/util/sidebar.js +38 -0
  338. package/dist/util/sortable-list.d.ts +64 -0
  339. package/dist/util/sortable-list.js +53 -0
  340. package/dist/util/stepper.d.ts +39 -0
  341. package/dist/util/stepper.js +38 -0
  342. package/dist/util/swipeable-list-item.d.ts +35 -0
  343. package/dist/util/swipeable-list-item.js +32 -0
  344. package/dist/util/theme-mode.d.ts +79 -0
  345. package/dist/util/theme-mode.js +121 -0
  346. package/dist/util/toaster.d.ts +92 -0
  347. package/dist/util/toaster.js +75 -0
  348. package/dist/util/tooltip.d.ts +9 -0
  349. package/dist/util/tooltip.js +18 -0
  350. package/dist/util/top-navbar.d.ts +10 -0
  351. package/dist/util/top-navbar.js +5 -0
  352. package/dist/util/touch-target.d.ts +30 -0
  353. package/dist/util/touch-target.js +30 -0
  354. package/dist/util/zabi-strings.d.ts +132 -0
  355. package/dist/util/zabi-strings.js +105 -0
  356. package/dist/zabi-components-colors.css +5 -2
  357. package/dist/zabi-components-theme-dark-only.css +543 -241
  358. package/dist/zabi-components-theme-dark.css +543 -241
  359. package/dist/zabi-components-theme-only.css +1584 -367
  360. package/dist/zabi-components-theme.css +1584 -367
  361. package/dist/zabi-components.css +3885 -518
  362. package/docs/lucide-icons.md +40 -17
  363. package/docs/theme-imports.md +81 -11
  364. package/package.json +35 -8
@@ -1,299 +1,419 @@
1
+ @source "./**/*.{svelte,js}";
2
+
1
3
  @theme {
2
4
  /*
3
5
  * Custom base (gray) ramp — single physical scale for --color-base-*.
4
- * 21 stops: 50 … 950 (lightest → darkest). Edit hex here; mirror the same block in .dark for standalone imports.
6
+ * 21 stops: 50 … 950 (lightest → darkest). Declared ONCE, here: .dark holds no raw palette,
7
+ * so an app that overrides --zabi-base-* on :root restyles both themes.
5
8
  * Dark: semantic step S maps to physical (1000 − S), e.g. 50↔950, 75↔925; 500 stays fixed.
6
9
  * Midpoints are frozen hex values (default mode: fixed).
7
10
  */
8
- --zabi-base-50: #fafafa
9
- --zabi-base-75: #f7f7f7
10
- --zabi-base-100: #f4f4f5
11
- --zabi-base-150: #ececee
12
- --zabi-base-200: #e4e4e7
13
- --zabi-base-250: #dcdcdf
14
- --zabi-base-300: #d4d4d8
15
- --zabi-base-350: #babac1
16
- --zabi-base-400: #a1a1aa
17
- --zabi-base-450: #898992
18
- --zabi-base-500: #71717a
19
- --zabi-base-550: #61616a
20
- --zabi-base-600: #52525b
21
- --zabi-base-650: #484850
22
- --zabi-base-700: #3f3f46
23
- --zabi-base-750: #333338
24
- --zabi-base-800: #27272a
25
- --zabi-base-850: #1f1f22
26
- --zabi-base-900: #18181b
27
- --zabi-base-925: #101013
28
- --zabi-base-950: #09090b
11
+ --zabi-base-50: #fafafa;
12
+ --zabi-base-75: #f7f7f7;
13
+ --zabi-base-100: #f4f4f5;
14
+ --zabi-base-150: #ececee;
15
+ --zabi-base-200: #e4e4e7;
16
+ --zabi-base-250: #dcdcdf;
17
+ --zabi-base-300: #d4d4d8;
18
+ --zabi-base-350: #babac1;
19
+ --zabi-base-400: #a1a1aa;
20
+ --zabi-base-450: #898992;
21
+ --zabi-base-500: #71717a;
22
+ --zabi-base-550: #61616a;
23
+ --zabi-base-600: #52525b;
24
+ --zabi-base-650: #484850;
25
+ --zabi-base-700: #3f3f46;
26
+ --zabi-base-750: #333338;
27
+ --zabi-base-800: #27272a;
28
+ --zabi-base-850: #1f1f22;
29
+ --zabi-base-900: #18181b;
30
+ --zabi-base-925: #101013;
31
+ --zabi-base-950: #09090b;
29
32
  /* Typography - Nunito Sans font family */
30
- --font-family-sans: 'Nunito Sans', ui-sans-serif, system-ui, sans-serif
33
+ --font-family-sans: 'Nunito Sans', ui-sans-serif, system-ui, sans-serif;
34
+ /* Headings follow the body face until an app sets this to a display font
35
+ * on :root. Applied to h1–h6 in the base layer below and by the Heading
36
+ * component. */
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;
40
+ /* Tailwind's own names for the same three faces. Its `font-sans` and
41
+ * `font-mono` utilities read --font-sans and --font-mono, which were its
42
+ * system stacks: `class="font-sans"` on a heading left the brand face, and
43
+ * nothing said so. They follow the tokens above now, and `font-heading` is
44
+ * the utility for the heading face. An app sets --font-family-*; these
45
+ * follow. */
46
+ --font-sans: var(--font-family-sans);
47
+ --font-mono: var(--font-family-mono);
48
+ --font-heading: var(--font-family-heading);
49
+ /* Font weights. These are the variables Tailwind's `font-normal`,
50
+ * `font-medium`, `font-semibold` and `font-bold` read, so every component
51
+ * weight follows an override here. `regular` is the name a brand uses for
52
+ * 400; `font-normal` resolves through it. */
53
+ --font-weight-regular: 400;
54
+ --font-weight-normal: var(--font-weight-regular);
55
+ --font-weight-medium: 500;
56
+ --font-weight-semibold: 600;
57
+ --font-weight-bold: 700;
31
58
  /* Brand Color Scale — physical ramp + semantic aliases (same mirror pattern as pine / base) */
32
- --zabi-brand-50: #f4f6ff
33
- --zabi-brand-100: #e9eeff
34
- --zabi-brand-200: #d3dcff
35
- --zabi-brand-300: #b5c6ff
36
- --zabi-brand-400: #92a9ff
37
- --zabi-brand-500: #6d87f1
38
- --zabi-brand-600: #4f68da
39
- --zabi-brand-700: #3c52ba
40
- --zabi-brand-800: #2b3e95
41
- --zabi-brand-900: #1c2c6d
42
- --zabi-brand-950: #111d49
43
- --color-brand-50: var(--zabi-brand-50)
44
- --color-brand-100: var(--zabi-brand-100)
45
- --color-brand-200: var(--zabi-brand-200)
46
- --color-brand-300: var(--zabi-brand-300)
47
- --color-brand-400: var(--zabi-brand-400)
48
- --color-brand-500: var(--zabi-brand-500)
49
- --color-brand-600: var(--zabi-brand-600)
50
- --color-brand-700: var(--zabi-brand-700)
51
- --color-brand-800: var(--zabi-brand-800)
52
- --color-brand-900: var(--zabi-brand-900)
53
- --color-brand-950: var(--zabi-brand-950)
59
+ --zabi-brand-50: #f4f6ff;
60
+ --zabi-brand-100: #e9eeff;
61
+ --zabi-brand-200: #d3dcff;
62
+ --zabi-brand-300: #b5c6ff;
63
+ --zabi-brand-400: #92a9ff;
64
+ --zabi-brand-500: #6d87f1;
65
+ --zabi-brand-600: #4f68da;
66
+ --zabi-brand-700: #3c52ba;
67
+ --zabi-brand-800: #2b3e95;
68
+ --zabi-brand-900: #1c2c6d;
69
+ --zabi-brand-950: #111d49;
70
+ --color-brand-50: var(--zabi-brand-50);
71
+ --color-brand-100: var(--zabi-brand-100);
72
+ --color-brand-200: var(--zabi-brand-200);
73
+ --color-brand-300: var(--zabi-brand-300);
74
+ --color-brand-400: var(--zabi-brand-400);
75
+ --color-brand-500: var(--zabi-brand-500);
76
+ --color-brand-600: var(--zabi-brand-600);
77
+ --color-brand-700: var(--zabi-brand-700);
78
+ --color-brand-800: var(--zabi-brand-800);
79
+ --color-brand-900: var(--zabi-brand-900);
80
+ --color-brand-950: var(--zabi-brand-950);
54
81
  /* Citron Color Scale — physical ramp + semantic aliases (same mirror pattern as pine / base) */
55
- --zabi-citron-50: #f6f7ef
56
- --zabi-citron-100: #edefdf
57
- --zabi-citron-200: #dcdfbf
58
- --zabi-citron-300: #c5ca95
59
- --zabi-citron-400: #aab063
60
- --zabi-citron-500: #8c9027
61
- --zabi-citron-600: #707400
62
- --zabi-citron-700: #5a5d00
63
- --zabi-citron-800: #454700
64
- --zabi-citron-900: #313200
65
- --zabi-citron-950: #202100
66
- --color-citron-50: var(--zabi-citron-50)
67
- --color-citron-100: var(--zabi-citron-100)
68
- --color-citron-200: var(--zabi-citron-200)
69
- --color-citron-300: var(--zabi-citron-300)
70
- --color-citron-400: var(--zabi-citron-400)
71
- --color-citron-500: var(--zabi-citron-500)
72
- --color-citron-600: var(--zabi-citron-600)
73
- --color-citron-700: var(--zabi-citron-700)
74
- --color-citron-800: var(--zabi-citron-800)
75
- --color-citron-900: var(--zabi-citron-900)
76
- --color-citron-950: var(--zabi-citron-950)
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;
93
+ --color-citron-50: var(--zabi-citron-50);
94
+ --color-citron-100: var(--zabi-citron-100);
95
+ --color-citron-200: var(--zabi-citron-200);
96
+ --color-citron-300: var(--zabi-citron-300);
97
+ --color-citron-400: var(--zabi-citron-400);
98
+ --color-citron-500: var(--zabi-citron-500);
99
+ --color-citron-600: var(--zabi-citron-600);
100
+ --color-citron-700: var(--zabi-citron-700);
101
+ --color-citron-800: var(--zabi-citron-800);
102
+ --color-citron-900: var(--zabi-citron-900);
103
+ --color-citron-950: var(--zabi-citron-950);
104
+ /* Accent Color Scale — the second brand colour (highlights, badges,
105
+ * celebrations). Defaults to the citron ramp; an app overrides
106
+ * --zabi-accent-50 … 950 on :root, once, and both themes follow. */
107
+ --zabi-accent-50: var(--zabi-citron-50);
108
+ --zabi-accent-100: var(--zabi-citron-100);
109
+ --zabi-accent-200: var(--zabi-citron-200);
110
+ --zabi-accent-300: var(--zabi-citron-300);
111
+ --zabi-accent-400: var(--zabi-citron-400);
112
+ --zabi-accent-500: var(--zabi-citron-500);
113
+ --zabi-accent-600: var(--zabi-citron-600);
114
+ --zabi-accent-700: var(--zabi-citron-700);
115
+ --zabi-accent-800: var(--zabi-citron-800);
116
+ --zabi-accent-900: var(--zabi-citron-900);
117
+ --zabi-accent-950: var(--zabi-citron-950);
118
+ --color-accent-50: var(--zabi-accent-50);
119
+ --color-accent-100: var(--zabi-accent-100);
120
+ --color-accent-200: var(--zabi-accent-200);
121
+ --color-accent-300: var(--zabi-accent-300);
122
+ --color-accent-400: var(--zabi-accent-400);
123
+ --color-accent-500: var(--zabi-accent-500);
124
+ --color-accent-600: var(--zabi-accent-600);
125
+ --color-accent-700: var(--zabi-accent-700);
126
+ --color-accent-800: var(--zabi-accent-800);
127
+ --color-accent-900: var(--zabi-accent-900);
128
+ --color-accent-950: var(--zabi-accent-950);
77
129
  /* Pine Color Scale — physical ramp + semantic aliases (mirror pattern matches --zabi-base-* / --color-base-*) */
78
- --zabi-pine-50: #f0f8f5
79
- --zabi-pine-100: #e2f1eb
80
- --zabi-pine-200: #c5e4d7
81
- --zabi-pine-300: #9fd1bd
82
- --zabi-pine-400: #70ba9e
83
- --zabi-pine-500: #399c7a
84
- --zabi-pine-600: #00805e
85
- --zabi-pine-700: #00674a
86
- --zabi-pine-800: #004f37
87
- --zabi-pine-900: #003826
88
- --zabi-pine-950: #002518
89
- --color-pine-50: var(--zabi-pine-50)
90
- --color-pine-100: var(--zabi-pine-100)
91
- --color-pine-200: var(--zabi-pine-200)
92
- --color-pine-300: var(--zabi-pine-300)
93
- --color-pine-400: var(--zabi-pine-400)
94
- --color-pine-500: var(--zabi-pine-500)
95
- --color-pine-600: var(--zabi-pine-600)
96
- --color-pine-700: var(--zabi-pine-700)
97
- --color-pine-800: var(--zabi-pine-800)
98
- --color-pine-900: var(--zabi-pine-900)
99
- --color-pine-950: var(--zabi-pine-950)
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;
141
+ --color-pine-50: var(--zabi-pine-50);
142
+ --color-pine-100: var(--zabi-pine-100);
143
+ --color-pine-200: var(--zabi-pine-200);
144
+ --color-pine-300: var(--zabi-pine-300);
145
+ --color-pine-400: var(--zabi-pine-400);
146
+ --color-pine-500: var(--zabi-pine-500);
147
+ --color-pine-600: var(--zabi-pine-600);
148
+ --color-pine-700: var(--zabi-pine-700);
149
+ --color-pine-800: var(--zabi-pine-800);
150
+ --color-pine-900: var(--zabi-pine-900);
151
+ --color-pine-950: var(--zabi-pine-950);
100
152
  /* Iris Color Scale — physical ramp + semantic aliases (same mirror pattern as pine / base) */
101
- --zabi-iris-50: #f6f6fd
102
- --zabi-iris-100: #ecedfb
103
- --zabi-iris-200: #dadbf6
104
- --zabi-iris-300: #c1c4ef
105
- --zabi-iris-400: #a5a7e2
106
- --zabi-iris-500: #8486cd
107
- --zabi-iris-600: #6969b4
108
- --zabi-iris-700: #535397
109
- --zabi-iris-800: #3f3f78
110
- --zabi-iris-900: #2c2c58
111
- --zabi-iris-950: #1d1d3a
112
- --color-iris-50: var(--zabi-iris-50)
113
- --color-iris-100: var(--zabi-iris-100)
114
- --color-iris-200: var(--zabi-iris-200)
115
- --color-iris-300: var(--zabi-iris-300)
116
- --color-iris-400: var(--zabi-iris-400)
117
- --color-iris-500: var(--zabi-iris-500)
118
- --color-iris-600: var(--zabi-iris-600)
119
- --color-iris-700: var(--zabi-iris-700)
120
- --color-iris-800: var(--zabi-iris-800)
121
- --color-iris-900: var(--zabi-iris-900)
122
- --color-iris-950: var(--zabi-iris-950)
153
+ --zabi-iris-50: #f6f6fd;
154
+ --zabi-iris-100: #ecedfb;
155
+ --zabi-iris-200: #dadbf6;
156
+ --zabi-iris-300: #c1c4ef;
157
+ --zabi-iris-400: #a5a7e2;
158
+ --zabi-iris-500: #8486cd;
159
+ --zabi-iris-600: #6969b4;
160
+ --zabi-iris-700: #535397;
161
+ --zabi-iris-800: #3f3f78;
162
+ --zabi-iris-900: #2c2c58;
163
+ --zabi-iris-950: #1d1d3a;
164
+ --color-iris-50: var(--zabi-iris-50);
165
+ --color-iris-100: var(--zabi-iris-100);
166
+ --color-iris-200: var(--zabi-iris-200);
167
+ --color-iris-300: var(--zabi-iris-300);
168
+ --color-iris-400: var(--zabi-iris-400);
169
+ --color-iris-500: var(--zabi-iris-500);
170
+ --color-iris-600: var(--zabi-iris-600);
171
+ --color-iris-700: var(--zabi-iris-700);
172
+ --color-iris-800: var(--zabi-iris-800);
173
+ --color-iris-900: var(--zabi-iris-900);
174
+ --color-iris-950: var(--zabi-iris-950);
123
175
  /* Warning Color Scale — physical ramp + semantic aliases (Tailwind amber) */
124
- --zabi-warning-50: #fbf6ed
125
- --zabi-warning-100: #f7ecda
126
- --zabi-warning-200: #f1d9b6
127
- --zabi-warning-300: #e8bf87
128
- --zabi-warning-400: #db9e4c
129
- --zabi-warning-500: #c17b00
130
- --zabi-warning-600: #9e6000
131
- --zabi-warning-700: #824c00
132
- --zabi-warning-800: #663800
133
- --zabi-warning-900: #4b2600
134
- --zabi-warning-950: #341800
135
- --color-warning-50: var(--zabi-warning-50)
136
- --color-warning-100: var(--zabi-warning-100)
137
- --color-warning-200: var(--zabi-warning-200)
138
- --color-warning-300: var(--zabi-warning-300)
139
- --color-warning-400: var(--zabi-warning-400)
140
- --color-warning-500: var(--zabi-warning-500)
141
- --color-warning-600: var(--zabi-warning-600)
142
- --color-warning-700: var(--zabi-warning-700)
143
- --color-warning-800: var(--zabi-warning-800)
144
- --color-warning-900: var(--zabi-warning-900)
145
- --color-warning-950: var(--zabi-warning-950)
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;
184
+ --zabi-warning-800: #663800;
185
+ --zabi-warning-900: #4b2600;
186
+ --zabi-warning-950: #341800;
187
+ --color-warning-50: var(--zabi-warning-50);
188
+ --color-warning-100: var(--zabi-warning-100);
189
+ --color-warning-200: var(--zabi-warning-200);
190
+ --color-warning-300: var(--zabi-warning-300);
191
+ --color-warning-400: var(--zabi-warning-400);
192
+ --color-warning-500: var(--zabi-warning-500);
193
+ --color-warning-600: var(--zabi-warning-600);
194
+ --color-warning-700: var(--zabi-warning-700);
195
+ --color-warning-800: var(--zabi-warning-800);
196
+ --color-warning-900: var(--zabi-warning-900);
197
+ --color-warning-950: var(--zabi-warning-950);
146
198
  /* Error Color Scale — physical ramp + semantic aliases (Tailwind red) */
147
- --zabi-error-50: #fff4f3
148
- --zabi-error-100: #ffe9e6
149
- --zabi-error-200: #ffd2cd
150
- --zabi-error-300: #ffb2ab
151
- --zabi-error-400: #ff877d
152
- --zabi-error-500: #ed564e
153
- --zabi-error-600: #d22828
154
- --zabi-error-700: #b20912
155
- --zabi-error-800: #8c0006
156
- --zabi-error-900: #660002
157
- --zabi-error-950: #460202
158
- --color-error-50: var(--zabi-error-50)
159
- --color-error-100: var(--zabi-error-100)
160
- --color-error-200: var(--zabi-error-200)
161
- --color-error-300: var(--zabi-error-300)
162
- --color-error-400: var(--zabi-error-400)
163
- --color-error-500: var(--zabi-error-500)
164
- --color-error-600: var(--zabi-error-600)
165
- --color-error-700: var(--zabi-error-700)
166
- --color-error-800: var(--zabi-error-800)
167
- --color-error-900: var(--zabi-error-900)
168
- --color-error-950: var(--zabi-error-950)
199
+ --zabi-error-50: #fff4f3;
200
+ --zabi-error-100: #ffe9e6;
201
+ --zabi-error-200: #ffd2cd;
202
+ --zabi-error-300: #ffb2ab;
203
+ --zabi-error-400: #ff877d;
204
+ --zabi-error-500: #ed564e;
205
+ --zabi-error-600: #d22828;
206
+ --zabi-error-700: #b20912;
207
+ --zabi-error-800: #8c0006;
208
+ --zabi-error-900: #660002;
209
+ --zabi-error-950: #460202;
210
+ --color-error-50: var(--zabi-error-50);
211
+ --color-error-100: var(--zabi-error-100);
212
+ --color-error-200: var(--zabi-error-200);
213
+ --color-error-300: var(--zabi-error-300);
214
+ --color-error-400: var(--zabi-error-400);
215
+ --color-error-500: var(--zabi-error-500);
216
+ --color-error-600: var(--zabi-error-600);
217
+ --color-error-700: var(--zabi-error-700);
218
+ --color-error-800: var(--zabi-error-800);
219
+ --color-error-900: var(--zabi-error-900);
220
+ --color-error-950: var(--zabi-error-950);
169
221
  /* Base Color Scale — semantic tokens alias the physical ramp (light: 1:1) */
170
- --color-base-50: var(--zabi-base-50)
171
- --color-base-75: var(--zabi-base-75)
172
- --color-base-100: var(--zabi-base-100)
173
- --color-base-150: var(--zabi-base-150)
174
- --color-base-200: var(--zabi-base-200)
175
- --color-base-250: var(--zabi-base-250)
176
- --color-base-300: var(--zabi-base-300)
177
- --color-base-350: var(--zabi-base-350)
178
- --color-base-400: var(--zabi-base-400)
179
- --color-base-450: var(--zabi-base-450)
180
- --color-base-500: var(--zabi-base-500)
181
- --color-base-550: var(--zabi-base-550)
182
- --color-base-600: var(--zabi-base-600)
183
- --color-base-650: var(--zabi-base-650)
184
- --color-base-700: var(--zabi-base-700)
185
- --color-base-750: var(--zabi-base-750)
186
- --color-base-800: var(--zabi-base-800)
187
- --color-base-850: var(--zabi-base-850)
188
- --color-base-900: var(--zabi-base-900)
189
- --color-base-925: var(--zabi-base-925)
190
- --color-base-950: var(--zabi-base-950)
222
+ --color-base-50: var(--zabi-base-50);
223
+ --color-base-75: var(--zabi-base-75);
224
+ --color-base-100: var(--zabi-base-100);
225
+ --color-base-150: var(--zabi-base-150);
226
+ --color-base-200: var(--zabi-base-200);
227
+ --color-base-250: var(--zabi-base-250);
228
+ --color-base-300: var(--zabi-base-300);
229
+ --color-base-350: var(--zabi-base-350);
230
+ --color-base-400: var(--zabi-base-400);
231
+ --color-base-450: var(--zabi-base-450);
232
+ --color-base-500: var(--zabi-base-500);
233
+ --color-base-550: var(--zabi-base-550);
234
+ --color-base-600: var(--zabi-base-600);
235
+ --color-base-650: var(--zabi-base-650);
236
+ --color-base-700: var(--zabi-base-700);
237
+ --color-base-750: var(--zabi-base-750);
238
+ --color-base-800: var(--zabi-base-800);
239
+ --color-base-850: var(--zabi-base-850);
240
+ --color-base-900: var(--zabi-base-900);
241
+ --color-base-925: var(--zabi-base-925);
242
+ --color-base-950: var(--zabi-base-950);
191
243
  /* Background Colors */
192
244
  /* Surface elevation — four semantic levels, lowest → highest.
193
245
  * base: page/app shell · raised: cards, panels, sidebars · elevated: nested cards, hover/active fills
194
246
  * overlay: modals, sheets, menus, popovers, toasts. Light mode keeps white surfaces + shadows;
195
247
  * dark mode (see .dark) steps each level up in OKLCH lightness because shadows don't read on dark.
248
+ *
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.
196
254
  * Keep this block BELOW the "Background Colors" marker: scripts/sync-theme-tokens.js regenerates
197
255
  * everything between the base-scale aliases and that marker. */
198
- --color-surface-base: var(--color-base-100)
199
- --color-surface-raised: #ffffff
200
- --color-surface-elevated: var(--color-base-50)
201
- --color-surface-overlay: #ffffff
256
+ --color-surface-base: var(--color-base-150);
257
+ --color-surface-raised: #ffffff;
258
+ --color-surface-elevated: var(--color-base-100);
259
+ --color-surface-overlay: #ffffff;
260
+ /* Inset — a recessed area ON a raised surface (a well, a code sample, a stat
261
+ * strip inside a card). It is the ramp step between the page and the raised
262
+ * surface in both themes, so it always reads as cut into the card, never as
263
+ * floating above it. In dark this is the step the input field already used;
264
+ * --color-input points here. In light it shares base-100 with `elevated`,
265
+ * because below a white card the only direction left is down. */
266
+ --color-surface-inset: var(--color-base-100);
202
267
  /* Hover/active fill for rows and icon buttons inside an overlay (must read above the overlay) */
203
- --color-surface-overlay-hover: var(--color-base-100)
204
- /* 1px edge for overlays: invisible in light (shadow carries elevation), visible in dark */
205
- --color-border-overlay: transparent
206
- --color-background: var(--color-surface-base)
207
- --color-background-secondary: var(--color-base-50)
208
- --color-background-tertiary: var(--color-base-100)
268
+ --color-surface-overlay-hover: var(--color-base-150);
269
+ /* 1px edge for overlays. An ink tint in light, so a white menu on a white
270
+ * card still has an outline where its shadow is thinnest; a solid step in dark. */
271
+ --color-border-overlay: rgba(9, 9, 11, 0.1);
272
+ --color-background: var(--color-surface-base);
273
+ --color-background-secondary: var(--color-base-50);
274
+ --color-background-tertiary: var(--color-base-150);
209
275
  /* Page Colors */
210
- --color-page: var(--color-base-100)
211
- --color-page-secondary: var(--color-base-200)
276
+ --color-page: var(--color-base-150);
277
+ --color-page-secondary: var(--color-base-200);
212
278
  /* Card Colors — aliases of the surface levels (kept for compatibility) */
213
- --color-card: var(--color-surface-raised)
214
- --color-card-hover: var(--color-base-100)
215
- --color-card-active: var(--color-base-100)
216
- --color-card-elevated: var(--color-surface-overlay)
279
+ --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);
284
+ --color-card-elevated: var(--color-surface-overlay);
217
285
  /* Surfaces — numbered aliases (kept for compatibility; prefer surface-base/raised/elevated/overlay) */
218
- --color-surface-1: var(--color-surface-raised)
219
- --color-surface-2: var(--color-surface-elevated)
220
- --color-surface-3: var(--color-base-75)
221
- --color-surface-4: var(--color-base-100)
286
+ --color-surface-1: var(--color-surface-raised);
287
+ --color-surface-2: var(--color-surface-elevated);
288
+ --color-surface-3: var(--color-base-75);
289
+ --color-surface-4: var(--color-base-100);
222
290
  /* Control track — the unselected rail of a Toggle or switch. A real token
223
291
  * rather than a raw ramp step, so the hover/active direction is defined once
224
292
  * and inverts correctly with the theme. */
225
- --color-control-track: var(--color-base-400)
226
- --color-control-track-hover: var(--color-base-450)
227
- --color-control-track-active: var(--color-base-500)
293
+ --color-control-track: var(--color-base-400);
294
+ --color-control-track-hover: var(--color-base-450);
295
+ --color-control-track-active: var(--color-base-500);
296
+ /* Progress — the bar of Progress. The fill is the primary action, so it
297
+ * follows a pinned primary; the track is the field fill it always was. */
298
+ --color-progress-fill: var(--color-action-primary);
299
+ --color-progress-track: var(--color-input);
228
300
  /* Interaction fills — surface-relative on purpose.
229
301
  * A hard-coded ramp step (e.g. base-100) can coincide exactly with the
230
302
  * surface it sits on, which is how ghost hover became invisible: in dark
231
303
  * mode --color-base-100 IS --color-surface-base. An alpha tint is always
232
304
  * one step away from whatever is underneath it. */
233
- --color-surface-hover: rgba(9, 9, 11, 0.06)
234
- --color-surface-active: rgba(9, 9, 11, 0.11)
305
+ --color-surface-hover: rgba(9, 9, 11, 0.09);
306
+ --color-surface-active: rgba(9, 9, 11, 0.15);
235
307
  /* Overlay Colors */
236
- --color-overlay: rgba(0, 0, 0, 0.5)
308
+ --color-overlay: rgba(0, 0, 0, 0.5);
237
309
  /* Input Colors
238
310
  * The field is a RAISED surface, not a grey well — a grey fill on a grey
239
311
  * page reads as disabled. The disabled state is the only grey field. */
240
- --color-input: var(--color-surface-raised)
241
- --color-input-border: var(--color-base-350)
242
- --color-input-hover: var(--color-base-150)
243
- --color-input-focus: var(--color-surface-raised)
244
- --color-input-disabled: var(--color-base-100)
312
+ --color-input: var(--color-surface-raised);
313
+ /* The edge of a form field (WCAG 1.4.11): 3:1 on the field fill, the page and
314
+ * the card, held by the contrast guard. base-500 is 4.83:1 on white and
315
+ * 4.10:1 on the page; base-450 was 2.94:1 on the page, base-350 1.93:1. */
316
+ --color-input-border: var(--color-base-500);
317
+ /* Hover edge for a field. Light-mode hover is meant to be carried by the
318
+ * border, not by greying the fill; dark keeps its fill step and leaves this
319
+ * equal to the resting border. One step past the resting edge. */
320
+ --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. */
323
+ --color-input-hover: var(--color-base-100);
324
+ /* Pressed, for a field that is pressed rather than typed in: the Select
325
+ * 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);
330
+ --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);
245
334
  /* Text Colors */
246
- --color-headline: var(--color-base-900)
247
- --color-body: var(--color-base-800)
248
- --color-description: var(--color-base-600)
249
- --color-caption: var(--color-base-550)
335
+ --color-headline: var(--color-base-900);
336
+ --color-body: var(--color-base-800);
337
+ --color-description: var(--color-base-600);
338
+ --color-caption: var(--color-base-550);
250
339
  /* ≥ 4.5:1 on every surface level (base-500 was 4.40 on surface-base) */
251
- --color-input-placeholder: var(--color-base-500)
252
- --color-label: var(--color-base-700)
340
+ /* Placeholder text, and the format hint of an empty DateField or TimeField.
341
+ * It is text someone has to read, so it is held to 4.5:1 on every fill a
342
+ * field can show: resting, hover, focus and pressed. base-500 was 4.83:1 on
343
+ * the white field but 4.40:1 on the hover fill and 3.81:1 on the pressed
344
+ * one; base-550 is 6.13, 5.58 and 4.83. The value text (--color-body) stays
345
+ * 2.4:1 stronger, so an empty field still reads as empty. */
346
+ --color-input-placeholder: var(--color-base-550);
347
+ --color-label: var(--color-base-700);
253
348
  /* brand-600 clears 4.5:1 on a card but only 4.42:1 on the page surface, so
254
349
  * links sit one step darker. */
255
- --color-link: var(--color-brand-700)
256
- --color-link-hover: var(--color-brand-800)
350
+ --color-link: var(--color-brand-700);
351
+ --color-link-hover: var(--color-brand-800);
257
352
  /* Navigation menu item — menubar triggers, menu links, inline/sidebar nav rows */
258
- --color-nav-menu-item: var(--color-body)
259
- --color-nav-menu-item-hover: var(--color-headline)
260
- --color-nav-menu-item-active: var(--color-link)
353
+ --color-nav-menu-item: var(--color-body);
354
+ --color-nav-menu-item-hover: var(--color-headline);
355
+ --color-nav-menu-item-active: var(--color-link);
261
356
  /* Surface-relative on purpose: base-100 IS surface-base in both themes,
262
357
  * so the old value made sidebar row hover do nothing at all. */
263
- --color-nav-menu-hover: var(--color-surface-hover)
264
- --color-nav-menu-active: var(--color-action-primary-subtle)
265
- --color-nav-menu-active-hover: var(--color-action-primary-subtle-hover)
266
- --color-nav-menu-focus: var(--color-brand-500)
267
- --color-success-text: var(--color-pine-700)
268
- --color-warning-text: var(--color-warning-700)
269
- --color-neutral-text: var(--color-base-700)
270
- --color-energetic-text: var(--color-citron-700)
271
- --color-error-text: var(--color-error-700)
272
- --color-inverse: var(--color-base-100)
273
- --color-disabled: var(--color-base-400)
358
+ --color-nav-menu-hover: var(--color-surface-hover);
359
+ --color-nav-menu-active: var(--color-action-primary-subtle);
360
+ --color-nav-menu-active-hover: var(--color-action-primary-subtle-hover);
361
+ --color-nav-menu-focus: var(--color-focus);
362
+ --color-success-text: var(--color-pine-700);
363
+ --color-warning-text: var(--color-warning-700);
364
+ --color-neutral-text: var(--color-base-700);
365
+ --color-energetic-text: var(--color-citron-700);
366
+ --color-error-text: var(--color-error-700);
367
+ --color-inverse: var(--color-base-100);
368
+ --color-disabled: var(--color-base-400);
274
369
  /* Border Colors */
275
- --color-border: var(--color-base-300)
276
- --color-border-weak: var(--color-base-300)
277
- --color-border-medium: var(--color-base-400)
278
- --color-border-strong: var(--color-base-500)
279
- /* Focus Colors */
280
- --color-focus: var(--color-brand-500)
281
- --color-focus-weak: var(--color-brand-600)
282
- --color-focus-medium: var(--color-brand-700)
283
- --color-focus-strong: var(--color-brand-800)
370
+ --color-border: var(--color-base-300);
371
+ --color-border-weak: var(--color-base-300);
372
+ --color-border-medium: var(--color-base-400);
373
+ --color-border-strong: var(--color-base-500);
374
+ /* Control boundary — the edge of a control that has nothing else to be seen
375
+ * by, such as the outline of an empty Rating star (its first user).
376
+ * WCAG 1.4.11 asks 3:1 for it against whatever it sits on, so it is held to
377
+ * 3:1 on every surface level in both themes (scripts/check-contrast.js).
378
+ * The decorative edges above are not: --color-border-strong is the mirror's
379
+ * fixed point, the same grey in both themes, and is 2.49:1 on the dark
380
+ * elevated surface and 1.98:1 on the dark overlay. .dark pins this one step
381
+ * lighter for that reason. */
382
+ --color-control-border: var(--color-base-500);
383
+ /* Focus Colors
384
+ * brand-600, not brand-500: a focus indicator needs 3:1 against what is
385
+ * around it, and brand-500 was 2.99:1 on the page. brand-600 is also the
386
+ * primary button fill, so on a primary button the ring is separated by its
387
+ * 2px offset gap (--color-focus-ring-offset), which .focus-ring always draws.
388
+ * .dark restates the same steps; the mirror makes them --zabi-brand-400 and up. */
389
+ --color-focus: var(--color-brand-600);
390
+ --color-focus-weak: var(--color-brand-700);
391
+ --color-focus-medium: var(--color-brand-800);
392
+ --color-focus-strong: var(--color-brand-900);
284
393
  /* Aliases for `ring-focus-ring`, `.focus-ring`, and form utils */
285
- --color-focus-ring: var(--color-focus)
286
- --color-focus-ring-offset: var(--color-card)
394
+ --color-focus-ring: var(--color-focus);
395
+ --color-focus-ring-offset: var(--color-card);
396
+ /* `.focus-ring--muted`: the neutral ring of a ghost or link control, quiet
397
+ * by having no hue, not by having less contrast. The rule used to read
398
+ * --color-base-500 directly, which does not move between themes: 4.1:1 or
399
+ * more in light, 2.49:1 on the dark elevated surface. .dark pins it one step
400
+ * lighter; it is held to 3:1 on every surface level in both themes. */
401
+ --color-focus-ring-muted: var(--color-base-500);
402
+ /* `.focus-ring--danger`: the ring of a destructive control. It is the error
403
+ * colour; a role of its own so that a brand or accent block can re-point
404
+ * it with the other rings (the error colour is about 1:1 on a brand fill,
405
+ * and a focused danger Button there showed no ring). */
406
+ --color-focus-ring-danger: var(--color-error);
287
407
  /* Primary Colors */
288
- --color-primary: var(--color-brand-600)
289
- --color-primary-weak: var(--color-brand-700)
290
- --color-primary-medium: var(--color-brand-800)
291
- --color-primary-strong: var(--color-brand-900)
408
+ --color-primary: var(--color-brand-600);
409
+ --color-primary-weak: var(--color-brand-700);
410
+ --color-primary-medium: var(--color-brand-800);
411
+ --color-primary-strong: var(--color-brand-900);
292
412
  /* Secondary Colors */
293
- --color-secondary: var(--color-base-600)
294
- --color-secondary-weak: var(--color-base-700)
295
- --color-secondary-medium: var(--color-base-800)
296
- --color-secondary-strong: var(--color-base-900)
413
+ --color-secondary: var(--color-base-600);
414
+ --color-secondary-weak: var(--color-base-700);
415
+ --color-secondary-medium: var(--color-base-800);
416
+ --color-secondary-strong: var(--color-base-900);
297
417
  /* ----------------------------------------------------------------
298
418
  * SEMANTIC FAMILIES
299
419
  * Every family resolves to the SAME step on the shared lightness curve, so
@@ -304,8 +424,8 @@
304
424
  * <family>-weak step 700 pressed / emphasis
305
425
  * <family>-medium step 800 strongest fill
306
426
  * <family>-strong step 900 darkest
307
- * <family>-subtle step 100 tinted fill (badges, alerts)
308
- * <family>-border step 200 tinted edge
427
+ * <family>-subtle step 200 tinted fill (badges, alerts); .dark pins step 100
428
+ * <family>-border step 300 tinted edge; .dark pins step 200
309
429
  * <family>-text step 700 text on a subtle fill or a page surface
310
430
  *
311
431
  * Warning, error and energetic previously sat at step 500 — the mirror's
@@ -314,57 +434,74 @@
314
434
  * and fine in dark.
315
435
  * ---------------------------------------------------------------- */
316
436
  /* Success Colors */
317
- --color-success: var(--color-pine-600)
318
- --color-success-weak: var(--color-pine-700)
319
- --color-success-medium: var(--color-pine-800)
320
- --color-success-strong: var(--color-pine-900)
321
- --color-success-subtle: var(--color-pine-100)
322
- --color-success-border: var(--color-pine-200)
437
+ --color-success: var(--color-pine-600);
438
+ --color-success-weak: var(--color-pine-700);
439
+ --color-success-medium: var(--color-pine-800);
440
+ --color-success-strong: var(--color-pine-900);
441
+ --color-success-subtle: var(--color-pine-200);
442
+ --color-success-border: var(--color-pine-300);
323
443
  /* Warning Colors */
324
- --color-warning: var(--color-warning-600)
325
- --color-warning-weak: var(--color-warning-700)
326
- --color-warning-medium: var(--color-warning-800)
327
- --color-warning-strong: var(--color-warning-900)
328
- --color-warning-subtle: var(--color-warning-100)
329
- --color-warning-border: var(--color-warning-200)
444
+ --color-warning: var(--color-warning-600);
445
+ --color-warning-weak: var(--color-warning-700);
446
+ --color-warning-medium: var(--color-warning-800);
447
+ --color-warning-strong: var(--color-warning-900);
448
+ --color-warning-subtle: var(--color-warning-200);
449
+ --color-warning-border: var(--color-warning-300);
330
450
  /* Error Colors */
331
- --color-error: var(--color-error-600)
332
- --color-error-weak: var(--color-error-700)
333
- --color-error-medium: var(--color-error-800)
334
- --color-error-strong: var(--color-error-900)
335
- --color-error-subtle: var(--color-error-100)
336
- --color-error-border: var(--color-error-200)
451
+ --color-error: var(--color-error-600);
452
+ --color-error-weak: var(--color-error-700);
453
+ --color-error-medium: var(--color-error-800);
454
+ --color-error-strong: var(--color-error-900);
455
+ --color-error-subtle: var(--color-error-200);
456
+ --color-error-border: var(--color-error-300);
337
457
  /* Energetic Colors (Citron) */
338
- --color-energetic: var(--color-citron-600)
339
- --color-energetic-weak: var(--color-citron-700)
340
- --color-energetic-medium: var(--color-citron-800)
341
- --color-energetic-strong: var(--color-citron-900)
342
- --color-energetic-subtle: var(--color-citron-100)
343
- --color-energetic-border: var(--color-citron-200)
458
+ --color-energetic: var(--color-citron-600);
459
+ --color-energetic-weak: var(--color-citron-700);
460
+ --color-energetic-medium: var(--color-citron-800);
461
+ --color-energetic-strong: var(--color-citron-900);
462
+ --color-energetic-subtle: var(--color-citron-200);
463
+ --color-energetic-border: var(--color-citron-300);
464
+ /* Accent Colors — the second brand colour, on --zabi-accent-* (citron by
465
+ * default). The same recipe as the primary action: fill at 600, hover 700,
466
+ * active 800, so "more pressed" is "more contrast" in both themes; tint,
467
+ * edge and text as in the families above. `energetic` keeps pointing at
468
+ * citron itself and does not move when an app re-colours the accent. */
469
+ --color-accent: var(--color-accent-600);
470
+ --color-accent-hover: var(--color-accent-700);
471
+ --color-accent-active: var(--color-accent-800);
472
+ --color-accent-subtle: var(--color-accent-200);
473
+ --color-accent-border: var(--color-accent-300);
474
+ --color-accent-text: var(--color-accent-700);
475
+ /* Label on a solid accent fill — see "on brand" below for the two knobs. */
476
+ --zabi-on-accent: #ffffff;
477
+ --zabi-on-accent-dark: var(--zabi-accent-950);
478
+ --color-on-accent: var(--zabi-on-accent);
344
479
  /* Neutral Colors
345
480
  * The base ramp is wider than the chromatic ones on purpose (it also drives
346
481
  * text, borders and surfaces), so neutral cannot sit on exactly the same
347
482
  * step. base-550 is the closest match to the chromatic 600s that still
348
483
  * clears AA; .dark pins base-600, because base-500 is the mirror's fixed
349
484
  * point and would not invert at all. */
350
- --color-neutral: var(--color-base-550)
351
- --color-neutral-weak: var(--color-base-600)
352
- --color-neutral-medium: var(--color-base-700)
353
- --color-neutral-strong: var(--color-base-900)
354
- /* base-200, not base-100: base-100 IS surface-base, which made a neutral
355
- * badge measure 1.00:1 against the page and read as bare text. */
356
- --color-neutral-subtle: var(--color-base-200)
357
- --color-neutral-border: var(--color-base-200)
485
+ --color-neutral: var(--color-base-550);
486
+ --color-neutral-weak: var(--color-base-600);
487
+ --color-neutral-medium: var(--color-base-700);
488
+ --color-neutral-strong: var(--color-base-900);
489
+ /* One visible step past the page (base-150) and two past a card. It was
490
+ * 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);
358
495
  /* Info Colors */
359
- --color-info: var(--color-iris-600)
360
- --color-info-weak: var(--color-iris-700)
361
- --color-info-medium: var(--color-iris-800)
362
- --color-info-strong: var(--color-iris-900)
363
- --color-info-active: var(--color-iris-400)
364
- --color-info-subtle: var(--color-iris-100)
365
- --color-info-border: var(--color-iris-200)
496
+ --color-info: var(--color-iris-600);
497
+ --color-info-weak: var(--color-iris-700);
498
+ --color-info-medium: var(--color-iris-800);
499
+ --color-info-strong: var(--color-iris-900);
500
+ --color-info-active: var(--color-iris-400);
501
+ --color-info-subtle: var(--color-iris-200);
502
+ --color-info-border: var(--color-iris-300);
366
503
  /* Text alias */
367
- --color-info-text: var(--color-iris-700)
504
+ --color-info-text: var(--color-iris-700);
368
505
  /* ========================================
369
506
  ACTION COLORS - For interactive elements (buttons, links, etc.)
370
507
  ======================================== */
@@ -377,56 +514,80 @@
377
514
  * contrast against the page" in both themes. Never point active at a step on
378
515
  * the far side of the ramp: active used to be brand-400 against a brand-50
379
516
  * label, which is 1.66:1 — the label vanished while the button was held. */
380
- --color-action-primary: var(--color-brand-600)
381
- --color-action-primary-hover: var(--color-brand-700)
382
- --color-action-primary-active: var(--color-brand-800)
383
- --color-action-primary-subtle: var(--color-brand-100)
384
- --color-action-primary-subtle-hover: var(--color-brand-200)
385
- /* Pinned rather than aliased to brand-50: the ramp's lightest tint lands at
386
- * exactly 4.50:1 on brand-600 — passing, but with no margin. Pure white
387
- * gives 4.86:1. The .dark block pins the inverse. */
388
- --color-action-primary-text: #ffffff
517
+ --color-action-primary: var(--color-brand-600);
518
+ --color-action-primary-hover: var(--color-brand-700);
519
+ --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);
522
+ /* Held down, on a control whose resting fill is the subtle one: a toggled-on
523
+ * ghost IconButton. It used the hover step, which is 1.24:1 against the
524
+ * resting fill and, with a mouse, is what the button already shows. Half a
525
+ * step past hover is 1.42:1 against resting, and the icon (--color-link)
526
+ * 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));
528
+ /* "On brand" — the label on a primary fill.
529
+ * White rather than brand-50: the ramp's lightest tint lands at exactly
530
+ * 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).
532
+ *
533
+ * A light brand (amber, yellow) cannot carry white text, so both values are
534
+ * knobs an app sets once on :root, like the ramps:
535
+ * --zabi-on-brand label in light mode
536
+ * --zabi-on-brand-dark label in dark mode
537
+ * --color-on-brand is the role, remapped by .dark; components keep using
538
+ * --color-action-primary-text, which follows it. */
539
+ --zabi-on-brand: #ffffff;
540
+ --zabi-on-brand-dark: var(--zabi-brand-950);
541
+ --color-on-brand: var(--zabi-on-brand);
542
+ --color-action-primary-text: var(--color-on-brand);
389
543
  /* Secondary Actions - Used by bg-action-secondary utility class
390
544
  * A neutral alpha tint: reads as a real button on any surface level, and
391
545
  * cannot collide with the background the way a fixed ramp step can. The old
392
546
  * 10%-brand wash was so pale it barely registered as a control. */
393
- --color-action-secondary: rgba(9, 9, 11, 0.07)
394
- --color-action-secondary-hover: rgba(9, 9, 11, 0.12)
395
- --color-action-secondary-active: rgba(9, 9, 11, 0.17)
396
- --color-action-secondary-subtle: var(--color-base-100)
397
- --color-action-secondary-subtle-hover: var(--color-base-200)
398
- --color-action-secondary-text: var(--color-headline)
547
+ --color-action-secondary: rgba(9, 9, 11, 0.1);
548
+ --color-action-secondary-hover: rgba(9, 9, 11, 0.15);
549
+ --color-action-secondary-active: rgba(9, 9, 11, 0.2);
550
+ --color-action-secondary-subtle: var(--color-base-100);
551
+ --color-action-secondary-subtle-hover: var(--color-base-200);
552
+ --color-action-secondary-text: var(--color-headline);
399
553
  /* Disabled Actions - shared by every variant.
400
554
  * Disabled must be the QUIETEST state, never a brighter colour than the
401
555
  * enabled secondary. It used to be brand-500 plus opacity-50, which made a
402
556
  * disabled primary lighter and more colourful than an enabled secondary. */
403
- --color-action-disabled: var(--color-base-200)
404
- --color-action-disabled-text: var(--color-base-500)
405
- --color-action-disabled-border: var(--color-base-250)
557
+ --color-action-disabled: var(--color-base-250);
558
+ --color-action-disabled-text: var(--color-base-500);
559
+ --color-action-disabled-border: var(--color-base-300);
406
560
  /* Danger Actions - Used by bg-action-danger utility class.
407
561
  * Same ramp step as every other family, so the destructive action no longer
408
562
  * out-shouts the primary one. The bright red is spent on hover, where the
409
563
  * user is already committing. */
410
- --color-action-danger: var(--color-error-600)
411
- --color-action-danger-hover: var(--color-error-700)
412
- --color-action-danger-active: var(--color-error-800)
413
- --color-action-danger-subtle: var(--color-error-100)
414
- --color-action-danger-subtle-hover: var(--color-error-200)
415
- --color-action-danger-text: var(--color-error-50)
416
- /* Shadow Colors */
417
- --shadow-color: 0 0 0
418
- --shadow-opacity: 0.1
419
- --shadow-sm: 0 1px 3px 0 rgb(var(--shadow-color) / var(--shadow-opacity)), 0 1px 2px -1px rgb(var(--shadow-color) / var(--shadow-opacity))
420
- --shadow-md: 0 4px 6px -1px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 2px 4px -2px rgb(var(--shadow-color) / var(--shadow-opacity))
421
- --shadow-lg: 0 10px 15px -3px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 4px 6px -4px rgb(var(--shadow-color) / var(--shadow-opacity))
422
- --shadow-xl: 0 20px 25px -5px rgb(var(--shadow-color) / var(--shadow-opacity)), 0 8px 10px -6px rgb(var(--shadow-color) / var(--shadow-opacity))
564
+ --color-action-danger: var(--color-error-600);
565
+ --color-action-danger-hover: var(--color-error-700);
566
+ --color-action-danger-active: var(--color-error-800);
567
+ --color-action-danger-subtle: var(--color-error-100);
568
+ --color-action-danger-subtle-hover: var(--color-error-200);
569
+ /* The same for a toggled-on danger-tone IconButton: hover was 1.18:1 against
570
+ * the resting fill. Half a step past it is 1.32:1, and the icon
571
+ * (--color-error) keeps 3.36:1; on the whole step it is exactly 3.00. Dark needs no override:
572
+ * the same expression resolves through the mirrored steps. */
573
+ --color-action-danger-subtle-active: color-mix(in srgb, var(--color-error-300) 50%, var(--color-error-200));
574
+ --color-action-danger-text: var(--color-error-50);
575
+ /* Shadow Colors
576
+ * 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. */
578
+ --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));
423
584
  /* Spacing */
424
- --spacing-xs: 0.25rem
425
- --spacing-sm: 0.5rem
426
- --spacing-md: 1rem
427
- --spacing-lg: 1.5rem
428
- --spacing-xl: 2rem
429
- --spacing-2xl: 3rem
585
+ --spacing-xs: 0.25rem;
586
+ --spacing-sm: 0.5rem;
587
+ --spacing-md: 1rem;
588
+ --spacing-lg: 1.5rem;
589
+ --spacing-xl: 2rem;
590
+ --spacing-2xl: 3rem;
430
591
  /*
431
592
  * Sizing names for w-* / min-w-* / max-w-*.
432
593
  * Tailwind v4 resolves these utilities as --max-width-* (or --width-* / --min-width-*) → --spacing-* → --container-*.
@@ -434,65 +595,1121 @@
434
595
  * instead of Tailwind's 32rem container size. These keys are checked before --spacing-*, so they restore
435
596
  * the standard container scale while `p-lg`, `gap-md`, etc. keep using the spacing tokens.
436
597
  */
437
- --max-width-xs: 20rem
438
- --max-width-sm: 24rem
439
- --max-width-md: 28rem
440
- --max-width-lg: 32rem
441
- --max-width-xl: 36rem
442
- --max-width-2xl: 42rem
443
- --width-xs: 20rem
444
- --width-sm: 24rem
445
- --width-md: 28rem
446
- --width-lg: 32rem
447
- --width-xl: 36rem
448
- --width-2xl: 42rem
449
- --min-width-xs: 20rem
450
- --min-width-sm: 24rem
451
- --min-width-md: 28rem
452
- --min-width-lg: 32rem
453
- --min-width-xl: 36rem
454
- --min-width-2xl: 42rem
598
+ --max-width-xs: 20rem;
599
+ --max-width-sm: 24rem;
600
+ --max-width-md: 28rem;
601
+ --max-width-lg: 32rem;
602
+ --max-width-xl: 36rem;
603
+ --max-width-2xl: 42rem;
604
+ --width-xs: 20rem;
605
+ --width-sm: 24rem;
606
+ --width-md: 28rem;
607
+ --width-lg: 32rem;
608
+ --width-xl: 36rem;
609
+ --width-2xl: 42rem;
610
+ --min-width-xs: 20rem;
611
+ --min-width-sm: 24rem;
612
+ --min-width-md: 28rem;
613
+ --min-width-lg: 32rem;
614
+ --min-width-xl: 36rem;
615
+ --min-width-2xl: 42rem;
455
616
  /* ----------------------------------------------------------------
456
617
  * BORDER RADIUS — four values, chosen by ROLE, never by size.
457
618
  * A large button is a bigger box with the same corner as a small one.
458
619
  * Enforced by scripts/check-control-geometry.js.
459
620
  * ---------------------------------------------------------------- */
460
- --radius-control: 0.5rem
621
+ --radius-control: 0.5rem;
461
622
  /* 8px — buttons, inputs, selects, toggles */
462
- --radius-container: 0.75rem
623
+ --radius-container: 0.75rem;
463
624
  /* 12px — cards, alerts, panels, list items */
464
- --radius-overlay: 1rem
625
+ --radius-overlay: 1rem;
465
626
  /* 16px — modals, sheets, menus, popovers */
466
- --radius-pill: 9999px
627
+ --radius-pill: 9999px;
467
628
  /* badges, avatars, status dots */
468
629
  /* Legacy t-shirt radii. Kept so existing consumer overrides keep working;
469
630
  * components must not use them. */
470
- --radius-sm: 0.25rem
471
- --radius-md: 0.375rem
472
- --radius-lg: 0.5rem
473
- --radius-xl: 0.75rem
631
+ --radius-sm: 0.25rem;
632
+ --radius-md: 0.375rem;
633
+ --radius-lg: 0.5rem;
634
+ --radius-xl: 0.75rem;
474
635
  /* ----------------------------------------------------------------
475
636
  * CONTROL GEOMETRY — one height scale shared by every form control, so a
476
637
  * Button, Input, Select and IconButton of the same size are the same height
477
638
  * and line up in a row. They previously rendered at 40/48/64, 38/46/50 and
478
639
  * 32/40/48 respectively. Grid-aligned (8px).
479
640
  * ---------------------------------------------------------------- */
480
- --control-height-sm: 2rem
641
+ --control-height-sm: 2rem;
481
642
  /* 32px */
482
- --control-height-md: 2.5rem
643
+ --control-height-md: 2.5rem;
483
644
  /* 40px */
484
- --control-height-lg: 3rem
645
+ --control-height-lg: 3rem;
485
646
  /* 48px */
486
647
  /* Z-index */
487
- --z-dropdown: 1000
488
- --z-sticky: 1020
489
- --z-fixed: 1030
490
- --z-modal-backdrop: 1040
491
- --z-modal: 1050
492
- --z-popover: 1060
493
- --z-tooltip: 1070
494
- --z-toast: 1080
648
+ --z-dropdown: 1000;
649
+ --z-sticky: 1020;
650
+ --z-fixed: 1030;
651
+ --z-modal-backdrop: 1040;
652
+ --z-modal: 1050;
653
+ --z-popover: 1060;
654
+ --z-tooltip: 1070;
655
+ --z-toast: 1080;
495
656
  /* Tooltip — elevated hint surface (Tooltip.svelte); arrow uses --color-tooltip-bg */
496
- --color-tooltip-bg: var(--color-base-800)
497
- --color-tooltip-fg: var(--color-base-50)
498
- }
657
+ --color-tooltip-bg: var(--color-base-800);
658
+ --color-tooltip-fg: var(--color-base-50);
659
+ }
660
+
661
+ @layer base {
662
+ :root {
663
+ --tw-ring-offset-color: transparent;
664
+ }
665
+ }
666
+
667
+ @media (prefers-contrast: high) {
668
+ :root {
669
+ --color-tooltip-bg: CanvasText;
670
+ --color-tooltip-fg: Canvas;
671
+ }
672
+ }
673
+
674
+ body {
675
+ font-family: var(--font-family-sans);
676
+ }
677
+
678
+ @layer base {
679
+ h1,
680
+ h2,
681
+ h3,
682
+ h4,
683
+ h5,
684
+ h6 {
685
+ font-family: var(--font-family-heading);
686
+ }
687
+ }
688
+
689
+ :root,
690
+ [data-theme="light"] {
691
+ color-scheme: light;
692
+ }
693
+
694
+ .bg-base-50 {
695
+ background-color: var(--color-base-50);
696
+ }
697
+
698
+ .bg-base-75 {
699
+ background-color: var(--color-base-75);
700
+ }
701
+
702
+ .bg-base-100 {
703
+ background-color: var(--color-base-100);
704
+ }
705
+
706
+ .bg-base-150 {
707
+ background-color: var(--color-base-150);
708
+ }
709
+
710
+ .bg-base-200 {
711
+ background-color: var(--color-base-200);
712
+ }
713
+
714
+ .bg-base-250 {
715
+ background-color: var(--color-base-250);
716
+ }
717
+
718
+ .bg-base-300 {
719
+ background-color: var(--color-base-300);
720
+ }
721
+
722
+ .bg-base-350 {
723
+ background-color: var(--color-base-350);
724
+ }
725
+
726
+ .bg-base-400 {
727
+ background-color: var(--color-base-400);
728
+ }
729
+
730
+ .bg-base-450 {
731
+ background-color: var(--color-base-450);
732
+ }
733
+
734
+ .bg-base-500 {
735
+ background-color: var(--color-base-500);
736
+ }
737
+
738
+ .bg-base-550 {
739
+ background-color: var(--color-base-550);
740
+ }
741
+
742
+ .bg-base-600 {
743
+ background-color: var(--color-base-600);
744
+ }
745
+
746
+ .bg-base-650 {
747
+ background-color: var(--color-base-650);
748
+ }
749
+
750
+ .bg-base-700 {
751
+ background-color: var(--color-base-700);
752
+ }
753
+
754
+ .bg-base-750 {
755
+ background-color: var(--color-base-750);
756
+ }
757
+
758
+ .bg-base-800 {
759
+ background-color: var(--color-base-800);
760
+ }
761
+
762
+ .bg-base-850 {
763
+ background-color: var(--color-base-850);
764
+ }
765
+
766
+ .bg-base-900 {
767
+ background-color: var(--color-base-900);
768
+ }
769
+
770
+ .bg-base-925 {
771
+ background-color: var(--color-base-925);
772
+ }
773
+
774
+ .bg-base-950 {
775
+ background-color: var(--color-base-950);
776
+ }
777
+
778
+ @media (hover: hover) {
779
+ .hover\:bg-base-50:hover {
780
+ background-color: var(--color-base-50);
781
+ }
782
+
783
+ .hover\:bg-base-75:hover {
784
+ background-color: var(--color-base-75);
785
+ }
786
+
787
+ .hover\:bg-base-100:hover {
788
+ background-color: var(--color-base-100);
789
+ }
790
+
791
+ .hover\:bg-base-150:hover {
792
+ background-color: var(--color-base-150);
793
+ }
794
+
795
+ .hover\:bg-base-200:hover {
796
+ background-color: var(--color-base-200);
797
+ }
798
+
799
+ .hover\:bg-base-250:hover {
800
+ background-color: var(--color-base-250);
801
+ }
802
+
803
+ .hover\:bg-base-300:hover {
804
+ background-color: var(--color-base-300);
805
+ }
806
+
807
+ .hover\:bg-base-350:hover {
808
+ background-color: var(--color-base-350);
809
+ }
810
+
811
+ .hover\:bg-base-400:hover {
812
+ background-color: var(--color-base-400);
813
+ }
814
+
815
+ .hover\:bg-base-450:hover {
816
+ background-color: var(--color-base-450);
817
+ }
818
+
819
+ .hover\:bg-base-500:hover {
820
+ background-color: var(--color-base-500);
821
+ }
822
+
823
+ .hover\:bg-base-550:hover {
824
+ background-color: var(--color-base-550);
825
+ }
826
+
827
+ .hover\:bg-base-600:hover {
828
+ background-color: var(--color-base-600);
829
+ }
830
+
831
+ .hover\:bg-base-650:hover {
832
+ background-color: var(--color-base-650);
833
+ }
834
+
835
+ .hover\:bg-base-700:hover {
836
+ background-color: var(--color-base-700);
837
+ }
838
+
839
+ .hover\:bg-base-750:hover {
840
+ background-color: var(--color-base-750);
841
+ }
842
+
843
+ .hover\:bg-base-800:hover {
844
+ background-color: var(--color-base-800);
845
+ }
846
+
847
+ .hover\:bg-base-850:hover {
848
+ background-color: var(--color-base-850);
849
+ }
850
+
851
+ .hover\:bg-base-900:hover {
852
+ background-color: var(--color-base-900);
853
+ }
854
+
855
+ .hover\:bg-base-925:hover {
856
+ background-color: var(--color-base-925);
857
+ }
858
+
859
+ .hover\:bg-base-950:hover {
860
+ background-color: var(--color-base-950);
861
+ }
862
+ }
863
+
864
+ .bg-card {
865
+ background-color: var(--color-card);
866
+ }
867
+
868
+ @media (hover: hover) {
869
+ .hover\:bg-card-hover:hover {
870
+ background-color: var(--color-card-hover);
871
+ }
872
+ }
873
+
874
+ .bg-surface-1 {
875
+ background-color: var(--color-surface-1);
876
+ }
877
+
878
+ .bg-surface-2 {
879
+ background-color: var(--color-surface-2);
880
+ }
881
+
882
+ .bg-surface-3 {
883
+ background-color: var(--color-surface-3);
884
+ }
885
+
886
+ .bg-surface-4 {
887
+ background-color: var(--color-surface-4);
888
+ }
889
+
890
+ .bg-overlay {
891
+ background-color: var(--color-overlay);
892
+ }
893
+
894
+ .bg-input {
895
+ background-color: var(--color-input);
896
+ }
897
+
898
+ @media (hover: hover) {
899
+ .hover\:bg-input-hover:hover {
900
+ background-color: var(--color-input-hover);
901
+ }
902
+ }
903
+
904
+ .focus-visible\:bg-input-focus:focus-visible {
905
+ background-color: var(--color-input-focus);
906
+ }
907
+
908
+ .active\:bg-input-focus:active {
909
+ background-color: var(--color-input-focus);
910
+ }
911
+
912
+ .active\:bg-input-hover:active {
913
+ background-color: var(--color-input-hover);
914
+ }
915
+
916
+ .active\:bg-input-active:active {
917
+ background-color: var(--color-input-active, var(--color-input-hover));
918
+ }
919
+
920
+ .active\:bg-card-active:active {
921
+ background-color: var(--color-card-active);
922
+ }
923
+
924
+ .disabled\:bg-input-disabled:disabled {
925
+ background-color: var(--color-input-disabled);
926
+ }
927
+
928
+ .bg-page {
929
+ background-color: var(--color-page);
930
+ }
931
+
932
+ .bg-brand-50 {
933
+ background-color: var(--color-brand-50);
934
+ }
935
+
936
+ .bg-brand-100 {
937
+ background-color: var(--color-brand-100);
938
+ }
939
+
940
+ .bg-brand-200 {
941
+ background-color: var(--color-brand-200);
942
+ }
943
+
944
+ .bg-brand-300 {
945
+ background-color: var(--color-brand-300);
946
+ }
947
+
948
+ .bg-brand-400 {
949
+ background-color: var(--color-brand-400);
950
+ }
951
+
952
+ .bg-brand-500 {
953
+ background-color: var(--color-brand-500);
954
+ }
955
+
956
+ .bg-brand-600 {
957
+ background-color: var(--color-brand-600);
958
+ }
959
+
960
+ .bg-brand-700 {
961
+ background-color: var(--color-brand-700);
962
+ }
963
+
964
+ .bg-brand-800 {
965
+ background-color: var(--color-brand-800);
966
+ }
967
+
968
+ .bg-brand-900 {
969
+ background-color: var(--color-brand-900);
970
+ }
971
+
972
+ .bg-brand-950 {
973
+ background-color: var(--color-brand-950);
974
+ }
975
+
976
+ @media (hover: hover) {
977
+ .hover\:bg-brand-50:hover {
978
+ background-color: var(--color-brand-50);
979
+ }
980
+
981
+ .hover\:bg-brand-100:hover {
982
+ background-color: var(--color-brand-100);
983
+ }
984
+
985
+ .hover\:bg-brand-200:hover {
986
+ background-color: var(--color-brand-200);
987
+ }
988
+ }
989
+
990
+ .text-brand-50 {
991
+ color: var(--color-brand-50);
992
+ }
993
+
994
+ .text-brand-100 {
995
+ color: var(--color-brand-100);
996
+ }
997
+
998
+ .text-brand-200 {
999
+ color: var(--color-brand-200);
1000
+ }
1001
+
1002
+ .text-brand-300 {
1003
+ color: var(--color-brand-300);
1004
+ }
1005
+
1006
+ .text-brand-400 {
1007
+ color: var(--color-brand-400);
1008
+ }
1009
+
1010
+ .text-brand-500 {
1011
+ color: var(--color-brand-500);
1012
+ }
1013
+
1014
+ .text-brand-600 {
1015
+ color: var(--color-brand-600);
1016
+ }
1017
+
1018
+ .text-brand-700 {
1019
+ color: var(--color-brand-700);
1020
+ }
1021
+
1022
+ .text-brand-800 {
1023
+ color: var(--color-brand-800);
1024
+ }
1025
+
1026
+ .text-brand-900 {
1027
+ color: var(--color-brand-900);
1028
+ }
1029
+
1030
+ .text-brand-950 {
1031
+ color: var(--color-brand-950);
1032
+ }
1033
+
1034
+ .border-brand-50 {
1035
+ border-color: var(--color-brand-50);
1036
+ }
1037
+
1038
+ .border-brand-100 {
1039
+ border-color: var(--color-brand-100);
1040
+ }
1041
+
1042
+ .border-brand-500 {
1043
+ border-color: var(--color-brand-500);
1044
+ }
1045
+
1046
+ .border-brand-600 {
1047
+ border-color: var(--color-brand-600);
1048
+ }
1049
+
1050
+ .text-headline {
1051
+ color: var(--color-headline);
1052
+ }
1053
+
1054
+ .text-body {
1055
+ color: var(--color-body);
1056
+ }
1057
+
1058
+ .text-description {
1059
+ color: var(--color-description);
1060
+ }
1061
+
1062
+ .text-caption {
1063
+ color: var(--color-caption);
1064
+ }
1065
+
1066
+ .text-input-placeholder {
1067
+ color: var(--color-input-placeholder);
1068
+ }
1069
+
1070
+ .placeholder\:text-input-placeholder:disabled::placeholder {
1071
+ color: var(--color-action-disabled-text);
1072
+ }
1073
+
1074
+ .text-label {
1075
+ color: var(--color-label);
1076
+ }
1077
+
1078
+ .text-link {
1079
+ color: var(--color-link);
1080
+ }
1081
+
1082
+ @media (hover: hover) {
1083
+ .text-link:hover {
1084
+ color: var(--color-link-hover);
1085
+ }
1086
+ }
1087
+
1088
+ .text-link:active {
1089
+ color: var(--color-link-hover);
1090
+ }
1091
+
1092
+ .text-nav-menu-item {
1093
+ color: var(--color-nav-menu-item);
1094
+ }
1095
+
1096
+ @media (hover: hover) {
1097
+ .hover\:text-nav-menu-item-hover:hover {
1098
+ color: var(--color-nav-menu-item-hover);
1099
+ }
1100
+ }
1101
+
1102
+ .text-nav-menu-item-active {
1103
+ color: var(--color-nav-menu-item-active);
1104
+ }
1105
+
1106
+ .bg-nav-menu-hover {
1107
+ background-color: var(--color-nav-menu-hover);
1108
+ }
1109
+
1110
+ .bg-nav-menu-active {
1111
+ background-color: var(--color-nav-menu-active);
1112
+ }
1113
+
1114
+ .active\:bg-nav-menu-active-hover:active {
1115
+ background-color: var(--color-nav-menu-active-hover);
1116
+ }
1117
+
1118
+ .bg-nav-menu-item-active {
1119
+ background-color: var(--color-nav-menu-item-active);
1120
+ }
1121
+
1122
+ .text-success {
1123
+ color: var(--color-success-text);
1124
+ }
1125
+
1126
+ .text-warning {
1127
+ color: var(--color-warning-text);
1128
+ }
1129
+
1130
+ .text-error {
1131
+ color: var(--color-error-text);
1132
+ }
1133
+
1134
+ .text-info {
1135
+ color: var(--color-info-text);
1136
+ }
1137
+
1138
+ .text-neutral {
1139
+ color: var(--color-neutral-text);
1140
+ }
1141
+
1142
+ .text-energetic {
1143
+ color: var(--color-energetic-text);
1144
+ }
1145
+
1146
+ .text-accent {
1147
+ color: var(--color-accent-text);
1148
+ }
1149
+
1150
+ .text-inverse {
1151
+ color: var(--color-inverse);
1152
+ }
1153
+
1154
+ .text-disabled {
1155
+ color: var(--color-disabled);
1156
+ }
1157
+
1158
+ .border-border {
1159
+ border-color: var(--color-border);
1160
+ }
1161
+
1162
+ .border-border-medium {
1163
+ border-color: var(--color-border-medium);
1164
+ }
1165
+
1166
+ .border-primary {
1167
+ border-color: var(--color-border);
1168
+ }
1169
+
1170
+ .border-secondary {
1171
+ border-color: var(--color-border-secondary);
1172
+ }
1173
+
1174
+ @media (hover: hover) {
1175
+ .border-hover:hover {
1176
+ border-color: var(--color-border-hover);
1177
+ }
1178
+ }
1179
+
1180
+ .border-disabled:disabled {
1181
+ border-color: var(--color-border-disabled);
1182
+ }
1183
+
1184
+ .bg-success {
1185
+ background-color: var(--color-success);
1186
+ }
1187
+
1188
+ .bg-warning {
1189
+ background-color: var(--color-warning);
1190
+ }
1191
+
1192
+ .bg-error {
1193
+ background-color: var(--color-error);
1194
+ }
1195
+
1196
+ .bg-info {
1197
+ background-color: var(--color-info);
1198
+ }
1199
+
1200
+ .bg-neutral {
1201
+ background-color: var(--color-neutral);
1202
+ }
1203
+
1204
+ .bg-energetic {
1205
+ background-color: var(--color-energetic);
1206
+ }
1207
+
1208
+ .bg-accent {
1209
+ background-color: var(--color-accent);
1210
+ }
1211
+
1212
+ .bg-secondary {
1213
+ background-color: var(--color-secondary);
1214
+ }
1215
+
1216
+ .border-success {
1217
+ border-color: var(--color-success);
1218
+ }
1219
+
1220
+ .border-warning {
1221
+ border-color: var(--color-warning);
1222
+ }
1223
+
1224
+ .border-error {
1225
+ border-color: var(--color-error);
1226
+ }
1227
+
1228
+ .border-info {
1229
+ border-color: var(--color-info);
1230
+ }
1231
+
1232
+ .border-neutral {
1233
+ border-color: var(--color-neutral);
1234
+ }
1235
+
1236
+ .border-energetic {
1237
+ border-color: var(--color-energetic);
1238
+ }
1239
+
1240
+ .border-accent {
1241
+ border-color: var(--color-accent);
1242
+ }
1243
+
1244
+ .border-secondary {
1245
+ border-color: var(--color-secondary);
1246
+ }
1247
+
1248
+ @layer components {
1249
+ .focus-ring {
1250
+ --zabi-focus-ring-color: var(--color-focus-ring);
1251
+ --zabi-focus-ring-offset-color: var(--color-focus-ring-offset);
1252
+ outline: none;
1253
+ }
1254
+
1255
+ .focus-ring:focus-visible {
1256
+ outline: none;
1257
+ --tw-ring-offset-shadow:
1258
+ 0 0 0 2px var(--zabi-focus-ring-offset-color),
1259
+ 0 0 0 4px var(--zabi-focus-ring-color);
1260
+ box-shadow:
1261
+ var(--tw-inset-shadow, 0 0 #0000),
1262
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1263
+ var(--tw-ring-offset-shadow),
1264
+ var(--tw-ring-shadow, 0 0 #0000),
1265
+ var(--tw-shadow, 0 0 #0000);
1266
+ }
1267
+ .focus-ring--nav {
1268
+ --zabi-focus-ring-color: var(--color-nav-menu-focus);
1269
+ }
1270
+ .focus-ring--danger {
1271
+ --zabi-focus-ring-color: var(--color-focus-ring-danger, var(--color-error));
1272
+ }
1273
+ .focus-ring--muted {
1274
+ --zabi-focus-ring-color: var(--color-focus-ring-muted, var(--color-base-500));
1275
+ }
1276
+ :where(:has(> .on-brand, > .on-accent):not(.on-brand, .on-accent, .on-brand *, .on-accent *)) {
1277
+ --zabi-theme-headline: var(--color-headline);
1278
+ --zabi-theme-body: var(--color-body);
1279
+ --zabi-theme-label: var(--color-label);
1280
+ --zabi-theme-description: var(--color-description);
1281
+ --zabi-theme-caption: var(--color-caption);
1282
+ --zabi-theme-link: var(--color-link);
1283
+ --zabi-theme-link-hover: var(--color-link-hover);
1284
+ --zabi-theme-border: var(--color-border);
1285
+ --zabi-theme-border-medium: var(--color-border-medium);
1286
+ --zabi-theme-border-strong: var(--color-border-strong);
1287
+ --zabi-theme-control-border: var(--color-control-border);
1288
+ --zabi-theme-focus-ring: var(--color-focus-ring);
1289
+ --zabi-theme-focus-ring-muted: var(--color-focus-ring-muted);
1290
+ --zabi-theme-nav-menu-focus: var(--color-nav-menu-focus);
1291
+ --zabi-theme-focus-ring-offset: var(--color-focus-ring-offset);
1292
+ --zabi-theme-focus-ring-danger: var(--color-focus-ring-danger, var(--color-error));
1293
+ }
1294
+
1295
+ .on-brand {
1296
+ color: var(--color-on-brand);
1297
+ --color-focus-ring: var(--color-on-brand);
1298
+ --color-focus-ring-muted: var(--color-on-brand);
1299
+ --color-nav-menu-focus: var(--color-on-brand);
1300
+ --color-focus-ring-offset: var(--color-action-primary);
1301
+ --color-focus-ring-danger: var(--color-on-brand);
1302
+ --color-headline: var(--color-on-brand);
1303
+ --color-body: var(--color-on-brand);
1304
+ --color-label: var(--color-on-brand);
1305
+ --color-description: var(--color-on-brand);
1306
+ --color-caption: var(--color-on-brand);
1307
+ --color-link: var(--color-on-brand);
1308
+ --color-link-hover: var(--color-on-brand);
1309
+ --color-border: var(--color-on-brand);
1310
+ --color-border-medium: var(--color-on-brand);
1311
+ --color-border-strong: var(--color-on-brand);
1312
+ --color-control-border: var(--color-on-brand);
1313
+ }
1314
+
1315
+ .on-accent {
1316
+ color: var(--color-on-accent);
1317
+ --color-focus-ring: var(--color-on-accent);
1318
+ --color-focus-ring-muted: var(--color-on-accent);
1319
+ --color-nav-menu-focus: var(--color-on-accent);
1320
+ --color-focus-ring-offset: var(--color-accent);
1321
+ --color-focus-ring-danger: var(--color-on-accent);
1322
+ --color-headline: var(--color-on-accent);
1323
+ --color-body: var(--color-on-accent);
1324
+ --color-label: var(--color-on-accent);
1325
+ --color-description: var(--color-on-accent);
1326
+ --color-caption: var(--color-on-accent);
1327
+ --color-link: var(--color-on-accent);
1328
+ --color-link-hover: var(--color-on-accent);
1329
+ --color-border: var(--color-on-accent);
1330
+ --color-border-medium: var(--color-on-accent);
1331
+ --color-border-strong: var(--color-on-accent);
1332
+ --color-control-border: var(--color-on-accent);
1333
+ }
1334
+ :where(.on-brand, .on-accent)
1335
+ :where(
1336
+ .bg-card, .bg-card-elevated, .bg-background, .bg-surface-base,
1337
+ .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,
1339
+ .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,
1342
+ .bg-nav-menu-active, .bg-action-disabled, .list-group, .on-surface
1343
+ ) {
1344
+ color: var(--zabi-theme-body);
1345
+ --color-headline: var(--zabi-theme-headline);
1346
+ --color-body: var(--zabi-theme-body);
1347
+ --color-label: var(--zabi-theme-label);
1348
+ --color-description: var(--zabi-theme-description);
1349
+ --color-caption: var(--zabi-theme-caption);
1350
+ --color-link: var(--zabi-theme-link);
1351
+ --color-link-hover: var(--zabi-theme-link-hover);
1352
+ --color-border: var(--zabi-theme-border);
1353
+ --color-border-medium: var(--zabi-theme-border-medium);
1354
+ --color-border-strong: var(--zabi-theme-border-strong);
1355
+ --color-control-border: var(--zabi-theme-control-border);
1356
+ }
1357
+ :where(.on-brand, .on-accent)
1358
+ :where(
1359
+ .bg-card, .bg-card-elevated, .bg-background, .bg-surface-base,
1360
+ .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,
1362
+ .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,
1365
+ .bg-nav-menu-active, .bg-action-disabled, .list-group, .on-surface
1366
+ )
1367
+ > :where(*) {
1368
+ --color-focus-ring: var(--zabi-theme-focus-ring);
1369
+ --color-focus-ring-muted: var(--zabi-theme-focus-ring-muted);
1370
+ --color-nav-menu-focus: var(--zabi-theme-nav-menu-focus);
1371
+ --color-focus-ring-offset: var(--zabi-theme-focus-ring-offset);
1372
+ --color-focus-ring-danger: var(--zabi-theme-focus-ring-danger);
1373
+ }
1374
+ .list-group {
1375
+ @apply space-y-1 overflow-hidden rounded-xl border border-border p-1;
1376
+ background-color: var(--color-surface-1);
1377
+ --zabi-list-row-radius: calc(var(--radius-container) - 0.25rem - 1px);
1378
+ }
1379
+ .focus-brand {
1380
+ --zabi-focus-ring-color: var(--color-focus-ring);
1381
+ --zabi-focus-ring-offset-color: var(--color-focus-ring-offset);
1382
+ outline: none;
1383
+ }
1384
+
1385
+ .focus-brand:focus-visible {
1386
+ outline: none;
1387
+ --tw-ring-offset-shadow:
1388
+ 0 0 0 2px var(--zabi-focus-ring-offset-color),
1389
+ 0 0 0 4px var(--zabi-focus-ring-color);
1390
+ box-shadow:
1391
+ var(--tw-inset-shadow, 0 0 #0000),
1392
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1393
+ var(--tw-ring-offset-shadow),
1394
+ var(--tw-ring-shadow, 0 0 #0000),
1395
+ var(--tw-shadow, 0 0 #0000);
1396
+ }
1397
+
1398
+ .focus-nav {
1399
+ --zabi-focus-ring-color: var(--color-nav-menu-focus);
1400
+ --zabi-focus-ring-offset-color: var(--color-focus-ring-offset);
1401
+ outline: none;
1402
+ }
1403
+
1404
+ .focus-nav:focus-visible {
1405
+ outline: none;
1406
+ --tw-ring-offset-shadow:
1407
+ 0 0 0 2px var(--zabi-focus-ring-offset-color),
1408
+ 0 0 0 4px var(--zabi-focus-ring-color);
1409
+ box-shadow:
1410
+ var(--tw-inset-shadow, 0 0 #0000),
1411
+ var(--tw-inset-ring-shadow, 0 0 #0000),
1412
+ var(--tw-ring-offset-shadow),
1413
+ var(--tw-ring-shadow, 0 0 #0000),
1414
+ var(--tw-shadow, 0 0 #0000);
1415
+ }
1416
+ .selection-control-label-row-interaction {
1417
+ @apply rounded-md transition-colors outline-none cursor-pointer hover:bg-surface-hover active:bg-surface-active has-disabled:opacity-50 has-disabled:cursor-not-allowed has-disabled:hover:bg-transparent has-disabled:active:bg-transparent;
1418
+ box-shadow: none;
1419
+ }
1420
+
1421
+ .selection-control-label-row-interaction:has(:focus-visible) {
1422
+ box-shadow:
1423
+ 0 0 0 2px var(--color-focus-ring-offset),
1424
+ 0 0 0 4px var(--color-focus-ring);
1425
+ }
1426
+ .selection-control-option-row {
1427
+ box-shadow: none;
1428
+ }
1429
+
1430
+ .selection-control-option-row:has(:checked) {
1431
+ box-shadow:
1432
+ 0 0 0 2px var(--color-focus-ring-offset),
1433
+ 0 0 0 4px var(--color-focus-ring);
1434
+ }
1435
+ }
1436
+
1437
+ @media (forced-colors: active) {
1438
+ .focus-ring:focus-visible,
1439
+ .focus-brand:focus-visible,
1440
+ .focus-nav:focus-visible,
1441
+ .selection-control-label-row-interaction:has(:focus-visible) {
1442
+ outline: 2px solid Highlight;
1443
+ outline-offset: 2px;
1444
+ }
1445
+ }
1446
+
1447
+ .bg-action-primary {
1448
+ background-color: var(--color-action-primary);
1449
+ }
1450
+
1451
+ @media (hover: hover) {
1452
+ .bg-action-primary:hover {
1453
+ background-color: var(--color-action-primary-hover);
1454
+ }
1455
+ }
1456
+
1457
+ .bg-action-primary:active {
1458
+ background-color: var(--color-action-primary-active);
1459
+ }
1460
+
1461
+ .bg-action-primary:disabled {
1462
+ background-color: var(--color-action-disabled);
1463
+ color: var(--color-action-disabled-text);
1464
+ }
1465
+
1466
+ .bg-action-primary-subtle {
1467
+ background-color: var(--color-action-primary-subtle);
1468
+ }
1469
+
1470
+ @media (hover: hover) {
1471
+ .bg-action-primary-subtle:hover {
1472
+ background-color: var(--color-action-primary-subtle-hover);
1473
+ }
1474
+ }
1475
+
1476
+ .text-action-primary {
1477
+ color: var(--color-action-primary-text);
1478
+ }
1479
+
1480
+ .bg-action-secondary {
1481
+ background-color: var(--color-action-secondary);
1482
+ }
1483
+
1484
+ @media (hover: hover) {
1485
+ .bg-action-secondary:hover {
1486
+ background-color: var(--color-action-secondary-hover);
1487
+ }
1488
+ }
1489
+
1490
+ .bg-action-secondary:active {
1491
+ background-color: var(--color-action-secondary-active);
1492
+ }
1493
+
1494
+ .bg-action-secondary:disabled {
1495
+ background-color: var(--color-action-disabled);
1496
+ color: var(--color-action-disabled-text);
1497
+ }
1498
+
1499
+ .bg-action-secondary-subtle {
1500
+ background-color: var(--color-action-secondary-subtle);
1501
+ }
1502
+
1503
+ @media (hover: hover) {
1504
+ .bg-action-secondary-subtle:hover {
1505
+ background-color: var(--color-action-secondary-subtle-hover);
1506
+ }
1507
+ }
1508
+
1509
+ .bg-action-danger {
1510
+ background-color: var(--color-action-danger);
1511
+ }
1512
+
1513
+ @media (hover: hover) {
1514
+ .bg-action-danger:hover {
1515
+ background-color: var(--color-action-danger-hover);
1516
+ }
1517
+ }
1518
+
1519
+ .bg-action-danger:active {
1520
+ background-color: var(--color-action-danger-active);
1521
+ }
1522
+
1523
+ .bg-action-danger:disabled {
1524
+ background-color: var(--color-action-disabled);
1525
+ color: var(--color-action-disabled-text);
1526
+ }
1527
+
1528
+ .bg-action-danger-subtle {
1529
+ background-color: var(--color-action-danger-subtle);
1530
+ }
1531
+
1532
+ @media (hover: hover) {
1533
+ .bg-action-danger-subtle:hover {
1534
+ background-color: var(--color-action-danger-subtle-hover);
1535
+ }
1536
+ }
1537
+
1538
+ @media (hover: hover) {
1539
+ .hover\:text-body:hover {
1540
+ color: var(--color-body);
1541
+ }
1542
+
1543
+ .hover\:text-headline:hover {
1544
+ color: var(--color-headline);
1545
+ }
1546
+
1547
+ .hover\:text-link:hover {
1548
+ color: var(--color-link);
1549
+ }
1550
+
1551
+ .enabled\:hover\:text-error-text:enabled:hover {
1552
+ color: var(--color-error-text);
1553
+ }
1554
+
1555
+ .group:hover .group-hover\:text-headline\/90 {
1556
+ color: color-mix(in oklab, var(--color-headline) 90%, transparent);
1557
+ }
1558
+ }
1559
+
1560
+ .active\:text-headline:active {
1561
+ color: var(--color-headline);
1562
+ }
1563
+
1564
+ .active\:text-link:active {
1565
+ color: var(--color-link);
1566
+ }
1567
+
1568
+ .disabled\:text-action-disabled-text:disabled {
1569
+ color: var(--color-action-disabled-text);
1570
+ }
1571
+
1572
+ .disabled\:hover\:text-description:disabled:hover {
1573
+ color: var(--color-description);
1574
+ }
1575
+
1576
+ @media (hover: hover) {
1577
+ .hover\:border-border-medium:hover {
1578
+ border-color: var(--color-border-medium);
1579
+ }
1580
+
1581
+ .enabled\:hover\:border-border-medium:enabled:hover {
1582
+ border-color: var(--color-border-medium);
1583
+ }
1584
+ }
1585
+
1586
+ .disabled\:border-transparent:disabled {
1587
+ border-color: transparent;
1588
+ }
1589
+
1590
+ .disabled\:hover\:border-transparent:disabled:hover {
1591
+ border-color: transparent;
1592
+ }
1593
+
1594
+ @media (hover: hover) {
1595
+ .hover\:bg-accent-hover:hover {
1596
+ background-color: var(--color-accent-hover);
1597
+ }
1598
+
1599
+ .hover\:text-accent-hover:hover {
1600
+ color: var(--color-accent-hover);
1601
+ }
1602
+
1603
+ .hover\:border-accent-hover:hover {
1604
+ border-color: var(--color-accent-hover);
1605
+ }
1606
+
1607
+ .hover\:bg-nav-menu-active-hover:hover {
1608
+ background-color: var(--color-nav-menu-active-hover);
1609
+ }
1610
+ }
1611
+
1612
+ .active\:bg-accent-active:active {
1613
+ background-color: var(--color-accent-active);
1614
+ }
1615
+
1616
+ .active\:text-accent-active:active {
1617
+ color: var(--color-accent-active);
1618
+ }
1619
+
1620
+ .active\:border-accent-active:active {
1621
+ border-color: var(--color-accent-active);
1622
+ }
1623
+
1624
+ .active\:bg-info-active:active {
1625
+ background-color: var(--color-info-active);
1626
+ }
1627
+
1628
+ .active\:text-info-active:active {
1629
+ color: var(--color-info-active);
1630
+ }
1631
+
1632
+ .active\:border-info-active:active {
1633
+ border-color: var(--color-info-active);
1634
+ }
1635
+
1636
+ .active\:bg-action-primary-subtle-hover:active {
1637
+ background-color: var(--color-action-primary-subtle-hover);
1638
+ }
1639
+
1640
+ .active\:bg-action-danger-subtle-hover:active {
1641
+ background-color: var(--color-action-danger-subtle-hover);
1642
+ }
1643
+
1644
+ .active\:bg-action-primary-subtle-active:active {
1645
+ background-color: var(--color-action-primary-subtle-active, var(--color-action-primary-subtle-hover));
1646
+ }
1647
+
1648
+ .active\:bg-action-danger-subtle-active:active {
1649
+ background-color: var(--color-action-danger-subtle-active, var(--color-action-danger-subtle-hover));
1650
+ }
1651
+
1652
+ .disabled\:bg-action-disabled:disabled {
1653
+ background-color: var(--color-action-disabled);
1654
+ }
1655
+
1656
+ .z-sticky {
1657
+ z-index: var(--z-sticky);
1658
+ }
1659
+
1660
+ .z-dropdown {
1661
+ z-index: var(--z-dropdown);
1662
+ }
1663
+
1664
+ .z-modal {
1665
+ z-index: var(--z-modal);
1666
+ }
1667
+
1668
+ .z-modal-backdrop {
1669
+ z-index: var(--z-modal-backdrop);
1670
+ }
1671
+
1672
+ .z-popover {
1673
+ z-index: var(--z-popover);
1674
+ }
1675
+
1676
+ .z-tooltip {
1677
+ z-index: var(--z-tooltip);
1678
+ }
1679
+
1680
+ .z-toast {
1681
+ z-index: var(--z-toast);
1682
+ }
1683
+
1684
+ @keyframes slideUp {
1685
+ from {
1686
+ transform: translateY(100%);
1687
+ }
1688
+ to {
1689
+ transform: translateY(0);
1690
+ }
1691
+ }
1692
+
1693
+ .scrollbar-semantic {
1694
+ scrollbar-width: thin;
1695
+ scrollbar-color: var(--color-base-400) var(--color-base-100);
1696
+ }
1697
+
1698
+ .scrollbar-semantic::-webkit-scrollbar {
1699
+ width: 10px;
1700
+ height: 10px;
1701
+ }
1702
+
1703
+ .scrollbar-semantic::-webkit-scrollbar-track {
1704
+ background-color: var(--color-base-100);
1705
+ }
1706
+
1707
+ .scrollbar-semantic::-webkit-scrollbar-thumb {
1708
+ background-color: var(--color-base-400);
1709
+ border-radius: var(--radius-md);
1710
+ border: 2px solid var(--color-base-100);
1711
+ }
1712
+
1713
+ .scrollbar-semantic::-webkit-scrollbar-thumb:hover {
1714
+ background-color: var(--color-base-500);
1715
+ }