@felloinnovations/brand-kit 0.4.0 → 0.5.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 (363) hide show
  1. package/AGENTS.md +198 -24
  2. package/CHANGELOG.md +197 -0
  3. package/README.md +34 -7
  4. package/design-system/01-how-claude-decides.md +26 -17
  5. package/design-system/02-principles.md +11 -6
  6. package/design-system/03-colour.md +134 -47
  7. package/design-system/04-type.md +45 -23
  8. package/design-system/05-space-and-layout.md +175 -52
  9. package/design-system/06-sizing-profiles.md +4 -4
  10. package/design-system/07-scrolling.md +66 -20
  11. package/design-system/08-choosing-components.md +50 -22
  12. package/design-system/09-charts.md +71 -28
  13. package/design-system/10-patterns.md +33 -10
  14. package/design-system/11-page-recipes.md +110 -23
  15. package/design-system/12-content.md +2 -1
  16. package/design-system/13-motion.md +330 -47
  17. package/design-system/14-accessibility.md +47 -24
  18. package/design-system/15-ai-experiences.md +11 -6
  19. package/design-system/16-creativity.md +1 -1
  20. package/design-system/17-decisions.md +357 -1
  21. package/design-system/18-checklist.md +79 -16
  22. package/design-system/19-public-pages.md +6 -4
  23. package/design-system/20-palettes.md +275 -0
  24. package/design-system/README.md +30 -17
  25. package/design-system/components/ActionList/README.md +96 -10
  26. package/design-system/components/ActionList/preview.html +52 -7
  27. package/design-system/components/ActionList/style.css +64 -0
  28. package/design-system/components/ActivityGrid/README.md +38 -2
  29. package/design-system/components/ActivityGrid/preview.html +1 -1
  30. package/design-system/components/ActivityGrid/style.css +35 -0
  31. package/design-system/components/AppShell/README.md +205 -75
  32. package/design-system/components/AppShell/preview.html +339 -58
  33. package/design-system/components/AppShell/style.css +154 -0
  34. package/design-system/components/Avatar/README.md +37 -10
  35. package/design-system/components/Avatar/preview.html +13 -4
  36. package/design-system/components/Avatar/style.css +14 -0
  37. package/design-system/components/Badge/README.md +41 -19
  38. package/design-system/components/Badge/preview.html +13 -10
  39. package/design-system/components/Badge/style.css +23 -0
  40. package/design-system/components/Banner/README.md +30 -9
  41. package/design-system/components/Banner/preview.html +1 -1
  42. package/design-system/components/Banner/style.css +19 -0
  43. package/design-system/components/Breadcrumb/README.md +58 -46
  44. package/design-system/components/Breadcrumb/preview.html +16 -16
  45. package/design-system/components/Breadcrumb/style.css +17 -0
  46. package/design-system/components/Button/README.md +113 -55
  47. package/design-system/components/Button/preview.html +98 -25
  48. package/design-system/components/Button/style.css +86 -0
  49. package/design-system/components/Card/README.md +158 -49
  50. package/design-system/components/Card/preview.html +141 -19
  51. package/design-system/components/Card/style.css +115 -0
  52. package/design-system/components/CardBoard/README.md +58 -37
  53. package/design-system/components/CardBoard/preview.html +26 -29
  54. package/design-system/components/ChatCard/README.md +115 -29
  55. package/design-system/components/ChatCard/preview.html +149 -32
  56. package/design-system/components/ChatCard/style.css +49 -0
  57. package/design-system/components/ChatShell/README.md +116 -0
  58. package/design-system/components/ChatShell/preview.html +201 -0
  59. package/design-system/components/ChatShell/style.css +86 -0
  60. package/design-system/components/ChatTurn/README.md +78 -35
  61. package/design-system/components/ChatTurn/preview.html +60 -28
  62. package/design-system/components/ChatTurn/style.css +50 -0
  63. package/design-system/components/CheckRow/README.md +141 -0
  64. package/design-system/components/CheckRow/preview.html +140 -0
  65. package/design-system/components/CheckRow/style.css +88 -0
  66. package/design-system/components/Checkbox/README.md +58 -22
  67. package/design-system/components/Checkbox/preview.html +112 -50
  68. package/design-system/components/Checkbox/style.css +45 -0
  69. package/design-system/components/Chip/README.md +78 -47
  70. package/design-system/components/Chip/preview.html +29 -4
  71. package/design-system/components/Chip/style.css +17 -0
  72. package/design-system/components/Combobox/README.md +44 -11
  73. package/design-system/components/Combobox/preview.html +35 -12
  74. package/design-system/components/Combobox/style.css +54 -0
  75. package/design-system/components/Composer/README.md +137 -35
  76. package/design-system/components/Composer/preview.html +115 -40
  77. package/design-system/components/Composer/style.css +81 -0
  78. package/design-system/components/ConfirmDialog/README.md +73 -52
  79. package/design-system/components/ConfirmDialog/preview.html +70 -26
  80. package/design-system/components/ConfirmDialog/style.css +5 -0
  81. package/design-system/components/Cover/preview.html +3 -3
  82. package/design-system/components/Cover/style.css +19 -0
  83. package/design-system/components/DateInput/README.md +77 -12
  84. package/design-system/components/DateInput/preview.html +27 -12
  85. package/design-system/components/DateInput/style.css +38 -0
  86. package/design-system/components/Dialog/README.md +112 -44
  87. package/design-system/components/Dialog/preview.html +141 -18
  88. package/design-system/components/Dialog/style.css +74 -0
  89. package/design-system/components/EmptyState/README.md +42 -12
  90. package/design-system/components/EmptyState/preview.html +11 -11
  91. package/design-system/components/EmptyState/style.css +9 -0
  92. package/design-system/components/EntryShell/README.md +73 -48
  93. package/design-system/components/EntryShell/preview.html +60 -27
  94. package/design-system/components/EntryShell/style.css +19 -0
  95. package/design-system/components/FeatureGrid/README.md +61 -39
  96. package/design-system/components/FeatureGrid/preview.html +2 -2
  97. package/design-system/components/FeatureGrid/style.css +20 -0
  98. package/design-system/components/FileUpload/README.md +33 -3
  99. package/design-system/components/FileUpload/preview.html +18 -4
  100. package/design-system/components/FileUpload/style.css +23 -0
  101. package/design-system/components/FilterBar/README.md +114 -0
  102. package/design-system/components/FilterBar/preview.html +82 -0
  103. package/design-system/components/FilterBar/style.css +22 -0
  104. package/design-system/components/Fold/README.md +84 -26
  105. package/design-system/components/Fold/preview.html +77 -34
  106. package/design-system/components/Fold/style.css +48 -0
  107. package/design-system/components/Footer/README.md +62 -39
  108. package/design-system/components/Footer/preview.html +5 -5
  109. package/design-system/components/Footer/style.css +30 -0
  110. package/design-system/components/FunnelBars/README.md +24 -3
  111. package/design-system/components/FunnelBars/preview.html +5 -5
  112. package/design-system/components/FunnelBars/style.css +13 -0
  113. package/design-system/components/GoalBars/README.md +54 -10
  114. package/design-system/components/GoalBars/preview.html +69 -28
  115. package/design-system/components/GoalBars/style.css +51 -0
  116. package/design-system/components/GoalTicks/README.md +74 -58
  117. package/design-system/components/GoalTicks/preview.html +41 -118
  118. package/design-system/components/GoalTicks/style.css +37 -0
  119. package/design-system/components/GoalTubes/README.md +29 -3
  120. package/design-system/components/GoalTubes/preview.html +6 -6
  121. package/design-system/components/GoalTubes/style.css +23 -0
  122. package/design-system/components/Heatmap/README.md +133 -0
  123. package/design-system/components/Heatmap/preview.html +168 -0
  124. package/design-system/components/Heatmap/style.css +119 -0
  125. package/design-system/components/Hero/README.md +58 -40
  126. package/design-system/components/Hero/preview.html +1 -1
  127. package/design-system/components/Hero/style.css +19 -0
  128. package/design-system/components/HoverCard/README.md +114 -0
  129. package/design-system/components/HoverCard/preview.html +107 -0
  130. package/design-system/components/HoverCard/style.css +59 -0
  131. package/design-system/components/IconButton/README.md +69 -38
  132. package/design-system/components/IconButton/preview.html +77 -43
  133. package/design-system/components/IconButton/style.css +45 -0
  134. package/design-system/components/Input/README.md +36 -11
  135. package/design-system/components/Input/preview.html +1 -1
  136. package/design-system/components/Input/style.css +23 -0
  137. package/design-system/components/KanbanBoard/README.md +93 -45
  138. package/design-system/components/KanbanBoard/preview.html +159 -43
  139. package/design-system/components/KanbanBoard/style.css +53 -0
  140. package/design-system/components/Kbd/README.md +25 -9
  141. package/design-system/components/Kbd/preview.html +6 -2
  142. package/design-system/components/Kbd/style.css +9 -0
  143. package/design-system/components/KitButton/README.md +81 -47
  144. package/design-system/components/KitButton/preview.html +35 -13
  145. package/design-system/components/KitButton/style.css +46 -0
  146. package/design-system/components/KitCard/README.md +75 -44
  147. package/design-system/components/KitCard/preview.html +18 -10
  148. package/design-system/components/KitCard/style.css +15 -0
  149. package/design-system/components/KitInput/README.md +54 -39
  150. package/design-system/components/KitInput/preview.html +7 -7
  151. package/design-system/components/KitInput/style.css +23 -0
  152. package/design-system/components/Leaderboard/README.md +76 -49
  153. package/design-system/components/Leaderboard/preview.html +61 -26
  154. package/design-system/components/Leaderboard/style.css +44 -0
  155. package/design-system/components/ListDetail/README.md +222 -0
  156. package/design-system/components/ListDetail/preview.html +213 -0
  157. package/design-system/components/ListDetail/style.css +148 -0
  158. package/design-system/components/LoadBar/README.md +79 -0
  159. package/design-system/components/LoadBar/preview.html +40 -0
  160. package/design-system/components/LoadBar/style.css +17 -0
  161. package/design-system/components/MarketingNav/README.md +76 -42
  162. package/design-system/components/MarketingNav/preview.html +37 -8
  163. package/design-system/components/MarketingNav/style.css +45 -0
  164. package/design-system/components/Matrix/README.md +129 -0
  165. package/design-system/components/Matrix/preview.html +99 -0
  166. package/design-system/components/Matrix/style.css +84 -0
  167. package/design-system/components/Menu/README.md +117 -41
  168. package/design-system/components/Menu/preview.html +85 -23
  169. package/design-system/components/Menu/style.css +61 -0
  170. package/design-system/components/Meter/README.md +39 -4
  171. package/design-system/components/Meter/preview.html +18 -1
  172. package/design-system/components/Meter/style.css +23 -0
  173. package/design-system/components/MetricTile/README.md +237 -0
  174. package/design-system/components/MetricTile/preview.html +241 -0
  175. package/design-system/components/MetricTile/style.css +129 -0
  176. package/design-system/components/Morph/README.md +106 -0
  177. package/design-system/components/Morph/preview.html +103 -0
  178. package/design-system/components/Morph/style.css +31 -0
  179. package/design-system/components/Motion/README.md +164 -0
  180. package/design-system/components/Motion/preview.html +2537 -0
  181. package/design-system/components/NumberInput/README.md +27 -8
  182. package/design-system/components/NumberInput/preview.html +21 -5
  183. package/design-system/components/NumberInput/style.css +34 -0
  184. package/design-system/components/PaceBar/README.md +75 -0
  185. package/design-system/components/PaceBar/preview.html +67 -0
  186. package/design-system/components/PaceBar/style.css +25 -0
  187. package/design-system/components/Page/README.md +57 -18
  188. package/design-system/components/Page/preview.html +15 -17
  189. package/design-system/components/Page/style.css +7 -0
  190. package/design-system/components/PageBar/README.md +90 -34
  191. package/design-system/components/PageBar/preview.html +60 -19
  192. package/design-system/components/PageBar/style.css +35 -0
  193. package/design-system/components/PageHero/README.md +87 -51
  194. package/design-system/components/PageHero/preview.html +35 -6
  195. package/design-system/components/PageHero/style.css +31 -0
  196. package/design-system/components/Pagination/README.md +70 -49
  197. package/design-system/components/Pagination/preview.html +24 -15
  198. package/design-system/components/Pagination/style.css +12 -0
  199. package/design-system/components/Panel/README.md +109 -51
  200. package/design-system/components/Panel/preview.html +118 -20
  201. package/design-system/components/Panel/style.css +51 -0
  202. package/design-system/components/PasswordInput/README.md +50 -18
  203. package/design-system/components/PasswordInput/preview.html +71 -21
  204. package/design-system/components/PasswordInput/style.css +31 -0
  205. package/design-system/components/Plate/README.md +75 -17
  206. package/design-system/components/Plate/preview.html +40 -7
  207. package/design-system/components/Plate/style.css +37 -0
  208. package/design-system/components/Popover/README.md +70 -49
  209. package/design-system/components/Popover/preview.html +44 -22
  210. package/design-system/components/Popover/style.css +41 -0
  211. package/design-system/components/PricingTable/README.md +69 -49
  212. package/design-system/components/PricingTable/preview.html +21 -21
  213. package/design-system/components/PricingTable/style.css +21 -0
  214. package/design-system/components/ProgressPetals/README.md +31 -3
  215. package/design-system/components/ProgressPetals/preview.html +14 -15
  216. package/design-system/components/ProgressPetals/style.css +27 -0
  217. package/design-system/components/README.md +151 -0
  218. package/design-system/components/Radio/README.md +40 -17
  219. package/design-system/components/Radio/preview.html +16 -1
  220. package/design-system/components/Radio/style.css +21 -0
  221. package/design-system/components/RankBar/README.md +29 -2
  222. package/design-system/components/RankBar/preview.html +14 -12
  223. package/design-system/components/RankBar/style.css +18 -0
  224. package/design-system/components/Ring/README.md +61 -11
  225. package/design-system/components/Ring/preview.html +55 -10
  226. package/design-system/components/Ring/style.css +49 -0
  227. package/design-system/components/ScoreHero/README.md +91 -0
  228. package/design-system/components/ScoreHero/preview.html +104 -0
  229. package/design-system/components/ScoreHero/style.css +32 -0
  230. package/design-system/components/Section/README.md +72 -33
  231. package/design-system/components/Section/preview.html +46 -16
  232. package/design-system/components/Section/style.css +18 -0
  233. package/design-system/components/Segmented/README.md +100 -55
  234. package/design-system/components/Segmented/preview.html +107 -26
  235. package/design-system/components/Segmented/style.css +94 -0
  236. package/design-system/components/SegmentedProgress/README.md +64 -0
  237. package/design-system/components/SegmentedProgress/preview.html +69 -0
  238. package/design-system/components/SegmentedProgress/style.css +11 -0
  239. package/design-system/components/Select/README.md +47 -12
  240. package/design-system/components/Select/preview.html +28 -2
  241. package/design-system/components/Select/style.css +22 -0
  242. package/design-system/components/ShareBar/README.md +69 -0
  243. package/design-system/components/ShareBar/preview.html +72 -0
  244. package/design-system/components/ShareBar/style.css +25 -0
  245. package/design-system/components/SideList/README.md +147 -0
  246. package/design-system/components/SideList/preview.html +139 -0
  247. package/design-system/components/SideList/style.css +94 -0
  248. package/design-system/components/Skeleton/README.md +52 -16
  249. package/design-system/components/Skeleton/preview.html +35 -23
  250. package/design-system/components/Skeleton/style.css +22 -0
  251. package/design-system/components/Slider/README.md +95 -0
  252. package/design-system/components/Slider/preview.html +49 -0
  253. package/design-system/components/Slider/style.css +13 -0
  254. package/design-system/components/Split/README.md +112 -0
  255. package/design-system/components/Split/preview.html +105 -0
  256. package/design-system/components/Split/style.css +30 -0
  257. package/design-system/components/Starter/README.md +21 -9
  258. package/design-system/components/Starter/preview.html +5 -5
  259. package/design-system/components/Stat/README.md +64 -43
  260. package/design-system/components/Stat/preview.html +3 -3
  261. package/design-system/components/Stat/style.css +15 -0
  262. package/design-system/components/StatTiles/README.md +88 -44
  263. package/design-system/components/StatTiles/preview.html +142 -71
  264. package/design-system/components/StatTiles/style.css +64 -0
  265. package/design-system/components/StatusLine/README.md +85 -0
  266. package/design-system/components/StatusLine/preview.html +49 -0
  267. package/design-system/components/StatusLine/style.css +14 -0
  268. package/design-system/components/StatusScreen/README.md +49 -35
  269. package/design-system/components/StatusScreen/preview.html +20 -5
  270. package/design-system/components/StatusScreen/style.css +9 -0
  271. package/design-system/components/StepLine/README.md +97 -0
  272. package/design-system/components/StepLine/preview.html +108 -0
  273. package/design-system/components/StepLine/style.css +62 -0
  274. package/design-system/components/Stepper/README.md +35 -13
  275. package/design-system/components/Stepper/style.css +13 -0
  276. package/design-system/components/StreakCalendar/README.md +22 -1
  277. package/design-system/components/StreakCalendar/preview.html +10 -10
  278. package/design-system/components/StreakCalendar/style.css +12 -0
  279. package/design-system/components/SuggestionChip/README.md +87 -0
  280. package/design-system/components/SuggestionChip/preview.html +42 -0
  281. package/design-system/components/SuggestionChip/style.css +20 -0
  282. package/design-system/components/Switch/README.md +44 -24
  283. package/design-system/components/Switch/preview.html +23 -8
  284. package/design-system/components/Switch/style.css +31 -0
  285. package/design-system/components/Table/README.md +129 -58
  286. package/design-system/components/Table/preview.html +106 -72
  287. package/design-system/components/Table/style.css +104 -0
  288. package/design-system/components/Tabs/README.md +71 -46
  289. package/design-system/components/Tabs/preview.html +56 -24
  290. package/design-system/components/Tabs/style.css +44 -0
  291. package/design-system/components/Testimonial/README.md +48 -32
  292. package/design-system/components/Testimonial/preview.html +14 -14
  293. package/design-system/components/Testimonial/style.css +12 -0
  294. package/design-system/components/TextArea/README.md +27 -11
  295. package/design-system/components/TextArea/preview.html +8 -2
  296. package/design-system/components/TextArea/style.css +12 -0
  297. package/design-system/components/ThemeSwitch/README.md +116 -0
  298. package/design-system/components/ThemeSwitch/preview.html +57 -0
  299. package/design-system/components/ThemeSwitch/style.css +6 -0
  300. package/design-system/components/TickRow/README.md +52 -36
  301. package/design-system/components/TickRow/preview.html +64 -41
  302. package/design-system/components/TickRow/style.css +23 -0
  303. package/design-system/components/TickStrip/README.md +95 -0
  304. package/design-system/components/TickStrip/preview.html +88 -0
  305. package/design-system/components/TickStrip/style.css +42 -0
  306. package/design-system/components/Tile/README.md +79 -18
  307. package/design-system/components/Tile/preview.html +91 -40
  308. package/design-system/components/Tile/style.css +36 -0
  309. package/design-system/components/Timeline/README.md +68 -48
  310. package/design-system/components/Timeline/preview.html +27 -15
  311. package/design-system/components/Timeline/style.css +25 -0
  312. package/design-system/components/Toast/README.md +70 -38
  313. package/design-system/components/Toast/preview.html +43 -8
  314. package/design-system/components/Toast/style.css +25 -0
  315. package/design-system/components/Tooltip/README.md +93 -35
  316. package/design-system/components/Tooltip/preview.html +69 -15
  317. package/design-system/components/Tooltip/style.css +78 -0
  318. package/design-system/components/TopBar/README.md +67 -53
  319. package/design-system/components/TopBar/preview.html +14 -27
  320. package/design-system/components/TopBar/style.css +35 -0
  321. package/design-system/components/TopicRail/README.md +108 -0
  322. package/design-system/components/TopicRail/preview.html +58 -0
  323. package/design-system/components/TopicRail/style.css +48 -0
  324. package/design-system/components/TrendBars/README.md +52 -14
  325. package/design-system/components/TrendBars/preview.html +65 -32
  326. package/design-system/components/TrendBars/style.css +25 -0
  327. package/design-system/components/TrendLine/README.md +164 -0
  328. package/design-system/components/TrendLine/preview.html +373 -0
  329. package/design-system/components/TrendLine/style.css +155 -0
  330. package/design-system/components/Well/README.md +64 -22
  331. package/design-system/components/Well/preview.html +14 -14
  332. package/design-system/components/Well/style.css +22 -0
  333. package/design-system/components/_house.css +324 -0
  334. package/design-system/components/bundle.css +4091 -744
  335. package/design-system/tokens.json +1314 -124
  336. package/dist/fello-core.css +2 -2
  337. package/dist/fello.css +6 -1369
  338. package/dist/fello.scoped.css +7 -0
  339. package/dist/index.d.ts +110 -11
  340. package/dist/index.js +781 -96
  341. package/dist/palettes.d.ts +464 -0
  342. package/dist/palettes.js +497 -0
  343. package/dist/scoped.d.ts +3 -0
  344. package/dist/scoped.js +16 -0
  345. package/dist/toast.d.ts +14 -0
  346. package/dist/toast.js +33 -29
  347. package/dist/tokens.d.ts +1686 -62
  348. package/dist/tokens.js +1668 -61
  349. package/package.json +20 -4
  350. package/scripts/check-palette.mjs +295 -0
  351. package/scripts/token-model.mjs +552 -0
  352. package/tokens/_dark.css +174 -0
  353. package/tokens/_palettes.css +46 -0
  354. package/tokens/_product.css +266 -53
  355. package/tokens/_source.hubl.css +39 -19
  356. package/tokens/design-tokens.json +319 -0
  357. package/tokens/palettes.ts +504 -0
  358. package/tokens/shadcn-compat.css +19 -19
  359. package/tokens/shadcn-compat.hsl.css +76 -0
  360. package/tokens/tokens.css +1292 -62
  361. package/tokens/tokens.md +588 -61
  362. package/tokens/tokens.root.css +1298 -62
  363. package/tokens/tokens.ts +1677 -64
@@ -0,0 +1,275 @@
1
+ # Palettes
2
+
3
+ One kit, many apps. A palette is a set of values for a short list of the kit's own tokens (the contract), named for
4
+ how it looks. Every app can keep its own slightly different colours while every component follows them, every word
5
+ stays AA, dark works, the focus ring stays visible, and two apps with two palettes can sit on one page (D15).
6
+
7
+ ## What a palette is
8
+
9
+ - **Only the contract.** A palette sets the tokens in the table below and nothing else. Everything else (hovers, the
10
+ sunk and press steps, menu lines, tints, fades, the shimmer, the hero glows, the act's hover) derives from them and
11
+ recomputes inside the element that sets the palette. A token outside the contract is an error in the check, with the
12
+ contract token to set instead.
13
+ - **The contract tokens the kit derives recompute too.** A few contract tokens default to another one: the focus ring
14
+ to the heading, the raised ground to the page, the alert words to the alert tone, the positive words to the finished
15
+ tone, the rating and the agent tones to their chart tones. Wherever a palette sits, on `<html>` or a container, each
16
+ of these follows that palette's inputs unless the palette sets it itself.
17
+ - **Named for how it looks**, never for an app: `default`, `cool`, `warm`. A new palette gets a look-based name too
18
+ (`sand`, `slate`), so it can serve the next app without a rename.
19
+ - **Colour only.** A palette never changes layout, size or spacing: the geometry check measures every catalog preview
20
+ in every built-in, light and dark, with no new finding.
21
+ - **Marks keep their tone; words keep AA** (D2). A palette that moves a tone keeps the mark exact and gives its words
22
+ an AA step, checked in light, night and the navy ground.
23
+
24
+ ## The built-ins
25
+
26
+ | Palette | How it looks | Set |
27
+ | --- | --- | --- |
28
+ | `default` | The kit's cream: a blue-grey sky at the top of the frame, the stage washed warm at its foot | nothing |
29
+ | `cool` | The same sky under a glass stage that stays cool to its foot, finer row lines, links in the heading navy | `data-palette="cool"` |
30
+ | `warm` | The plain warm cream with no sky over it, the stage washed from the cream to #FEF9F6 | `data-palette="warm"` |
31
+
32
+ Each built-in passes the palette check; the run is in `tokens/tokens.md` (Palettes, "The built-ins, checked").
33
+
34
+ No palette holds the first product's shipped tally navy (#093555). It differed from the default in that one tone, and
35
+ Seth's tally #2C4870 wins (D1), so the product adopts the default's tally.
36
+
37
+ ## The contract
38
+
39
+ Generated from `tokens/design-tokens.json` ("palette") by `scripts/generate-tokens.mjs`, so it cannot drift from the
40
+ code. Each cell is the light value, then the dark (night) one; `=` means the default's value. The navy ground's values
41
+ are in `tokens/tokens.md` and the JS export.
42
+
43
+ <!-- contract -->
44
+ | Token | Group | Meaning | default | cool | warm |
45
+ | --- | --- | --- | --- | --- | --- |
46
+ | `--color-bg-page` | ground | The page and every card's surface: the cream most words sit on. | `#fefbf9` / `#0f1922` | = | = |
47
+ | `--ws-frame-top` | ground | The top of the page wash behind a glass stage, fading into the page by 640 px; in dark the frame is flat and paints it (the shell, unless a palette says). | `#ebf0f5` / `#0a1118` | = | `#fefbf9` / `#0a1118` |
48
+ | `--ws-stage-foot` | ground | The foot of a washed stage, whose gradient starts at the page (light only). | `#fef9f6` / `#0f1922` | `#fefbf9` / `#0f1922` | = |
49
+ | `--color-surface` | ground | What is white: a marketing card, a well row under the pointer, a chat bubble, the glass of the stage. | `#ffffff` / `#131e28` | = | = |
50
+ | `--ws-raised` | ground | What floats off the page: a menu, a popover, a tooltip, a dialog, a panel, a toast. | `#fefbf9` / `#16222d` | = | = |
51
+ | `--ws-tray` | ground | The rim and foot of a rimmed card, and the well behind rows. | `#ededed` / `#1e2b38` | = | = |
52
+ | `--ws-edge-card` | edge | A card's and an outlined control's 0.5 px edge. | `#d3d3d3` / `#273544` | = | = |
53
+ | `--ws-edge` | edge | A divider between rows; a quiet line. | `#e8e8e8` / `#1e2a36` | `#e2e2e2` / `#1e2a36` | = |
54
+ | `--ws-edge-hover` | edge | An outlined control's edge under the pointer. | `#aaa49d` / `#8494a5` | = | = |
55
+ | `--ws-well-hover` | edge | A rimmed card's rim under the pointer. | `#e4e2df` / `#273544` | = | = |
56
+ | `--color-text-heading` | word | Titles, names, figures, navy marks, and the act fill (the primary button, a thumb, a checked box). | `#093555` / `#e8edf3` | = | = |
57
+ | `--color-text-body` | word | Body words: a card's line, a row. | `#545454` / `#b0bbc7` | = | = |
58
+ | `--color-text-muted` | word | Meta, labels, captions. | `#666666` / `#8494a5` | = | = |
59
+ | `--color-text-interactive` | word | Links and words that go somewhere, a falling number, "working". | `#495883` / `#93a6dc` | `#093555` / `#e8edf3` | = |
60
+ | `--ws-on-act` | act | Words and marks on the act fill. | `#ffffff` / `#0f1922` | = | = |
61
+ | `--ws-act-hover` | act | The act fill under the pointer. | `#0f4a73` / `#d7dce2` | = | = |
62
+ | `--ws-word-needs` | accent | Needs you, in words: the current page, something to fix (the accent's AA step). | `#a84b3c` / `#ff8b78` | = | = |
63
+ | `--ws-focus-color` | focus | The 2 px focus ring, outside or inset. | `#093555` / `#e8edf3` | = | = |
64
+ | `--ws-word-positive` | status | Good news in words. | `#09717a` / `#4fc7be` | = | = |
65
+ | `--ws-word-alert` | status | Something wrong now, in words. | `#b1042f` / `#ff5470` | = | = |
66
+ | `--ws-chart-finished` | chart | Tone 1: done, passed, positive marks. | `#098486` / `#23a8a3` | = | = |
67
+ | `--ws-chart-past-half` | chart | Tone 2: past halfway marks. | `#6d4fc2` / `#9a84ee` | = | = |
68
+ | `--ws-chart-under-half` | chart | Tone 3: under halfway marks and needs-you dots. Drawn with its word: its 3:1 is reported. | `#ff725c` / `#ff725c` | = | = |
69
+ | `--ws-chart-navy-light` | chart | Tone 4: a second navy, for a series beside the heading navy. | `#2e6088` / `#6e9cc4` | = | = |
70
+ | `--ws-chart-needs-work` | chart | Tone 5: needs work marks. Drawn with its word: its 3:1 is reported. | `#f370a4` / `#f370a4` | = | = |
71
+ | `--ws-chart-alert` | chart | Tone 6: alert marks. | `#b1042f` / `#ff5470` | = | = |
72
+ | `--ws-rating-strong` | rating | Strong: its marks. | `#098486` / `#3bb8b2` | = | = |
73
+ | `--ws-rating-middle` | rating | Getting there (the middle band): its marks. | `#495883` / `#93a6dc` | `#495883` / `#e8edf3` | = |
74
+ | `--ws-rating-needs-work` | rating | Needs work: its marks. | `#f370a4` / `#f370a4` | = | = |
75
+ | `--ws-agent-coach` | agent | The coaching assistant's mark. | `#098486` / `#3bb8b2` | = | = |
76
+ | `--ws-agent-growth` | agent | The growth assistant's mark. | `#6d4fc2` / `#9a84ee` | = | = |
77
+ | `--ws-agent-recruit` | agent | The recruiting assistant's mark. | `#ff725c` / `#ff725c` | = | = |
78
+ | `--ws-agent-tally` | agent | The money assistant's mark, and a softer act (a figure tab's current cell, a seat meter, a hatch). | `#2c4870` / `#e8edf3` | = | = |
79
+
80
+ - **ground**: What everything sits on. Every word is checked AA on each.
81
+ - **edge**: Hairlines, and the edges under the pointer.
82
+ - **word**: Words, each AA on every ground it can sit on.
83
+ - **act**: The one primary act. Its fill is the heading colour.
84
+ - **accent**: Needs you: the current page, something to fix.
85
+ - **focus**: The keyboard ring, 3:1 on every ground.
86
+ - **status**: Good and bad news, in words.
87
+ - **chart**: The six data tones charts draw with: told apart from each other (CIEDE2000 10 or more) and 3:1 on the chart ground. A tone marked withWords (salmon, pink) is always drawn beside its word, so its ratio is reported, not required: Seth draws them at 2.6:1 and marks keep his exact tone (D2).
88
+ - **rating**: One rating scale on every screen (D10): its marks. Their words are the status and word tokens.
89
+ - **agent**: Each assistant keeps one tone and nothing else names it (03-colour).
90
+ <!-- /contract -->
91
+
92
+ ## Apply one
93
+
94
+ ```html
95
+ <html data-palette="cool"> <!-- the whole page -->
96
+ <div class="fello" data-palette="warm"> <!-- one container -->
97
+ <div class="fello" data-palette="warm" data-theme="dark"> <!-- one container, dark -->
98
+ ```
99
+
100
+ - **On `<html>`**: the whole page. No attribute is the default palette.
101
+ - **On a container**: everything inside it follows; the rest of the page keeps its own. Any element works, with
102
+ `fello.css` or the scoped build.
103
+ - **Nested**: the nearest wins. A palette inside another, a theme inside a palette, a palette inside a theme, light
104
+ inside dark and dark inside light all resolve as written, in both builds. An element that sets a palette or a theme
105
+ also sets its own words to the body colour, so plain text inside it never keeps the page's grey. A browser without
106
+ `@scope` keeps the theme on the element that carries it (the common `<html data-theme>`) and loses only the nesting.
107
+ - **Load order never matters**: the kit's own contract values sit at no specificity, so a palette wins wherever its
108
+ file loads, before the kit or after it.
109
+ - **The navy ground** (`data-theme="dark" data-ground="navy"`) is a brand ground: where it sets a token it wins over
110
+ the palette.
111
+
112
+ ### Many apps in one bundle
113
+
114
+ When a host builds many apps into one bundle, each app takes the scoped build (one copy of the CSS serves them all) and
115
+ sets its palette, and its theme if it has one, on its own `.fello` root:
116
+
117
+ ```html
118
+ <div class="fello" data-palette="cool">...one app...</div>
119
+ <div class="fello" data-palette="warm" data-theme="dark">...another app, dark...</div>
120
+ ```
121
+
122
+ Nothing leaks between them or into the host. A portal (a menu, a tooltip, a dialog rendered outside the app's root)
123
+ carries the same `class="fello"`, `data-palette` and `data-theme` as the app's root, or it draws in the default.
124
+
125
+ ## Light and dark
126
+
127
+ Dark is the same opt-in as everywhere (Colour, "Dark theme"): `data-theme="dark"`, `"system"` on a dark OS, and the
128
+ navy ground beside either. A palette states a dark value only where the kit's dark does not suit it. A dark value it
129
+ leaves out falls back to the kit's own dark, derived from the dark inputs (so a dark page the palette does set still
130
+ moves it), never to the palette's light value. The check reports each one, with the value dark paints instead. This
131
+ holds for a built-in and for an app's own palette once it ships as `--emit` writes it (Make your own).
132
+
133
+ The dark tints and fades follow the dark page: a chip tint, a chart fade or a done tint in dark is its tone over the
134
+ dark page (within CIEDE2000 3.5 of the night literals they replaced), so a palette that moves the dark page moves them.
135
+
136
+ ## Make your own
137
+
138
+ 1. **Try the built-ins first.** Most apps fit one; a new palette is for a look none of them has. Name it for that look.
139
+ 2. **Write the checked form**: one file that sets only contract tokens, the light values on `[data-palette="name"]`
140
+ and the dark ones on `[data-palette="name"][data-theme="dark"]`. In dark, set only what the kit's dark does not
141
+ already give you. `--emit` writes the `system` rules and the navy ground for you:
142
+
143
+ ```css
144
+ /* sand: a warmer sky over the cream, softer row lines, a slate link. */
145
+ [data-palette="sand"] {
146
+ --ws-frame-top: #f5eee6;
147
+ --ws-edge: #e6e0d8;
148
+ --color-text-interactive: #3d5a80;
149
+ }
150
+ [data-palette="sand"][data-theme="dark"] {
151
+ --color-text-interactive: #9fb4d8;
152
+ }
153
+ ```
154
+
155
+ 3. **Check it**, and fix every error:
156
+
157
+ ```sh
158
+ node node_modules/@felloinnovations/brand-kit/scripts/check-palette.mjs src/sand.css
159
+ ```
160
+
161
+ It applies the palette over the kit as it paints once shipped and resolves every token in light, night and the navy
162
+ ground, then fails (exit 1) on a token outside the contract (naming the nearest contract token, or the one a
163
+ derived token comes from), a word under 4.5:1 on any ground it can sit on or on its own tint, a focus ring or an act
164
+ fill under 3:1, two chart tones closer than CIEDE2000 10, or a chart tone under 3:1 on the chart ground (salmon and
165
+ pink are drawn beside their words, so theirs is reported). It reports, without failing, each dark value left out
166
+ and what dark paints instead, and, on a file you wrote by hand, that it is not in the shipped form. The `sand` file
167
+ above passes:
168
+
169
+ ```
170
+ == src/sand.css
171
+ sand: passes (sets 3: --ws-frame-top, --ws-edge, --color-text-interactive)
172
+ report: dark: no --ws-frame-top, so it takes the kit's dark --ws-frame-top (#0a1118), derived from the dark inputs
173
+ report: dark: no --ws-edge, so it takes the kit's dark --ws-edge (#1e2a36), derived from the dark inputs
174
+ report: not in the shipped form: as written, its light values also paint in dark wherever the theme sits on another element than the palette; ship the output of `check-palette --emit`
175
+ 1 palette: 0 errors, 3 reports. Checked in light, night and navy: ...
176
+ ```
177
+
178
+ And a palette that sets a derived token and a pale grey fails, saying why:
179
+
180
+ ```
181
+ sand: 3 errors (sets 2: --ws-surface-sunk, --color-text-muted)
182
+ error contract: --ws-surface-sunk is not in the palette contract (a derived token); it derives from --color-bg-page: set that instead
183
+ error word: light: --color-text-muted #8a8a8a is under 4.5:1 on 18 grounds, lowest 2.78:1 on the press (--ws-surface-press #e9e6e4)
184
+ error word: light: --color-text-placeholder #909090 on --ws-field #ffffff is 3.19:1, under 4.5
185
+ report: dark: no --color-text-muted, so it takes the kit's dark --color-text-muted (#8494a5), derived from the dark inputs
186
+ ```
187
+
188
+ 4. **Ship what `--emit` writes**, never the file you wrote:
189
+
190
+ ```sh
191
+ node node_modules/@felloinnovations/brand-kit/scripts/check-palette.mjs --emit src/sand.css > src/sand.shipped.css
192
+ ```
193
+
194
+ It runs the same check (the report goes to stderr) and writes the palette in the built-ins' own form, with every
195
+ dark value left out filled with the kit's derived dark. Import `sand.shipped.css`: it nests anywhere (on `<html>`
196
+ or any container, either way round with the theme, light or dark, in `fello.css` and the scoped build, with the
197
+ navy ground over it), and load order no longer matters. As written by hand, a palette's light values also paint in
198
+ dark wherever the theme sits on another element than the palette (the theme on `<html>`, the palette on a
199
+ container): that is the "not in the shipped form" report. On an error `--emit` writes nothing and exits 1, so the
200
+ redirect leaves an empty file: fix the source and run it again. Run it again whenever the source changes; never
201
+ edit the shipped file by hand.
202
+
203
+ ## What a palette does not move
204
+
205
+ A few colours keep the brand under any palette. The checks rule them by name, so nothing else can hide among them.
206
+
207
+ - **The navy messages in dark**: `Toast`, the note tip (`Tooltip`'s navy note) and the `Footer` keep the brand navy
208
+ with white words in dark (`--ws-inverse`, `--ws-on-inverse`; D12). In light they are the act fill and its words, so
209
+ a palette moves them there.
210
+ - **The marketing brand marks**: `KitButton`'s salmon act and its navy act, and the `Cover` logo.
211
+ - **Fields on the navy ground**: white with navy words, a brand pair (a `Combobox` chip in one).
212
+ - **The chart fades, tints and empty cell on `:root`**: declared there as the literal they paint in light (charts draw
213
+ them as SVG gradient stops, which cannot be told to blend in sRGB), and derived on every element that sets a palette
214
+ or a theme. So a bare `:root { --ws-chart-under-half: X }` override with no `data-palette` no longer moves them. Use
215
+ a palette (`data-palette`, on `<html>` or a container), never a `:root` override.
216
+ - **The 0.4 channels** `--ws-ink-rgb` and `--ws-shade-rgb`: kept for a `rgba(var(--ws-ink-rgb), a)` written before
217
+ 0.5.0, they hold the default's values and do not follow a palette. Write
218
+ `color-mix(in srgb, var(--ws-ink) 5%, transparent)`, and `--ws-shade` for a drop.
219
+
220
+ ## How the kit proves it
221
+
222
+ In the kit's repo (`scripts/` other than `check-palette.mjs` and `token-model.mjs` is not in the package):
223
+
224
+ - **No leftover**: `node scripts/check-palette.mjs` with no file also reads every component's styles and fails on a
225
+ colour a component reads that no contract token moves, in light or dark, with the brand colours above ruled. Its
226
+ self-test (`--selftest`) plants one.
227
+ - **The poison test** (`scripts/palette-poison.mjs`, run in CI by `check-scope`): each of the 33 contract tokens in
228
+ turn is set to a wild colour, on `<html>` and then on a container around every catalog preview, light and dark. It
229
+ fails on a colour that does not follow the token on the container (stale), a colour outside the container that moves
230
+ (a leak), or a colour no token moves (a constant). Its self-test plants one of each.
231
+ - **Nesting**: `check-scope` also sets an app's palette shipped by `--emit` every way (on `<html>` and a container,
232
+ inside a theme and around one, the navy ground over it) in both builds, loaded before the kit and after it.
233
+
234
+ ## In JavaScript
235
+
236
+ For an app that injects its CSS or draws on a canvas, every built-in comes resolved: each contract token as the
237
+ literal it paints, in light, night and the navy ground. The contract rides along.
238
+
239
+ ```ts
240
+ import { palettes, contract, type PaletteName } from '@felloinnovations/brand-kit/palettes';
241
+
242
+ palettes.cool.light['--color-text-interactive']; // '#093555'
243
+ palettes.warm.dark['--color-bg-page']; // '#0f1922'
244
+ palettes.cool.navy['--ws-agent-tally']; // '#ffffff', the navy ground's value
245
+ contract.map((t) => t.name); // the 33 tokens a palette may set, each with its group and meaning
246
+ ```
247
+
248
+ The same names come from the package root. The CSS for every built-in is already in `fello.css`, `fello-core.css`,
249
+ `tokens.css` and the scoped build (`felloScopedCss`), so an app sets the attribute and needs nothing else.
250
+
251
+ ## Check a screen in a palette
252
+
253
+ In the kit's repo, the geometry check takes the palette like the theme, and names each shot after both
254
+ (`<Name>-<width>-cool-dark.png`):
255
+
256
+ ```sh
257
+ node scripts/check-geometry.mjs --widths 390,1440 --palette cool --theme dark
258
+ ```
259
+
260
+ The gallery's Components page has a theme and a palette switch (default, cool, warm): every preview draws in the pair
261
+ chosen there, and the choice is remembered on that device. Look at the screen in its palette, light and dark, before
262
+ calling it done (Checklist).
263
+
264
+ ## Who uses which (an example, 4 Nov 2026)
265
+
266
+ How the first apps map. It is an example, not a rule: an app picks a palette by how it should look, and an app's name
267
+ never goes into a token, a class, an attribute, a file name or an export.
268
+
269
+ | App | Palette | Theme |
270
+ | --- | --- | --- |
271
+ | North | `cool` | light |
272
+ | Fia (Seth's frames) | `warm` | light |
273
+ | Ignite | `default`: it shipped its tally in the brand navy, Seth's #2C4870 wins (D1) and it adopts it | light; the navy ground on brand and event pages |
274
+ | Revenue OS | `default` | light |
275
+ | Campfire's apps | each its own, on its own `.fello` root | each its own |
@@ -1,32 +1,44 @@
1
1
  Fello's design system for everything the company builds: product apps, dashboards and consoles, sign-in and onboarding,
2
2
  public web pages, emails, decks and quick mockups. It is a decision system as much as a style sheet: how to choose the
3
3
  face, screen and component for a job, how it looks, and how to check it. Lokesh wrote it from the first product built on
4
- the brand kit; the team broadened it with the other products and the website (history in Decisions). Names, sample data
5
- and assets are generic. Every token is in Tokens.
4
+ the brand kit; the team broadened it with the other products and the website, and 0.5.0 rebuilt its layout, surfaces,
5
+ type and motion on Seth's (the designer's) frames and his North app (history in Decisions). Names, sample data and assets
6
+ are generic. Every token is in Tokens.
6
7
 
7
8
  ## Start here
8
9
 
9
10
  - **In Claude**, say "use the Fello brand kit". For an artifact, a mockup, a one-off deck or an internal page, take the
10
11
  quick path at the top of How Claude decides; anything that ships follows its full steps.
11
- - **Two faces, never both on one surface**: the *product* face (after sign-in, or anything used to do work: cream cards,
12
- one solid navy button, 14 px body) and the *marketing* face (before sign-in, or anything that sells: white `KitCard`s,
12
+ - **Two faces, never both on one surface**: the *product* face (after sign-in, or anything used to do work: rimmed cream
13
+ cards, one solid navy button, 14 px body) and the *marketing* face (before sign-in, or anything that sells: white `KitCard`s,
13
14
  the salmon gradient `KitButton`, 16 px body). How Claude decides, step 0, maps every kind of job to its face.
14
- - **Wiring**: one stylesheet, `fello.css`, gives a page every token and component style. An artifact inlines it, a page
15
- links the pinned hosted file, an app installs the package (the table is in How Claude decides, step 0). The HubSpot
16
- site theme is out of scope.
15
+ - **Wiring**: `fello.css` gives a page every token and component style. An artifact inlines `fello-core.css` and the
16
+ blocks of the components it uses (`Starter`); a page links the pinned `fello.css`; an app installs the package (in
17
+ Tailwind v4, the Instrument Sans `@import` before `@import "tailwindcss"`); an app living inside someone else's bundle,
18
+ or any Tailwind v3 app, takes the scoped build under a `.fello` root and links the font itself (the table is in How
19
+ Claude decides, step 0). The HubSpot site theme is out of scope.
20
+ - **Light by default, dark when asked**: a page that sets nothing is light; `data-theme="dark"` or `"system"` on `<html>`
21
+ turns on the dark theme (Colour).
22
+ - **One kit, many apps**: an app that wants its own slightly different colours picks a palette (`data-palette="cool"`
23
+ or `"warm"`) or writes one from the contract, runs `check-palette` and ships what its `--emit` writes (Palettes).
24
+ Never retune tokens on `:root`.
25
+ - **Measured, not eyeballed**: the geometry check (`node scripts/check-geometry.mjs`) and the senior QA list in Checklist
26
+ are how "done" is proven.
17
27
 
18
28
  ## Fello at a glance
19
29
 
20
- Warm, calm, precise: Instrument Sans on a cream page, navy headings, body grey, flat surfaces with fine edges, colour
21
- spent on data rather than decoration, and no AI colours outside the Felix orb. The two faces are in How Claude decides.
30
+ Warm, calm, precise: Instrument Sans on a cream page, navy headings, body grey, flat cream surfaces in a fine grey rim,
31
+ one content edge, numbers in their columns, colour spent on data rather than decoration, motion that grows things from
32
+ where they were, and no AI colours outside the Felix orb. The two faces are in How Claude decides.
22
33
 
23
34
  ## Iconography
24
35
 
25
36
  In a product: Phosphor through one icon component in the project; a **line** icon for a control or an act, a **filled**
26
- one for a mark that names a thing or a state; 12 px with words, 16 alone, larger only in a disc or a hero; icons take the
27
- words' colour. One icon per meaning: `x` ends a dialog or removes one item; a side pane closes with the word "Close";
28
- chevrons move between items; three dots open a menu. On a public page: thin line art only (about 1.5 px stroke, round
29
- caps, one colour), never filled or duotone. Never emoji as icons. Charts and drawings are not icons.
37
+ one for a mark that names a thing or a state. Seth's line icons are a 1.5 px stroke with round caps and joins. Sizes:
38
+ 16 in a control or a row, with or without words; 12 inside small words (a meta line); 20 for a header's back act; larger
39
+ only in a disc or a hero. An inline icon in running text is `ws-icon`, never unsized. Icons take the words' colour;
40
+ a chevron is navy. One icon per meaning: `x` closes a dialog, a drawer or a panel, or removes one item; chevrons move between items or open a row; three dots open a menu. On a public page: thin
41
+ line art only (about 1.5 px stroke, round caps, one colour), never filled or duotone. Never emoji as icons. Charts and drawings are not icons.
30
42
 
31
43
  ## The chapters
32
44
 
@@ -34,14 +46,14 @@ caps, one colour), never filled or duotone. Never emoji as icons. Charts and dra
34
46
  | --- | --- |
35
47
  | How Claude decides | always first: the quick path, the faces, the wiring, the steps, the three levels of freedom |
36
48
  | Principles | a tie between two good options; the anti-patterns |
37
- | Colour | a colour, a state's tone, a contrast pair |
49
+ | Colour | a colour, a state's or a rating's tone, a contrast pair, the dark theme |
38
50
  | Type | the size and weight of any words |
39
- | Space and layout | gaps, widths, alignment, corners, elevation, responsive |
51
+ | Space and layout | gaps, edges, optical alignment, rimmed cards, dividers, number columns, corners, elevation, responsive |
40
52
  | Sizing profiles | compact, comfortable, touch or public web |
41
53
  | Scrolling | who scrolls and what stays |
42
54
  | Choosing components | a need, mapped to a catalog component |
43
55
  | Charts | any chart or figure |
44
- | Patterns | forms, editing, feedback, states, search, selection, permissions |
56
+ | Patterns | forms, editing, feedback, interaction states, loading and empty, search, selection, permissions |
45
57
  | Page recipes | the composition to start from |
46
58
  | Content | any words a person reads |
47
59
  | Motion | anything that moves |
@@ -49,8 +61,9 @@ caps, one colour), never filled or duotone. Never emoji as icons. Charts and dra
49
61
  | AI experiences | an agent, its chat and its cards |
50
62
  | Creativity | where expression is allowed, and how much |
51
63
  | Decisions | why a rule is so, and what is open |
52
- | Checklist | before anything is called done |
64
+ | Checklist | before anything is called done: the geometry check and the senior QA list |
53
65
  | Public pages | the marketing face: landing, campaign, event and demo pages |
66
+ | Palettes | an app's own colours: the contract, applying a palette to a page or a container, many apps in one bundle, making and checking your own |
54
67
 
55
68
  Each component's README says when to use it, its states and rules; copy its preview markup and `fello.css` styles it.
56
69
  The kit's marketing pieces say so in their first line and never go in a product screen.
@@ -1,41 +1,127 @@
1
1
  A card's ranked list of next acts: who or what, the reason in words, and the one act at the right of each row.
2
+ `--brief` is North's "what changed" list on a page's head: one quiet line each, its acts appearing on the line.
2
3
 
3
4
  ## Use it when
4
5
 
5
6
  - A dashboard or report says what to do next: "who needs a nudge", "deals to call back", "fixes to make" (Page recipes,
6
7
  a dashboard or console).
7
8
  - Each row is one thing with its own act, ordered by what matters most first.
9
+ - `--brief`: a page's head says what changed since the person last looked, one line per change, each opening in chat.
8
10
 
9
11
  ## Not for
10
12
 
11
13
  - Records to compare across many columns: use `Table`.
12
14
  - Suggested questions or prompts to tap into a chat: use `Well`.
13
15
  - A ranking by a number with bars: use `Leaderboard` (it can sit beside this list).
16
+ - Fixes to tick off and open in place: use `CheckRow`'s fix rows.
14
17
 
15
18
  ## Anatomy
16
19
 
17
20
  - Sits in a `Card` under its head (`.ws-head`: the title that answers, "Three agents need a nudge", and one line).
18
- - `ul.ws-action-list`, one `li.ws-action-list__row` per thing:
19
- - optional lead: an `Avatar` (`ws-avatar ws-avatar--plain ws-avatar--sm`) or a mark;
20
- - `.ws-action-list__text`: `.ws-action-list__title` (the name, 14 medium navy, an optional `Chip` beside it) and
21
- `.ws-action-list__reason` (why, in words, 13 body grey);
22
- - `.ws-action-list__act`: one `Button`, secondary, small, a verb and its object ("Text Theo").
23
- - Rows sit 20 px in from the card's edge (`--ws-card-inset`), like the head, with a hairline between them.
21
+ - `ul.ws-action-list`, one `li.ws-action-list__row` per thing: 12 above and below, the card's 20 px edge at both sides
22
+ (the head uses the same edge), parts 16 apart (Seth's fix row), a 0.5 px line between rows (`--ws-divider`):
23
+ - optional lead: an `Avatar` (`ws-avatar ws-avatar--plain ws-avatar--sm`, 28) or a mark;
24
+ - `.ws-action-list__text`: `__title` (Seth's row name, 15 / 20 medium navy, an optional `Chip` 8 beside it) and,
25
+ 4 under, `__reason` (why, in words, 14 / 20 body grey);
26
+ - `.ws-action-list__act`: one `Button`, secondary, small, a verb and its object ("Text Theo"); it never shrinks.
27
+ - every part sits on the name's first line, however many lines the reason runs to: that line is held at 24 (a
28
+ chip's height), and the lead and the act centre on it (a lead other than the 28 avatar sets
29
+ `--ws-action-list-lead` to its height). Under 24rem the act drops under the words, on their edge.
24
30
  - A bulk act for every row ("Nudge all 3") goes in the card's band, never as a second button on each row.
31
+ - `--brief` (North, style1.css 2100 to 2116): lines 6 apart (`--space-xxs-plus`), at least 40 tall, 10 px corners, a
32
+ glass ground (the surface at 55 %) with a 0.5 px navy edge at 8 %. Each line is one button (`__main`: 16 in, 12
33
+ between parts) holding the topic (`__lead`, 14 semibold navy), the gist (`__gist`, 14 body grey, one line, an ellipsis
34
+ and a `title`) and the "Open" act (`__go`, 13 / 18 semibold in salmon's AA word, `--ws-word-needs`, a 16 px arrow),
35
+ then a 24 px dismiss (`__dismiss`, an `IconButton --xs`, 40 on touch). On touch the line keeps 8 clear after "Open",
36
+ so the dismiss's 40 px hit area never covers the arrow.
25
37
 
26
38
  ## States
27
39
 
28
- - Loading: `Skeleton` rows in the rows' places. Empty: say the good news in the card's line ("Nobody needs a nudge this
29
- week") and drop the list. Pending: the pressed row's button shows its working state.
30
- - Long names and reasons wrap; the act stays at the right and never shrinks.
40
+ - **Loading**: ghost lines where the name and the reason go (`__ghost ws-shimmer`), still under reduced motion.
41
+ - **Empty**: say the good news in the card's line ("Nobody needs a nudge this week") and drop the list.
42
+ - **Pending**: the pressed row's button shows its working state.
43
+ - **Long names and reasons**: they wrap; the act stays at the right and never shrinks.
44
+ - **Narrow** (the list under 24rem, a phone's card): the act drops under the words, on their edge, so a reason never
45
+ breaks a word a line; a brief line's "Open" keeps only its arrow (its words stay in the line's name), so the gist keeps
46
+ the room.
47
+ - **`--brief`, hover**: the line goes to the surface and its edge a shade darker, a colour change only: it never lifts,
48
+ scales or casts a shade (D7; North's one lifting row is not taken); "Open" grows out of nothing (0 to 120 wide over
49
+ 320 ms on `--ws-ease-grow`, its arrow stepping 2 px forward) and the dismiss shows. Under reduced motion "Open" appears
50
+ at once and the arrow stays put.
51
+ - **`--brief`, focus**: keyboard focus on the line shows "Open" and the dismiss too, its ring drawn inside the line.
52
+ - **`--brief`, touch**: "Open" and the dismiss are always there (no hover to wait for).
31
53
 
32
- ## Rules
54
+ ## Behaviour
55
+
56
+ - Keyboard: a real list; each act is a real button. In `--brief` the line is one button (it opens the change in chat)
57
+ and the dismiss a second; both reachable by Tab.
58
+ - Pointer: a row of the card list is not itself a target; its act is. A brief line is.
59
+ - Motion: the hover colours over 200 ms (`--ws-duration-hover`); "Open" grows over 320 ms (`--ws-duration-settle`).
60
+
61
+ ## Content
33
62
 
34
63
  - The reason is a sentence with real figures and their period ("No calls since Tuesday, down from 30 last week"), never
35
64
  a status word alone. Colour is never the only signal: a chip carries words.
65
+ - A brief line is a topic and one plain sentence ("Pipeline: three deals moved to offer, $1.2M in all").
66
+ - No em dashes.
67
+
68
+ ## Props
69
+
70
+ | Name | Type | Meaning |
71
+ | --- | --- | --- |
72
+ | `items` | `{ id, lead?, title, chip?, reason, act: { label, onClick } }[]` | The rows, most important first |
73
+ | `variant` | `'card' \| 'brief'` | The card list or the brief lines |
74
+ | `onOpen`, `onDismiss` | functions | A brief line's two acts |
75
+
76
+ ## Rules
77
+
36
78
  - One act per row, secondary. The page's one primary is elsewhere.
79
+ - Rows sit on the card's 20 px edge, like its head: one content edge per card.
80
+ - A brief line's acts are never hover-only: focus shows them, touch always has them.
37
81
 
38
82
  ## Accessibility
39
83
 
40
84
  - A real list (`ul`/`li`). Each act's words name the person or thing, so a screen reader hears "Text Theo", not "Text".
85
+ - A dismiss's label names the line ("Dismiss: Pipeline").
41
86
  - On touch the buttons grow to 40 px; the row grows with them.
87
+
88
+ ## Source
89
+
90
+ - **Derived from**: the card's 20 px edge, Seth's fix row (308:2466: row names 15 / 20, parts 16 apart, 12 above and
91
+ below), the 0.5 px divider (D5), North's brief rows (style1.css 2100 to 2116), and `Button`.
92
+ - **Precedent**: the first product's "who needs a nudge" card; `--brief` added in 0.5.0 (4 Nov 2026).
93
+
94
+ ## Markup
95
+
96
+ ```html
97
+ <section class="ws-card ws-card--compound">
98
+ <header class="ws-head"><div><h3 class="ws-title">Three agents need a nudge</h3><p class="ws-body ws-card__line">Each made under half of the 50-call goal this week.</p></div></header>
99
+ <ul class="ws-action-list">
100
+ <li class="ws-action-list__row">
101
+ <span class="ws-avatar ws-avatar--plain ws-avatar--sm" aria-hidden="true">TL</span>
102
+ <div class="ws-action-list__text">
103
+ <p class="ws-action-list__title">Theo Lane <span class="ws-chip">9 calls</span></p>
104
+ <p class="ws-action-list__reason">No calls since Tuesday, down from 30 last week.</p>
105
+ </div>
106
+ <button type="button" class="ws-btn ws-btn--secondary ws-btn--sm ws-action-list__act">Text Theo</button>
107
+ </li>
108
+ </ul>
109
+ </section>
110
+
111
+ <ul class="ws-action-list ws-action-list--brief" aria-label="What changed since yesterday">
112
+ <li class="ws-action-list__brief">
113
+ <button type="button" class="ws-action-list__main">
114
+ <span class="ws-action-list__lead">Calls</span>
115
+ <span class="ws-action-list__gist" title="The team made 212 calls, 40 more than last week">The team made 212 calls, 40 more than last week</span>
116
+ <span class="ws-action-list__go">Open in chat <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg></span>
117
+ </button>
118
+ <button type="button" class="ws-icon-btn ws-icon-btn--xs ws-action-list__dismiss" aria-label="Dismiss: Calls"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
119
+ </li>
120
+ </ul>
121
+ ```
122
+
123
+ ## Styles
124
+
125
+ `design-system/components/ActionList/style.css`, in `bundle.css` and `fello.css`. Dark and the navy ground come from
126
+ the tokens (`--color-surface`, `--ws-ink`, `--ws-word-needs`). The brief's 10 px corner is
127
+ `--ws-radius-menu`.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Data" height=320 -->
1
+ <!-- @dsCard group="Data" height=720 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -8,8 +8,9 @@
8
8
  <link rel="stylesheet" href="../bundle.css">
9
9
  </head>
10
10
  <body>
11
- <div class="ws-stage">
12
- <section class="ws-card ws-card--compound" style="width: 480px; max-width: 100%;">
11
+ <div class="ws-stage ws-stage--grey">
12
+
13
+ <section class="ws-card ws-card--compound" style="width: 520px;">
13
14
  <header class="ws-head">
14
15
  <div>
15
16
  <h3 class="ws-title">Three agents need a nudge</h3>
@@ -28,10 +29,10 @@
28
29
  <li class="ws-action-list__row">
29
30
  <span class="ws-avatar ws-avatar--plain ws-avatar--sm" aria-hidden="true">JW</span>
30
31
  <div class="ws-action-list__text">
31
- <p class="ws-action-list__title">Jo Webb <span class="ws-chip">18 calls</span></p>
32
- <p class="ws-action-list__reason">Down from 41 last week. Nothing since Wednesday.</p>
32
+ <p class="ws-action-list__title">Josephine Whitfield-Abernathy <span class="ws-chip">18 calls</span></p>
33
+ <p class="ws-action-list__reason">Down from 41 last week. Nothing since Wednesday, and two of her three showings this week were moved.</p>
33
34
  </div>
34
- <button type="button" class="ws-btn ws-btn--secondary ws-btn--sm ws-action-list__act">Text Jo</button>
35
+ <button type="button" class="ws-btn ws-btn--secondary ws-btn--sm ws-action-list__act">Text Josephine</button>
35
36
  </li>
36
37
  <li class="ws-action-list__row">
37
38
  <span class="ws-avatar ws-avatar--plain ws-avatar--sm" aria-hidden="true">NP</span>
@@ -39,10 +40,54 @@
39
40
  <p class="ws-action-list__title">Nellie Park <span class="ws-chip">22 calls</span></p>
40
41
  <p class="ws-action-list__reason">Reached 2 of 22 people, the lowest rate on the team.</p>
41
42
  </div>
42
- <button type="button" class="ws-btn ws-btn--secondary ws-btn--sm ws-action-list__act">Text Nellie</button>
43
+ <button type="button" class="ws-btn ws-btn--secondary ws-btn--sm ws-action-list__act" aria-busy="true"><span class="ws-dot ws-working" aria-hidden="true"></span>Texting Nellie</button>
43
44
  </li>
44
45
  </ul>
45
46
  </section>
47
+
48
+ <div class="ws-stack ws-stack--component" style="width: 360px;">
49
+ <section class="ws-card ws-card--compound" aria-busy="true" aria-label="Who needs a nudge, loading">
50
+ <header class="ws-head"><div><h3 class="ws-title">Who needs a nudge</h3><p class="ws-body ws-card__line">Checking this week's calls.</p></div></header>
51
+ <ul class="ws-action-list">
52
+ <li class="ws-action-list__row"><div class="ws-action-list__text"><div class="ws-action-list__ghost ws-shimmer" style="width: 40%;"></div><div class="ws-action-list__ghost ws-shimmer" style="width: 80%;"></div></div></li>
53
+ <li class="ws-action-list__row"><div class="ws-action-list__text"><div class="ws-action-list__ghost ws-shimmer" style="width: 50%;"></div><div class="ws-action-list__ghost ws-shimmer" style="width: 70%;"></div></div></li>
54
+ </ul>
55
+ </section>
56
+ <section class="ws-card ws-card--compound">
57
+ <header class="ws-head"><div><h3 class="ws-title">Nobody needs a nudge</h3><p class="ws-body ws-card__line">All six are past half the 50-call goal this week.</p></div></header>
58
+ </section>
59
+ </div>
60
+
61
+ <div class="ws-stack" style="width: 640px;">
62
+ <span class="ws-muted">--brief, North's "what changed" lines on a page's head: hover turns a line to the surface (no lift) and shows Open and the dismiss; focus shows them too, touch always does</span>
63
+ <ul class="ws-action-list ws-action-list--brief" aria-label="What changed since yesterday">
64
+ <li class="ws-action-list__brief">
65
+ <button type="button" class="ws-action-list__main">
66
+ <span class="ws-action-list__lead">Pipeline</span>
67
+ <span class="ws-action-list__gist" title="Three deals moved to offer, $1.2M in all, the most in a week since August">Three deals moved to offer, $1.2M in all, the most in a week since August</span>
68
+ <span class="ws-action-list__go">Open in chat <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg></span>
69
+ </button>
70
+ <button type="button" class="ws-icon-btn ws-icon-btn--xs ws-action-list__dismiss" aria-label="Dismiss: Pipeline"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
71
+ </li>
72
+ <li class="ws-action-list__brief">
73
+ <button type="button" class="ws-action-list__main">
74
+ <span class="ws-action-list__lead">Calls</span>
75
+ <span class="ws-action-list__gist" title="The team made 212 calls, 40 more than last week">The team made 212 calls, 40 more than last week</span>
76
+ <span class="ws-action-list__go">Open in chat <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg></span>
77
+ </button>
78
+ <button type="button" class="ws-icon-btn ws-icon-btn--xs ws-action-list__dismiss" aria-label="Dismiss: Calls"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
79
+ </li>
80
+ <li class="ws-action-list__brief">
81
+ <button type="button" class="ws-action-list__main">
82
+ <span class="ws-action-list__lead">Showings</span>
83
+ <span class="ws-action-list__gist" title="Sam Okafor confirmed Saturday at 11">Sam Okafor confirmed Saturday at 11</span>
84
+ <span class="ws-action-list__go">Open in chat <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg></span>
85
+ </button>
86
+ <button type="button" class="ws-icon-btn ws-icon-btn--xs ws-action-list__dismiss" aria-label="Dismiss: Showings"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
87
+ </li>
88
+ </ul>
89
+ </div>
90
+
46
91
  </div>
47
92
  </body>
48
93
  </html>