@felloinnovations/brand-kit 0.4.0 → 0.5.1

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 +221 -0
  3. package/README.md +38 -9
  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 +135 -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 +367 -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 +53 -16
  249. package/design-system/components/Skeleton/preview.html +35 -23
  250. package/design-system/components/Skeleton/style.css +17 -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 +4086 -744
  335. package/design-system/tokens.json +1310 -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 +109 -10
  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 +173 -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 +1287 -62
  361. package/tokens/tokens.md +587 -61
  362. package/tokens/tokens.root.css +1293 -62
  363. package/tokens/tokens.ts +1677 -64
@@ -0,0 +1,74 @@
1
+ /* ---- Dialog: the native <dialog>, a cream pane in a 1 px tray rim over the navy scrim; --drawer floats in from the right edge ---- */
2
+ /* The pane (D5, Seth's check drawer 301:2011): the tray rim, 12 px corners (11 inside), the raised ground and one
3
+ floating lift, since it sits over a scrim. Every part sits 28 in from the sides, the band's own inset, so the title,
4
+ the content and the foot share one edge. It never grows past the window (K4): the head and the foot stay, the
5
+ content between them scrolls. Nothing is clipped (K9), so the foot rounds its own corners.
6
+ A plate, a well or a hover inside sits half a step above the pane (raised to press): the house sunk exactly in light,
7
+ and still seen in dark, where the page's sunk is the pane's own raised. The house points --ws-surface-sunk at --ws-raised-sunk here. */
8
+ .ws-dialog { --ws-dialog-inset: var(--ws-band-inset); display: flex; flex-direction: column; width: calc(100% - var(--space-xl)); max-width: 42rem; /* raw: Ignite's Dialog cap (max-w-2xl); no width token */ max-height: calc(100dvh - var(--space-xl)); padding: 0; overflow: visible; border: var(--ws-rim) solid var(--ws-tray); border-radius: var(--ws-radius-drawer); background: var(--ws-raised); color: var(--color-text-body); box-shadow: var(--ws-shadow-float); }
9
+ dialog.ws-dialog:not([open]) { display: none; }
10
+ .ws-dialog::backdrop { background: var(--ws-scrim); }
11
+ /* The compact head (K6): one title, at most one line under it, the close and at most two icon acts. Facts, chips and
12
+ buttons go in the content. It never wraps (a card's head drops its aside under a short title; here the close stays
13
+ top right and the title wraps beside it). The close is Seth's 32 px tray square, centred on the title's first line
14
+ (on its letters, which sit a hairline above the 28 px line's middle). Doubled class: IconButton's transparent
15
+ ground comes later in the bundle and would win. */
16
+ .ws-dialog > .ws-head { flex-wrap: nowrap; gap: var(--space-sm); padding: var(--ws-card-inset) var(--ws-dialog-inset) var(--space-md); }
17
+ /* A head with no content after it (a confirm) keeps the 20 the content leaves above the foot. */
18
+ .ws-dialog > .ws-head:has(+ .ws-band) { padding-bottom: var(--ws-card-inset); }
19
+ .ws-dialog > .ws-head > div { gap: var(--space-xxs); min-width: 0; }
20
+ .ws-icon-btn.ws-dialog__close { --ws-dialog-close: var(--ws-control-h); margin-block: calc((var(--ws-leading-title) - var(--ws-dialog-close)) / 2 - var(--ws-hairline)) calc((var(--ws-leading-title) - var(--ws-dialog-close)) / 2 + var(--ws-hairline)); border-radius: var(--ws-radius-row); background-color: var(--ws-tray); color: var(--color-text-heading); }
21
+ @media (hover: hover) { .ws-icon-btn.ws-dialog__close:hover { background-color: var(--ws-well-hover); } }
22
+ @media (pointer: coarse) { .ws-icon-btn.ws-dialog__close { --ws-dialog-close: var(--ws-touch); } }
23
+ /* The content scrolls on its own (K4) and holds its parts 16 apart. 4 px on top keeps a first field's focus ring. It runs
24
+ the pane's full width, so its own focus ring (a keyboard scroller) is drawn inside it, never over the rim (D8). */
25
+ .ws-dialog__content { display: flex; flex: 1 1 auto; flex-direction: column; gap: var(--space-md); min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: var(--space-xxs) var(--ws-dialog-inset) var(--ws-card-inset); }
26
+ .ws-dialog__content:focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
27
+ .ws-dialog > .ws-band { border-bottom-left-radius: var(--ws-radius-drawer-inner); border-bottom-right-radius: var(--ws-radius-drawer-inner); }
28
+ /* The foot's buttons as one group, right of its note: they wrap together, the one primary last. On a phone they fill
29
+ the width in equal halves, and stack, the primary at the bottom, where a half would be under 160 or a label would
30
+ break (Seth's pane foot, 301:2099, the same rule as Button's ws-btn-split). */
31
+ .ws-dialog__acts { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-left: auto; }
32
+ @media (max-width: 40rem) { .ws-dialog__acts { flex: 1 1 100%; } .ws-dialog__acts > * { flex: 1 1 var(--space-8xl); min-width: min(100%, max-content); } }
33
+ /* A short window or a phone (K6): the whole pane scrolls as one, only the head stays, so the content gets the screen
34
+ even when a head holds more than its title. The content still grows into a drawer's height, so its foot stays at
35
+ the bottom instead of floating under a short content. */
36
+ @media (max-height: 40rem), (max-width: 40rem) {
37
+ .ws-dialog { overflow-y: auto; overscroll-behavior: contain; }
38
+ .ws-dialog__content { flex: 1 0 auto; overflow: visible; }
39
+ .ws-dialog > .ws-head { position: sticky; top: 0; z-index: 1; border-radius: var(--ws-radius-drawer-inner) var(--ws-radius-drawer-inner) 0 0; background: var(--ws-raised); }
40
+ }
41
+ /* The drawer (K5): 440 wide, floating 12 in from the window's edges with the stage's corners; under 40rem it is the
42
+ whole screen. --start comes from the left edge. */
43
+ .ws-dialog--drawer { width: min(calc(100% - var(--ws-stage-inset) * 2), var(--ws-thing-width)); max-width: none; height: calc(100% - var(--ws-stage-inset) * 2); max-height: calc(100dvh - var(--ws-stage-inset) * 2); margin: var(--ws-stage-inset) var(--ws-stage-inset) var(--ws-stage-inset) auto; }
44
+ .ws-dialog--drawer-start { margin: var(--ws-stage-inset) auto var(--ws-stage-inset) var(--ws-stage-inset); }
45
+ @media (max-width: 40rem) {
46
+ .ws-dialog--drawer { width: 100%; height: 100%; max-height: 100dvh; margin: 0; border: 0; border-radius: 0; }
47
+ .ws-dialog--drawer > :is(.ws-head, .ws-band) { border-radius: 0; }
48
+ }
49
+ /* Motion (D7, North's window, js@540954): it grows 14 px up out of .98 on the settle spring (.32 / .1) as the scrim fades
50
+ in over .2 s, then its details settle in after it ("opens grow from their slot, then details settle": the head, the
51
+ content and the foot rise 6 px out of a 3 px blur over .32 s soft, .08 s after it and 22 ms apart, as North's opened
52
+ tile's details). It leaves faster and shorter: 8 px down to .98 over .12 s. A drawer slides in from its edge on the
53
+ grow curve over .55 s ("Card grows open") and goes back over .4 s ("Card closes back into place"). Native <dialog>
54
+ only: @starting-style for the entrance, display and overlay allow-discrete so the exit plays. With reduced motion it
55
+ simply appears and goes. */
56
+ dialog.ws-dialog { --ws-dialog-after: 80ms; /* raw: North's details wait .08 s (open.content delay) */ }
57
+ @media (prefers-reduced-motion: no-preference) {
58
+ dialog.ws-dialog, dialog.ws-dialog::backdrop { transition: opacity var(--ws-duration-exit) var(--ws-ease-exit), transform var(--ws-duration-exit) var(--ws-ease-exit), overlay var(--ws-duration-exit) var(--ws-ease-exit) allow-discrete, display var(--ws-duration-exit) var(--ws-ease-exit) allow-discrete; }
59
+ dialog.ws-dialog:not([open]) { opacity: 0; transform: translateY(var(--space-xs)) scale(var(--ws-open-scale-pane)); }
60
+ dialog.ws-dialog:not([open])::backdrop { opacity: 0; }
61
+ dialog.ws-dialog[open] { transition: opacity var(--ws-spring-settle-duration) var(--ws-spring-settle), transform var(--ws-spring-settle-duration) var(--ws-spring-settle), overlay 0s allow-discrete, display 0s allow-discrete; }
62
+ dialog.ws-dialog[open]::backdrop { transition: opacity var(--ws-duration-hover) var(--ws-ease-soft), overlay 0s allow-discrete, display 0s allow-discrete; }
63
+ dialog.ws-dialog--drawer[open] { transition: opacity var(--ws-duration-grow) var(--ws-ease-grow), transform var(--ws-duration-grow) var(--ws-ease-grow), overlay 0s allow-discrete, display 0s allow-discrete; }
64
+ dialog.ws-dialog--drawer:not([open]) { transform: translateX(calc(100% + var(--ws-stage-inset))); transition-duration: var(--ws-duration-shrink); transition-timing-function: var(--ws-ease-grow); }
65
+ dialog.ws-dialog--drawer-start:not([open]) { transform: translateX(calc(-100% - var(--ws-stage-inset))); }
66
+ dialog.ws-dialog[open] > * { animation: ws-settle var(--ws-duration-settle) var(--ws-ease-soft) var(--ws-dialog-after) backwards; }
67
+ @supports (animation-delay: calc(sibling-index() * 1ms)) { dialog.ws-dialog[open] > * { animation-delay: calc(var(--ws-dialog-after) + (sibling-index() - 1) * var(--ws-stagger-detail)); } }
68
+ @starting-style {
69
+ dialog.ws-dialog[open] { opacity: 0; transform: translateY(var(--space-sm-plus)) scale(var(--ws-open-scale-pane)); }
70
+ dialog.ws-dialog--drawer[open] { transform: translateX(calc(100% + var(--ws-stage-inset))); }
71
+ dialog.ws-dialog--drawer-start[open] { transform: translateX(calc(-100% - var(--ws-stage-inset))); }
72
+ dialog.ws-dialog[open]::backdrop { opacity: 0; }
73
+ }
74
+ }
@@ -1,9 +1,9 @@
1
- Nothing here yet: the same card the place would show, with its mark on the dots and the one act that fills it.
1
+ Nothing here yet: the same plain cream card the place would show, with its mark and the one act that fills it.
2
2
 
3
3
  ## Use it when
4
4
 
5
5
  - A page or a panel has no data yet for a reason the person can act on (nothing connected, nothing created, no matches).
6
- - An app's first screen should introduce itself before there is anything real to show (the app's own face, still, on the dots).
6
+ - An app's first screen should introduce itself before there is anything real to show (the app's own face, still, on the plain card).
7
7
  - A filtered list comes back with nothing: say so, and offer the one way to see something again.
8
8
 
9
9
  ## Not for
@@ -14,11 +14,14 @@ Nothing here yet: the same card the place would show, with its mark on the dots
14
14
 
15
15
  ## Anatomy
16
16
 
17
- - The same `Card`, on the dotted field (`chartDots`), centred text, `--space-md` side padding and `--space-2xl` top padding.
18
- - Its mark: an icon on a cream disc (`--radius-full`, the hairline shadow, `--color-text-heading` icon at `--space-md`, 16 px); a first-run introduction uses a smaller, plain 24 px `ws-disc` and line icon instead, standing in for an app's own illustration.
19
- - A 16 px semibold navy title (`--ws-text-value`, `ws-tracking-title`).
20
- - One sentence under it, `max-w-md`, body grey-7.
21
- - An optional action underneath, with `--space-xxs` of its own top padding.
17
+ - The same `Card` (the tray rim round the cream), plain cream with no dots (the dotted field is a chart's ground
18
+ only, owner's ruling of 2 Nov), centred text, 40 px above
19
+ (`--space-2xl`), 16 px at the sides and under, its parts 8 px apart.
20
+ - Its mark: an icon on a cream disc (`--radius-full`, the hairline shadow, `--color-text-heading` icon at `--space-md`, 16 px); a first-run introduction uses a smaller, plain 24 px disc on the sunk cream (`ws-empty-state__mark--intro`, a 12 px line icon, no shadow) instead, standing in for an app's own illustration.
21
+ - A 15 / 22 semibold navy title (`ws-section`, Seth's section title).
22
+ - One sentence under it, 14 / 20 in `--color-text-body`, at most 260 px wide.
23
+ - The act in the card's band (`ws-band`, its buttons in `ws-band__acts`); in a card under 26rem the act takes the
24
+ band's whole line.
22
25
 
23
26
  ## Variants and sizes
24
27
 
@@ -32,14 +35,18 @@ Nothing here yet: the same card the place would show, with its mark on the dots
32
35
  - **First use**: the small intro disc, a welcoming title, the one act that starts things.
33
36
  - **No matches**: a search or filter icon, a title naming what did not match, an act that clears the filter.
34
37
  - **Unavailable data**: an icon naming what is missing, a title that says what is not connected, an act that connects it.
35
- - **With an action**: the act sits under the sentence, its own small gap above it.
38
+ - **With an action**: the act sits in the band, at its end on a wide card, across the whole band on a narrow one.
36
39
  - **Without an action**: the card ends after the sentence; nothing is invented to fill the space.
40
+ - **Long title**: it wraps, centred; nothing is cut off.
41
+ - **Loading**: not an empty state. Use `Skeleton` until the answer arrives.
42
+ - **Dark**: the card and the disc follow the theme.
37
43
 
38
44
  ## Behaviour
39
45
 
40
46
  - Keyboard: its title is a real heading (`h2`), so the empty card is reachable like any other section; its action, if given, is a normal button or link.
41
47
  - Pointer and touch: only the action (if any) is interactive; the rest of the card is static.
42
- - Motion: the whole card rises in (`ws-rise`, `--ws-duration-settle` on `--ws-ease-soft`) like any other arriving card.
48
+ - Motion: the whole card settles in (`ws-settle`: 6 px, out of a 3 px blur, `--ws-duration-settle`) like any other
49
+ arriving card.
43
50
  - Reduced motion: it appears in place without rising.
44
51
 
45
52
  ## Content
@@ -60,13 +67,15 @@ Nothing here yet: the same card the place would show, with its mark on the dots
60
67
 
61
68
  ## Rules
62
69
 
63
- - "An empty state is the same card with the place's mark on the dots and the act that fills it in the band" (the system's own pattern).
70
+ - An empty state is the same plain cream card with the place's mark and the act that fills it in the band; the dots
71
+ are a chart's ground only, never an empty state's (owner, 2 Nov; logged in 17-decisions).
64
72
  - A card whose data does not exist is left out, never faked: `EmptyState` is for "there is an answer, and it is nothing you can act on yet", never a stand-in for data that will never come.
65
- - The same dots, the same card edge, the same title size as every other chart card: an empty state never looks like a different kind of surface.
73
+ - The same card rim, the same cream, the same title as every other card: an empty state never looks like a different
74
+ kind of surface.
66
75
 
67
76
  ## Source
68
77
 
69
- **Derived from**: the card system's dotted-field pattern, generalized so a plain 24 px disc and line icon stand in
78
+ **Derived from**: the card system's empty-state pattern (once drawn on the dotted field, now a plain card), generalized so a plain 24 px disc and line icon stand in
70
79
  for an app's own illustration rather than requiring one. **Precedent**: the first product built on the system (its
71
80
  own first-run screen used an agent's face image in this slot).
72
81
 
@@ -74,3 +83,24 @@ own first-run screen used an agent's face image in this slot).
74
83
  band" (the card's footer band, with its 28 px sides and inset shade). The reference implementation has no footer
75
84
  band at all: its action is a plain centred slot directly under the sentence. This preview follows the documented
76
85
  band rule; the component as built does not currently draw one.
86
+
87
+ ## Markup
88
+
89
+ ```html
90
+ <div class="ws-card">
91
+ <div class="ws-empty-state__body">
92
+ <span class="ws-empty-state__mark" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><circle cx="7" cy="7" r="4.5" stroke="currentColor" stroke-width="1.5"/><path d="M13 13l-2.5-2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span>
93
+ <h2 class="ws-section">No leads match</h2>
94
+ <p class="ws-body ws-empty-state__words">Try a different stage or clear the filter.</p>
95
+ </div>
96
+ <footer class="ws-band">
97
+ <div class="ws-band__words"><p class="ws-band__title">Clear the filter</p></div>
98
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Clear</button></div>
99
+ </footer>
100
+ </div>
101
+ ```
102
+
103
+ ## Styles
104
+
105
+ `EmptyState/style.css` (the body and the mark); the card and the band are `Card` and the house. Tokens:
106
+ `--space-2xl`, `--space-md`, `--space-xl`, `--ws-shadow-hairline`, `--ws-surface-sunk`, `--color-text-heading`.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Cards" height=596 -->
1
+ <!-- @dsCard group="Cards" height=352 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -8,11 +8,11 @@
8
8
  <link rel="stylesheet" href="../bundle.css">
9
9
  </head>
10
10
  <body>
11
- <div class="ws-stage ws-stage--grey">
11
+ <div class="ws-stage">
12
12
 
13
- <div class="ws-stack" style="min-width: 300px;">
13
+ <div class="ws-stack" style="width: 340px;">
14
14
  <span class="ws-muted">First use: an introduction, a plain disc and icon standing in for the app's own mark</span>
15
- <div class="ws-card ws-dots">
15
+ <div class="ws-card">
16
16
  <div class="ws-empty-state__body">
17
17
  <span class="ws-empty-state__mark ws-empty-state__mark--intro" aria-hidden="true">
18
18
  <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4.5h10a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H7l-2.5 2v-2H3a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1z"/></svg>
@@ -25,14 +25,14 @@
25
25
  <p class="ws-band__title">Start your first call</p>
26
26
  <p class="ws-band__how">The assistant lines up who to call next</p>
27
27
  </div>
28
- <button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Start</button>
28
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Start</button></div>
29
29
  </footer>
30
30
  </div>
31
31
  </div>
32
32
 
33
- <div class="ws-stack" style="min-width: 300px;">
33
+ <div class="ws-stack" style="width: 340px;">
34
34
  <span class="ws-muted">No matches</span>
35
- <div class="ws-card ws-dots">
35
+ <div class="ws-card">
36
36
  <div class="ws-empty-state__body">
37
37
  <span class="ws-empty-state__mark" aria-hidden="true">
38
38
  <svg viewBox="0 0 16 16" fill="none"><circle cx="7" cy="7" r="4.5" stroke="currentColor" stroke-width="1.5"/><path d="M13 13l-2.5-2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -44,14 +44,14 @@
44
44
  <div class="ws-band__words">
45
45
  <p class="ws-band__title">Clear the filter</p>
46
46
  </div>
47
- <button type="button" class="ws-btn ws-btn--secondary">Clear</button>
47
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Clear</button></div>
48
48
  </footer>
49
49
  </div>
50
50
  </div>
51
51
 
52
- <div class="ws-stack" style="min-width: 300px;">
52
+ <div class="ws-stack" style="width: 340px;">
53
53
  <span class="ws-muted">Unavailable data: left out, never faked, except where its own act still fits the band</span>
54
- <div class="ws-card ws-dots">
54
+ <div class="ws-card">
55
55
  <div class="ws-empty-state__body">
56
56
  <span class="ws-empty-state__mark" aria-hidden="true">
57
57
  <svg viewBox="0 0 16 16" fill="none"><path d="M8 2l6 3.5v5L8 14l-6-3.5v-5L8 2z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M8 8v3M8 5.5v.01" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
@@ -63,7 +63,7 @@
63
63
  <div class="ws-band__words">
64
64
  <p class="ws-band__title">Connect your site</p>
65
65
  </div>
66
- <button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Connect</button>
66
+ <div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Connect</button></div>
67
67
  </footer>
68
68
  </div>
69
69
  </div>
@@ -0,0 +1,9 @@
1
+ /* ---- EmptyState: a plain cream card with a mark, a title, one sentence and the act in the band (the dots are a chart's ground only) ---- */
2
+ .ws-empty-state__body { display: flex; flex-direction: column; align-items: center; gap: var(--space-xs); padding: var(--space-2xl) var(--space-md) var(--space-md); text-align: center; }
3
+ /* The mark: an icon on a cream disc with the hairline; a first run uses the plain 24 px ws-disc instead (--intro). */
4
+ .ws-empty-state__mark { display: flex; width: var(--space-xl); height: var(--space-xl); align-items: center; justify-content: center; border-radius: var(--radius-full); background: var(--color-bg-page); box-shadow: var(--ws-shadow-hairline); }
5
+ .ws-empty-state__mark svg { width: var(--space-md); height: var(--space-md); color: var(--color-text-heading); }
6
+ .ws-empty-state__mark--intro { width: var(--space-lg); height: var(--space-lg); background: var(--ws-surface-sunk); box-shadow: none; }
7
+ .ws-empty-state__mark--intro svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
8
+ .ws-empty-state__words { max-width: calc(var(--space-9xl) + var(--space-4xl) - var(--space-xxs)); }
9
+
@@ -1,82 +1,107 @@
1
- The frame for every page before the product's main workspace: the wordmark top left, a centred column rising in, and on a wide
2
- window a grey panel beside it holding a sample of the product's own cards.
1
+ The frame for every page before the product's main workspace: the wordmark top left, a centred column, and on a wide
2
+ frame a grey panel beside it holding a sample of the product's own cards.
3
3
 
4
4
  ## Use it when
5
5
 
6
- - Sign-in, an invite, or any of the welcome steps need the product's frame before a person has a team or a chat
7
- to land in.
8
- - A status screen (an expired invite, a setup gate) needs the same quiet, centred frame.
6
+ - Sign-in, an invite, or any welcome step needs the product's frame before a person has a team or a chat to land in.
7
+ - A gate before the product (an expired invite, a setup step) needs the same quiet, centred frame.
9
8
 
10
9
  ## Not for
11
10
 
12
- - Anything inside the main workspace itself: once a person is signed in, `Workspace` and the sidebar take over: `EntryShell`
13
- never wraps a chat or an app page.
14
- - A dialog or a drawer: those float over the workspace; `EntryShell` is a whole page's own frame.
15
- - A page that needs the full window's width: the column is capped (`max-w-sm` by default, `max-w-xl` for a wider
16
- step), never edge to edge.
11
+ - Anything inside the workspace: once a person is signed in, `AppShell` (or the chat) takes over.
12
+ - A dialog or a drawer: those float over the workspace.
13
+ - A whole-page failure: `StatusScreen`.
17
14
 
18
15
  ## Anatomy
19
16
 
20
- - Wordmark: top left of the main column, plain navy text "Fello" at 16 px semibold (`--font-size-md`,
21
- `--color-text-heading`); no logo file exists for this system, so the column shows the name alone, no `href` since
22
- there is nowhere to link yet.
23
- - Centre: the column rises in (`ws-arrive`) and sits in the middle of the height, the sign-in form alone, no cast of
24
- faces above it.
25
- - Form: one card's worth of fields and the product's one large navy button, full width
26
- (`ws-btn--lg`, `--ws-control-h-md`, 36 px).
27
- - Aside (from a wide window only): a panel of the sidebar's own grey (`--ws-page`), `--ws-radius-panel` (16 px)
28
- corners, holding one or more sample cards, the first on its own, the rest a step lower and after it, each
29
- rising in on its own beat.
17
+ - The shell (`.ws-entry-shell`): a size container named `ws-entry-shell`. It fills its parent (K17): a parent with a
18
+ height (`min-height: 100%`), a flex column that has only a `min-height` (`flex: 1 0 auto`), or `--page` for the
19
+ window's (`100dvh`).
20
+ - Main (`__main`): the cream ground, 24 inside.
21
+ - Wordmark (`__wordmark`): "Fello" in navy, 16 / 24 semibold, top left, no link.
22
+ - Centre (`__center`): the column, centred both ways, 40 above and below.
23
+ - Form (`__form`): up to 320 wide (`--space-9xl` + `--space-7xl`), its parts 24 apart; the title (`__title`)
24
+ 24 / 32 semibold, centred; the field the large one, 36 tall (40 on touch); the one large navy button, full width.
25
+ - Aside (`__aside`): from 48rem of the shell's own width only. The grey (`--ws-page`), 16 px corners, 8 in from the
26
+ frame, 40 inside, centred, holding an eyebrow and sample cards (`__samples`, 16 apart; `__sample`, 16 inside, a label
27
+ in `ws-muted` over Seth's 32 / 38 tile figure, `__sample-figure`). It is `aria-hidden`.
30
28
 
31
29
  ## Variants and sizes
32
30
 
33
- | Width | Shows |
31
+ | Its own width | Shows |
34
32
  | --- | --- |
35
- | Narrow (no `preview`, or under `lg`) | The main column alone, centred in the full width |
36
- | Wide, with a `preview` | The main column capped, the grey aside beside it with its sample cards |
33
+ | Under 48rem | The main column alone, the form centred in it |
34
+ | 48rem and up, with an aside | The main column and the grey aside, each half, both the frame's full height |
37
35
 
38
36
  ## States
39
37
 
40
- - **Default**: as drawn above, the form ready for input.
41
- - **Rising in**: the whole centred column arrives with `ws-arrive`; the aside's cards rise in after it, each a
42
- beat later than the one before (`ws-rise`, staggered by `--ws-duration-instant` per card).
43
- - **Submitting**: the one button shows its own pending state (a working dot, disabled siblings): not drawn in
44
- this static preview; see `Button`'s `pending` prop.
45
- - **Narrow window**: the aside is hidden entirely (`hidden lg:flex`), never shrunk to fit beside the form.
38
+ - **Default**: the form ready for input.
39
+ - **Arriving**: the centre arrives (`ws-arrive`), the sample cards settle in after it (`ws-settle`, `--ws-i`).
40
+ - **Error**: the field's error under it (`ws-field-msg--error`, `aria-describedby`), the field's salmon edge.
41
+ - **Submitting**: the button's own pending state (see `Button`); nothing else moves.
42
+ - **Narrow**: the aside is left out, never squeezed beside the form.
46
43
 
47
44
  ## Behaviour
48
45
 
49
- - Keyboard: the email field and the one button are the whole tab order.
50
- - The frame scrolls itself on a standalone page (21 Oct 2026): a long welcome step is never cut off, unlike the
51
- workspace's own canvas, which never scrolls on its own.
52
- - Motion: everything here uses `--ws-ease-soft`; reduced motion lands every piece in place without rising.
53
- - The aside is `aria-hidden`: it is a picture of the product, nothing in it can be reached by keyboard or read by
54
- a screen reader.
46
+ - Keyboard: the field and the button are the whole tab order.
47
+ - The frame scrolls itself on a standalone page; a long step is never cut off.
48
+ - Motion on `--ws-ease-soft`; reduced motion lands every piece in place.
49
+ - The aside is a picture: hidden from screen readers, nothing in it to press.
55
50
 
56
51
  ## Content
57
52
 
58
- - The heading names the one act ("Sign in"), sentence case, no em dashes.
59
- - The button's words are the one act in full ("Continue"), never a bare "Submit" or "Go".
60
- - The aside's sample numbers are realistic but never real: "26 cold calls", not a live figure.
53
+ - The title names the one act ("Sign in"), sentence case.
54
+ - The button's words are the act in full ("Continue"), never "Submit".
55
+ - The aside's numbers are realistic but never real.
61
56
 
62
57
  ## Props
63
58
 
64
59
  | Name | Type | Meaning |
65
60
  | --- | --- | --- |
66
61
  | `children` | `ReactNode` | The page's own form or steps |
67
- | `preview` | `ReactNode[]` | Sample cards for the aside; its absence hides the aside entirely |
68
- | `note` | `string` | The aside's small eyebrow label |
69
- | `width` | `string` | The column's cap (`max-w-sm` default, `max-w-xl` for a longer step) |
62
+ | `preview` | `ReactNode[]` | Sample cards for the aside; without it there is no aside |
63
+ | `note` | `string` | The aside's eyebrow |
64
+ | `page` | `boolean` | Fills the window (`--page`) |
70
65
 
71
66
  ## Rules
72
67
 
73
- - **The preview is a picture of the product**, never real data: it is hidden from screen readers and holds
74
- nothing to press.
75
- - No microphone test step and no consent popup appear on any entry page (the system's rule); none is drawn here
76
- either.
68
+ - **The preview is a picture of the product**, never real data.
69
+ - No microphone test and no consent popup on any entry page.
77
70
 
78
71
  ## Source
79
72
 
80
- **Derived from**: the product's entry frame (the wordmark, the rising centred column, the grey aside previewing
81
- sample cards). **Precedent**: the first product built on the system (its own wordmark is a coloured mark and name;
82
- this system draws plain navy text instead, since no shared logo file exists).
73
+ **Derived from**: the product's entry frame (the wordmark, the centred column, the grey aside of samples), Seth's 32 /
74
+ 38 tile figure (D6) and Revenue OS fault K17 (the shell did not fill its frame: on Sign in the aside stopped at 780 in a
75
+ 900 window). **Precedent**: the first product built on the system.
76
+
77
+ ## Markup
78
+
79
+ ```html
80
+ <div class="ws-entry-shell ws-entry-shell--page">
81
+ <div class="ws-entry-shell__main">
82
+ <span class="ws-entry-shell__wordmark">Fello</span>
83
+ <div class="ws-entry-shell__center ws-arrive">
84
+ <form class="ws-entry-shell__form">
85
+ <h1 class="ws-entry-shell__title">Sign in</h1>
86
+ <div class="ws-field">
87
+ <label class="ws-label" for="email">Email</label>
88
+ <input class="ws-input" id="email" type="email" autocomplete="email">
89
+ </div>
90
+ <div class="ws-entry-shell__acts"><button type="submit" class="ws-btn ws-btn--primary ws-btn--lg">Continue</button></div>
91
+ </form>
92
+ </div>
93
+ </div>
94
+ <aside class="ws-entry-shell__aside" aria-hidden="true">
95
+ <p class="ws-eyebrow">What&rsquo;s waiting</p>
96
+ <div class="ws-entry-shell__samples">
97
+ <div class="ws-card ws-entry-shell__sample"><span class="ws-muted">Cold calls</span><span class="ws-entry-shell__sample-figure">26</span></div>
98
+ </div>
99
+ </aside>
100
+ </div>
101
+ ```
102
+
103
+ ## Styles
104
+
105
+ `EntryShell/style.css`, with `Input`, `Button` and `Card` for the field, the button and the samples. Tokens: `--ws-page`,
106
+ `--color-bg-page`, `--ws-radius-panel`, `--ws-control-h-md`, `--ws-text-figure`, `--ws-leading-figure`,
107
+ `--ws-tracking-display`, `--space-9xl`, `--space-7xl`, `--space-2xl`, `--space-lg`.
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Desk" height=488 -->
1
+ <!-- @dsCard group="Desk" height=984 -->
2
2
  <!doctype html>
3
3
  <html>
4
4
  <head>
@@ -8,37 +8,70 @@
8
8
  <link rel="stylesheet" href="../bundle.css">
9
9
  </head>
10
10
  <body>
11
- <div class="ws-stage" style="justify-content: center;">
12
- <div style="display: grid; width: 900px; max-width: 100%; min-height: 440px; border: var(--ws-hairline) solid var(--ws-edge-card); border-radius: var(--ws-radius-panel); overflow: hidden;"><div class="ws-entry-shell">
13
- <div class="ws-entry-shell__main">
14
- <span class="ws-entry-shell__wordmark">Fello</span>
15
- <div class="ws-entry-shell__center">
16
- <form class="ws-entry-shell__form" onsubmit="return false;">
17
- <h1 class="ws-entry-shell__title">Sign in</h1>
18
- <div class="ws-field">
19
- <label class="ws-label" for="es-email">Email</label>
20
- <input class="ws-input" id="es-email" type="email" placeholder="ryan@theyoungteam.example" autocomplete="email">
11
+ <div class="ws-stage ws-stage--column" style="align-items: center;">
12
+
13
+ <div class="ws-stack" style="width: 900px; max-width: 100%;">
14
+ <span class="ws-muted">From 48rem of its own width: the form centred in its column, the grey aside of samples beside it, both the frame's full height</span>
15
+ <div style="display: grid; min-height: 440px; border-radius: var(--ws-radius-panel); overflow: hidden; box-shadow: var(--ws-shadow-hairline);"><div class="ws-entry-shell">
16
+ <div class="ws-entry-shell__main">
17
+ <span class="ws-entry-shell__wordmark">Fello</span>
18
+ <div class="ws-entry-shell__center ws-arrive">
19
+ <form class="ws-entry-shell__form" onsubmit="return false;">
20
+ <h1 class="ws-entry-shell__title">Sign in</h1>
21
+ <div class="ws-field">
22
+ <label class="ws-label" for="es-email">Email</label>
23
+ <input class="ws-input" id="es-email" type="email" placeholder="ryan@theyoungteam.example" autocomplete="email">
24
+ </div>
25
+ <div class="ws-entry-shell__acts">
26
+ <button type="submit" class="ws-btn ws-btn--primary ws-btn--lg">Continue</button>
27
+ </div>
28
+ </form>
29
+ </div>
30
+ </div>
31
+ <aside class="ws-entry-shell__aside" aria-hidden="true">
32
+ <p class="ws-eyebrow">What&rsquo;s waiting</p>
33
+ <div class="ws-entry-shell__samples">
34
+ <div class="ws-card ws-entry-shell__sample ws-settle" style="--ws-i: 1;">
35
+ <span class="ws-muted">Cold calls</span>
36
+ <span class="ws-entry-shell__sample-figure">26</span>
21
37
  </div>
22
- <div class="ws-entry-shell__acts">
23
- <button type="submit" class="ws-btn ws-btn--primary ws-btn--lg">Continue</button>
38
+ <div class="ws-card ws-entry-shell__sample ws-settle" style="--ws-i: 2;">
39
+ <span class="ws-muted">New leads</span>
40
+ <span class="ws-entry-shell__sample-figure">4</span>
24
41
  </div>
25
- </form>
26
- </div>
27
- </div>
28
- <aside class="ws-entry-shell__aside" aria-hidden="true">
29
- <p class="ws-eyebrow">What&rsquo;s waiting</p>
30
- <div class="ws-entry-shell__samples">
31
- <div class="ws-card ws-entry-shell__sample ws-rise">
32
- <span class="ws-muted">Cold calls</span>
33
- <span class="ws-entry-shell__sample-figure">26</span>
34
42
  </div>
35
- <div class="ws-card ws-entry-shell__sample ws-rise" style="animation-delay: var(--ws-stagger);">
36
- <span class="ws-muted">New leads</span>
37
- <span class="ws-entry-shell__sample-figure">4</span>
43
+ </aside>
44
+ </div></div>
45
+ </div>
46
+
47
+ <div class="ws-stack" style="width: 560px; max-width: 100%;">
48
+ <span class="ws-muted">Under 48rem: the form alone, the aside left out rather than squeezed; an error under the field</span>
49
+ <div style="display: grid; min-height: 440px; border-radius: var(--ws-radius-panel); overflow: hidden; box-shadow: var(--ws-shadow-hairline);"><div class="ws-entry-shell">
50
+ <div class="ws-entry-shell__main">
51
+ <span class="ws-entry-shell__wordmark">Fello</span>
52
+ <div class="ws-entry-shell__center">
53
+ <form class="ws-entry-shell__form" onsubmit="return false;">
54
+ <h1 class="ws-entry-shell__title">Sign in</h1>
55
+ <div class="ws-field">
56
+ <label class="ws-label" for="es-email-2">Email</label>
57
+ <input class="ws-input" id="es-email-2" type="email" value="ryan@theyoungteam" aria-invalid="true" aria-describedby="es-email-2-msg" autocomplete="email">
58
+ <p class="ws-field-msg ws-field-msg--error" id="es-email-2-msg">
59
+ <svg viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><circle cx="6" cy="6" r="4.5"/><path d="M6 3.75v2.5M6 8.25v.01"/></svg>
60
+ Add the part after the @, like theyoungteam.com
61
+ </p>
62
+ </div>
63
+ <div class="ws-entry-shell__acts">
64
+ <button type="submit" class="ws-btn ws-btn--primary ws-btn--lg">Continue</button>
65
+ </div>
66
+ </form>
38
67
  </div>
39
68
  </div>
40
- </aside>
41
- </div></div>
69
+ <aside class="ws-entry-shell__aside" aria-hidden="true">
70
+ <p class="ws-eyebrow">What&rsquo;s waiting</p>
71
+ </aside>
72
+ </div></div>
73
+ </div>
74
+
42
75
  </div>
43
76
  </body>
44
77
  </html>
@@ -0,0 +1,19 @@
1
+ /* ---- EntryShell: the sign-in page, the form centred in its 320 column and, from 48rem of the shell's own width, the grey
2
+ aside of samples. It fills its parent (K17): a parent with a height, a flex column with only a min-height (flex: 1),
3
+ or --page for the window's. ---- */
4
+ .ws-entry-shell { container: ws-entry-shell / inline-size; display: flex; flex: 1 0 auto; min-height: 100%; }
5
+ .ws-entry-shell--page { min-height: 100dvh; }
6
+ .ws-entry-shell__main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; padding: var(--space-lg) var(--space-lg); background: var(--color-bg-page); }
7
+ .ws-entry-shell__wordmark { align-self: flex-start; font-size: var(--font-size-md); line-height: var(--space-lg); font-weight: 600; color: var(--color-text-heading); }
8
+ .ws-entry-shell__center { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-lg); padding: var(--space-2xl) 0; }
9
+ .ws-entry-shell__form { width: 100%; max-width: calc(var(--space-9xl) + var(--space-7xl)); display: flex; flex-direction: column; gap: var(--space-lg); }
10
+ .ws-entry-shell__title { margin: 0; font-size: var(--font-size-xl); line-height: var(--space-xl); font-weight: 600; letter-spacing: var(--ws-tracking-title); color: var(--color-text-heading); text-align: center; }
11
+ /* The sign-in field is the large one, 36 px (still 40 on touch). */
12
+ .ws-entry-shell .ws-input { min-height: var(--ws-control-h-md); }
13
+ .ws-entry-shell__acts { display: flex; flex-direction: column; gap: var(--space-sm); text-align: center; }
14
+ .ws-entry-shell__aside { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: var(--space-md); margin: var(--space-xs); padding: var(--space-2xl); border-radius: var(--ws-radius-panel); background: var(--ws-page); }
15
+ .ws-entry-shell__samples { display: flex; gap: var(--space-md); }
16
+ .ws-entry-shell__sample { flex: 1; min-width: 0; padding: var(--ws-card-padding-lg); display: flex; flex-direction: column; gap: var(--space-xxs); }
17
+ .ws-entry-shell__sample-figure { font-size: var(--ws-text-figure); line-height: var(--ws-leading-figure); font-weight: 400; letter-spacing: var(--ws-tracking-display); color: var(--color-text-heading); font-variant-numeric: tabular-nums; }
18
+ /* A narrow shell is the form alone: the aside is a picture, never squeezed beside it. */
19
+ @container ws-entry-shell (max-width: 48rem) { .ws-entry-shell__aside { display: none; } }