@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,64 @@
1
+ /* ---- ActionList: a card's ranked list of next acts: who or what, the reason in words, the one act at the right. --brief
2
+ is North's "what changed" list on a page's head: one quiet 40 px line each, the line taking the surface on hover with
3
+ its acts appearing on it ---- */
4
+ .ws-action-list { container: ws-action-list / inline-size; display: flex; flex-direction: column; }
5
+ /* A row: 12 above and below, the card's 20 px edge at both sides (the head above it uses the same edge), 16 between
6
+ parts (Seth's fix row), a 0.5 px line between rows. Every part sits on the name's first line (Seth's fix row), however
7
+ many lines the reason runs to: that line is 24 (a chip's height, held without one), and the lead (the 28 avatar;
8
+ another mark sets --ws-action-list-lead to its height) and the act are trimmed to it by their margins, so they centre on it. */
9
+ .ws-action-list__row { --ws-action-list-line: var(--space-lg); --ws-action-list-lead: var(--ws-control-h-sm); --ws-action-list-act: var(--ws-control-h-sm); display: flex; align-items: flex-start; gap: var(--space-md); padding: var(--space-sm) var(--ws-card-inset); }
10
+ .ws-action-list__row > :first-child:not(.ws-action-list__text) { flex-shrink: 0; margin-block: calc((var(--ws-action-list-line) - var(--ws-action-list-lead)) / 2); }
11
+ @media (pointer: coarse) { .ws-action-list__row { --ws-action-list-act: var(--ws-touch); } }
12
+ .ws-action-list__row + .ws-action-list__row { border-top: var(--ws-divider); }
13
+ .ws-action-list__text { display: flex; flex: 1; flex-direction: column; gap: var(--space-xxs); min-width: 0; }
14
+ /* The name: Seth's row name, 15 / 20 medium navy, an optional chip beside it; the reason a 14 / 20 description. */
15
+ .ws-action-list__title { display: flex; flex-wrap: wrap; align-items: center; min-height: var(--ws-action-list-line); gap: var(--space-xxs) var(--space-xs); font-size: var(--ws-text-section); line-height: var(--ws-leading-row); font-weight: 500; color: var(--color-text-heading); }
16
+ .ws-action-list__reason { font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); color: var(--color-text-body); }
17
+ .ws-action-list__act { flex-shrink: 0; margin-block: calc((var(--ws-action-list-line) - var(--ws-action-list-act)) / 2); }
18
+ /* Loading: a ghost line where the name and the reason go (add ws-shimmer). */
19
+ .ws-action-list__ghost { display: block; height: calc(var(--space-xs) + var(--space-3xs)); border-radius: var(--ws-radius-bar); background: var(--ws-track); }
20
+ .ws-action-list__ghost.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
21
+
22
+ /* --brief (North): rows 6 apart, 40 tall, 10 px corners, a glass ground with a 0.5 px navy edge. Hover: the line goes
23
+ to the surface and its edge a shade darker, nothing lifts or grows (D7; North's lifting row is not taken), its "Open"
24
+ act grows out and its dismiss shows; both also show on keyboard focus, and on touch they are always there. */
25
+ .ws-action-list--brief { gap: var(--space-xxs-plus); }
26
+ .ws-action-list__brief { position: relative; display: flex; align-items: center; min-height: var(--ws-row-h-dense); border-radius: var(--ws-radius-menu); background: color-mix(in srgb, var(--color-surface) 55%, transparent); box-shadow: inset 0 0 0 var(--ws-hairline) color-mix(in srgb, var(--ws-ink) 8%, transparent); transition: background-color var(--ws-duration-hover) var(--ws-ease-soft), box-shadow var(--ws-duration-hover) var(--ws-ease-soft); }
27
+ .ws-action-list__main { display: flex; flex: 1; align-items: center; align-self: stretch; gap: var(--space-sm); min-width: 0; padding: 0 var(--space-xxs) 0 var(--space-md); border: 0; border-radius: inherit; background: none; font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); text-align: left; cursor: pointer; }
28
+ .ws-action-list__main:focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
29
+ .ws-action-list__lead { flex: none; font-weight: 600; color: var(--color-text-heading); }
30
+ .ws-action-list__gist { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-body); }
31
+ /* "Open": the needs-you word (salmon's AA step), a 16 px arrow; folded to nothing until the line is hovered or focused. */
32
+ .ws-action-list__go { display: inline-flex; flex: none; align-items: center; gap: var(--space-xxs); max-width: 0; overflow: hidden; opacity: 0; white-space: nowrap; font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 600; color: var(--ws-word-needs); transition: opacity var(--ws-duration-hover) var(--ws-ease-soft); }
33
+ .ws-action-list__go svg { width: var(--ws-icon); height: var(--ws-icon); flex-shrink: 0; }
34
+ .ws-action-list__dismiss { margin-right: var(--space-xs); opacity: 0; color: var(--color-text-muted); transition: opacity var(--ws-duration-hover) var(--ws-ease-soft), background-color var(--ws-duration-hover) var(--ws-ease-soft); }
35
+ .ws-action-list__main:focus-visible .ws-action-list__go { max-width: var(--space-7xl); opacity: 1; }
36
+ .ws-action-list__dismiss:focus-visible, .ws-action-list__brief:focus-within .ws-action-list__dismiss { opacity: 1; }
37
+ @media (hover: hover) {
38
+ .ws-action-list__brief:hover { background-color: var(--color-surface); box-shadow: inset 0 0 0 var(--ws-hairline) color-mix(in srgb, var(--ws-ink) 10%, transparent); }
39
+ .ws-action-list__brief:hover .ws-action-list__go { max-width: var(--space-7xl); opacity: 1; }
40
+ .ws-action-list__brief:hover .ws-action-list__dismiss { opacity: 1; }
41
+ .ws-action-list__dismiss:hover { background: var(--ws-hover-strong); color: var(--color-text-heading); }
42
+ }
43
+ /* Motion, only where it is wanted: "Open" growing out, the arrow's step. */
44
+ @media (prefers-reduced-motion: no-preference) {
45
+ .ws-action-list__go { transition: max-width var(--ws-duration-settle) var(--ws-ease-grow), opacity var(--ws-duration-hover) var(--ws-ease-soft); }
46
+ .ws-action-list__go svg { transition: transform var(--ws-duration-hover) var(--ws-ease-soft); }
47
+ }
48
+ @media (hover: hover) and (prefers-reduced-motion: no-preference) {
49
+ .ws-action-list__brief:hover .ws-action-list__go svg { transform: translateX(var(--space-3xs)); }
50
+ }
51
+ @media (hover: none) { .ws-action-list__go { max-width: none; opacity: 1; } .ws-action-list__dismiss { opacity: 1; } }
52
+ /* On touch the dismiss's 40 px hit area reaches 8 past its box: the line keeps 8 clear after "Open" so a tap on the
53
+ arrow never dismisses. */
54
+ @media (pointer: coarse) { .ws-action-list__main { padding-right: var(--space-xs); } }
55
+ /* Narrow (a list under 24rem, a phone's card): the act drops under the words, on their edge, so the reason keeps the
56
+ row's width instead of breaking a word a line; a brief line's "Open" keeps only its arrow (its words, at no size,
57
+ stay in the line's name), so the gist keeps the room. */
58
+ @container ws-action-list (max-width: 24rem) {
59
+ .ws-action-list__row { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: var(--space-xs) var(--space-md); }
60
+ .ws-action-list__text, .ws-action-list__act { grid-column: 2; }
61
+ .ws-action-list__text:first-child, .ws-action-list__text:first-child ~ * { grid-column: 1 / -1; }
62
+ .ws-action-list__act { justify-self: start; margin-block: 0; }
63
+ .ws-action-list__go { gap: 0; font-size: 0; }
64
+ }
@@ -14,7 +14,8 @@ Who reached out, two weeks of day cells a row, a navy dot for a day done and a c
14
14
 
15
15
  **Anatomy**
16
16
 
17
- - Two week blocks of seven day cells, Monday to Sunday, a narrow gap between them; each cell is a square that scales with the column.
17
+ - Two week blocks of seven day cells, Monday to Sunday, a narrow gap between them; each cell is a square that scales with the column up to 32 px (`--space-xl`), then stops; in a wider card the
18
+ spare room goes after the count, so the days still read as a calendar.
18
19
  - A day with outreach: a navy dot, lighter the longer ago it was, filling the full cell as a circle.
19
20
  - A day without: an empty cream square with the slot's fine edge, `--ws-radius-control` (4 px) corners.
20
21
  - Today: the same empty square outlined in salmon at half strength.
@@ -29,12 +30,28 @@ Who reached out, two weeks of day cells a row, a navy dot for a day done and a c
29
30
  | `tip` | A day with outreach shows its own small card (its call and outcome) while pointed at |
30
31
  | `more` | Adds the quiet line under the grid for names outside the matrix |
31
32
 
33
+ **Parts and modifiers**
34
+
35
+ - `.ws-activity-grid__grid--week`: one week instead of two (seven day columns, no gap column).
36
+ - `.ws-activity-grid__letter`: a day's initial over its column (11 px muted); `--today` is today's, in the salmon word.
37
+ - `.ws-activity-grid__letter--today`: today's initial, in `--ws-word-needs`; under 18rem it is the only letter left.
38
+ - `.ws-activity-grid__dot--past`: a day done a week ago, a lighter navy.
39
+ - `.ws-activity-grid__dot--pointed`: the day under the pointer, salmon (`--ws-chart-under-half` (chart tone 3, so a palette that sets it moves it); with a `__tip`).
40
+ - `.ws-activity-grid__today`: today's cell while nothing is done yet: a salmon edge (`--ws-chart-under-half` at half strength).
41
+ - `.ws-activity-grid__empty--future`: a day not reached yet: a dashed edge.
42
+ - `.ws-activity-grid__count--zero`: a row with no days done: the count in regular muted grey.
43
+ - `.ws-activity-grid__note`: the quiet line under the grid (12 px muted) naming who has not reached out.
44
+ - `.ws-activity-grid__tip`: a day's own small card over its cell (use with `ws-menu`), 8 above it.
45
+ - `.ws-activity-grid__tip-title`: the tip's first line, medium.
46
+
32
47
  **States**
33
48
 
34
49
  - Default: the matrix simply shows; rows read top to bottom by who did the most.
35
50
  - Hover (`tip` given): the pointed-at day's dot turns salmon and its small card appears above it.
36
51
  - Quiet: a person with every cell empty, name and count both muted grey, never highlighted as an error.
37
- - Narrow: columns shrink and stay square; the label column keeps its own width.
52
+ - Narrow: columns shrink and stay square; the label column keeps its own width. Under 18rem (two weeks in a phone
53
+ card) the gap halves to 2 and the day letters go, all but today's, so no two letters run into each other; the week
54
+ labels still mark each week's start.
38
55
  - Disabled / error / focus / pressed / selected: do not apply to the grid itself; only a `tip` cell responds to a pointer.
39
56
  - Reduced motion: cells are simply in place.
40
57
 
@@ -69,3 +86,22 @@ Who reached out, two weeks of day cells a row, a navy dot for a day done and a c
69
86
  ## Source
70
87
 
71
88
  **Derived from**: the system's chart rules for a day-cell matrix, the navy "done" tone and the quiet-line pattern for naming who hasn't acted (tokens: `--ws-radius-control`, `--color-brand-navy`, `--ws-word-needs`). **Precedent**: the first product built on the system.
89
+
90
+ ## Markup
91
+
92
+ ```html
93
+ <div class="ws-dots ws-activity-grid__body">
94
+ <figure class="ws-activity-grid__grid" aria-label="Days with outreach, last two weeks: Priya 6 days">
95
+ <!-- head row: an empty cell, the week, the gap, the week, the count column -->
96
+ <span aria-hidden="true"></span><span class="ws-activity-grid__week" aria-hidden="true">Week of Sep 28</span><span aria-hidden="true"></span>
97
+ <!-- one row a person: the name, 7 day cells, the gap, 7 day cells, the count -->
98
+ <span class="ws-activity-grid__name ws-activity-grid__name--active" aria-hidden="true">Priya</span>
99
+ <span class="ws-activity-grid__cell"><span class="ws-activity-grid__dot"></span></span>
100
+ <span class="ws-activity-grid__cell"><span class="ws-activity-grid__empty"></span></span>
101
+ <span class="ws-activity-grid__count" aria-hidden="true">6</span>
102
+ </figure>
103
+ </div>
104
+ ```
105
+
106
+ **Styles**: `ActivityGrid/style.css`, in `bundle.css` and `fello.css` as `.ws-activity-grid`. Every value is a token. `.ws-activity-grid` itself has no styles: it is the hook that
107
+ names the chart (and the root for its modifiers); its parts carry the styles.
@@ -119,7 +119,7 @@
119
119
 
120
120
  <div class="ws-stack">
121
121
  <span class="ws-muted">A day pointed at can show its own small card (`tip`); a quiet name stays grey</span>
122
- <div style="width: 300px;">
122
+ <div style="width: 300px; padding-top: var(--space-xl);">
123
123
  <div class="ws-card ws-card--inset ws-activity-grid">
124
124
  <figure class="ws-activity-grid__grid ws-activity-grid__grid--week" aria-label="Days with outreach, this week: Priya 3 days, Dana 0 days">
125
125
  <span aria-hidden="true"></span>
@@ -0,0 +1,35 @@
1
+ /* ---- ActivityGrid: who reached out, two weeks of day cells a row and a count at the end ---- */
2
+ .ws-activity-grid__body { display: flex; flex-direction: column; gap: var(--space-xl); padding: var(--space-md) var(--ws-card-inset) var(--space-xxs-plus); container-type: inline-size; }
3
+ /* Day columns share the room up to 32 px each, then stop: in a wide card the days stay a calendar (not 64 px discs)
4
+ and the count stays beside them, the spare room after it. */
5
+ .ws-activity-grid__grid { display: grid; width: 100%; grid-template-columns: minmax(var(--space-4xl), max-content) repeat(7, minmax(0, var(--space-xl))) var(--space-xs) repeat(7, minmax(0, var(--space-xl))) calc(var(--space-md) + var(--space-xs) * 0.75); justify-content: start; gap: var(--space-xxs); align-items: center; }
6
+ .ws-activity-grid__grid--week { grid-template-columns: minmax(var(--space-4xl), max-content) repeat(7, minmax(0, var(--space-xl))) calc(var(--space-md) + var(--space-xs) * 0.75); }
7
+ .ws-activity-grid__week { grid-column: span 7; align-self: end; font-size: var(--ws-text-micro); font-weight: 500; line-height: var(--font-size-xs); color: var(--color-text-body); text-wrap: balance; }
8
+ .ws-activity-grid__letter { text-align: center; font-size: var(--ws-text-micro); font-weight: 500; color: var(--color-text-muted); }
9
+ .ws-activity-grid__letter--today { color: var(--ws-word-needs); }
10
+ .ws-activity-grid__name { padding-right: var(--space-xs); font-size: var(--ws-text-meta); line-height: var(--space-md); color: var(--color-text-muted); white-space: nowrap; }
11
+ .ws-activity-grid__name--active { font-weight: 500; color: var(--color-text-heading); }
12
+ .ws-activity-grid__cell { position: relative; width: 100%; aspect-ratio: 1; }
13
+ /* A day done: a navy dot, a week ago a lighter navy; salmon while pointed at. */
14
+ .ws-activity-grid__dot { display: block; width: 100%; height: 100%; border-radius: var(--radius-full); background: var(--color-text-heading); }
15
+ .ws-activity-grid__dot--past { background: color-mix(in srgb, var(--ws-chart-navy-light) 40%, var(--color-text-heading)); }
16
+ .ws-activity-grid__dot--pointed { background: var(--ws-chart-under-half); }
17
+ .ws-activity-grid__empty, .ws-activity-grid__today { display: block; width: 100%; height: 100%; border-radius: var(--ws-radius-control); border: var(--ws-hairline) solid var(--ws-edge-slot); background: var(--color-bg-page); }
18
+ .ws-activity-grid__today { border: var(--ws-line) solid color-mix(in srgb, var(--ws-chart-under-half) 50%, var(--color-bg-page)); }
19
+ .ws-activity-grid__empty--future { border-style: dashed; }
20
+ .ws-activity-grid__count { text-align: right; font-size: var(--ws-text-chart); font-weight: 600; color: var(--color-text-heading); font-variant-numeric: tabular-nums; }
21
+ .ws-activity-grid__count--zero { font-weight: 400; color: var(--color-text-muted); }
22
+ .ws-activity-grid__note { font-size: var(--ws-text-dense); color: var(--color-text-muted); }
23
+ /* Narrow (a phone's card, two weeks under 18rem): the day columns fall under 9 px, where 11 px day letters would run
24
+ into each other. The gap halves so the cells stay as large as they can, and the letters go, all but today's; the
25
+ week labels still say where each week starts. */
26
+ @container (max-width: 18rem) {
27
+ .ws-activity-grid__grid { column-gap: var(--space-3xs); }
28
+ .ws-activity-grid__letter:not(.ws-activity-grid__letter--today) { visibility: hidden; }
29
+ /* today's letter is wider than its column now: centre it on the column rather than let it run off to the right */
30
+ .ws-activity-grid__letter--today { justify-self: center; }
31
+ }
32
+ /* A day's own small card (tip), a menu lifted over its cell. Use with ws-menu. */
33
+ .ws-activity-grid__tip { position: absolute; left: 50%; bottom: calc(100% + var(--space-xs)); transform: translateX(-50%); padding: var(--space-sm); }
34
+ .ws-activity-grid__tip-title { font-weight: 500; }
35
+
@@ -1,110 +1,240 @@
1
- A conventional product shell for a project that is not chat-first: a left nav of grouped rows, a top bar with the page's
2
- name and its one act, and a cream stage between them.
1
+ A product's frame, drawn from Seth's North app: a 232 px nav of grouped rows on the frame's wash, a glass stage beside
2
+ it, a 56 px bar at the stage's top and a body that owns the scroll. It folds to a 64 px rail and, on a phone, gives the
3
+ nav to a drawer.
3
4
 
4
5
  ## Use it when
5
6
 
6
- - The product's work happens on pages a person browses and acts on, not in one running conversation (a chat-first
7
- product uses `Sidebar` and a chat instead; see Not for).
8
- - There are more sections than fit as a flat list and they fall into a few groups (Work, Reports, Settings).
9
- - Every page needs the same place to search and the same place for its one primary act.
10
- - A team member needs a persistent reminder of who they are signed in as, at the foot of the nav.
7
+ - The product's work happens on pages a person moves between: a pipeline, a report, a list, settings.
8
+ - There are more destinations than fit a flat list, and they fall into a few groups (Reports, Settings).
9
+ - Every page needs the same place for its name, its acts and a way to fold the nav away.
10
+ - A team member needs to see who they are signed in as, pinned at the foot of the nav.
11
11
 
12
12
  ## Not for
13
13
 
14
- - A chat-first product where people act by talking to an agent and the pages only show results: use `Sidebar`, organised
15
- by app and thread, with no top bar.
16
- - A single-purpose tool with under about five destinations and no groups: a plain list of `ws-row`s needs no eyebrows or
17
- shell.
18
- - A page's own filters or view switches: those are `Tabs` or `Segmented` inside the stage, never nav rows.
19
- - The marketing site: it keeps the kit's own `MarketingNav`.
14
+ - A chat-first screen where people act by talking to an agent: that is a chat (`ChatShell`, from WP-cards) with the
15
+ thread's own `PageBar` when a report opens full screen.
16
+ - A handful of destinations with no groups: a `TopBar` across the top reads better.
17
+ - A page's own filters or view switches: those are `Tabs` or `Segmented` in the body, never nav rows.
18
+ - The marketing site: it keeps `MarketingNav`.
20
19
 
21
20
  ## Anatomy
22
21
 
23
- - Nav: `--ws-sidebar-width` (232 px) wide, no card of its own, sitting on `--ws-page` beside the stage.
24
- - Wordmark: the product's name in plain navy type, 16 px semibold (`--ws-text-value`), `--color-text-heading`. A
25
- chat-first product's own `Sidebar` draws its own orb and iridescent wordmark instead; a page-based product supplies
26
- its mark in this slot when it has one.
27
- - A group: an eyebrow (12 px, 600, uppercase, `--letter-spacing-overline`, `--color-text-muted`) above its rows.
28
- - A row: 32 px tall (`--ws-control-h`, the `ws-row` shape), a 20 px line icon (`--ws-icon-lg` is 20 px, used here as a
29
- 20 px line icon rather than a face), 14 px medium navy words (`--color-text-heading`), `--ws-radius-row` (6 px) corners.
30
- The current row is washed `--ws-sidebar-hover`; a count chip (the sidebar's badge shape: the `--ws-tint-needs` wash,
31
- its number in `--ws-word-needs`, since salmon itself is never words) sits right-aligned for what needs the person.
32
- - The person: at the nav's foot, a hairline (`--ws-edge-card`) above it, a neutral `--ws-avatar` disc with navy initials,
33
- their name 14 px medium navy, their role 12 px muted.
34
- - Top bar: `--ws-header-h` (56 px), on the stage, a hairline below it; the page's name 26 px semibold (`--font-size-2xl`,
35
- the `headline` role) at the left, a 36 px search box (`--ws-control-h-md`, 4 px corners, the field's hairline) and one
36
- `primary`, `large` button at the right.
37
- - Stage: a 16 px cornered cream surface (`--ws-radius-panel`, drawn with the `ws-card` hairline outline so it reads as one
38
- surface against the grey), 24 px gutters (`--ws-gutter`) inside it; the gutter is the canvas's, so a page never adds its
39
- own side padding.
40
- - The shell fills its parent's height (`height: 100%`): on a page, give that parent the window's height (`100dvh`).
41
- - In fello.css: `.ws-app-shell`, `__nav`, `__wordmark`, `__eyebrow` (with `ws-eyebrow`), `__rows`, `__row` (+ `--current`),
42
- `__name`, `__count`, `__foot`, `__stage`, `__bar`, `__title`, `__search`, `__body`; folded: `__rail`, `__mark`
43
- (+ `--current`, `--wordmark`).
22
+ - **Frame** (`.ws-app-shell`): the window's ground, `--ws-frame` (Seth's `#EBF0F5` to cream wash over 640 px). It
23
+ fills its parent's height: give that parent the window's (`100dvh`). It is a size container named `ws-app-shell`.
24
+ - **Nav** (`__nav`): 232 px (`--ws-sidebar-width`), no card of its own, on the frame. It sits on the stage's insets
25
+ (13 top, 12 bottom) so its top and foot line up with the stage.
26
+ - Head (`__head`): 56 tall (`--ws-header-h`), so the product's name sits on the bar's line. The name (`__wordmark`)
27
+ 18 / 24 semibold navy; at its right one 32 px icon button that folds the nav. Sides 12 and 8 (the groups'), the name 10 inside them, so it starts on the row icons' edge, 22 in.
28
+ - Groups (`__groups`): the part that scrolls, between the head and the person. Each group (`__group`) has 12 / 8
29
+ sides and 4 above and below. A 1 px rule (`--ws-edge-card`) runs the nav's full width between groups, none above
30
+ the first.
31
+ - Group name (`__eyebrow`): Seth's sentence-case head, 11 / 16 medium in muted, 28 tall with 12 above the words, on
32
+ the icons' edge (22 from the nav's side). Seth draws it at 10 px; the kit keeps its 11 px floor.
33
+ - Rows (`__rows`, `__row`): 28 tall (`--ws-control-h-sm`, 40 on touch), 2 apart, 10 px sides, 6 px corners. A 20 px
34
+ icon box (the 16 px icon inside it), 4 px, then the name (`__name`) in 13 / 18 medium body grey, truncated with
35
+ its full words in `title`. Rows are real links (`<a href>`).
36
+ - Count (`__count`): Seth's navy pill, 18 tall, at least 18 wide, 11 px semibold figures in the act fill's word
37
+ colour (`--ws-on-act`).
38
+ - The person (`__foot`): pinned at the foot under a full-width 1 px rule, never scrolled away, 12 above and 6 below,
39
+ on the rows' edges (22 in at the left, 18 at the right: the groups' 12 / 8 and a row's 10). A 28 px avatar, 10 px,
40
+ then the name 13 / 16 medium navy (`__foot-name`) over the role in `ws-muted`.
41
+ - **Stage** (`__stage`): `--ws-glass` with a 4 px blur (`--ws-glass-blur`), a 1 px `--ws-edge-stage` edge, 16 px corners
42
+ (`--ws-radius-panel`), 13 from the window's top (`--ws-stage-inset-top`), 12 from its right and bottom
43
+ (`--ws-stage-inset`), no gap to the nav (the nav's own 8 px is the gap). `--wash` gives it the Fia frames' cream
44
+ wash (`--ws-stage-wash`) instead of glass.
45
+ - **Bar** (`__bar`): at least 56 tall, 8 above and below (a bar that wraps never touches the stage's edge), on the
46
+ content's 32 px edges, flat. It holds the page's name (`__title`, 16 / 22
47
+ semibold, one line), a `Breadcrumb`, or a `PageBar` (put both classes on one `<header>`), and at its right the acts
48
+ (`__acts`, 8 apart): a search box (`__search`: a `<label>` round an `<input type="search">`, 220 wide, giving down
49
+ to 160, 32 tall (40 on touch), the field's inset hairline, the focus ring on the box) and the page's one primary. Its
50
+ 0.5 px edge (an inset hairline, so the bar stays a whole 56 and its controls sit on whole pixels) shows only once the
51
+ body has scrolled (`__bar--scrolled`).
52
+ - **Body** (`__body`): the page itself. 16 under the bar, 32 at the sides, 40 at the foot, its parts 16 apart. It
53
+ scrolls and never chains into the window (`overscroll-behavior: contain`), it is a size container (as `.ws-page` is),
54
+ and its content is capped at the board's two columns (1128, `2 x --ws-chart-card-w + --ws-gap-component`, the same
55
+ as `.ws-page`; Seth's North caps at 1119) on one start edge, so a section, its tiles, a board and a `Split` all end
56
+ on one edge. Put no `.ws-page` inside it.
57
+ - `__body--wide`: a Fia app page (Grow, Fixes, Inbox, Tally) runs the body's full width, Seth's 1350 in a 1416
58
+ stage, with no cap.
59
+ - A filled page (a `ws-split--fill` straight in the body, Seth's report and its drawer) ends 24 above the stage's
60
+ foot (`--ws-gap-group`) instead of 40.
61
+ - **Menu button** (`__menu`): an icon button in the bar, shown only in the phone form (never beside the open nav or
62
+ the folded rail).
63
+ - **Touch**: the search box is 40 tall and its words 16, so a phone or tablet never zooms into it on focus.
64
+ - In fello.css: `.ws-app-shell` (+ `--folded`, `--wash`), `__nav`, `__head`, `__wordmark`, `__groups`, `__group`,
65
+ `__eyebrow`, `__rows`, `__row` (+ `--current`), `__name`, `__count`, `__foot`, `__foot-words`, `__foot-name`,
66
+ `__stage`, `__bar` (+ `--scrolled`), `__title`, `__acts`, `__search`, `__menu`, `__body` (+ `--wide`); the 0.4
67
+ rail markup `__rail` and `__mark` (+ `--current`, `--wordmark`) still draws, and so does a 0.4 nav (wordmark, group
68
+ names, rows and person straight in `__nav`, no `__head` or `__groups`): the nav itself scrolls then, with the
69
+ wordmark and the person pinned to its ends.
44
70
 
45
71
  ## Variants and sizes
46
72
 
47
73
  | Variant | Width | Shows |
48
74
  | --- | --- | --- |
49
- | Open (default) | 232 px (`--ws-sidebar-width`) | Wordmark, grouped rows with words and counts, the person |
50
- | Folded | 72 px (`--ws-rail-width`) | The same rows as marks only, centred, no words, no counts, no person name |
75
+ | Open (default) | 232 px | The head, grouped rows with names and counts, the person |
76
+ | Folded (`--folded`) | 64 px | The same nav: 40 px rows of icons, the current one on its pill; names faded (still read aloud), counts gone, each row's name and count in its `title` (a pointer's tooltip, a screen reader's description), group names and rules gone, the avatar centred |
77
+ | Phone (under 60rem of the shell) | none | The bar's menu button opens the same nav in a drawer at the drawer's width; the stage goes edge to edge, 16 px sides |
78
+
79
+ | Body | Content width | Use |
80
+ | --- | --- | --- |
81
+ | `__body` (default) | Up to 1128, on the start edge | A page of sections, tiles and boards (North) |
82
+ | `__body--wide` | The body's full width | A Fia app page drawn at 1350 (Grow, Fixes, Inbox, Tally) |
51
83
 
52
84
  ## States
53
85
 
54
- - **Default**: a quiet row, navy words, no wash.
55
- - **Hover**: `--ws-sidebar-hover` under the pointer.
56
- - **Current**: the page's own row keeps the wash without the pointer (`aria-current="page"`).
57
- - **Needs you**: the salmon count chip on a row, same shape as the sidebar's badge.
58
- - **Folded**: labels and counts disappear; each mark keeps an `aria-label` so it stays reachable.
59
- - **Touch**: rows and the search box expand to the 40 px floor; the primary button is already `large` (36 px boxed, 48 px
60
- full width on a phone per the house rule for every submit and mobile CTA).
61
- - **Narrow stage**: below 768 px the nav becomes the phone pattern (a folded bar or a drawer, not drawn here); the top
62
- bar's search collapses to an icon button first.
86
+ - **Rest**: body-grey names, muted icons, no wash.
87
+ - **Hover** (pointers that hover): Seth's navy wash, `--ws-hover` (5%), on the row's 6 px corners.
88
+ - **Press**: `--ws-hover-strong` (6%). Rows never scale.
89
+ - **Current** (`aria-current="page"`, or `--current`): a white pill (`--color-surface`, 4 px corners, Seth's two soft
90
+ navy shades, a light rim in dark), the icon in salmon (a mark keeps Seth's coral) and the name at salmon's AA word
91
+ step, `--color-text-brand-strong` (D2). Hovering it changes nothing.
92
+ - **Focus**: the 2 px navy ring drawn inside the row (D8), so rows 2 apart never cut it. A body with nothing in it to
93
+ focus takes the keyboard itself (so it can be scrolled by keys); its ring is drawn inside it too, since the stage
94
+ clips anything outside.
95
+ - **Needs you**: the navy count pill. A bare number, its meaning in `.ws-sr` words inside it ("7 waiting"), never
96
+ `aria-label` on the span (ARIA does not let a plain span carry a label).
97
+ - **Long name**: truncates on one line, the full name in `title`.
98
+ - **Folded**: only the icons show, so every row carries its name (and its count, "Pipeline, 7 waiting") in `title`;
99
+ in React, a `Tooltip` on hover and focus.
100
+ - **Many rows**: the groups scroll; the head and the person stay. In 0.4 markup (no `__groups`) the nav scrolls and the
101
+ wordmark and the person stick to its ends, on the frame's wash.
102
+ - **Scrolled**: `__bar--scrolled` shows the bar's 0.5 px edge. Set it from the body's scroll:
103
+ `body.onscroll = () => bar.classList.toggle('ws-app-shell__bar--scrolled', body.scrollTop > 0)`.
104
+ - **Loading**: the body holds `.ws-shimmer` ghosts the size of what is coming, with `aria-busy="true"` and a
105
+ `<span class="ws-sr" role="status">` saying what is loading (never `aria-label` on the body's `div`); the nav and
106
+ bar stay.
107
+ - **Phone**: see Variants. On a phone keep the bar to one line: the page's name, at most two icon acts. The search
108
+ box goes; give the bar a search icon act or put the search at the top of the drawer. With `viewport-fit=cover` the
109
+ bar keeps clear of the notch and the body's foot clear of the home bar (`env(safe-area-inset-*)`), as the sides do.
63
110
 
64
111
  ## Behaviour
65
112
 
66
- - Keyboard: every row is a real link or button in document order; the current page is `aria-current="page"`, not colour
67
- alone.
68
- - Pointer: hover washes the row under the pointer; nothing opens on hover alone (no flyouts from this shell).
69
- - Motion: the current row's wash can glide between rows on `--ws-ease-soft` as in `Sidebar`, or simply be present; the
70
- fold trades width over `--ws-duration-settle`. Reduced motion: both land without animating.
71
- - Touch: 40 px floor on every boxed control, 24 px on a word-only act, same as every other control in the system.
113
+ - Keyboard: rows are links in document order; the fold button carries `aria-expanded` and toggles `--folded` on the
114
+ shell. The phone's drawer is a `Dialog` (`ws-dialog--drawer`) holding the same `__nav` markup; the head's button
115
+ becomes its close.
116
+ - Pointer: hover only tints. Nothing opens on hover.
117
+ - Motion (North): the fold trades width over `--ws-duration-shift` on `--ws-ease-shift`; the rows, the current pill
118
+ and the fold button ride the nav's edge as it moves (nothing jumps to the middle and back), names fade over
119
+ `--ws-duration-hover`, washes ease in over 200 ms, the bar's edge over `--ws-duration-settle`. The current pill
120
+ slides to the new page's row, across groups (North's "Sidebar active row slide", `springs.nav` .4 / .1), plain CSS
121
+ with no script and no new markup: the current row is a CSS anchor and the rows' scroller (`__groups`, or a 0.4 nav
122
+ that holds its rows) draws the travelling pill in its `::before`, under the rows and the group names, its four edges
123
+ easing on motion's own `spring(.4, .1)` written out as `linear()` (550 ms; `--ws-spring-nav-duration` and `--ws-spring-nav`). At rest the current row paints its own pill (the 0.4 look); while the rows are pointed at
124
+ or hold focus the travelling pill takes its place, so a page chosen then (an app that routes without a reload)
125
+ slides. The fold and a resize carry the pill with its row at once. Without CSS anchor positioning the pill moves at
126
+ once; the 0.4 rail's marks stay put. The hover wash growing from the pointer (Seth's 18 px seed) is not drawn yet.
127
+ Reduced motion: everything lands at once. Try it in the preview: click a row.
128
+ - Touch: rows and the menu button grow to the 40 px floor (K10).
129
+ - Nothing inside the stage is trapped by its glass: the blur is drawn by a layer under the content (`::before`), not by
130
+ the stage, because an element with a `backdrop-filter` becomes the box of every `position: fixed` thing inside it. So
131
+ a toaster, a phone's full-screen `Panel` or anything the app fixes to the window reaches the window from inside the
132
+ stage; menus, popovers and dialogs sit in the top layer, a full-screen chat card is lifted there by `morph()`, and a
133
+ tooltip is anchored to the window. The stage still clips what is inside it to its 16 px corners.
134
+ - The shell owns the scroll (K1, K2): only the body and the groups scroll; nothing in them is squashed.
72
135
 
73
136
  ## Content
74
137
 
75
- - A group's eyebrow names the kind of page ("Work", "Reports"), uppercase, two words at most.
76
- - A row's name is the page's own name, sentence case, truncated rather than wrapped.
77
- - The top bar's title repeats the current page's name exactly, once: the row does not repeat it below.
138
+ - A group's name says what kind of page it holds ("Reports"), sentence case, two words at most. The first group can
139
+ go without one.
140
+ - A row's name is the page's own name, sentence case.
141
+ - The bar names the page once, exactly as its row does; no second heading repeats it in the body.
78
142
  - No em dashes; a count is a bare number.
79
143
 
80
144
  ## Props
81
145
 
82
146
  | Name | Type | Meaning |
83
147
  | --- | --- | --- |
84
- | `groups` | `{ eyebrow: string; items: NavRow[] }[]` | The nav's sections, in order |
85
- | `NavRow` | `{ label, icon, href, current?, count? }` | One row: its words, its 20 px icon, whether it is the current page, its count chip |
86
- | `person` | `{ name, role, initials }` | The foot block |
87
- | `folded` | `boolean` | Shows the 72 px rail instead of the 232 px nav |
88
- | `title` | `string` | The top bar's page name |
89
- | `search` | `{ placeholder, onSearch }` | The top bar's search box |
90
- | `primaryAction` | `{ label, onClick }` | The top bar's one `primary`, `large` button |
148
+ | `groups` | `{ name?: string; items: NavRow[] }[]` | The nav's groups, in order |
149
+ | `NavRow` | `{ label, icon, href, current?, count? }` | One row: its words, its 16 px icon, whether it is the current page, its count |
150
+ | `person` | `{ name, role, initials }` | The foot |
151
+ | `folded` | `boolean` | The 64 px rail |
152
+ | `bar` | `ReactNode` | The bar's content: a title, a `Breadcrumb` or a `PageBar`, and its acts |
153
+ | `wash` | `boolean` | The cream stage instead of glass |
91
154
 
92
155
  ## Rules
93
156
 
94
- - **One navy button per page**: the top bar's primary act is the page's one navy button; a row or the stage's own cards
95
- never add a second (desk-rules §1).
96
- - **The gutter is the canvas's**: the stage pads its own content at 24 px; a page placed inside never adds its own side
97
- margin (space-and-layout.md, "A page never adds its own padding inside the canvas").
98
- - **Groups, not a flat list**: once destinations exceed about five, they fall under an eyebrow rather than running
99
- together, the same proximity rule as any group of rows (space-and-layout.md, "Grouping").
100
- - **One navy button per page** and the shared gutters and header height carry over unchanged from a chat-first shell
101
- to a page-based one.
102
- - The brand kit has no shell, nav or top bar of its own to diverge from; this piece is assembled entirely from the
103
- shared sizing, colour and spacing tokens.
157
+ - **One navy button per page**: the bar's primary is the page's one; nothing in the body adds a second.
158
+ - **The body is the page**: it brings the 32 px gutter; a page inside never adds its own padding or a `.ws-page`.
159
+ - **The person never scrolls away** and the head never moves: only the groups scroll (K11).
160
+ - **Real links, `aria-current="page"`**: never a clickable `<li>`, never colour alone.
161
+ - **Seth's tokens only**: no raw colour, size or corner; dark comes from the tokens (D12).
104
162
 
105
163
  ## Source
106
164
 
107
- **Derived from**: a chat-first shell's nav row (32 px row, sliding current wash, salmon count badge), its stage
108
- gutters and header height, and the one-navy-button-per-page rule, adapted from a chat-first shell to a page-based one.
109
- **Precedent**: an intentional addition decided from the system, 26 Oct 2026 (the first product built on the system is
110
- chat-first and never needed this shell).
165
+ **Derived from**: Seth's North app (`style1.css` 22 to 112, 531 to 560; the 232 px sidebar, its 28 px rows, rules,
166
+ navy count, white current pill, the 64 px rail, the glass stage and the frame), the Fia frames' 56 px thread header and
167
+ 32 px gutter (D4), and Revenue OS faults K1, K2, K3, K11 and K12. **Precedent**: kit 0.4's AppShell, upgraded in place
168
+ 4 Nov 2026 (the 0.4 markup still draws).
169
+
170
+ ## Markup
171
+
172
+ ```html
173
+ <div class="ws-app-shell">
174
+ <nav class="ws-app-shell__nav" aria-label="Main">
175
+ <div class="ws-app-shell__head">
176
+ <span class="ws-app-shell__wordmark">Fello</span>
177
+ <button type="button" class="ws-icon-btn" aria-label="Fold the menu" aria-expanded="true">
178
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2.5" width="12" height="11" rx="2"/><path d="M6 2.5v11"/></svg>
179
+ </button>
180
+ </div>
181
+ <div class="ws-app-shell__groups">
182
+ <div class="ws-app-shell__group">
183
+ <ul class="ws-app-shell__rows">
184
+ <li><a href="/pipeline" class="ws-app-shell__row" aria-current="page">
185
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="12" height="10" rx="1.5"/><path d="M2 6.5h12"/></svg>
186
+ <span class="ws-app-shell__name">Pipeline</span>
187
+ <span class="ws-app-shell__count">7<span class="ws-sr"> waiting</span></span>
188
+ </a></li>
189
+ </ul>
190
+ </div>
191
+ <div class="ws-app-shell__group">
192
+ <h2 class="ws-app-shell__eyebrow">Reports</h2>
193
+ <ul class="ws-app-shell__rows">
194
+ <li><a href="/performance" class="ws-app-shell__row">
195
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13V8M8 13V3M13 13V9.5"/></svg>
196
+ <span class="ws-app-shell__name">Performance</span>
197
+ </a></li>
198
+ </ul>
199
+ </div>
200
+ </div>
201
+ <div class="ws-app-shell__foot">
202
+ <span class="ws-avatar ws-avatar--sm ws-avatar--plain">PN</span>
203
+ <span class="ws-app-shell__foot-words">
204
+ <span class="ws-app-shell__foot-name">Priya Nair</span>
205
+ <span class="ws-muted">Team lead</span>
206
+ </span>
207
+ </div>
208
+ </nav>
209
+ <div class="ws-app-shell__stage">
210
+ <header class="ws-app-shell__bar">
211
+ <button type="button" class="ws-icon-btn ws-app-shell__menu" aria-label="Open the menu">
212
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M2.5 4.5h11M2.5 8h11M2.5 11.5h11"/></svg>
213
+ </button>
214
+ <h1 class="ws-app-shell__title">Pipeline</h1>
215
+ <div class="ws-app-shell__acts">
216
+ <label class="ws-app-shell__search">
217
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><circle cx="6.8" cy="6.8" r="3.8"/><path d="M9.7 9.7l3.6 3.6"/></svg>
218
+ <input type="search" placeholder="Search leads" aria-label="Search leads">
219
+ </label>
220
+ <button type="button" class="ws-btn ws-btn--primary">Add a lead</button>
221
+ </div>
222
+ </header>
223
+ <main class="ws-app-shell__body">
224
+ <!-- the page: sections, tiles, a board, a Split -->
225
+ </main>
226
+ </div>
227
+ </div>
228
+ ```
229
+
230
+ ## Styles
231
+
232
+ `AppShell/style.css`, with `IconButton`, `Button` and `Avatar` for the bar's acts and the person (`ws-muted` is the
233
+ house's). Tokens: `--ws-frame`,
234
+ `--ws-glass`, `--ws-glass-blur`, `--ws-stage-wash`, `--ws-edge-stage`, `--ws-stage-inset-top`, `--ws-stage-inset`,
235
+ `--ws-sidebar-width`, `--ws-header-h`, `--ws-control-h-sm`, `--ws-touch`, `--ws-field`, `--ws-field-ink`,
236
+ `--ws-focus-width`, `--ws-focus-color`, `--ws-focus-offset`, `--ws-radius-row`, `--ws-radius-control`,
237
+ `--ws-radius-panel`, `--ws-hover`, `--ws-hover-strong`, `--ws-float-rim`, `--ws-shade`, `--ws-ink`,
238
+ `--color-surface`, `--color-text-brand-strong`, `--ws-chart-under-half`, `--ws-on-act`, `--ws-edge-card`,
239
+ `--ws-hairline`, `--ws-chart-card-w`, `--ws-gap-component`, `--ws-gap-group`, `--ws-text-value`, `--ws-duration-shift`, `--ws-ease-shift`. The shell sets `--ws-gutter` to `--space-xl` (32)
240
+ for everything inside it.