@exxatdesignux/ui 0.2.18 → 0.3.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 (618) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +43 -4
  4. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
  5. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
  6. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
  7. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
  8. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
  9. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
  10. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
  11. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
  12. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
  13. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
  14. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
  15. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
  16. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
  17. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
  18. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
  19. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
  20. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
  21. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  23. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  24. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  25. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  26. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  27. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  28. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
  29. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
  30. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
  31. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
  32. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
  33. package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
  34. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +9 -9
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  39. package/consumer-extras/handbook/glossary.md +57 -0
  40. package/consumer-extras/handbook/reference-implementations.md +126 -0
  41. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  42. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  43. package/consumer-extras/patterns/data-views-pattern.md +14 -14
  44. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  45. package/dist/components/data-table/filter-date-calendar.js +280 -0
  46. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  47. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  48. package/dist/components/data-table/filter-text-value-input.js +561 -0
  49. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  50. package/dist/components/data-table/index.d.ts +45 -0
  51. package/dist/components/data-table/index.js +3085 -0
  52. package/dist/components/data-table/index.js.map +1 -0
  53. package/dist/components/data-table/pagination.d.ts +28 -0
  54. package/dist/components/data-table/pagination.js +3264 -0
  55. package/dist/components/data-table/pagination.js.map +1 -0
  56. package/dist/components/data-table/types.d.ts +84 -0
  57. package/dist/components/data-table/types.js +3 -0
  58. package/dist/components/data-table/types.js.map +1 -0
  59. package/dist/components/data-table/use-table-state.d.ts +116 -0
  60. package/dist/components/data-table/use-table-state.js +670 -0
  61. package/dist/components/data-table/use-table-state.js.map +1 -0
  62. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  63. package/dist/components/data-views/board-card-primitives.js +84 -0
  64. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  65. package/dist/components/data-views/data-row-list.d.ts +33 -0
  66. package/dist/components/data-views/data-row-list.js +106 -0
  67. package/dist/components/data-views/data-row-list.js.map +1 -0
  68. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  69. package/dist/components/data-views/finder-panel-view.js +388 -0
  70. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  71. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  72. package/dist/components/data-views/folder-grid-view.js +58 -0
  73. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  74. package/dist/components/data-views/hub-table.d.ts +167 -0
  75. package/dist/components/data-views/hub-table.js +5561 -0
  76. package/dist/components/data-views/hub-table.js.map +1 -0
  77. package/dist/components/data-views/index.d.ts +27 -0
  78. package/dist/components/data-views/index.js +6575 -0
  79. package/dist/components/data-views/index.js.map +1 -0
  80. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  81. package/dist/components/data-views/list-page-board-card.js +264 -0
  82. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  84. package/dist/components/data-views/list-page-board-template.js +137 -0
  85. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  86. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  87. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  88. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  89. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  90. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  91. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  93. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  94. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  96. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  97. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  98. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  99. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  100. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  102. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  103. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  104. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  105. package/dist/components/data-views/os-folder-glyph.js +104 -0
  106. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  107. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  108. package/dist/components/data-views/outline-tree-menu.js +131 -0
  109. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  110. package/dist/components/table-properties/column-row.d.ts +22 -0
  111. package/dist/components/table-properties/column-row.js +153 -0
  112. package/dist/components/table-properties/column-row.js.map +1 -0
  113. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  114. package/dist/components/table-properties/draggable-list.js +53 -0
  115. package/dist/components/table-properties/draggable-list.js.map +1 -0
  116. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  117. package/dist/components/table-properties/drawer-button.js +2748 -0
  118. package/dist/components/table-properties/drawer-button.js.map +1 -0
  119. package/dist/components/table-properties/drawer.d.ts +100 -0
  120. package/dist/components/table-properties/drawer.js +2595 -0
  121. package/dist/components/table-properties/drawer.js.map +1 -0
  122. package/dist/components/table-properties/filter-card.d.ts +24 -0
  123. package/dist/components/table-properties/filter-card.js +854 -0
  124. package/dist/components/table-properties/filter-card.js.map +1 -0
  125. package/dist/components/table-properties/index.d.ts +14 -0
  126. package/dist/components/table-properties/index.js +2768 -0
  127. package/dist/components/table-properties/index.js.map +1 -0
  128. package/dist/components/table-properties/sort-card.d.ts +20 -0
  129. package/dist/components/table-properties/sort-card.js +102 -0
  130. package/dist/components/table-properties/sort-card.js.map +1 -0
  131. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  132. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  133. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  135. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  136. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  137. package/dist/components/templates/index.d.ts +9 -0
  138. package/dist/components/templates/index.js +2720 -0
  139. package/dist/components/templates/index.js.map +1 -0
  140. package/dist/components/templates/list-page.d.ts +83 -0
  141. package/dist/components/templates/list-page.js +2433 -0
  142. package/dist/components/templates/list-page.js.map +1 -0
  143. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  144. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  145. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  146. package/dist/components/ui/accordion.d.ts +10 -0
  147. package/dist/components/ui/accordion.js +74 -0
  148. package/dist/components/ui/accordion.js.map +1 -0
  149. package/dist/components/ui/alert-dialog.d.ts +37 -0
  150. package/dist/components/ui/alert-dialog.js +201 -0
  151. package/dist/components/ui/alert-dialog.js.map +1 -0
  152. package/dist/components/ui/avatar.d.ts +84 -0
  153. package/dist/components/ui/avatar.js +328 -0
  154. package/dist/components/ui/avatar.js.map +1 -0
  155. package/dist/components/ui/badge.d.ts +13 -0
  156. package/dist/components/ui/badge.js +49 -0
  157. package/dist/components/ui/badge.js.map +1 -0
  158. package/dist/components/ui/banner.d.ts +62 -0
  159. package/dist/components/ui/banner.js +364 -0
  160. package/dist/components/ui/banner.js.map +1 -0
  161. package/dist/components/ui/breadcrumb.d.ts +14 -0
  162. package/dist/components/ui/breadcrumb.js +114 -0
  163. package/dist/components/ui/breadcrumb.js.map +1 -0
  164. package/dist/components/ui/button.d.ts +16 -0
  165. package/dist/components/ui/button.js +59 -0
  166. package/dist/components/ui/button.js.map +1 -0
  167. package/dist/components/ui/calendar.d.ts +13 -0
  168. package/dist/components/ui/calendar.js +238 -0
  169. package/dist/components/ui/calendar.js.map +1 -0
  170. package/dist/components/ui/card.d.ts +14 -0
  171. package/dist/components/ui/card.js +102 -0
  172. package/dist/components/ui/card.js.map +1 -0
  173. package/dist/components/ui/chart.d.ts +58 -0
  174. package/dist/components/ui/chart.js +292 -0
  175. package/dist/components/ui/chart.js.map +1 -0
  176. package/dist/components/ui/checkbox.d.ts +23 -0
  177. package/dist/components/ui/checkbox.js +155 -0
  178. package/dist/components/ui/checkbox.js.map +1 -0
  179. package/dist/components/ui/coach-mark.d.ts +27 -0
  180. package/dist/components/ui/coach-mark.js +306 -0
  181. package/dist/components/ui/coach-mark.js.map +1 -0
  182. package/dist/components/ui/collapsible.d.ts +8 -0
  183. package/dist/components/ui/collapsible.js +35 -0
  184. package/dist/components/ui/collapsible.js.map +1 -0
  185. package/dist/components/ui/command.d.ts +36 -0
  186. package/dist/components/ui/command.js +274 -0
  187. package/dist/components/ui/command.js.map +1 -0
  188. package/dist/components/ui/context-menu.d.ts +32 -0
  189. package/dist/components/ui/context-menu.js +245 -0
  190. package/dist/components/ui/context-menu.js.map +1 -0
  191. package/dist/components/ui/date-picker-field.d.ts +38 -0
  192. package/dist/components/ui/date-picker-field.js +550 -0
  193. package/dist/components/ui/date-picker-field.js.map +1 -0
  194. package/dist/components/ui/dialog.d.ts +22 -0
  195. package/dist/components/ui/dialog.js +200 -0
  196. package/dist/components/ui/dialog.js.map +1 -0
  197. package/dist/components/ui/dot-pattern.d.ts +21 -0
  198. package/dist/components/ui/dot-pattern.js +139 -0
  199. package/dist/components/ui/dot-pattern.js.map +1 -0
  200. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  201. package/dist/components/ui/drag-handle-grip.js +15 -0
  202. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  203. package/dist/components/ui/drawer.d.ts +16 -0
  204. package/dist/components/ui/drawer.js +125 -0
  205. package/dist/components/ui/drawer.js.map +1 -0
  206. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  207. package/dist/components/ui/dropdown-menu.js +353 -0
  208. package/dist/components/ui/dropdown-menu.js.map +1 -0
  209. package/dist/components/ui/export-drawer.d.ts +11 -0
  210. package/dist/components/ui/export-drawer.js +1658 -0
  211. package/dist/components/ui/export-drawer.js.map +1 -0
  212. package/dist/components/ui/field.d.ts +30 -0
  213. package/dist/components/ui/field.js +249 -0
  214. package/dist/components/ui/field.js.map +1 -0
  215. package/dist/components/ui/form.d.ts +28 -0
  216. package/dist/components/ui/form.js +110 -0
  217. package/dist/components/ui/form.js.map +1 -0
  218. package/dist/components/ui/hover-card.d.ts +9 -0
  219. package/dist/components/ui/hover-card.js +43 -0
  220. package/dist/components/ui/hover-card.js.map +1 -0
  221. package/dist/components/ui/input-group.d.ts +20 -0
  222. package/dist/components/ui/input-group.js +219 -0
  223. package/dist/components/ui/input-group.js.map +1 -0
  224. package/dist/components/ui/input-mask.d.ts +39 -0
  225. package/dist/components/ui/input-mask.js +118 -0
  226. package/dist/components/ui/input-mask.js.map +1 -0
  227. package/dist/components/ui/input.d.ts +5 -0
  228. package/dist/components/ui/input.js +30 -0
  229. package/dist/components/ui/input.js.map +1 -0
  230. package/dist/components/ui/kbd.d.ts +20 -0
  231. package/dist/components/ui/kbd.js +45 -0
  232. package/dist/components/ui/kbd.js.map +1 -0
  233. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  234. package/dist/components/ui/key-metrics-context.js +26 -0
  235. package/dist/components/ui/key-metrics-context.js.map +1 -0
  236. package/dist/components/ui/key-metrics.d.ts +131 -0
  237. package/dist/components/ui/key-metrics.js +1015 -0
  238. package/dist/components/ui/key-metrics.js.map +1 -0
  239. package/dist/components/ui/label.d.ts +6 -0
  240. package/dist/components/ui/label.js +28 -0
  241. package/dist/components/ui/label.js.map +1 -0
  242. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  243. package/dist/components/ui/list-page-view-frame.js +24 -0
  244. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  245. package/dist/components/ui/page-header.d.ts +51 -0
  246. package/dist/components/ui/page-header.js +372 -0
  247. package/dist/components/ui/page-header.js.map +1 -0
  248. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  249. package/dist/components/ui/payment-card-fields.js +80 -0
  250. package/dist/components/ui/payment-card-fields.js.map +1 -0
  251. package/dist/components/ui/popover.d.ts +10 -0
  252. package/dist/components/ui/popover.js +47 -0
  253. package/dist/components/ui/popover.js.map +1 -0
  254. package/dist/components/ui/radio-group.d.ts +29 -0
  255. package/dist/components/ui/radio-group.js +190 -0
  256. package/dist/components/ui/radio-group.js.map +1 -0
  257. package/dist/components/ui/resizable.d.ts +16 -0
  258. package/dist/components/ui/resizable.js +51 -0
  259. package/dist/components/ui/resizable.js.map +1 -0
  260. package/dist/components/ui/scroll-area.d.ts +8 -0
  261. package/dist/components/ui/scroll-area.js +66 -0
  262. package/dist/components/ui/scroll-area.js.map +1 -0
  263. package/dist/components/ui/select.d.ts +18 -0
  264. package/dist/components/ui/select.js +186 -0
  265. package/dist/components/ui/select.js.map +1 -0
  266. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  267. package/dist/components/ui/selection-tile-grid.js +347 -0
  268. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  269. package/dist/components/ui/separator.d.ts +7 -0
  270. package/dist/components/ui/separator.js +33 -0
  271. package/dist/components/ui/separator.js.map +1 -0
  272. package/dist/components/ui/sheet.d.ts +18 -0
  273. package/dist/components/ui/sheet.js +181 -0
  274. package/dist/components/ui/sheet.js.map +1 -0
  275. package/dist/components/ui/sidebar.d.ts +94 -0
  276. package/dist/components/ui/sidebar.js +805 -0
  277. package/dist/components/ui/sidebar.js.map +1 -0
  278. package/dist/components/ui/skeleton.d.ts +5 -0
  279. package/dist/components/ui/skeleton.js +22 -0
  280. package/dist/components/ui/skeleton.js.map +1 -0
  281. package/dist/components/ui/slider.d.ts +7 -0
  282. package/dist/components/ui/slider.js +66 -0
  283. package/dist/components/ui/slider.js.map +1 -0
  284. package/dist/components/ui/sonner.d.ts +6 -0
  285. package/dist/components/ui/sonner.js +38 -0
  286. package/dist/components/ui/sonner.js.map +1 -0
  287. package/dist/components/ui/status-badge.d.ts +38 -0
  288. package/dist/components/ui/status-badge.js +77 -0
  289. package/dist/components/ui/status-badge.js.map +1 -0
  290. package/dist/components/ui/table.d.ts +13 -0
  291. package/dist/components/ui/table.js +115 -0
  292. package/dist/components/ui/table.js.map +1 -0
  293. package/dist/components/ui/tabs.d.ts +15 -0
  294. package/dist/components/ui/tabs.js +93 -0
  295. package/dist/components/ui/tabs.js.map +1 -0
  296. package/dist/components/ui/textarea.d.ts +6 -0
  297. package/dist/components/ui/textarea.js +25 -0
  298. package/dist/components/ui/textarea.js.map +1 -0
  299. package/dist/components/ui/tip.d.ts +12 -0
  300. package/dist/components/ui/tip.js +61 -0
  301. package/dist/components/ui/tip.js.map +1 -0
  302. package/dist/components/ui/toggle-group.d.ts +14 -0
  303. package/dist/components/ui/toggle-group.js +104 -0
  304. package/dist/components/ui/toggle-group.js.map +1 -0
  305. package/dist/components/ui/toggle-switch.d.ts +10 -0
  306. package/dist/components/ui/toggle-switch.js +33 -0
  307. package/dist/components/ui/toggle-switch.js.map +1 -0
  308. package/dist/components/ui/toggle.d.ts +13 -0
  309. package/dist/components/ui/toggle.js +51 -0
  310. package/dist/components/ui/toggle.js.map +1 -0
  311. package/dist/components/ui/tooltip.d.ts +10 -0
  312. package/dist/components/ui/tooltip.js +68 -0
  313. package/dist/components/ui/tooltip.js.map +1 -0
  314. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  315. package/dist/components/ui/view-segmented-control.js +167 -0
  316. package/dist/components/ui/view-segmented-control.js.map +1 -0
  317. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  318. package/dist/hooks/use-app-theme.d.ts +24 -0
  319. package/dist/hooks/use-app-theme.js +286 -0
  320. package/dist/hooks/use-app-theme.js.map +1 -0
  321. package/dist/hooks/use-coach-mark.d.ts +86 -0
  322. package/dist/hooks/use-coach-mark.js +218 -0
  323. package/dist/hooks/use-coach-mark.js.map +1 -0
  324. package/dist/hooks/use-mobile.d.ts +3 -0
  325. package/dist/hooks/use-mobile.js +29 -0
  326. package/dist/hooks/use-mobile.js.map +1 -0
  327. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  328. package/dist/hooks/use-mod-key-label.js +25 -0
  329. package/dist/hooks/use-mod-key-label.js.map +1 -0
  330. package/dist/index.d.ts +120 -0
  331. package/dist/index.js +13324 -0
  332. package/dist/index.js.map +1 -0
  333. package/dist/lib/compose-refs.d.ts +6 -0
  334. package/dist/lib/compose-refs.js +17 -0
  335. package/dist/lib/compose-refs.js.map +1 -0
  336. package/dist/lib/conditional-rule-match.d.ts +30 -0
  337. package/dist/lib/conditional-rule-match.js +66 -0
  338. package/dist/lib/conditional-rule-match.js.map +1 -0
  339. package/dist/lib/data-list-display-options.d.ts +26 -0
  340. package/dist/lib/data-list-display-options.js +14 -0
  341. package/dist/lib/data-list-display-options.js.map +1 -0
  342. package/dist/lib/data-list-view-registry.d.ts +2 -0
  343. package/dist/lib/data-list-view-registry.js +102 -0
  344. package/dist/lib/data-list-view-registry.js.map +1 -0
  345. package/dist/lib/data-list-view-surface.d.ts +2 -0
  346. package/dist/lib/data-list-view-surface.js +80 -0
  347. package/dist/lib/data-list-view-surface.js.map +1 -0
  348. package/dist/lib/data-list-view.d.ts +21 -0
  349. package/dist/lib/data-list-view.js +25 -0
  350. package/dist/lib/data-list-view.js.map +1 -0
  351. package/dist/lib/date-filter.d.ts +22 -0
  352. package/dist/lib/date-filter.js +61 -0
  353. package/dist/lib/date-filter.js.map +1 -0
  354. package/dist/lib/dev-log.d.ts +8 -0
  355. package/dist/lib/dev-log.js +10 -0
  356. package/dist/lib/dev-log.js.map +1 -0
  357. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  358. package/dist/lib/dropdown-menu-surface.js +6 -0
  359. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  360. package/dist/lib/editable-target.d.ts +12 -0
  361. package/dist/lib/editable-target.js +12 -0
  362. package/dist/lib/editable-target.js.map +1 -0
  363. package/dist/lib/list-page-table-properties.d.ts +35 -0
  364. package/dist/lib/list-page-table-properties.js +81 -0
  365. package/dist/lib/list-page-table-properties.js.map +1 -0
  366. package/dist/lib/raf-throttle.d.ts +23 -0
  367. package/dist/lib/raf-throttle.js +27 -0
  368. package/dist/lib/raf-throttle.js.map +1 -0
  369. package/dist/lib/row-height.d.ts +16 -0
  370. package/dist/lib/row-height.js +10 -0
  371. package/dist/lib/row-height.js.map +1 -0
  372. package/dist/lib/table-properties-types.d.ts +83 -0
  373. package/dist/lib/table-properties-types.js +19 -0
  374. package/dist/lib/table-properties-types.js.map +1 -0
  375. package/dist/lib/utils.d.ts +5 -0
  376. package/dist/lib/utils.js +11 -0
  377. package/dist/lib/utils.js.map +1 -0
  378. package/package.json +83 -18
  379. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  380. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  381. package/src/components/data-table/index.tsx +1678 -0
  382. package/src/components/data-table/pagination.tsx +255 -0
  383. package/src/components/data-table/types.ts +96 -0
  384. package/src/components/data-table/use-table-state.ts +767 -0
  385. package/src/components/data-views/board-card-primitives.tsx +93 -0
  386. package/src/components/data-views/data-row-list.tsx +183 -0
  387. package/src/components/data-views/finder-panel-view.tsx +405 -0
  388. package/src/components/data-views/folder-grid-view.tsx +86 -0
  389. package/src/components/data-views/hub-table.tsx +498 -0
  390. package/src/components/data-views/index.ts +28 -0
  391. package/src/components/data-views/list-page-board-card.tsx +192 -0
  392. package/src/components/data-views/list-page-board-template.tsx +122 -0
  393. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  394. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  395. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  396. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  397. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  398. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  399. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  400. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  401. package/src/components/table-properties/column-row.tsx +90 -0
  402. package/src/components/table-properties/draggable-list.ts +54 -0
  403. package/src/components/table-properties/drawer-button.tsx +300 -0
  404. package/src/components/table-properties/drawer.tsx +1148 -0
  405. package/src/components/table-properties/filter-card.tsx +251 -0
  406. package/src/components/table-properties/index.ts +36 -0
  407. package/src/components/table-properties/sort-card.tsx +63 -0
  408. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  409. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  410. package/src/components/templates/index.ts +33 -0
  411. package/src/components/templates/list-page.tsx +602 -0
  412. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  413. package/src/components/ui/accordion.tsx +92 -0
  414. package/src/components/ui/alert-dialog.tsx +221 -0
  415. package/src/components/ui/avatar.tsx +13 -2
  416. package/src/components/ui/banner.tsx +2 -2
  417. package/src/components/ui/calendar.tsx +1 -1
  418. package/src/components/ui/coach-mark.tsx +1 -1
  419. package/src/components/ui/context-menu.tsx +291 -0
  420. package/src/components/ui/date-picker-field.tsx +2 -2
  421. package/src/components/ui/dot-pattern.tsx +183 -0
  422. package/src/components/ui/export-drawer.tsx +375 -0
  423. package/src/components/ui/hover-card.tsx +66 -0
  424. package/src/components/ui/key-metrics-context.tsx +78 -0
  425. package/src/components/ui/key-metrics.tsx +1133 -0
  426. package/src/components/ui/list-page-view-frame.tsx +64 -0
  427. package/src/components/ui/page-header.tsx +244 -0
  428. package/src/components/ui/payment-card-fields.tsx +2 -2
  429. package/src/components/ui/resizable.tsx +68 -0
  430. package/src/components/ui/scroll-area.tsx +72 -0
  431. package/src/components/ui/selection-tile-grid.tsx +9 -2
  432. package/src/components/ui/sidebar.tsx +84 -12
  433. package/src/components/ui/slider.tsx +83 -0
  434. package/src/globals.css +494 -151
  435. package/src/globals.d.ts +20 -0
  436. package/src/index.ts +68 -1
  437. package/src/lib/conditional-rule-match.ts +119 -0
  438. package/src/lib/data-list-display-options.ts +35 -0
  439. package/src/lib/data-list-view-registry.ts +104 -0
  440. package/src/lib/data-list-view-surface.ts +83 -0
  441. package/src/lib/data-list-view.ts +47 -0
  442. package/src/lib/dev-log.ts +10 -0
  443. package/src/lib/editable-target.ts +20 -0
  444. package/src/lib/list-page-table-properties.ts +48 -0
  445. package/src/lib/raf-throttle.ts +45 -0
  446. package/src/lib/row-height.ts +19 -0
  447. package/src/lib/table-properties-types.ts +98 -0
  448. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  449. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  450. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  451. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  452. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  453. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  454. package/template/AGENTS.md +84 -20
  455. package/template/app/(app)/examples/page.tsx +0 -1
  456. package/template/app/(app)/layout.tsx +17 -4
  457. package/template/app/(app)/question-bank/layout.tsx +1 -1
  458. package/template/app/(app)/question-bank/new/page.tsx +11 -24
  459. package/template/app/globals.css +13 -1972
  460. package/template/components/ask-leo-sidebar.tsx +5 -1
  461. package/template/components/brand-color-picker.tsx +2 -2
  462. package/template/components/charts-overview.tsx +1 -1
  463. package/template/components/compliance-table.tsx +240 -384
  464. package/template/components/dashboard-report-charts.tsx +1 -1
  465. package/template/components/dashboard-tabs.tsx +1 -1
  466. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  467. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  468. package/template/components/data-table/index.tsx +1 -1634
  469. package/template/components/data-table/pagination.tsx +1 -255
  470. package/template/components/data-table/types.ts +1 -94
  471. package/template/components/data-table/use-table-state.test.ts +420 -0
  472. package/template/components/data-table/use-table-state.ts +1 -758
  473. package/template/components/data-view-dashboard-charts-compliance.tsx +2 -2
  474. package/template/components/data-view-dashboard-charts-team.tsx +2 -2
  475. package/template/components/data-view-dashboard-charts.tsx +2 -2
  476. package/template/components/data-views/board-card-primitives.tsx +1 -93
  477. package/template/components/data-views/data-row-list.tsx +1 -183
  478. package/template/components/data-views/finder-panel-view.tsx +1 -405
  479. package/template/components/data-views/folder-grid-view.tsx +1 -86
  480. package/template/components/data-views/hub-table.tsx +1 -0
  481. package/template/components/data-views/index.ts +42 -1
  482. package/template/components/data-views/list-page-board-card.tsx +1 -192
  483. package/template/components/data-views/list-page-board-template.tsx +1 -122
  484. package/template/components/data-views/list-page-connected-view-body.tsx +1 -0
  485. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  486. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -60
  487. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  488. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  489. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  490. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  491. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  492. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  493. package/template/components/export-drawer.test.tsx +71 -0
  494. package/template/components/export-drawer.tsx +1 -375
  495. package/template/components/exxat-product-logo.tsx +5 -5
  496. package/template/components/hub-tree-panel-view.tsx +2 -2
  497. package/template/components/invite-collaborators-drawer.tsx +3 -3
  498. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  499. package/template/components/key-metrics.tsx +1 -1063
  500. package/template/components/leo-insight-indicator.tsx +2 -2
  501. package/template/components/new-placement-back-btn.tsx +1 -1
  502. package/template/components/new-placement-form.tsx +63 -189
  503. package/template/components/new-question-composer.tsx +432 -402
  504. package/template/components/onboarding/index.ts +9 -0
  505. package/template/components/onboarding/onboarding-01.tsx +1 -1
  506. package/template/components/onboarding/onboarding-02.tsx +1 -1
  507. package/template/components/onboarding/onboarding-03.tsx +1 -1
  508. package/template/components/onboarding/onboarding-04.tsx +1 -1
  509. package/template/components/page-header.tsx +8 -226
  510. package/template/components/placement-board-card.tsx +71 -83
  511. package/template/components/placements-board-view.tsx +3 -10
  512. package/template/components/placements-client.tsx +10 -42
  513. package/template/components/placements-list-view.tsx +22 -69
  514. package/template/components/placements-table-columns.tsx +8 -438
  515. package/template/components/placements-table.tsx +588 -1296
  516. package/template/components/product-switcher.tsx +1 -1
  517. package/template/components/product-wordmark.tsx +2 -1
  518. package/template/components/question-bank-client.tsx +4 -1
  519. package/template/components/question-bank-hub-client.tsx +1 -1
  520. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  521. package/template/components/question-bank-secondary-nav.tsx +3 -3
  522. package/template/components/question-bank-table.tsx +294 -526
  523. package/template/components/rotations-empty-state.tsx +1 -1
  524. package/template/components/rotations-panel-activator.tsx +1 -1
  525. package/template/components/settings-appearance-card.tsx +1 -1
  526. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  527. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +4 -4
  528. package/template/components/sidebar/index.ts +16 -0
  529. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  530. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +6 -3
  531. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  532. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  533. package/template/components/site-header.tsx +1 -1
  534. package/template/components/{sites-all-client.tsx → sites-client.tsx} +1 -1
  535. package/template/components/sites-table.tsx +124 -257
  536. package/template/components/table-properties/column-row.tsx +1 -90
  537. package/template/components/table-properties/draggable-list.ts +1 -49
  538. package/template/components/table-properties/drawer-button.tsx +1 -249
  539. package/template/components/table-properties/drawer.tsx +1 -1105
  540. package/template/components/table-properties/filter-card.tsx +1 -251
  541. package/template/components/table-properties/sort-card.tsx +1 -59
  542. package/template/components/table-properties/types.ts +28 -71
  543. package/template/components/team-table.tsx +242 -382
  544. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  545. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  546. package/template/components/templates/list-page.tsx +1 -584
  547. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -62
  548. package/template/components/templates/new-focus-template.tsx +659 -0
  549. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  550. package/template/components/ui/accordion.tsx +1 -0
  551. package/template/components/ui/alert-dialog.tsx +1 -0
  552. package/template/components/ui/context-menu.tsx +1 -0
  553. package/template/components/ui/dot-pattern.tsx +1 -183
  554. package/template/components/ui/hover-card.tsx +1 -0
  555. package/template/components/ui/resizable.tsx +1 -68
  556. package/template/components/ui/scroll-area.tsx +1 -0
  557. package/template/components/ui/slider.tsx +1 -0
  558. package/template/docs/blueprints/README.md +86 -0
  559. package/template/docs/blueprints/_template.md +91 -0
  560. package/template/docs/blueprints/board-card.md +123 -0
  561. package/template/docs/blueprints/data-table.md +139 -0
  562. package/template/docs/blueprints/key-metrics.md +128 -0
  563. package/template/docs/blueprints/list-page-template.md +123 -0
  564. package/template/docs/blueprints/page-header.md +130 -0
  565. package/template/docs/command-menu-pattern.md +1 -1
  566. package/template/docs/component-selection-guide.md +224 -0
  567. package/template/docs/components-audit-2026-05.md +158 -0
  568. package/template/docs/data-views-pattern.md +14 -14
  569. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  570. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  571. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  572. package/template/docs/migrations/README.md +100 -0
  573. package/template/docs/migrations/_template.md +64 -0
  574. package/template/docs/token-taxonomy.md +416 -0
  575. package/template/eslint.config.mjs +27 -0
  576. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  577. package/template/lib/command-menu-config.ts +0 -1
  578. package/template/lib/compliance-supported-views.ts +10 -0
  579. package/template/lib/conditional-rule-match.ts +6 -97
  580. package/template/lib/data-list-display-options.ts +1 -35
  581. package/template/lib/data-list-view-registry.ts +1 -0
  582. package/template/lib/data-list-view-surface.ts +1 -69
  583. package/template/lib/data-list-view.ts +1 -38
  584. package/template/lib/dev-log.ts +1 -8
  585. package/template/lib/editable-target.ts +1 -10
  586. package/template/lib/hub-connected-view-renderers.ts +58 -0
  587. package/template/lib/list-hub-supported-views.ts +10 -0
  588. package/template/lib/list-page-table-properties.ts +1 -52
  589. package/template/lib/mock/navigation.tsx +0 -8
  590. package/template/lib/mock/placements.ts +0 -7
  591. package/template/lib/placement-board-card-layout.ts +41 -41
  592. package/template/lib/placements-supported-views.ts +12 -0
  593. package/template/lib/question-bank-supported-views.ts +12 -0
  594. package/template/lib/raf-throttle.ts +1 -45
  595. package/template/lib/row-height.ts +4 -10
  596. package/template/lib/sidebar-state-cookie.ts +11 -2
  597. package/template/lib/sites-supported-views.ts +10 -0
  598. package/template/lib/team-supported-views.ts +10 -0
  599. package/template/package.json +1 -0
  600. package/template/tests/setup.ts +25 -0
  601. package/src/theme.css +0 -1132
  602. package/template/app/(app)/data-list/[id]/page.tsx +0 -44
  603. package/template/app/(app)/data-list/new/page.tsx +0 -34
  604. package/template/app/(app)/data-list/page.tsx +0 -10
  605. package/template/components/compliance-list-view.tsx +0 -54
  606. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  607. package/template/components/dashboard-onboarding.tsx +0 -21
  608. package/template/components/question-bank-list-view.tsx +0 -53
  609. package/template/components/section-cards.tsx +0 -106
  610. package/template/components/sites-list-view.tsx +0 -42
  611. package/template/components/team-list-view.tsx +0 -59
  612. package/template/lib/placement-lifecycle.ts +0 -5
  613. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  614. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  615. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  616. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  617. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  618. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -1,1979 +1,20 @@
1
1
  /* ==========================================================================
2
- EXXAT DESIGN SYSTEM — globals.css
3
- Brands: Exxat One (Lavender · hue 270) · Exxat Prism (Rose · hue 343)
2
+ EXXAT DESIGN SYSTEM — apps/web globals.css
3
+ ------------------------------------------------------------------
4
+ Canonical theme tokens, custom variants, and base-layer styles
5
+ live in `@exxatdesignux/ui/globals.css`. Edits should land there
6
+ (the package CSS is the source of truth); this file only declares
7
+ the Tailwind `@source` so the consumer's location is honoured.
8
+
9
+ Workspace dev: `@source` points at the package's `src/` directly so
10
+ the IDE / Turbopack pick up new utility usages without a rebuild.
11
+ The `sync-template-from-web.mjs` script rewrites this path to
12
+ `../node_modules/@exxatdesignux/ui/src` for the npm starter.
13
+
4
14
  Standard: WCAG 2.1 Level AA
5
- • Text contrast ≥ 4.5 : 1 (SC 1.4.3)
6
- • UI control contrast ≥ 3 : 1 (SC 1.4.11)
7
- • Focus ring ≥ 3 : 1 (SC 2.4.11)
8
- • Touch targets ≥ 44 × 44 px (SC 2.5.5 / mobile)
9
15
  ========================================================================== */
10
16
 
11
- @import "tailwindcss";
12
- @import "tw-animate-css";
17
+ @import "@exxatdesignux/ui/globals.css";
13
18
 
14
19
  /* Ensure Tailwind scans the shared UI package for utility classes (repo-relative — stable with pnpm + Turbopack). */
15
20
  @source "../node_modules/@exxatdesignux/ui/src";
16
-
17
- /* RTL layout direction support */
18
- @custom-variant dark (&:is(.dark *));
19
-
20
- /* High-contrast variant — in-app High or Windows (JSON) contrast */
21
- @custom-variant hc (&:is([data-contrast="high"] *, [data-contrast="windows"] *));
22
-
23
- /* --------------------------------------------------------------------------
24
- Tailwind v4 theme bridge — maps CSS custom-props → utility classes
25
- -------------------------------------------------------------------------- */
26
- @theme inline {
27
- /* Typography */
28
- --font-heading: "ivypresto-text";
29
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
30
- /* Minimum product text: 11px — use `text-xs` or larger; avoid arbitrary classes below 11px */
31
- --text-xs: 0.6875rem; /* 11px at 16px root */
32
-
33
- /* Semantic color map */
34
- --color-background: var(--background);
35
- --color-foreground: var(--foreground);
36
- --color-card: var(--card);
37
- --color-card-foreground: var(--card-foreground);
38
- --color-popover: var(--popover);
39
- --color-popover-foreground: var(--popover-foreground);
40
- --color-primary: var(--primary);
41
- --color-primary-foreground: var(--primary-foreground);
42
- --color-secondary: var(--secondary);
43
- --color-secondary-foreground: var(--secondary-foreground);
44
- --color-muted: var(--muted);
45
- --color-muted-foreground: var(--muted-foreground);
46
- --color-accent: var(--accent);
47
- --color-accent-foreground: var(--accent-foreground);
48
- --color-destructive: var(--destructive);
49
- --color-destructive-foreground: var(--destructive-foreground);
50
- --color-border: var(--border);
51
- --color-border-control: var(--border-control);
52
- --color-input: var(--input);
53
- --color-input-background: var(--input-background);
54
- --color-ring: var(--ring);
55
- /* Modal / sheet / drawer scrim */
56
- --color-overlay: var(--overlay);
57
-
58
- /* Chart tokens */
59
- --color-chart-1: var(--chart-1);
60
- --color-chart-2: var(--chart-2);
61
- --color-chart-3: var(--chart-3);
62
- --color-chart-4: var(--chart-4);
63
- --color-chart-5: var(--chart-5);
64
-
65
- /* Chip / badge tokens (AA-compliant on light bg: ≥ 4.5:1) */
66
- --color-chip-1: var(--chip-1);
67
- --color-chip-2: var(--chip-2);
68
- --color-chip-3: var(--chip-3);
69
- --color-chip-4: var(--chip-4);
70
- --color-chip-5: var(--chip-5);
71
- --color-chip-destructive: var(--chip-destructive);
72
-
73
- /* Brand accent + Exxat One tint scale (see :root --brand-*) */
74
- --color-brand: var(--brand-color);
75
- --color-brand-dark: var(--brand-color-dark);
76
- --color-brand-foreground: var(--brand-foreground);
77
- --color-brand-tint: var(--brand-tint);
78
- --color-brand-tint-light: var(--brand-tint-light);
79
- --color-brand-tint-subtle: var(--brand-tint-subtle);
80
- --color-brand-color-light: var(--brand-color-light);
81
- --color-brand-deep: var(--brand-color-deep);
82
-
83
- /* Prism banner highlight */
84
- --color-banner-prism: var(--banner-prism-bg);
85
-
86
- /* Sidebar */
87
- --color-sidebar: var(--sidebar);
88
- --color-sidebar-foreground: var(--sidebar-foreground);
89
- --color-sidebar-primary: var(--sidebar-primary);
90
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
91
- --color-sidebar-accent: var(--sidebar-accent);
92
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
93
- --color-sidebar-border: var(--sidebar-border);
94
- --color-sidebar-ring: var(--sidebar-ring);
95
- /* WCAG 1.4.3 — always mixed against real --sidebar (lavender / rose / dark) */
96
- --color-sidebar-section-label: var(--sidebar-section-label-foreground);
97
-
98
- /* Interactive hover — single source for ghost controls, lists, table chrome */
99
- --color-interactive-hover: var(--interactive-hover);
100
- --color-interactive-hover-foreground: var(--interactive-hover-foreground);
101
- --color-interactive-hover-subtle: var(--interactive-hover-subtle);
102
- --color-interactive-hover-soft: var(--interactive-hover-soft);
103
- --color-interactive-hover-medium: var(--interactive-hover-medium);
104
- --color-interactive-hover-strong: var(--interactive-hover-strong);
105
- --color-interactive-hover-row: var(--interactive-hover-row);
106
-
107
- /* DataTable — opaque surfaces for pinned/sticky cells and row states */
108
- --color-dt-row-bg: var(--dt-row-bg);
109
- --color-dt-row-hover: var(--dt-row-hover);
110
- --color-dt-row-selected: var(--dt-row-selected);
111
- --color-dt-row-selected-fg: var(--dt-row-selected-fg);
112
- --color-dt-header-bg: var(--dt-header-bg);
113
- --color-dt-group-bg: var(--dt-group-bg);
114
- --color-dt-new-row-bg: var(--dt-new-row-bg);
115
- --color-dt-new-row-border: var(--dt-new-row-border);
116
-
117
- /* Border-radius scale (4 px base → 8 px default) */
118
- --radius-sm: 4px;
119
- --radius-md: 8px;
120
- --radius-lg: 12px;
121
- --radius-xl: 16px;
122
- --radius-2xl: 20px;
123
- --radius-3xl: 24px;
124
- }
125
-
126
- /* --------------------------------------------------------------------------
127
- Text size (Settings → Appearance)
128
- Pattern: root `font-size` steps like iOS Larger Text / Android font scale /
129
- browser zoom-at-root so rem-based components track together. We keep steps
130
- modest; `compact` redefines `--text-xs` so minimum UI copy stays 11px (Exxat
131
- accessibility rule) when the root is slightly below 16px.
132
- -------------------------------------------------------------------------- */
133
- html[data-text-size="compact"] {
134
- font-size: 94%;
135
- --text-xs: 0.7333rem; /* ~11px when 1rem ≈ 15px */
136
- }
137
- html[data-text-size="large"] {
138
- font-size: 112.5%;
139
- }
140
-
141
- /* ==========================================================================
142
- :root — Exxat One · Light Mode (brand hue 286.1)
143
- All contrast ratios verified against oklch(1 0 0) white background.
144
- ========================================================================== */
145
- :root {
146
- /* font-size intentionally NOT overridden here.
147
- Shadcn components assume 1rem = 16px (browser default).
148
- Overriding to 87.5% / 14px breaks rem-based spacing on all devices,
149
- and compounds incorrectly at Windows 150% system zoom.
150
- If a compact 14px density is needed, apply it at the component/page level
151
- via a scoped class, not globally on :root. */
152
- /* Minimum readable UI copy: 11px (`text-xs` / --text-xs). Do not use smaller arbitrary sizes. */
153
-
154
- /* ── Layout ─────────────────────────────────────────────────── */
155
- /* SiteHeader / breadcrumb height. Mirrored on the SidebarProvider for
156
- descendants; declared here too so JS that reads from documentElement
157
- (e.g. DataTable sticky-head offset) can resolve it. Plain px so
158
- `parseFloat` can read it as a number. Keep in sync with `headerHeight`
159
- in components/sidebar-shell.tsx (currently `calc(var(--spacing) * 12)` = 48px). */
160
- --header-height: 48px;
161
-
162
- /* ── Typography ─────────────────────────────────────────────── */
163
- /* Ivy Presto loaded via Adobe Fonts Kit wuk5wqn (use.typekit.net) */
164
- --font-heading: "ivypresto-text";
165
-
166
- /* ── Brand — Exxat One (hue 286.1) ─────────────────────────── */
167
- /* Primary surface — requested token */
168
- --brand-tint: oklch(0.9676 0.016 286.1);
169
- /* Lighter / darker washes (same hue) for nested UI & hovers */
170
- --brand-tint-light: oklch(0.993 0.007 286.1);
171
- --brand-tint-subtle: oklch(0.935 0.024 286.1);
172
- /* Interactive accent + scale (readable on white; pairs with --brand-tint) */
173
- --brand-color: oklch(0.50 0.14 286.1);
174
- --brand-color-light: oklch(0.78 0.09 286.1);
175
- --brand-color-dark: oklch(0.38 0.11 286.1);
176
- --brand-color-deep: oklch(0.28 0.085 286.1);
177
- --brand-foreground: oklch(0.985 0 0);
178
- /* Fixed swatches for brand picker (Exxat One vs Prism), independent of active theme */
179
- --brand-preview-one: var(--brand-tint);
180
- --brand-preview-prism: oklch(0.57 0.24 342);
181
-
182
- /**
183
- * Ask Leo panel tints (same mixes as the vertical wash). Use for blobs, cards, etc.
184
- * `--leo-surface-gradient` is the full linear wash on `AskLeoSidebar`.
185
- */
186
- --leo-surface-tint-a: color-mix(in oklch, var(--brand-color) 4%, var(--background));
187
- --leo-surface-tint-b: color-mix(in oklch, var(--brand-color) 8%, var(--background));
188
- --leo-surface-gradient: linear-gradient(180deg, var(--leo-surface-tint-a) 0%, var(--leo-surface-tint-b) 100%);
189
-
190
- /* KeyMetrics `variant="flat"` — no band surface; bottom brand glow only (OKLCH). */
191
- --key-metrics-flat-cell-bg: transparent;
192
- --key-metrics-flat-divider: color-mix(in oklch, var(--sidebar-border) 55%, transparent);
193
- --key-metrics-flat-band-radial: radial-gradient(
194
- ellipse 120% 68% at 50% 100%,
195
- color-mix(in oklch, var(--brand-color) 20%, transparent) 0%,
196
- color-mix(in oklch, var(--brand-color) 8%, transparent) 42%,
197
- transparent 72%
198
- );
199
- --key-metrics-flat-band-shadow: none;
200
- --key-metrics-card-glow-radial: radial-gradient(
201
- ellipse 110% 90% at 50% 100%,
202
- color-mix(in oklch, var(--brand-color) 18%, transparent) 0%,
203
- transparent 65%
204
- );
205
-
206
- /* ── Surfaces ────────────────────────────────────────────────── */
207
- --background: oklch(1 0 0);
208
- --foreground: oklch(0.145 0 0); /* ≈ #1A1A1A — 17:1 on white ✓ */
209
- --card: oklch(1 0 0);
210
- --card-foreground: oklch(0.145 0 0);
211
- --popover: oklch(1 0 0);
212
- --popover-foreground: oklch(0.145 0 0);
213
-
214
- /* ── Primary ─────────────────────────────────────────────────── */
215
- /* Default / ghost / solid primary actions — neutral charcoal (style guide) */
216
- --primary: oklch(0.3457 0.0052 286.13);
217
- --primary-foreground: oklch(0.985 0 0);
218
-
219
- /* ── Secondary / Muted / Accent ──────────────────────────────── */
220
- --secondary: oklch(0.95 0.0058 264.53);
221
- --secondary-foreground: oklch(0.082 0 0);
222
- --muted: oklch(0.945 0.002 270);
223
- --muted-foreground: oklch(0.50 0.012 270); /* 5.5:1 on white ✓ */
224
- --accent: oklch(0.925 0.005 260);
225
- --accent-foreground: oklch(0.082 0 0);
226
-
227
- /* ── Destructive ─────────────────────────────────────────────── */
228
- /* oklch(0.55 0.22 25) ≈ #C0392B — 5.1:1 on white ✓ */
229
- --destructive: oklch(0.55 0.22 25);
230
- --destructive-foreground: oklch(1 0 0);
231
-
232
- /* ── Borders ─────────────────────────────────────────────────── */
233
- /* Decorative: cards, dividers — no AA contrast requirement */
234
- --border: oklch(0.92 0.002 270);
235
-
236
- /* Form-field boundary — WCAG 1.4.11 requires 3:1 against bg.
237
- --border-control-3: L=0.62 ≈ #90929A → borderline; use with care.
238
- --border-control-35: L=0.25 → ≥ 3.5:1 — recommended for inputs. */
239
- --border-control: oklch(0.82 0.004 270); /* subtle (layout use only) */
240
- --border-control-3: oklch(0.6196 0.0092 270); /* ≈ 3:1 on white (minimum) */
241
- --border-control-35: oklch(0.25 0.01 270); /* ≈ 3.5:1+ (recommended) */
242
- --control-border: var(--border-control-3); /* default form-field border */
243
-
244
- /* ── Input ───────────────────────────────────────────────────── */
245
- /* Raised contrast target for control outlines (>= 3.1:1 on white). */
246
- --input: oklch(0.62 0.01 264.52);
247
- --input-background: oklch(0.97 0.002 270);
248
-
249
- /* ── Focus ring ──────────────────────────────────────────────── */
250
- /* 3:1+ contrast on both light & dark backgrounds (WCAG 2.4.11) */
251
- --ring: oklch(0.25 0 0);
252
-
253
- /* ── Charts ──────────────────────────────────────────────────── */
254
- --chart-1: oklch(0.55 0.22 264.116);
255
- --chart-2: oklch(0.48 0.15 184.704);
256
- --chart-3: oklch(0.32 0.08 227.392);
257
- --chart-4: oklch(0.65 0.18 84.429);
258
- --chart-5: oklch(0.58 0.18 70.08);
259
-
260
- /* ── Chip / Badge ────────────────────────────────────────────── */
261
- /* AA-compliant on white: all ≥ 4.5:1 (WCAG 1.4.3) */
262
- --chip-1: oklch(0.38 0.18 264); /* indigo */
263
- --chip-2: oklch(0.35 0.14 184); /* teal */
264
- --chip-3: oklch(0.32 0.08 227); /* slate */
265
- --chip-4: oklch(0.42 0.12 84); /* amber */
266
- --chip-5: oklch(0.42 0.14 70); /* orange */
267
- --chip-destructive: oklch(0.40 0.18 25); /* red */
268
-
269
- /* ── Prism promo banner ──────────────────────────────────────── */
270
- /* Rose hue 343 — used universally regardless of active theme */
271
- --banner-prism-bg: oklch(0.97 0.02 343);
272
-
273
- /* ── Sidebar — Exxat One brand tint ───────────────────────────── */
274
- --sidebar: var(--brand-tint);
275
- --sidebar-foreground: oklch(0.145 0 0);
276
- --sidebar-primary: oklch(0.082 0 0);
277
- --sidebar-primary-foreground: oklch(0.985 0 0);
278
- --sidebar-accent: oklch(0.945 0.025 286.1);
279
- --sidebar-accent-foreground: oklch(0.3457 0.0052 286.13);
280
- --sidebar-border: oklch(0.92 0.025 286.1);
281
- --sidebar-ring: oklch(0.25 0 0);
282
- /* Nav section titles — ≥4.5:1 vs --sidebar (not vs page white) */
283
- --sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 58%, var(--sidebar));
284
- /* Nested secondary rail — elevation 1: brand wash, lighter than `--sidebar` / `--brand-tint`. */
285
- --secondary-panel-bg: color-mix(in oklch, var(--background) 40%, var(--brand-tint-light) 60%);
286
-
287
- /* Browser UI (meta theme-color) — aligned with --brand-tint */
288
- --theme-color-chrome: #f3f2f8;
289
-
290
- /* ── Border radius ───────────────────────────────────────────── */
291
- --radius: 0.5rem; /* 8px base */
292
-
293
- /* ── Density / touch targets ─────────────────────────────────── */
294
- --scaling: 1;
295
- --control-height: calc(40px * var(--scaling));
296
- --control-height-sm: calc(32px * var(--scaling));
297
- /* WCAG 2.5.5 — minimum 44×44 px touch target (mobile only) */
298
- --control-height-touch: 44px;
299
- --control-padding-y: calc(8px * var(--scaling));
300
- --control-padding-x: calc(12px * var(--scaling));
301
- --table-row-height: calc(48px * var(--scaling));
302
-
303
- /* ── Interactive hover (ties to --muted / --accent — theme overrides apply) ─ */
304
- --interactive-hover: var(--muted);
305
- --interactive-hover-foreground: var(--foreground);
306
- --interactive-hover-subtle: color-mix(in oklch, var(--muted) 50%, var(--background));
307
- --interactive-hover-soft: color-mix(in oklch, var(--muted) 40%, var(--background));
308
- --interactive-hover-medium: color-mix(in oklch, var(--muted) 60%, var(--background));
309
- --interactive-hover-strong: color-mix(in oklch, var(--muted) 70%, var(--background));
310
- --interactive-hover-row: color-mix(in oklch, var(--accent) 50%, var(--background));
311
-
312
- /* ── DataTable — opaque row/cell surfaces (pinned cells MUST be opaque) ── */
313
- --dt-row-bg: var(--background);
314
- --dt-row-hover: oklch(0.972 0.001 270);
315
- --dt-row-selected: oklch(0.962 0.003 260);
316
- --dt-row-selected-fg: var(--foreground);
317
- --dt-header-bg: var(--background);
318
- --dt-group-bg: oklch(0.972 0.001 270);
319
- --dt-new-row-bg: oklch(from var(--brand-color) 0.985 0.006 h);
320
- --dt-new-row-border: var(--brand-color);
321
-
322
- /* ── Transitions ─────────────────────────────────────────────── */
323
- --transition-fast: 0.15s ease;
324
- --transition-normal: 0.25s ease-in-out;
325
- --transition-colors: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
326
-
327
- /* ── Shadows ─────────────────────────────────────────────────── */
328
- --shadow-sm: oklch(0 0 0 / 0.08) 0px 1px 2px 0px;
329
- --shadow-md: oklch(0 0 0 / 0.08) 0px 2px 4px -1px, oklch(0 0 0 / 0.06) 0px 1px 2px;
330
- --shadow-lg: oklch(0 0 0 / 0.10) 0px 4px 8px -2px, oklch(0 0 0 / 0.06) 0px 2px 4px;
331
-
332
- /* ── Sticky column edge fade (data tables) ───────────────────── */
333
- --sticky-edge-fade: oklch(0 0 0 / 0.08);
334
-
335
- /* ── Overlay scrim (Sheet / Drawer / Dialog) ─────────────────── */
336
- /* Softer than raw bg-black/10; follows foreground hue (not pure black) */
337
- --overlay: color-mix(in oklch, var(--foreground) 5%, transparent);
338
-
339
- /* ── Avatar initials (table) ───────────────────────────────────── */
340
- /* Soft brand wash + brand ink — no black fills; ≥4.5:1 on white rows */
341
- --avatar-initials-bg: color-mix(in oklch, var(--brand-color) 14%, oklch(1 0 0));
342
- --avatar-initials-fg: var(--brand-color-dark);
343
-
344
- /* ── KPI insight severity (KeyMetrics) ────────────────────────── */
345
- --insight-severity-warning-bg: color-mix(in oklch, var(--chart-4) 15%, transparent);
346
- --insight-severity-warning-fg: color-mix(in oklch, var(--chart-4) 75%, var(--foreground));
347
- --insight-severity-info-bg: color-mix(in oklch, var(--chart-1) 14%, transparent);
348
- --insight-severity-info-fg: color-mix(in oklch, var(--chart-1) 75%, var(--foreground));
349
-
350
- /* ── Tinted icon discs — soft wash (≈14% tint like legacy inline styles); contrast from --chip-* / brand-dark on fg */
351
- --icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
352
- --icon-disc-chart-2-fg: var(--chip-2);
353
- --icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
354
- --icon-disc-chart-4-fg: var(--chip-4);
355
- --icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
356
- --icon-disc-brand-fg: var(--brand-color-dark);
357
- --icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
358
- --icon-disc-danger-fg: var(--chip-destructive);
359
-
360
- /* ── Conditional formatting rule backgrounds (table drawer) ─── */
361
- --conditional-rule-green: color-mix(in oklch, var(--chart-2) 22%, transparent);
362
- --conditional-rule-yellow: color-mix(in oklch, var(--chart-4) 30%, transparent);
363
- --conditional-rule-blue: color-mix(in oklch, var(--chart-1) 22%, transparent);
364
- --conditional-rule-red: color-mix(in oklch, var(--destructive) 22%, transparent);
365
- --conditional-rule-purple: color-mix(in oklch, var(--brand-color) 22%, transparent);
366
- --conditional-rule-orange: color-mix(in oklch, var(--chart-5) 25%, transparent);
367
- }
368
-
369
- /* ==========================================================================
370
- Dark Mode — Exxat One base (neutral surfaces; brand uses --brand-*)
371
- ========================================================================== */
372
- .dark {
373
- --sticky-edge-fade: oklch(0 0 0 / 0.32);
374
-
375
- /* Canvas — charcoal grey (not near-black) */
376
- --background: oklch(0.20 0.008 270);
377
- --foreground: oklch(0.985 0 0);
378
- --card: oklch(0.255 0.008 270);
379
- --card-foreground: oklch(0.985 0 0);
380
- --popover: oklch(0.255 0.008 270);
381
- --popover-foreground: oklch(0.985 0 0);
382
- --primary: oklch(0.985 0 0);
383
- --primary-foreground: oklch(0.3457 0.0052 286.13);
384
- --secondary: oklch(0.31 0.04 270);
385
- --secondary-foreground: oklch(0.985 0 0);
386
- --muted: oklch(0.31 0.04 270);
387
- --muted-foreground: oklch(0.72 0.012 270); /* ≥ 4.5:1 on dark bg ✓ */
388
- --accent: oklch(0.33 0.06 270);
389
- --accent-foreground: oklch(0.985 0 0);
390
- --destructive: oklch(0.65 0.20 25); /* brighter for dark bg */
391
- --destructive-foreground: oklch(0.10 0 0);
392
-
393
- /* KeyMetrics flat band — no surface; bottom brand glow only (OKLCH). */
394
- --key-metrics-flat-cell-bg: transparent;
395
- --key-metrics-flat-divider: color-mix(in oklch, var(--sidebar-border) 55%, transparent);
396
- --key-metrics-flat-band-radial: radial-gradient(
397
- ellipse 120% 68% at 50% 100%,
398
- color-mix(in oklch, var(--brand-color) 26%, transparent) 0%,
399
- color-mix(in oklch, var(--brand-color) 10%, transparent) 42%,
400
- transparent 72%
401
- );
402
- --key-metrics-flat-band-shadow: none;
403
- --key-metrics-card-glow-radial: radial-gradient(
404
- ellipse 110% 90% at 50% 100%,
405
- color-mix(in oklch, var(--brand-color) 22%, transparent) 0%,
406
- transparent 62%
407
- );
408
-
409
- /* Borders — visible but not washed out on dark surfaces */
410
- --border: oklch(0.38 0.008 270);
411
- --border-control: oklch(0.72 0.012 270);
412
- --border-control-3: oklch(0.78 0.012 270);
413
- --border-control-35: oklch(0.75 0.012 270);
414
- --control-border: var(--border-control-3);
415
-
416
- --input: oklch(0.72 0.012 270);
417
- --input-background: oklch(0.255 0 0);
418
-
419
- /* Focus ring — 3:1+ on dark bg */
420
- --ring: oklch(0.85 0 0);
421
-
422
- /* Charts — higher lightness for dark surfaces */
423
- --chart-1: oklch(0.70 0.22 264.376);
424
- --chart-2: oklch(0.75 0.15 162.48);
425
- --chart-3: oklch(0.78 0.12 227.392);
426
- --chart-4: oklch(0.80 0.18 84.429);
427
- --chart-5: oklch(0.75 0.18 70.08);
428
-
429
- /* Chips — AA-compliant on dark bg (L raised) */
430
- --chip-1: oklch(0.72 0.18 264);
431
- --chip-2: oklch(0.72 0.14 184);
432
- --chip-3: oklch(0.78 0.12 227);
433
- --chip-4: oklch(0.78 0.14 84);
434
- --chip-5: oklch(0.78 0.16 70);
435
- --chip-destructive: oklch(0.72 0.18 25);
436
-
437
- /* Tinted icon discs — same soft transparency wash; fg stays readable on dark canvas */
438
- --icon-disc-chart-2-bg: color-mix(in oklch, var(--chart-2) 14%, transparent);
439
- --icon-disc-chart-2-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-2));
440
- --icon-disc-chart-4-bg: color-mix(in oklch, var(--chart-4) 14%, transparent);
441
- --icon-disc-chart-4-fg: color-mix(in oklch, var(--foreground) 10%, var(--chart-4));
442
- --icon-disc-brand-bg: color-mix(in oklch, var(--brand-color) 12%, transparent);
443
- --icon-disc-brand-fg: color-mix(in oklch, var(--foreground) 8%, var(--brand-color));
444
- --icon-disc-danger-bg: color-mix(in oklch, var(--destructive) 14%, transparent);
445
- --icon-disc-danger-fg: color-mix(in oklch, var(--foreground) 8%, var(--destructive));
446
-
447
- /* Sidebar */
448
- --sidebar: oklch(0.245 0.015 270);
449
- --sidebar-foreground: oklch(0.985 0 0);
450
- --sidebar-primary: oklch(0.488 0.243 264.376);
451
- --sidebar-primary-foreground: oklch(0.985 0 0);
452
- --sidebar-accent: oklch(0.30 0.012 270);
453
- --sidebar-accent-foreground: oklch(0.985 0 0);
454
- --sidebar-border: oklch(0.38 0.010 270);
455
- --sidebar-ring: oklch(0.85 0 0);
456
- --sidebar-section-label-foreground: color-mix(in oklch, var(--sidebar-foreground) 48%, var(--sidebar));
457
- /* Nested secondary rail — elevation 1: brand stack, lifted toward `--card` / page. */
458
- --secondary-panel-bg: color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%);
459
- --theme-color-chrome: #2f2d36;
460
-
461
- /* Lifted scrim on dark — white-tinted veil, not heavy black */
462
- --overlay: color-mix(in oklch, var(--foreground) 10%, transparent);
463
-
464
- /* Mid lavender chip + light text — no black circle; contrasts on dark table rows */
465
- --avatar-initials-bg: color-mix(in oklch, var(--brand-color) 38%, oklch(0.40 0.05 286.1));
466
- --avatar-initials-fg: oklch(0.99 0.01 286.1);
467
-
468
- /* DataTable — opaque surfaces for dark mode */
469
- --dt-row-bg: var(--background);
470
- --dt-row-hover: oklch(0.24 0.01 270);
471
- --dt-row-selected: oklch(0.27 0.02 270);
472
- --dt-row-selected-fg: var(--foreground);
473
- --dt-header-bg: var(--background);
474
- --dt-group-bg: oklch(0.24 0.01 270);
475
- --dt-new-row-bg: oklch(from var(--brand-color) 0.22 0.02 h);
476
- --dt-new-row-border: var(--brand-color);
477
- }
478
-
479
- /* ==========================================================================
480
- Theme: Exxat One · Lavender (explicit — also applied as :root default)
481
- Usage: <html class="theme-one"> or <html class="theme-lavender">
482
- ========================================================================== */
483
- .theme-one,
484
- .theme-lavender {
485
- --brand-tint: oklch(0.9676 0.016 286.1);
486
- --brand-tint-light: oklch(0.993 0.007 286.1);
487
- --brand-tint-subtle: oklch(0.935 0.024 286.1);
488
- --brand-color: oklch(0.50 0.14 286.1);
489
- --brand-color-light: oklch(0.78 0.09 286.1);
490
- --brand-color-dark: oklch(0.38 0.11 286.1);
491
- --brand-color-deep: oklch(0.28 0.085 286.1);
492
- --ring: var(--brand-color-dark);
493
- }
494
-
495
- /* Light surfaces only — must NOT override .dark (otherwise muted/accent stay “paper white” in dark mode) */
496
- .theme-one:not(.dark),
497
- .theme-lavender:not(.dark) {
498
- --sidebar: var(--brand-tint);
499
- --sidebar-accent: oklch(0.945 0.025 286.1);
500
- --sidebar-border: oklch(0.92 0.025 286.1);
501
- --secondary: oklch(0.95 0.012 286.1);
502
- --accent: oklch(0.925 0.015 286.1);
503
- --muted: oklch(0.945 0.008 286.1);
504
- }
505
-
506
- .theme-one.dark,
507
- .dark.theme-one,
508
- .theme-lavender.dark,
509
- .dark.theme-lavender {
510
- --ring: var(--brand-color);
511
- --background: oklch(0.20 0.008 286.1);
512
- --sidebar: oklch(0.245 0.015 286.1);
513
- --sidebar-accent: oklch(0.30 0.012 286.1);
514
- --sidebar-border: oklch(0.38 0.010 286.1);
515
- /* Restore dark surfaces (base .dark is overridden by :not(.dark) rules above when both classes apply) */
516
- --secondary: oklch(0.31 0.04 286.1);
517
- --muted: oklch(0.31 0.04 286.1);
518
- --accent: oklch(0.33 0.06 286.1);
519
- --brand-tint-light: oklch(0.30 0.014 286.1);
520
- }
521
-
522
- /* ==========================================================================
523
- Theme: Exxat Prism · Rose · hue 343
524
- Usage: <html class="theme-prism"> or <html class="theme-rose">
525
- ========================================================================== */
526
- .theme-prism,
527
- .theme-rose {
528
- --brand-tint: oklch(0.97 0.02 343);
529
- --brand-tint-light: oklch(0.992 0.01 343);
530
- --brand-tint-subtle: oklch(0.93 0.028 343);
531
- --brand-color: oklch(0.57 0.24 342); /* Prism rose */
532
- --brand-color-light: oklch(0.78 0.14 342);
533
- --brand-color-dark: oklch(0.42 0.24 342);
534
- --brand-color-deep: oklch(0.32 0.20 342);
535
- --ring: var(--brand-color-dark);
536
- }
537
-
538
- .theme-prism:not(.dark),
539
- .theme-rose:not(.dark) {
540
- --sidebar: oklch(0.97 0.02 343);
541
- --sidebar-accent: oklch(0.945 0.025 343);
542
- --sidebar-border: oklch(0.92 0.025 343);
543
- --secondary: oklch(0.95 0.012 343);
544
- --accent: oklch(0.925 0.015 343);
545
- --muted: oklch(0.945 0.008 343);
546
- --banner-prism-bg: oklch(0.97 0.02 343);
547
- --theme-color-chrome: #fff5f9;
548
- }
549
-
550
- .theme-prism.dark,
551
- .dark.theme-prism,
552
- .theme-rose.dark,
553
- .dark.theme-rose {
554
- --ring: var(--brand-color);
555
- --background: oklch(0.20 0.008 342);
556
- --sidebar: oklch(0.245 0.015 342);
557
- --sidebar-accent: oklch(0.30 0.012 342);
558
- --sidebar-border: oklch(0.38 0.010 342);
559
- --secondary: oklch(0.31 0.04 342);
560
- --muted: oklch(0.31 0.04 342);
561
- --accent: oklch(0.33 0.06 342);
562
- --theme-color-chrome: #2a2428;
563
- --brand-tint-light: oklch(0.30 0.014 342);
564
- }
565
-
566
- /* ==========================================================================
567
- Theme: Exxat Assessment · Green · hue 159.88
568
- Usage: <html class="theme-assessment">
569
- ========================================================================== */
570
- .theme-assessment {
571
- --brand-tint: oklch(0.965 0.018 159.88);
572
- --brand-tint-light: oklch(0.992 0.008 159.88);
573
- --brand-tint-subtle: oklch(0.93 0.028 159.88);
574
- --brand-color: oklch(0.7 0.0913 159.88);
575
- --brand-color-light: oklch(0.82 0.072 159.88);
576
- --brand-color-dark: oklch(0.48 0.0913 159.88);
577
- --brand-color-deep: oklch(0.34 0.075 159.88);
578
- --ring: var(--brand-color-dark);
579
- }
580
-
581
- .theme-assessment:not(.dark) {
582
- --sidebar: var(--brand-tint);
583
- --sidebar-accent: oklch(0.945 0.026 159.88);
584
- --sidebar-border: oklch(0.90 0.026 159.88);
585
- --secondary: oklch(0.95 0.012 159.88);
586
- --accent: oklch(0.925 0.016 159.88);
587
- --muted: oklch(0.945 0.008 159.88);
588
- --theme-color-chrome: #f1faf5;
589
- }
590
-
591
- .theme-assessment.dark,
592
- .dark.theme-assessment {
593
- --ring: var(--brand-color);
594
- --background: oklch(0.20 0.008 159.88);
595
- --sidebar: oklch(0.245 0.015 159.88);
596
- --sidebar-accent: oklch(0.30 0.012 159.88);
597
- --sidebar-border: oklch(0.38 0.010 159.88);
598
- --secondary: oklch(0.31 0.04 159.88);
599
- --muted: oklch(0.31 0.04 159.88);
600
- --accent: oklch(0.33 0.06 159.88);
601
- --theme-color-chrome: #242a27;
602
- }
603
-
604
- /* ==========================================================================
605
- Theme: Custom product · user-selected hue
606
- Usage: <html class="theme-custom" style="--custom-product-brand-color: …">
607
- ========================================================================== */
608
- /*
609
- * Tint chroma is **derived from the source's chroma** so neighbouring hues
610
- * (e.g. Blue h=252 vs Indigo h=280 vs Purple h=286) read as distinct pale
611
- * tints instead of collapsing to the same near-white. The earlier formula
612
- * pinned chroma to a fixed `0.018`, which is below the hue-discrimination
613
- * threshold at L≈0.96 for closely-spaced hues — that's why Blue / Indigo /
614
- * Purple looked identical in the sidebar.
615
- *
616
- * `max(<floor>, calc(c * <fraction>))` rules:
617
- * - vibrant brand colours (c ≈ 0.10–0.23) get a meaningfully tinted
618
- * sidebar / accent / muted scale → product chrome visibly changes per
619
- * pick
620
- * - low-chroma custom-hex picks (greys) fall back to the floor so they
621
- * don't render as pure white
622
- * - lightness + hue stay pinned to the original mock-up values, so the
623
- * overall "very pale background" feel is unchanged
624
- */
625
- .theme-custom {
626
- --brand-tint: oklch(from var(--custom-product-brand-color) 0.965 max(0.018, calc(c * 0.20)) h);
627
- --brand-tint-light: oklch(from var(--custom-product-brand-color) 0.992 max(0.008, calc(c * 0.08)) h);
628
- --brand-tint-subtle: oklch(from var(--custom-product-brand-color) 0.93 max(0.028, calc(c * 0.30)) h);
629
- --brand-color: var(--custom-product-brand-color);
630
- --brand-color-light: oklch(from var(--custom-product-brand-color) 0.82 c h);
631
- --brand-color-dark: oklch(from var(--custom-product-brand-color) 0.48 c h);
632
- --brand-color-deep: oklch(from var(--custom-product-brand-color) 0.34 c h);
633
- --ring: var(--brand-color-dark);
634
- }
635
-
636
- .theme-custom:not(.dark) {
637
- --sidebar: var(--brand-tint);
638
- --sidebar-accent: oklch(from var(--custom-product-brand-color) 0.945 max(0.026, calc(c * 0.28)) h);
639
- --sidebar-border: oklch(from var(--custom-product-brand-color) 0.90 max(0.026, calc(c * 0.28)) h);
640
- --secondary: oklch(from var(--custom-product-brand-color) 0.95 max(0.012, calc(c * 0.14)) h);
641
- --accent: oklch(from var(--custom-product-brand-color) 0.925 max(0.016, calc(c * 0.18)) h);
642
- --muted: oklch(from var(--custom-product-brand-color) 0.945 max(0.008, calc(c * 0.10)) h);
643
- --theme-color-chrome: color-mix(in oklch, var(--custom-product-brand-color) 10%, white);
644
- }
645
-
646
- .theme-custom.dark,
647
- .dark.theme-custom {
648
- --ring: var(--brand-color);
649
- --background: oklch(from var(--custom-product-brand-color) 0.20 max(0.008, calc(c * 0.10)) h);
650
- --sidebar: oklch(from var(--custom-product-brand-color) 0.245 max(0.015, calc(c * 0.18)) h);
651
- --sidebar-accent: oklch(from var(--custom-product-brand-color) 0.30 max(0.012, calc(c * 0.14)) h);
652
- --sidebar-border: oklch(from var(--custom-product-brand-color) 0.38 max(0.010, calc(c * 0.12)) h);
653
- --secondary: oklch(from var(--custom-product-brand-color) 0.31 max(0.04, calc(c * 0.40)) h);
654
- --muted: oklch(from var(--custom-product-brand-color) 0.31 max(0.04, calc(c * 0.40)) h);
655
- --accent: oklch(from var(--custom-product-brand-color) 0.33 max(0.06, calc(c * 0.50)) h);
656
- --theme-color-chrome: color-mix(in oklch, var(--custom-product-brand-color) 12%, black);
657
- }
658
-
659
- /* ==========================================================================
660
- HIGH CONTRAST MODE
661
- ──────────────────────────────────────────────────────────────────────────
662
- Three guiding principles (WCAG 1.4.6 Enhanced + research-backed UX):
663
-
664
- 1. FORCED-COLORS APPROACH
665
- Strip gradients, shadows, and background images.
666
- Use borders to define shape and elevation — not fills.
667
- Limited palette: 4–6 named tokens, nothing decorative.
668
-
669
- 2. DON'T RELY ON COLOR ALONE
670
- Error/warning states get a thick border AND an icon differentiator.
671
- Charts and badges use luminance separation (grayscale steps), not hue.
672
- Interactive state (hover / focus / active) is communicated via outline,
673
- not background-color change alone.
674
-
675
- 3. DARK MODE ≠ HIGH CONTRAST
676
- Dark mode = aesthetic; uses subtle greys.
677
- High-contrast dark = functional; uses near-black grey canvas, pure white
678
- (#FFF), and a "hot" neon-yellow focus accent for maximum visibility.
679
- ========================================================================== */
680
-
681
- /* ── Light High Contrast ─────────────────────────────────────────────────── */
682
- /* Fluent 2 / Microsoft 6-color strategy. */
683
- /* Highlight = saturated bright brand color (follows theme hue). */
684
- html[data-contrast="high"]:not(.dark) {
685
- --hc-highlight: oklch(from var(--brand-color) 0.35 0.30 h);
686
- --hc-highlight-text: oklch(1 0 0);
687
-
688
- --background: oklch(1 0 0);
689
- --foreground: oklch(0.14 0 0);
690
- --card: oklch(1 0 0);
691
- --card-foreground: oklch(0.14 0 0);
692
- --popover: oklch(1 0 0);
693
- --popover-foreground: oklch(0.14 0 0);
694
- --primary: oklch(0.14 0 0);
695
- --primary-foreground: oklch(1 0 0);
696
- --secondary: oklch(1 0 0);
697
- --secondary-foreground: oklch(0.14 0 0);
698
- --muted: oklch(0.94 0 0);
699
- --muted-foreground: oklch(0.14 0 0);
700
- --accent: var(--hc-highlight);
701
- --accent-foreground: var(--hc-highlight-text);
702
- --destructive: oklch(0.45 0.24 25);
703
- --destructive-foreground: oklch(1 0 0);
704
- --border: oklch(0.14 0 0);
705
- --border-control: oklch(0.14 0 0);
706
- --border-control-3: oklch(0.14 0 0);
707
- --border-control-35: oklch(0.14 0 0);
708
- --control-border: oklch(0.14 0 0);
709
- --input: oklch(0.14 0 0);
710
- --input-background: oklch(1 0 0);
711
- --ring: var(--hc-highlight);
712
- --sidebar: oklch(1 0 0);
713
- --sidebar-foreground: oklch(0.14 0 0);
714
- --sidebar-primary: oklch(0.14 0 0);
715
- --sidebar-primary-foreground: oklch(1 0 0);
716
- --sidebar-accent: oklch(0.90 0 0);
717
- --sidebar-accent-foreground: oklch(0.14 0 0);
718
- --sidebar-border: oklch(0.14 0 0);
719
- --sidebar-ring: var(--hc-highlight);
720
- --sidebar-section-label-foreground: oklch(0.40 0 0);
721
- --chart-1: oklch(0.14 0 0);
722
- --chart-2: oklch(0.35 0 0);
723
- --chart-3: oklch(0.55 0 0);
724
- --chart-4: oklch(0.72 0 0);
725
- --chart-5: oklch(0.86 0 0);
726
- --chip-1: oklch(0.14 0 0);
727
- --chip-2: oklch(0.14 0 0);
728
- --chip-3: oklch(0.14 0 0);
729
- --chip-4: oklch(0.14 0 0);
730
- --chip-5: oklch(0.14 0 0);
731
- --chip-destructive: oklch(0.45 0.24 25);
732
- --interactive-hover: oklch(0.88 0 0);
733
- --interactive-hover-foreground: oklch(0.14 0 0);
734
- --interactive-hover-subtle: oklch(0.92 0 0);
735
- --interactive-hover-soft: oklch(0.92 0 0);
736
- --interactive-hover-medium: oklch(0.86 0 0);
737
- --interactive-hover-strong: oklch(0.82 0 0);
738
- --interactive-hover-row: oklch(0.88 0 0);
739
- --overlay: color-mix(in oklch, var(--foreground) 18%, transparent);
740
- --dt-row-bg: oklch(1 0 0);
741
- --dt-row-hover: oklch(0.92 0 0);
742
- --dt-row-selected: var(--accent);
743
- --dt-row-selected-fg: var(--accent-foreground);
744
- --dt-header-bg: oklch(1 0 0);
745
- --dt-group-bg: oklch(0.92 0 0);
746
- --dt-new-row-bg: oklch(1 0 0);
747
- --dt-new-row-border: oklch(0.14 0 0);
748
- }
749
-
750
- /* ── Dark High Contrast ──────────────────────────────────────────────────── */
751
- /* Same 6-color strategy inverted for dark canvas. */
752
- /* Highlight = very bright saturated brand (like MS cyan but brand hue). */
753
- html[data-contrast="high"].dark {
754
- --hc-highlight: oklch(from var(--brand-color) 0.78 0.30 h);
755
- --hc-highlight-text: oklch(0.08 0 0);
756
-
757
- --background: oklch(0.14 0 0);
758
- --foreground: oklch(0.96 0 0);
759
- --card: oklch(0.14 0 0);
760
- --card-foreground: oklch(0.96 0 0);
761
- --popover: oklch(0.20 0 0);
762
- --popover-foreground: oklch(0.96 0 0);
763
- --primary: oklch(0.96 0 0);
764
- --primary-foreground: oklch(0.10 0 0);
765
- --secondary: oklch(0.14 0 0);
766
- --secondary-foreground: oklch(0.96 0 0);
767
- --muted: oklch(0.22 0 0);
768
- --muted-foreground: oklch(0.96 0 0);
769
- --accent: var(--hc-highlight);
770
- --accent-foreground: var(--hc-highlight-text);
771
- --destructive: oklch(0.72 0.18 18);
772
- --destructive-foreground: oklch(0.10 0 0);
773
- --border: oklch(0.75 0 0);
774
- --border-control: oklch(0.75 0 0);
775
- --border-control-3: oklch(0.75 0 0);
776
- --border-control-35: oklch(0.75 0 0);
777
- --control-border: oklch(0.75 0 0);
778
- --input: oklch(0.75 0 0);
779
- --input-background: oklch(0.14 0 0);
780
- --ring: var(--hc-highlight);
781
- --sidebar: oklch(0.14 0 0);
782
- --sidebar-foreground: oklch(0.96 0 0);
783
- --sidebar-primary: oklch(0.96 0 0);
784
- --sidebar-primary-foreground: oklch(0.10 0 0);
785
- --sidebar-accent: oklch(0.24 0 0);
786
- --sidebar-accent-foreground: oklch(0.96 0 0);
787
- --sidebar-border: oklch(0.75 0 0);
788
- --sidebar-ring: var(--hc-highlight);
789
- --sidebar-section-label-foreground: oklch(0.65 0 0);
790
- --chart-1: oklch(0.96 0 0);
791
- --chart-2: oklch(0.75 0 0);
792
- --chart-3: oklch(0.55 0 0);
793
- --chart-4: oklch(0.38 0 0);
794
- --chart-5: oklch(0.22 0 0);
795
- --chip-1: oklch(0.96 0 0);
796
- --chip-2: oklch(0.96 0 0);
797
- --chip-3: oklch(0.96 0 0);
798
- --chip-4: oklch(0.96 0 0);
799
- --chip-5: oklch(0.96 0 0);
800
- --chip-destructive: oklch(0.72 0.18 18);
801
- --interactive-hover: oklch(0.26 0 0);
802
- --interactive-hover-foreground: oklch(0.96 0 0);
803
- --interactive-hover-subtle: oklch(0.22 0 0);
804
- --interactive-hover-soft: oklch(0.22 0 0);
805
- --interactive-hover-medium: oklch(0.28 0 0);
806
- --interactive-hover-strong: oklch(0.32 0 0);
807
- --interactive-hover-row: oklch(0.26 0 0);
808
- --overlay: color-mix(in oklch, var(--foreground) 22%, transparent);
809
- --dt-row-bg: oklch(0.14 0 0);
810
- --dt-row-hover: oklch(0.22 0 0);
811
- --dt-row-selected: var(--accent);
812
- --dt-row-selected-fg: var(--accent-foreground);
813
- --dt-header-bg: oklch(0.14 0 0);
814
- --dt-group-bg: oklch(0.22 0 0);
815
- --dt-new-row-bg: oklch(0.14 0 0);
816
- --dt-new-row-border: oklch(0.96 0 0);
817
- }
818
-
819
- /* Neutralize brand tint washes in HC so bg-brand-tint doesn't compete */
820
- html:is([data-contrast="high"], [data-contrast="windows"]):not(.dark) {
821
- --brand-tint: oklch(0.94 0 0);
822
- --brand-tint-light: oklch(0.97 0 0);
823
- --brand-tint-subtle: oklch(0.98 0 0);
824
- }
825
- html:is([data-contrast="high"], [data-contrast="windows"]).dark {
826
- --brand-tint: oklch(0.22 0 0);
827
- --brand-tint-light: oklch(0.18 0 0);
828
- --brand-tint-subtle: oklch(0.16 0 0);
829
- }
830
-
831
- /* ── Structural rules shared by BOTH light and dark HC ──────────────────── */
832
- /* Pattern 1: "Borders over Fills" — strip decorative chrome */
833
- html:is([data-contrast="high"], [data-contrast="windows"]) {
834
-
835
- /* 1a. Remove ALL box-shadows (elevation via outline, not shadow) */
836
- & * {
837
- box-shadow: none !important;
838
- text-shadow: none !important;
839
- }
840
-
841
- /* 1b. Strip gradient fills from cards; use border to define shape */
842
- & [data-slot="card"] {
843
- background-image: none !important;
844
- border: 2px solid var(--foreground) !important;
845
- }
846
-
847
- /* 1c. Thicker borders on all form controls (WCAG 1.4.11: 3:1 UI contrast) */
848
- & [data-slot="input"],
849
- & [data-slot="select-trigger"],
850
- & [data-slot="textarea"],
851
- & [data-slot="checkbox"],
852
- & [data-slot="switch"] {
853
- border-width: 2px !important;
854
- border-color: var(--foreground) !important;
855
- }
856
-
857
- /* 1d. Sidebar defined by its edge border, not background colour */
858
- & [data-slot="sidebar"] {
859
- border-inline-end: 2px solid var(--sidebar-border) !important;
860
- }
861
-
862
- /* 1e. Tab list — border not fill */
863
- & [data-slot="tabs-list"] {
864
- background-color: transparent !important;
865
- border: 2px solid var(--foreground) !important;
866
- }
867
-
868
- /* 1f. Badge / chip — border-based; no decorative fills */
869
- & [data-slot="badge"] {
870
- border-width: 2px !important;
871
- border-color: var(--foreground) !important;
872
- background-color: var(--background) !important;
873
- font-weight: 700 !important;
874
- box-shadow: none !important;
875
- outline: none !important;
876
- color: var(--foreground) !important;
877
- }
878
-
879
- & [data-slot="badge"] * {
880
- color: var(--foreground) !important;
881
- }
882
-
883
- /* Status chip — same treatment as Badge (border-based, no decorative fill) */
884
- & [data-slot="status-badge"] {
885
- border-width: 2px !important;
886
- border-color: var(--foreground) !important;
887
- background-color: var(--background) !important;
888
- font-weight: 700 !important;
889
- box-shadow: none !important;
890
- outline: none !important;
891
- color: var(--foreground) !important;
892
- }
893
-
894
- /* Sidebar wrapper is positioning-only when it wraps Badge/StatusBadge — avoid double border */
895
- & [data-slot="sidebar-menu-badge"]:has([data-slot="badge"]),
896
- & [data-slot="sidebar-menu-badge"]:has([data-slot="status-badge"]) {
897
- border-width: 0 !important;
898
- background-color: transparent !important;
899
- box-shadow: none !important;
900
- outline: none !important;
901
- }
902
-
903
- & [data-slot="view-toolbar-count"] {
904
- border-width: 2px !important;
905
- border-color: currentColor !important;
906
- background-color: var(--background) !important;
907
- font-weight: 700 !important;
908
- color: var(--foreground) !important;
909
- box-shadow: none !important;
910
- outline: none !important;
911
- }
912
-
913
- & [data-slot="sidebar-menu-badge"]:not(:has([data-slot="badge"])):not(:has([data-slot="status-badge"])) {
914
- border-width: 2px !important;
915
- border-color: currentColor !important;
916
- background-color: var(--background) !important;
917
- font-weight: 700 !important;
918
- color: var(--foreground) !important;
919
- }
920
-
921
- /* Segmented tab buttons: global HC button border + count pill border = double ring */
922
- & button[data-slot="view-segmented-item"] {
923
- border-width: 0 !important;
924
- border-color: transparent !important;
925
- }
926
-
927
- /* Radix Tabs — active state must not rely on muted fill / pseudo underline only */
928
- & [data-slot="tabs-trigger"] {
929
- color: var(--foreground) !important;
930
- opacity: 1 !important;
931
- }
932
-
933
- & [data-slot="tabs-trigger"][data-state="active"] {
934
- background-color: var(--accent) !important;
935
- color: var(--accent-foreground) !important;
936
- outline: none !important;
937
- font-weight: 600 !important;
938
- }
939
-
940
- /* KPI strip + chart card mini-metrics — force readable copy (muted grays fail in HC) */
941
- & [data-slot="key-metrics"] :where(span, p, button, a, i, label, div) {
942
- color: var(--foreground) !important;
943
- }
944
-
945
- & [data-slot="key-metrics"] :where(svg) {
946
- color: var(--foreground) !important;
947
- }
948
-
949
- /* List / menu rows — Highlight brand color for selection */
950
- & [data-slot="dropdown-menu-item"][data-highlighted],
951
- & [data-slot="dropdown-menu-checkbox-item"][data-highlighted],
952
- & [data-slot="dropdown-menu-radio-item"][data-highlighted],
953
- & [data-slot="dropdown-menu-sub-trigger"][data-highlighted],
954
- & [data-slot="select-item"][data-highlighted],
955
- & [data-slot="command-item"][data-selected],
956
- & [data-slot="command-item"][aria-selected="true"] {
957
- background-color: var(--accent) !important;
958
- color: var(--accent-foreground) !important;
959
- }
960
-
961
- & [data-slot="dropdown-menu-item"][data-highlighted] *,
962
- & [data-slot="dropdown-menu-checkbox-item"][data-highlighted] *,
963
- & [data-slot="dropdown-menu-radio-item"][data-highlighted] *,
964
- & [data-slot="dropdown-menu-sub-trigger"][data-highlighted] *,
965
- & [data-slot="select-item"][data-highlighted] *,
966
- & [data-slot="command-item"][data-selected] *,
967
- & [data-slot="command-item"][aria-selected="true"] * {
968
- color: var(--accent-foreground) !important;
969
- }
970
-
971
- /* List hub views toolbar + segmented radiogroup (not Radix Tabs / tabs-list) */
972
- & [data-slot="view-segmented-toolbar"] {
973
- background-color: transparent !important;
974
- border: 2px solid var(--foreground) !important;
975
- }
976
-
977
- & [data-slot="view-segmented-item"][aria-pressed="true"],
978
- & [data-slot="view-segmented-item"][aria-checked="true"] {
979
- background-color: var(--accent) !important;
980
- color: var(--accent-foreground) !important;
981
- outline: none !important;
982
- }
983
-
984
- /* Floating surfaces — portal menus, popovers, sheets, dialogs */
985
- & [data-slot="dropdown-menu-content"],
986
- & [data-slot="dropdown-menu-sub-content"],
987
- & [data-slot="popover-content"],
988
- & [data-slot="select-content"],
989
- & [data-slot="dialog-content"],
990
- & [data-slot="sheet-content"],
991
- & [data-slot="drawer-content"] {
992
- border: 2px solid var(--foreground) !important;
993
- background-color: var(--background) !important;
994
- color: var(--foreground) !important;
995
- }
996
-
997
- & [data-slot="command"] {
998
- background-color: var(--background) !important;
999
- color: var(--foreground) !important;
1000
- }
1001
-
1002
- /* Strip conditional-formatting inline bg from table cells in HC */
1003
- & td[style*="background"] {
1004
- background: var(--dt-row-bg) !important;
1005
- }
1006
- & td.pinned-cell {
1007
- background-color: var(--dt-row-bg) !important;
1008
- }
1009
- & tr:hover td.pinned-cell,
1010
- & tr:hover td {
1011
- background-color: var(--dt-row-hover) !important;
1012
- }
1013
- & tr[data-state="selected"] td.pinned-cell,
1014
- & tr[data-state="selected"] td {
1015
- background-color: var(--dt-row-selected) !important;
1016
- color: var(--dt-row-selected-fg) !important;
1017
- }
1018
-
1019
- /* Table selected rows — Highlight brand color (like MS Teams selection) */
1020
- & tr[data-state="selected"] {
1021
- background-color: var(--dt-row-selected) !important;
1022
- color: var(--dt-row-selected-fg) !important;
1023
- }
1024
- & tr[data-state="selected"] *:not([data-slot="checkbox"] *):not([data-slot="badge"] *):not([data-slot="checkbox"]):not([data-slot="badge"]) {
1025
- color: var(--accent-foreground) !important;
1026
- }
1027
- & tr[data-state="selected"] [data-slot="badge"] {
1028
- background-color: var(--accent-foreground) !important;
1029
- color: var(--accent) !important;
1030
- border-color: var(--accent-foreground) !important;
1031
- }
1032
- & tr[data-state="selected"] [data-slot="badge"] * {
1033
- color: var(--accent) !important;
1034
- }
1035
-
1036
- & tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"],
1037
- & tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] {
1038
- background-color: var(--accent-foreground) !important;
1039
- border-color: var(--accent-foreground) !important;
1040
- color: var(--accent) !important;
1041
- }
1042
- & tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"] *,
1043
- & tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] * {
1044
- color: var(--accent) !important;
1045
- }
1046
- & tr[data-state="selected"] [data-slot="checkbox"]:not([data-state="checked"]):not([data-state="indeterminate"]) {
1047
- background-color: var(--accent) !important;
1048
- border-color: var(--accent-foreground) !important;
1049
- color: var(--accent-foreground) !important;
1050
- }
1051
-
1052
- /* ── Pattern 2: Stronger focus ring (WCAG 2.4.11 / 2.4.12) ── */
1053
- & :focus-visible {
1054
- outline: 3px solid var(--ring) !important;
1055
- outline-offset: 3px !important;
1056
- }
1057
-
1058
- /* ── Pattern 2: Error state — thick border + no colour-only signal ── */
1059
- & [aria-invalid="true"],
1060
- & [data-invalid] {
1061
- border-width: 3px !important;
1062
- border-color: var(--destructive) !important;
1063
- /* Downstream: pair with a ⚠ icon in the component for non-colour signal */
1064
- }
1065
-
1066
- /* ── Pattern 3: Active nav — Highlight brand fill (like MS Teams) ── */
1067
- & [data-slot="sidebar-menu-button"][data-active="true"] {
1068
- background-color: var(--accent) !important;
1069
- color: var(--accent-foreground) !important;
1070
- outline: none !important;
1071
- }
1072
- & [data-slot="sidebar-menu-button"][data-active="true"] * {
1073
- color: var(--accent-foreground) !important;
1074
- }
1075
- & [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"],
1076
- & [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] {
1077
- background-color: var(--accent-foreground) !important;
1078
- color: var(--accent) !important;
1079
- border-color: var(--accent-foreground) !important;
1080
- }
1081
- & [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"] *,
1082
- & [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] * {
1083
- color: var(--accent) !important;
1084
- }
1085
- & [data-slot="toggle-group-item"][data-state="on"] {
1086
- outline: 2px solid var(--accent) !important;
1087
- outline-offset: -2px !important;
1088
- background-color: var(--accent) !important;
1089
- color: var(--accent-foreground) !important;
1090
- }
1091
-
1092
- /* ── Pattern 3b: Checked checkboxes — Highlight brand fill ── */
1093
- & [data-slot="checkbox"][data-state="checked"],
1094
- & [data-slot="checkbox"][data-state="indeterminate"] {
1095
- background-color: var(--accent) !important;
1096
- border-color: var(--accent) !important;
1097
- color: var(--accent-foreground) !important;
1098
- }
1099
- & [data-slot="checkbox"][data-state="checked"] *,
1100
- & [data-slot="checkbox"][data-state="indeterminate"] * {
1101
- color: var(--accent-foreground) !important;
1102
- }
1103
-
1104
- /* ── Pattern 3c: Checked radio buttons — Highlight brand fill ── */
1105
- & [data-slot="radio-group-item"][data-state="checked"] {
1106
- background-color: var(--accent) !important;
1107
- border-color: var(--accent) !important;
1108
- color: var(--accent-foreground) !important;
1109
- }
1110
- & [data-slot="radio-group-item"][data-state="checked"] [data-slot="radio-group-indicator"] span {
1111
- background-color: var(--accent-foreground) !important;
1112
- }
1113
-
1114
- /* ── Pattern 3d: Toggle on state — Highlight brand fill ── */
1115
- & [data-slot="toggle"][data-state="on"] {
1116
- background-color: var(--accent) !important;
1117
- color: var(--accent-foreground) !important;
1118
- border: 2px solid var(--accent) !important;
1119
- }
1120
-
1121
- /* ── Pattern 3e: Switch (toggle-switch) — visible track + knob ── */
1122
- & [role="switch"] {
1123
- border: 2px solid var(--foreground) !important;
1124
- background-color: var(--background) !important;
1125
- }
1126
- & [role="switch"][aria-checked="true"] {
1127
- background-color: var(--accent) !important;
1128
- border-color: var(--accent) !important;
1129
- }
1130
- & [role="switch"] > span {
1131
- background-color: var(--foreground) !important;
1132
- }
1133
- & [role="switch"][aria-checked="true"] > span {
1134
- background-color: var(--accent-foreground) !important;
1135
- }
1136
-
1137
- /* ── Pattern 3f: Select / dropdown item focus — Highlight brand fill ── */
1138
- & [data-slot="select-item"]:focus,
1139
- & [data-slot="dropdown-menu-item"]:focus,
1140
- & [data-slot="dropdown-menu-checkbox-item"]:focus,
1141
- & [data-slot="dropdown-menu-radio-item"]:focus,
1142
- & [data-slot="dropdown-menu-sub-trigger"]:focus {
1143
- background-color: var(--accent) !important;
1144
- color: var(--accent-foreground) !important;
1145
- }
1146
- & [data-slot="select-item"]:focus *,
1147
- & [data-slot="dropdown-menu-item"]:focus *,
1148
- & [data-slot="dropdown-menu-checkbox-item"]:focus *,
1149
- & [data-slot="dropdown-menu-radio-item"]:focus *,
1150
- & [data-slot="dropdown-menu-sub-trigger"]:focus * {
1151
- color: var(--accent-foreground) !important;
1152
- }
1153
-
1154
- /* ── Pattern 3g: Dropdown check / radio indicator — inherit from parent ── */
1155
- & [data-slot="dropdown-menu-checkbox-item"][data-state="checked"],
1156
- & [data-slot="dropdown-menu-radio-item"][data-state="checked"] {
1157
- font-weight: 700 !important;
1158
- }
1159
-
1160
- /* ── Pattern 4: Board cards — border-defined, no decorative fills ── */
1161
- & [data-slot="board-card"] {
1162
- border: 2px solid var(--foreground) !important;
1163
- background-image: none !important;
1164
- }
1165
-
1166
- /* ── Pattern 6: List hub status badges — border not fill ── */
1167
- & [data-slot="list-hub-status-badge"] {
1168
- border: 2px solid var(--foreground) !important;
1169
- background-color: var(--background) !important;
1170
- font-weight: 700 !important;
1171
- color: var(--foreground) !important;
1172
- }
1173
-
1174
- /* ── Pattern 7: Insight cards — border-based, strip gradient bg ── */
1175
- & [aria-label="Insight"],
1176
- & [data-slot="insight-card"] {
1177
- border: 2px solid var(--foreground) !important;
1178
- background-image: none !important;
1179
- background: var(--background) !important;
1180
- }
1181
-
1182
- /* ── Pattern 8: Coach marks — strong border + readable text ── */
1183
- & [data-slot="coach-mark"] {
1184
- border: 2px solid var(--foreground) !important;
1185
- background: var(--background) !important;
1186
- background-color: var(--background) !important;
1187
- color: var(--foreground) !important;
1188
- background-image: none !important;
1189
- opacity: 1 !important;
1190
- }
1191
- & [data-slot="coach-mark"] *:not(button):not(button *) {
1192
- color: var(--foreground) !important;
1193
- }
1194
-
1195
- /* ── Pattern 9: Avatars — thicken ring, strip blend modes, force contrast ── */
1196
- & [data-slot="avatar"] {
1197
- border: 2px solid var(--foreground) !important;
1198
- }
1199
- & [data-slot="avatar"]::after {
1200
- display: none !important;
1201
- }
1202
- & [data-slot="avatar-fallback"] {
1203
- background-color: var(--background) !important;
1204
- color: var(--foreground) !important;
1205
- }
1206
- & tr[data-state="selected"] [data-slot="avatar"] {
1207
- border-color: var(--accent-foreground) !important;
1208
- }
1209
- & tr[data-state="selected"] [data-slot="avatar-fallback"] {
1210
- background-color: var(--accent-foreground) !important;
1211
- color: var(--accent) !important;
1212
- }
1213
-
1214
- /* ── Pattern 10: Breadcrumbs — ensure separators are visible ── */
1215
- & [data-slot="breadcrumb-separator"] {
1216
- color: var(--foreground) !important;
1217
- }
1218
- & [data-slot="breadcrumb-link"] {
1219
- color: var(--foreground) !important;
1220
- text-decoration: underline !important;
1221
- }
1222
- & [data-slot="breadcrumb-page"] {
1223
- color: var(--foreground) !important;
1224
- font-weight: 700 !important;
1225
- }
1226
-
1227
- /* ── Pattern 11: Tooltip / popover arrow — match border ── */
1228
- & [data-slot="tooltip-content"] {
1229
- border: 2px solid var(--foreground) !important;
1230
- background-color: var(--background) !important;
1231
- color: var(--foreground) !important;
1232
- }
1233
-
1234
- /* ── Pattern 12: Separator — visible in HC ── */
1235
- & [data-slot="separator"] {
1236
- background-color: var(--foreground) !important;
1237
- opacity: 1 !important;
1238
- }
1239
-
1240
- /* ── Pattern 13: Strip ALL hardcoded Tailwind palette colors ──────────── */
1241
- & [data-slot="banner"],
1242
- & [data-slot="local-banner"] {
1243
- background-color: var(--background) !important;
1244
- background-image: none !important;
1245
- border: 2px solid var(--foreground) !important;
1246
- color: var(--foreground) !important;
1247
- }
1248
- & [data-slot="banner"] *,
1249
- & [data-slot="local-banner"] * {
1250
- color: var(--foreground) !important;
1251
- }
1252
-
1253
- & .recharts-bar-rectangle,
1254
- & .recharts-funnel-trapezoid {
1255
- stroke: var(--background) !important;
1256
- stroke-width: 2 !important;
1257
- }
1258
-
1259
- & [role="progressbar"] {
1260
- border: 1px solid var(--foreground) !important;
1261
- background-color: var(--background) !important;
1262
- }
1263
- & [role="progressbar"] > * {
1264
- background-color: var(--foreground) !important;
1265
- }
1266
-
1267
- & [class*="text-emerald"],
1268
- & [class*="text-amber"],
1269
- & [class*="text-red-"],
1270
- & [class*="text-blue-"],
1271
- & [class*="text-green-"],
1272
- & [class*="text-yellow-"],
1273
- & [class*="text-slate-"],
1274
- & [class*="text-orange-"],
1275
- & [class*="text-pink-"],
1276
- & [class*="text-purple-"] {
1277
- color: var(--foreground) !important;
1278
- }
1279
-
1280
- & [class*="text-brand"] {
1281
- color: var(--accent) !important;
1282
- }
1283
- & [class*="bg-brand"]:not([data-slot="coach-mark"]) {
1284
- background-color: var(--background) !important;
1285
- }
1286
- & [class*="border-brand"] {
1287
- border-color: var(--foreground) !important;
1288
- }
1289
-
1290
- & [class*="bg-emerald"],
1291
- & [class*="bg-amber"],
1292
- & [class*="bg-red-"],
1293
- & [class*="bg-blue-"],
1294
- & [class*="bg-green-"],
1295
- & [class*="bg-yellow-"],
1296
- & [class*="bg-slate-"],
1297
- & [class*="bg-orange-"],
1298
- & [class*="bg-pink-"],
1299
- & [class*="bg-purple-"] {
1300
- background-color: var(--background) !important;
1301
- }
1302
-
1303
- & [class*="border-emerald"],
1304
- & [class*="border-amber"],
1305
- & [class*="border-red-"],
1306
- & [class*="border-blue-"],
1307
- & [class*="border-green-"],
1308
- & [class*="border-yellow-"],
1309
- & [class*="border-slate-"],
1310
- & [class*="border-orange-"],
1311
- & [class*="border-pink-"],
1312
- & [class*="border-purple-"] {
1313
- border-color: var(--foreground) !important;
1314
- }
1315
- }
1316
-
1317
- /* Coach mark HC override (top-level, outside nesting — bulletproof for portaled content) */
1318
- html:is([data-contrast="high"], [data-contrast="windows"]) [data-slot="coach-mark"] {
1319
- border: 2px solid var(--foreground) !important;
1320
- background: var(--background) !important;
1321
- background-color: var(--background) !important;
1322
- color: var(--foreground) !important;
1323
- background-image: none !important;
1324
- opacity: 1 !important;
1325
- }
1326
- html:is([data-contrast="high"], [data-contrast="windows"]) [data-slot="coach-mark"] *:not(button):not(button *) {
1327
- color: var(--foreground) !important;
1328
- }
1329
-
1330
- /* ── OS-level "Increase Contrast" — macOS / iOS / Android ───────────────── */
1331
- @media (prefers-contrast: more) {
1332
- :root:not([data-contrast="off"]):not([data-contrast="windows"]) {
1333
- --foreground: oklch(0.06 0 0);
1334
- --muted-foreground: oklch(0.10 0 0);
1335
- --border: oklch(0.10 0 0);
1336
- --border-control: oklch(0.06 0 0);
1337
- --border-control-35: oklch(0.06 0 0);
1338
- --border-control-3: oklch(0.06 0 0);
1339
- --ring: oklch(0.06 0 0);
1340
- }
1341
- .dark:not([data-contrast="off"]):not([data-contrast="windows"]) {
1342
- --foreground: oklch(1 0 0);
1343
- --muted-foreground: oklch(0.88 0 0);
1344
- --border: oklch(1 0 0);
1345
- --border-control: oklch(0.88 0 0);
1346
- --border-control-35: oklch(0.88 0 0);
1347
- --border-control-3: oklch(0.88 0 0);
1348
- --ring: oklch(0.97 0.19 110); /* neon yellow on dark */
1349
- }
1350
- }
1351
-
1352
- /* ── Windows Forced Colors (High Contrast Mode in OS) ───────────────────── */
1353
- /* When `forced-colors: active`, Windows REPLACES our colours entirely. */
1354
- /* Our job: map semantic roles to system palette keywords so the OS */
1355
- /* colouring makes sense, and ensure borders/outlines remain visible. */
1356
- @media (forced-colors: active) {
1357
- :root {
1358
- --border: CanvasText;
1359
- --border-control: CanvasText;
1360
- --border-control-35: CanvasText;
1361
- --border-control-3: CanvasText;
1362
- --ring: Highlight;
1363
- --destructive: LinkText;
1364
- }
1365
-
1366
- /* Always show a 2px outline so focus is forced-color-safe */
1367
- :focus-visible {
1368
- outline: 2px solid Highlight !important;
1369
- outline-offset: 2px !important;
1370
- }
1371
-
1372
- body {
1373
- background-color: Canvas;
1374
- color: CanvasText;
1375
- }
1376
-
1377
- a { color: LinkText; }
1378
- button { border: 1px solid ButtonText !important; }
1379
-
1380
- /* Cards: OS strips bg fills — add explicit border so shape is preserved */
1381
- [data-slot="card"],
1382
- .card {
1383
- border: 2px solid CanvasText !important;
1384
- }
1385
-
1386
- /* Sidebar edge */
1387
- [data-slot="sidebar"] {
1388
- border-inline-end: 2px solid CanvasText !important;
1389
- }
1390
-
1391
- /* Wrapper-only sidebar badge (no inner Badge) — rare; keep single ring */
1392
- [data-slot="sidebar-menu-badge"]:not(:has([data-slot="badge"])) {
1393
- border: 2px solid CanvasText !important;
1394
- background-color: Canvas !important;
1395
- color: CanvasText !important;
1396
- outline: none !important;
1397
- box-shadow: none !important;
1398
- }
1399
-
1400
- /* Positioning shell around <Badge/> — do not draw a second ring */
1401
- [data-slot="sidebar-menu-badge"]:has([data-slot="badge"]) {
1402
- border: none !important;
1403
- background: transparent !important;
1404
- outline: none !important;
1405
- box-shadow: none !important;
1406
- }
1407
-
1408
- [data-slot="badge"],
1409
- [data-slot="view-toolbar-count"] {
1410
- border: 2px solid CanvasText !important;
1411
- background-color: Canvas !important;
1412
- color: CanvasText !important;
1413
- outline: none !important;
1414
- box-shadow: none !important;
1415
- }
1416
-
1417
- [data-slot="badge"] *,
1418
- [data-slot="view-toolbar-count"] * {
1419
- color: CanvasText !important;
1420
- }
1421
-
1422
- /* Avoid button chrome + inner count pill = double border */
1423
- button[data-slot="view-segmented-item"] {
1424
- border: none !important;
1425
- }
1426
-
1427
- /* Radix Tabs (ChartCard, library, etc.) — gray inactive + invisible active in OS HC */
1428
- [data-slot="tabs-list"] {
1429
- border: 2px solid CanvasText !important;
1430
- background-color: transparent !important;
1431
- }
1432
-
1433
- [data-slot="tabs-trigger"] {
1434
- color: CanvasText !important;
1435
- background-color: transparent !important;
1436
- opacity: 1 !important;
1437
- }
1438
-
1439
- [data-slot="tabs-trigger"][data-state="active"] {
1440
- background-color: Highlight !important;
1441
- color: HighlightText !important;
1442
- outline: none !important;
1443
- font-weight: 600 !important;
1444
- }
1445
-
1446
- /* Key metrics strip — labels/values/trend icons must not stay muted */
1447
- [data-slot="key-metrics"] :where(span, p, button, a, i, label, div) {
1448
- color: CanvasText !important;
1449
- }
1450
-
1451
- /* Menu / select / command palette — accent fill is often low-contrast in forced mode */
1452
- [data-slot="dropdown-menu-item"][data-highlighted]:not([data-disabled]),
1453
- [data-slot="dropdown-menu-checkbox-item"][data-highlighted]:not([data-disabled]),
1454
- [data-slot="dropdown-menu-radio-item"][data-highlighted]:not([data-disabled]),
1455
- [data-slot="dropdown-menu-sub-trigger"][data-highlighted]:not([data-disabled]),
1456
- [data-slot="select-item"][data-highlighted]:not([data-disabled]),
1457
- [data-slot="command-item"][data-selected]:not([data-disabled]),
1458
- [data-slot="command-item"][aria-selected="true"]:not([data-disabled]) {
1459
- background-color: Highlight !important;
1460
- color: HighlightText !important;
1461
- }
1462
-
1463
- [data-slot="dropdown-menu-item"][data-highlighted] *,
1464
- [data-slot="dropdown-menu-checkbox-item"][data-highlighted] *,
1465
- [data-slot="dropdown-menu-radio-item"][data-highlighted] *,
1466
- [data-slot="dropdown-menu-sub-trigger"][data-highlighted] *,
1467
- [data-slot="select-item"][data-highlighted] *,
1468
- [data-slot="command-item"][data-selected] *,
1469
- [data-slot="command-item"][aria-selected="true"] * {
1470
- color: HighlightText !important;
1471
- }
1472
-
1473
- /* Views toolbar (list hubs) + segmented radiogroup — selection via outline, not fill */
1474
- [data-slot="view-segmented-toolbar"] {
1475
- border: 2px solid CanvasText !important;
1476
- background: transparent !important;
1477
- }
1478
-
1479
- [data-slot="view-segmented-item"] {
1480
- color: CanvasText !important;
1481
- background: transparent !important;
1482
- }
1483
-
1484
- [data-slot="view-segmented-item"][aria-pressed="true"],
1485
- [data-slot="view-segmented-item"][aria-checked="true"] {
1486
- background-color: Highlight !important;
1487
- color: HighlightText !important;
1488
- outline: none !important;
1489
- }
1490
-
1491
- /* Sidebar active item — Highlight brand fill */
1492
- [data-slot="sidebar-menu-button"][data-active="true"] {
1493
- background-color: Highlight !important;
1494
- color: HighlightText !important;
1495
- outline: none !important;
1496
- }
1497
- [data-slot="sidebar-menu-button"][data-active="true"] * {
1498
- color: HighlightText !important;
1499
- }
1500
- [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"],
1501
- [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] {
1502
- background-color: HighlightText !important;
1503
- color: Highlight !important;
1504
- border-color: HighlightText !important;
1505
- }
1506
- [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="badge"] *,
1507
- [data-slot="sidebar-menu-button"][data-active="true"] [data-slot="sidebar-menu-badge"] * {
1508
- color: Highlight !important;
1509
- }
1510
-
1511
- /* Strip conditional-formatting inline bg in forced-colors */
1512
- td[style*="background"] {
1513
- background: Canvas !important;
1514
- }
1515
- td.pinned-cell {
1516
- background-color: Canvas !important;
1517
- }
1518
- tr:hover td,
1519
- tr:hover td.pinned-cell {
1520
- background-color: Highlight !important;
1521
- color: HighlightText !important;
1522
- }
1523
-
1524
- /* Table selected rows — Highlight brand fill */
1525
- tr[data-state="selected"] {
1526
- background-color: Highlight !important;
1527
- color: HighlightText !important;
1528
- }
1529
- tr[data-state="selected"] td {
1530
- background: Highlight !important;
1531
- background-color: Highlight !important;
1532
- color: HighlightText !important;
1533
- }
1534
- tr[data-state="selected"] *:not([data-slot="checkbox"] *):not([data-slot="badge"] *):not([data-slot="checkbox"]):not([data-slot="badge"]) {
1535
- color: HighlightText !important;
1536
- }
1537
- tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"],
1538
- tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] {
1539
- background-color: HighlightText !important;
1540
- border-color: HighlightText !important;
1541
- color: Highlight !important;
1542
- }
1543
- tr[data-state="selected"] [data-slot="checkbox"][data-state="checked"] *,
1544
- tr[data-state="selected"] [data-slot="checkbox"][data-state="indeterminate"] * {
1545
- color: Highlight !important;
1546
- }
1547
- tr[data-state="selected"] [data-slot="checkbox"]:not([data-state="checked"]):not([data-state="indeterminate"]) {
1548
- background-color: Highlight !important;
1549
- border-color: HighlightText !important;
1550
- color: HighlightText !important;
1551
- }
1552
- tr[data-state="selected"] [data-slot="badge"] {
1553
- background-color: HighlightText !important;
1554
- color: Highlight !important;
1555
- border-color: HighlightText !important;
1556
- }
1557
- tr[data-state="selected"] [data-slot="badge"] * {
1558
- color: Highlight !important;
1559
- }
1560
- tr[data-state="selected"] [data-slot="avatar"] {
1561
- border-color: HighlightText !important;
1562
- }
1563
- tr[data-state="selected"] [data-slot="avatar-fallback"] {
1564
- background-color: HighlightText !important;
1565
- color: Highlight !important;
1566
- }
1567
- /* Badge in forced-colors — opaque canvas bg */
1568
- [data-slot="badge"] {
1569
- background-color: Canvas !important;
1570
- border-color: CanvasText !important;
1571
- color: CanvasText !important;
1572
- }
1573
-
1574
- /* Checked checkboxes — Highlight fill */
1575
- [data-slot="checkbox"][data-state="checked"] *,
1576
- [data-slot="checkbox"][data-state="indeterminate"] * {
1577
- color: HighlightText !important;
1578
- }
1579
-
1580
- /* Avatar in forced-colors */
1581
- [data-slot="avatar"] {
1582
- border: 2px solid CanvasText !important;
1583
- }
1584
- [data-slot="avatar"]::after {
1585
- display: none !important;
1586
- }
1587
- [data-slot="avatar-fallback"] {
1588
- background-color: Canvas !important;
1589
- color: CanvasText !important;
1590
- }
1591
-
1592
- /* Checked checkboxes / radios — Highlight fill */
1593
- [data-slot="checkbox"][data-state="checked"],
1594
- [data-slot="checkbox"][data-state="indeterminate"] {
1595
- background-color: Highlight !important;
1596
- border-color: Highlight !important;
1597
- color: HighlightText !important;
1598
- }
1599
- [data-slot="radio-group-item"][data-state="checked"] {
1600
- background-color: Highlight !important;
1601
- border-color: Highlight !important;
1602
- }
1603
-
1604
- /* Switch ON — Highlight fill */
1605
- [role="switch"][aria-checked="true"] {
1606
- background-color: Highlight !important;
1607
- border-color: Highlight !important;
1608
- }
1609
- [role="switch"][aria-checked="true"] > span {
1610
- background-color: HighlightText !important;
1611
- }
1612
-
1613
- /* Toggle ON — Highlight fill */
1614
- [data-slot="toggle"][data-state="on"],
1615
- [data-slot="toggle-group-item"][data-state="on"] {
1616
- background-color: Highlight !important;
1617
- color: HighlightText !important;
1618
- border-color: Highlight !important;
1619
- }
1620
-
1621
- /* Progress bars — bordered track with CanvasText fill */
1622
- [role="progressbar"] {
1623
- border: 1px solid CanvasText !important;
1624
- background-color: Canvas !important;
1625
- }
1626
- [role="progressbar"] > * {
1627
- background-color: CanvasText !important;
1628
- }
1629
-
1630
- /* Portal overlays — explicit Canvas pairing (OS often strips popover fills) */
1631
- [data-slot="dropdown-menu-content"],
1632
- [data-slot="dropdown-menu-sub-content"],
1633
- [data-slot="popover-content"],
1634
- [data-slot="select-content"],
1635
- [data-slot="dialog-content"],
1636
- [data-slot="sheet-content"],
1637
- [data-slot="drawer-content"] {
1638
- border: 2px solid CanvasText !important;
1639
- background-color: Canvas !important;
1640
- color: CanvasText !important;
1641
- }
1642
-
1643
- [data-slot="command"] {
1644
- background-color: Canvas !important;
1645
- color: CanvasText !important;
1646
- }
1647
-
1648
- /* Board cards — border-defined shape when fills are stripped */
1649
- [data-slot="board-card"] {
1650
- border: 2px solid CanvasText !important;
1651
- background-color: Canvas !important;
1652
- color: CanvasText !important;
1653
- }
1654
-
1655
- /* List hub status badges — border-only, text readable */
1656
- [data-slot="list-hub-status-badge"] {
1657
- border: 2px solid CanvasText !important;
1658
- background-color: Canvas !important;
1659
- color: CanvasText !important;
1660
- font-weight: 700 !important;
1661
- }
1662
-
1663
- /* Insight cards — strip gradient, add border */
1664
- [aria-label="Insight"],
1665
- [data-slot="insight-card"] {
1666
- border: 2px solid CanvasText !important;
1667
- background: Canvas !important;
1668
- color: CanvasText !important;
1669
- }
1670
-
1671
- /* Coach marks / guided tours */
1672
- [data-slot="coach-mark"] {
1673
- border: 2px solid CanvasText !important;
1674
- background-color: Canvas !important;
1675
- color: CanvasText !important;
1676
- }
1677
- [data-slot="coach-mark"] * {
1678
- color: CanvasText !important;
1679
- }
1680
-
1681
- /* Avatars — thicken existing ::after ring */
1682
- [data-slot="avatar"]::after {
1683
- border-width: 2px !important;
1684
- border-color: CanvasText !important;
1685
- }
1686
-
1687
- /* Breadcrumbs */
1688
- [data-slot="breadcrumb-separator"] {
1689
- color: CanvasText !important;
1690
- }
1691
- [data-slot="breadcrumb-link"] {
1692
- color: LinkText !important;
1693
- }
1694
- [data-slot="breadcrumb-page"] {
1695
- color: CanvasText !important;
1696
- font-weight: 700 !important;
1697
- }
1698
-
1699
- /* Tooltip */
1700
- [data-slot="tooltip-content"] {
1701
- border: 2px solid CanvasText !important;
1702
- background-color: Canvas !important;
1703
- color: CanvasText !important;
1704
- }
1705
-
1706
- /* Export drawer */
1707
- [data-slot="export-drawer"] {
1708
- border: 2px solid CanvasText !important;
1709
- background-color: Canvas !important;
1710
- color: CanvasText !important;
1711
- }
1712
-
1713
- /* Separators */
1714
- [data-slot="separator"] {
1715
- background-color: CanvasText !important;
1716
- opacity: 1 !important;
1717
- }
1718
-
1719
- /* Charts — forced-colors strips SVG fills; add stroke as fallback */
1720
- svg path, svg rect, svg circle {
1721
- forced-color-adjust: none;
1722
- }
1723
-
1724
- /* Recharts radial bars, lines, and area — explicit stroke fallbacks */
1725
- .recharts-radial-bar-sector,
1726
- .recharts-line-curve,
1727
- .recharts-area-curve {
1728
- forced-color-adjust: none;
1729
- stroke: CanvasText !important;
1730
- }
1731
-
1732
- .recharts-radial-bar-background-sector {
1733
- forced-color-adjust: none;
1734
- fill: Canvas !important;
1735
- stroke: GrayText !important;
1736
- }
1737
-
1738
- .recharts-cartesian-axis-tick-value {
1739
- fill: CanvasText !important;
1740
- }
1741
-
1742
- .recharts-cartesian-grid line {
1743
- stroke: GrayText !important;
1744
- }
1745
-
1746
- .recharts-legend-item-text {
1747
- color: CanvasText !important;
1748
- }
1749
-
1750
- .recharts-tooltip-wrapper {
1751
- border: 2px solid CanvasText !important;
1752
- background-color: Canvas !important;
1753
- }
1754
- }
1755
-
1756
- /* ==========================================================================
1757
- Base layer — global element defaults with AA focus management
1758
- ========================================================================== */
1759
- @layer base {
1760
- /* Reset + border-color default */
1761
- *, *::before, *::after {
1762
- @apply border-border;
1763
- box-sizing: border-box;
1764
- }
1765
-
1766
- /* Body — outer canvas matches sidebar; main column uses bg-background (white in light) */
1767
- body {
1768
- @apply bg-sidebar text-foreground antialiased;
1769
- font-family: var(--font-sans);
1770
- /* 14px baseline on body. 1rem stays = 16px so all shadcn rem-based
1771
- layout (spacing, heights, radii) is unaffected at any zoom level. */
1772
- font-size: 0.875rem;
1773
- line-height: 1.5;
1774
- /* Font smoothing (Tailwind `antialiased` = -webkit-font-smoothing + -moz-osx):
1775
- Industry practice per Josh Comeau’s CSS reset and 2024 cross-browser testing
1776
- (e.g. David Bushell): the -webkit property affects macOS WebKit browsers only —
1777
- it tones down browser-only subpixel AA (Mojave+ system UI already moved away).
1778
- Windows/Linux/iOS/Android: no practical effect; OS font rasterizer (ClearType, etc.)
1779
- owns rendering. Safe to apply on body for Mac parity without changing Windows output. */
1780
- }
1781
-
1782
- html {
1783
- @apply font-sans;
1784
- color-scheme: light;
1785
- /* Match sidebar canvas (body) on overscroll */
1786
- background-color: var(--sidebar);
1787
- }
1788
-
1789
- html.dark {
1790
- color-scheme: dark;
1791
- }
1792
-
1793
- /* ── Focus management (WCAG 2.4.11 / 2.4.7) ──────────────────── */
1794
- /* Visible on keyboard navigation only; hidden for mouse users */
1795
- :focus-visible {
1796
- outline: 2px solid var(--ring);
1797
- outline-offset: 2px;
1798
- border-radius: var(--radius-sm, 4px);
1799
- }
1800
-
1801
- /* Suppress outline for mouse/touch (Safari workaround) */
1802
- :focus:not(:focus-visible) {
1803
- outline: none;
1804
- }
1805
-
1806
- /* ── Reduced motion (WCAG 2.3.3) ────────────────────────────── */
1807
- @media (prefers-reduced-motion: reduce) {
1808
- *, *::before, *::after {
1809
- animation-duration: 0.01ms !important;
1810
- animation-iteration-count: 1 !important;
1811
- transition-duration: 0.01ms !important;
1812
- scroll-behavior: auto !important;
1813
- }
1814
- }
1815
-
1816
- /* ── Touch targets (WCAG 2.5.5) ─────────────────────────────── */
1817
- /* Applied via utility: min-h-[var(--control-height-touch)] */
1818
- /* Coarse pointer only: browser zoom (200–400%) shrinks the *layout* viewport
1819
- in CSS px, so max-width: 767px becomes true on desktop — without pointer: coarse,
1820
- 44px min-height hits every button and [role=checkbox], stretching 16px-wide
1821
- checkboxes into tall pills and blowing up table/toolbar controls. Real phones
1822
- and tablets report pointer: coarse. */
1823
- @media (max-width: 767px) and (pointer: coarse) {
1824
- button,
1825
- [role="button"],
1826
- [role="radio"],
1827
- [role="switch"],
1828
- [role="menuitem"],
1829
- [role="tab"],
1830
- a {
1831
- min-height: var(--control-height-touch, 44px);
1832
- }
1833
- }
1834
- /* Checkboxes use compact box + pseudo-element hit slop (see ui/checkbox). */
1835
-
1836
- /* ── Heading hierarchy ───────────────────────────────────────── */
1837
- /* Ivy Presto (font-heading) applied ONLY via explicit class/inline style
1838
- on PageHeader <h1>. All other headings use Inter (font-sans). */
1839
- h1, h2, h3, h4, h5, h6 {
1840
- font-family: var(--font-sans);
1841
- font-weight: 600;
1842
- line-height: 1.25;
1843
- color: var(--foreground);
1844
- }
1845
-
1846
- /* ── Skip to main content (WCAG 2.4.1) ─────────────────────── */
1847
- .skip-to-content {
1848
- position: absolute;
1849
- left: -9999px;
1850
- top: auto;
1851
- width: 1px;
1852
- height: 1px;
1853
- overflow: hidden;
1854
- z-index: 9999;
1855
- }
1856
-
1857
- .skip-to-content:focus {
1858
- position: fixed;
1859
- top: 0;
1860
- left: 0;
1861
- width: auto;
1862
- height: auto;
1863
- padding: 0.75rem 1.25rem;
1864
- background: var(--background);
1865
- color: var(--foreground);
1866
- border: 2px solid var(--ring);
1867
- border-radius: var(--radius-md);
1868
- font-weight: 600;
1869
- font-size: 1rem;
1870
- z-index: 9999;
1871
- }
1872
- }
1873
-
1874
- /* ==========================================================================
1875
- Utility layer — design-system helpers
1876
- ========================================================================== */
1877
- @layer utilities {
1878
- /* Visually hidden but accessible to screen readers (WCAG 1.3.1) */
1879
- .sr-only {
1880
- position: absolute;
1881
- width: 1px;
1882
- height: 1px;
1883
- padding: 0;
1884
- margin: -1px;
1885
- overflow: hidden;
1886
- clip: rect(0, 0, 0, 0);
1887
- white-space: nowrap;
1888
- border-width: 0;
1889
- }
1890
-
1891
- /* AA-safe muted text — use instead of text-muted-foreground on light bg */
1892
- .text-aa-muted {
1893
- color: oklch(0.50 0.012 270); /* 5.5:1 on white ✓ */
1894
- }
1895
-
1896
- /* Touch-target wrapper for icon buttons (mobile only) */
1897
- .touch-target {
1898
- min-height: var(--control-height-touch, 44px);
1899
- min-width: var(--control-height-touch, 44px);
1900
- display: inline-flex;
1901
- align-items: center;
1902
- justify-content: center;
1903
- }
1904
-
1905
- @media (min-width: 768px) {
1906
- .touch-target {
1907
- min-height: unset;
1908
- min-width: unset;
1909
- }
1910
- }
1911
-
1912
- /* Form field border — use --control-border (3:1 minimum) */
1913
- .field-border {
1914
- border-color: var(--control-border);
1915
- }
1916
-
1917
- /* Exxat Prism highlight banner */
1918
- .banner-prism {
1919
- background-color: var(--banner-prism-bg);
1920
- }
1921
-
1922
- /* Sidebar nav — little pop when an item becomes active. Key swap on the
1923
- wrapper remounts the span, so the animation replays on selection. */
1924
- @keyframes sidebar-icon-pop {
1925
- 0% { opacity: 0.4; transform: scale(0.7) rotate(-6deg); }
1926
- 60% { opacity: 1; transform: scale(1.15) rotate(2deg); }
1927
- 100% { opacity: 1; transform: scale(1) rotate(0); }
1928
- }
1929
-
1930
- /* Radix Collapsible / Accordion — slide the children open/closed using the
1931
- `--radix-collapsible-content-height` CSS var that Radix sets on the
1932
- content element. Mirrors the shadcn accordion pattern (Tailwind v3
1933
- "accordion-down" / "accordion-up"); we keep our own name so it can be
1934
- reused by both Collapsible and Accordion primitives. */
1935
- @keyframes collapsible-down {
1936
- from { height: 0; }
1937
- to { height: var(--radix-collapsible-content-height); }
1938
- }
1939
- @keyframes collapsible-up {
1940
- from { height: var(--radix-collapsible-content-height); }
1941
- to { height: 0; }
1942
- }
1943
-
1944
- /* Ask Leo suggestion chips — staggered fade-in + lift on first render. */
1945
- @keyframes leo-chip-in {
1946
- 0% { opacity: 0; transform: translateY(8px) scale(0.96); }
1947
- 100% { opacity: 1; transform: translateY(0) scale(1); }
1948
- }
1949
-
1950
- /* Leo typing indicator — 3 dots bouncing opacity/scale, staggered via delay. */
1951
- @keyframes leo-typing-dot {
1952
- 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
1953
- 40% { opacity: 1; transform: scale(1); }
1954
- }
1955
-
1956
- /* Whole-panel brand radial glow pulse — runs on the BG layer while Leo thinks. */
1957
- @keyframes leo-panel-pulse {
1958
- 0%, 100% { opacity: 0.5; transform: scale(1); }
1959
- 50% { opacity: 0.75; transform: scale(1.01); }
1960
- }
1961
-
1962
- /* Chart “Leo insight” marker — soft breathing halo behind the chip. */
1963
- @keyframes leo-chart-insight-halo {
1964
- 0%, 100% { opacity: 0.45; transform: scale(1); }
1965
- 50% { opacity: 0.72; transform: scale(1.12); }
1966
- }
1967
-
1968
- /* Accent dot on the insight marker — gentle pulse (respect motion-reduce in markup). */
1969
- @keyframes leo-chart-insight-dot {
1970
- 0%, 100% { opacity: 0.9; transform: scale(1); }
1971
- 50% { opacity: 1; transform: scale(1.35); }
1972
- }
1973
- }
1974
-
1975
- /* After all @layer rules: win over Tailwind preflight / layer merge so real controls show a pointer. */
1976
- button:not(:disabled):not([disabled]),
1977
- [role="button"]:not([aria-disabled="true"]):not([data-disabled]) {
1978
- cursor: pointer;
1979
- }