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