@mthanh/vespercli 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +3 -2
  2. package/assets/CATALOG.md +9 -2
  3. package/assets/claude/.claude-plugin/marketplace.json +9 -9
  4. package/assets/claude/.claude-plugin/plugin.json +1 -1
  5. package/assets/claude/agents/code-planner.md +1 -1
  6. package/assets/claude/agents/code-reviewer.md +1 -1
  7. package/assets/claude/agents/code-tester.md +1 -1
  8. package/assets/claude/agents/copywriter.md +1 -1
  9. package/assets/claude/agents/feature-wrap-document.md +1 -1
  10. package/assets/claude/agents/janitor.md +1 -1
  11. package/assets/claude/agents/modernization.md +1 -1
  12. package/assets/claude/agents/principal-software-engineer.md +1 -1
  13. package/assets/claude/agents/refine-issue.md +1 -1
  14. package/assets/claude/agents/se-system-architecture-reviewer.md +1 -1
  15. package/assets/claude/agents/se-technical-writer.md +1 -1
  16. package/assets/claude/agents/skill-creator.md +1 -1
  17. package/assets/claude/agents/task-researcher.md +1 -1
  18. package/assets/claude/agents/technical-product-manager.md +1 -1
  19. package/assets/claude/agents/vision-analyst.md +1 -1
  20. package/assets/claude/agents/vitest.md +1 -1
  21. package/assets/claude/agents/workspace-learner.md +2 -2
  22. package/assets/claude/packs/backend/.claude-plugin/plugin.json +1 -1
  23. package/assets/claude/packs/backend/agents/firebase-developer.md +1 -1
  24. package/assets/claude/packs/backend/agents/nodejs-express-developer.md +1 -1
  25. package/assets/claude/packs/docs/.claude-plugin/plugin.json +1 -1
  26. package/assets/claude/packs/frontend/.claude-plugin/plugin.json +1 -1
  27. package/assets/claude/packs/frontend/agents/expert-nextjs-developer.md +1 -1
  28. package/assets/claude/packs/frontend/agents/expert-react-frontend-engineer.md +1 -1
  29. package/assets/claude/packs/frontend/agents/jest-react-component-analyzer.md +1 -1
  30. package/assets/claude/packs/frontend/agents/jest-react-scenario-scanner.md +1 -1
  31. package/assets/claude/packs/frontend/agents/jest-react-test-generator.md +1 -1
  32. package/assets/claude/packs/frontend/agents/jest-react-test-planner.md +1 -1
  33. package/assets/claude/packs/frontend/skills/design-taste-frontend/LICENSE +21 -0
  34. package/assets/claude/packs/frontend/skills/design-taste-frontend/SKILL.md +529 -0
  35. package/assets/claude/packs/frontend/skills/design-taste-frontend/UPSTREAM.json +7 -0
  36. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/app.css +216 -0
  37. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/base.css +105 -0
  38. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/base.js +37 -0
  39. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/charts.js +617 -0
  40. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.css +28 -0
  41. package/assets/claude/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.js +133 -0
  42. package/assets/claude/packs/frontend/skills/design-taste-frontend/evals/evals.json +76 -0
  43. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/app.json +1327 -0
  44. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/directions.json +1078 -0
  45. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/heroes.json +1086 -0
  46. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/motions.json +92 -0
  47. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/palettes.json +1485 -0
  48. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/photos.json +7240 -0
  49. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/sections.json +4429 -0
  50. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/sites.json +8350 -0
  51. package/assets/claude/packs/frontend/skills/design-taste-frontend/library/type.json +2024 -0
  52. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/app-screens.md +1199 -0
  53. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/colour.md +141 -0
  54. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/copy.md +177 -0
  55. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/critique.md +182 -0
  56. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/imagery.md +791 -0
  57. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/layout.md +292 -0
  58. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/motion.md +980 -0
  59. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/research.md +356 -0
  60. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/scenes.md +174 -0
  61. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/tells.md +115 -0
  62. package/assets/claude/packs/frontend/skills/design-taste-frontend/references/type.md +170 -0
  63. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/assets.mjs +865 -0
  64. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/draw.mjs +584 -0
  65. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/inspect.mjs +303 -0
  66. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/app-draw.mjs +203 -0
  67. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/cdp.mjs +248 -0
  68. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/probe.mjs +909 -0
  69. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lib/rules.mjs +243 -0
  70. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/lint.mjs +119 -0
  71. package/assets/claude/packs/frontend/skills/design-taste-frontend/scripts/scenes.mjs +124 -0
  72. package/assets/claude/packs/graphify/.claude-plugin/plugin.json +1 -1
  73. package/assets/claude/packs/integrations/.claude-plugin/plugin.json +1 -1
  74. package/assets/claude/packs/playwright/.claude-plugin/plugin.json +1 -1
  75. package/assets/claude/packs/playwright/agents/playwright-component-analyzer.md +1 -1
  76. package/assets/claude/packs/playwright/agents/playwright-scenario-scanner.md +1 -1
  77. package/assets/claude/packs/playwright/agents/playwright-test-generator.md +1 -1
  78. package/assets/claude/packs/playwright/agents/playwright-test-planner.md +1 -1
  79. package/assets/claude/packs/playwright/agents/playwright-tester.md +1 -1
  80. package/assets/claude/packs/polyglot/.claude-plugin/plugin.json +1 -1
  81. package/assets/claude/packs/styles/.claude-plugin/plugin.json +1 -1
  82. package/assets/copilot/agents/code-planner.agent.md +1 -1
  83. package/assets/copilot/agents/code-reviewer.agent.md +1 -1
  84. package/assets/copilot/agents/code-tester.agent.md +1 -1
  85. package/assets/copilot/agents/copywriter.agent.md +1 -1
  86. package/assets/copilot/agents/feature-wrap-document.agent.md +1 -1
  87. package/assets/copilot/agents/janitor.agent.md +1 -1
  88. package/assets/copilot/agents/modernization.agent.md +1 -1
  89. package/assets/copilot/agents/principal-software-engineer.agent.md +1 -1
  90. package/assets/copilot/agents/refine-issue.agent.md +1 -1
  91. package/assets/copilot/agents/se-system-architecture-reviewer.agent.md +1 -1
  92. package/assets/copilot/agents/se-technical-writer.agent.md +1 -1
  93. package/assets/copilot/agents/skill-creator.agent.md +1 -1
  94. package/assets/copilot/agents/task-researcher.agent.md +1 -1
  95. package/assets/copilot/agents/technical-product-manager.agent.md +1 -1
  96. package/assets/copilot/agents/vision-analyst.agent.md +1 -1
  97. package/assets/copilot/agents/vitest.agent.md +1 -1
  98. package/assets/copilot/agents/workspace-learner.agent.md +2 -2
  99. package/assets/copilot/packs/backend/agents/firebase-developer.agent.md +1 -1
  100. package/assets/copilot/packs/backend/agents/nodejs-express-developer.agent.md +1 -1
  101. package/assets/copilot/packs/frontend/agents/expert-nextjs-developer.agent.md +1 -1
  102. package/assets/copilot/packs/frontend/agents/expert-react-frontend-engineer.agent.md +1 -1
  103. package/assets/copilot/packs/frontend/agents/jest-react-component-analyzer.agent.md +1 -1
  104. package/assets/copilot/packs/frontend/agents/jest-react-scenario-scanner.agent.md +1 -1
  105. package/assets/copilot/packs/frontend/agents/jest-react-test-generator.agent.md +1 -1
  106. package/assets/copilot/packs/frontend/agents/jest-react-test-planner.agent.md +1 -1
  107. package/assets/copilot/packs/frontend/skills/design-taste-frontend/LICENSE +21 -0
  108. package/assets/copilot/packs/frontend/skills/design-taste-frontend/SKILL.md +529 -0
  109. package/assets/copilot/packs/frontend/skills/design-taste-frontend/UPSTREAM.json +7 -0
  110. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/app.css +216 -0
  111. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/base.css +105 -0
  112. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/base.js +37 -0
  113. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/charts.js +617 -0
  114. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.css +28 -0
  115. package/assets/copilot/packs/frontend/skills/design-taste-frontend/assets/scenes/stage.js +133 -0
  116. package/assets/copilot/packs/frontend/skills/design-taste-frontend/evals/evals.json +76 -0
  117. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/app.json +1327 -0
  118. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/directions.json +1078 -0
  119. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/heroes.json +1086 -0
  120. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/motions.json +92 -0
  121. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/palettes.json +1485 -0
  122. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/photos.json +7240 -0
  123. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/sections.json +4429 -0
  124. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/sites.json +8350 -0
  125. package/assets/copilot/packs/frontend/skills/design-taste-frontend/library/type.json +2024 -0
  126. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/app-screens.md +1199 -0
  127. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/colour.md +141 -0
  128. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/copy.md +177 -0
  129. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/critique.md +182 -0
  130. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/imagery.md +791 -0
  131. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/layout.md +292 -0
  132. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/motion.md +980 -0
  133. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/research.md +356 -0
  134. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/scenes.md +174 -0
  135. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/tells.md +115 -0
  136. package/assets/copilot/packs/frontend/skills/design-taste-frontend/references/type.md +170 -0
  137. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/assets.mjs +865 -0
  138. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/draw.mjs +584 -0
  139. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/inspect.mjs +303 -0
  140. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/app-draw.mjs +203 -0
  141. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/cdp.mjs +248 -0
  142. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/probe.mjs +909 -0
  143. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lib/rules.mjs +243 -0
  144. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/lint.mjs +119 -0
  145. package/assets/copilot/packs/frontend/skills/design-taste-frontend/scripts/scenes.mjs +124 -0
  146. package/assets/copilot/packs/playwright/agents/playwright-component-analyzer.agent.md +1 -1
  147. package/assets/copilot/packs/playwright/agents/playwright-scenario-scanner.agent.md +1 -1
  148. package/assets/copilot/packs/playwright/agents/playwright-test-generator.agent.md +1 -1
  149. package/assets/copilot/packs/playwright/agents/playwright-test-planner.agent.md +1 -1
  150. package/assets/copilot/packs/playwright/agents/playwright-tester.agent.md +1 -1
  151. package/assets/manifest.json +2 -0
  152. package/dist/cli.min.js +102 -102
  153. package/package.json +1 -1
  154. package/scripts/__snapshots__/generate-claude-assets.test.js.snap +1 -1
  155. package/scripts/generate-claude-assets.strict.test.js +1 -1
  156. package/scripts/generate-claude-assets.test.js +6 -6
  157. package/scripts/packs-layout.test.js +2 -1
@@ -0,0 +1,1327 @@
1
+ {
2
+ "version": 1,
3
+ "about": "App-screen library for tasteskill: styles (directions), shells and screen patterns, distilled from the study of 23 desktop product screens (17 light, 6 dark, 17 products) chosen by the owner. Every number is a measurement from the study or a median over it, except where a note says a value was moved for contrast or for the house palette bans. Reference products are not named; the screenshots stay private.",
4
+ "styles": [
5
+ {
6
+ "id": "achromatic-ledger",
7
+ "name": "Achromatic ledger",
8
+ "theme": "light",
9
+ "basis": "4 screens: a seller home, a per-agent insights page, a generated report, a settings page with usage numbers",
10
+ "suits": [
11
+ "finance",
12
+ "commerce",
13
+ "devtools",
14
+ "support",
15
+ "report",
16
+ "workspace",
17
+ "builder"
18
+ ],
19
+ "idea": "The chrome holds no colour at all; money and counts are set in ink, the one chart hue marks the screen's main data element, and the only other hue is a small signal where a figure changed.",
20
+ "colourBudget": "under 1% coloured pixels; the chrome is ink, the one chart hue goes on the main data element, and the only other hue is a small change signal",
21
+ "tokens": {
22
+ "ground": "#f8f8f8",
23
+ "surface": "#ffffff",
24
+ "raised": "#eeeeee",
25
+ "border": "#e6e6e6",
26
+ "rule": "#f0f0f0",
27
+ "control": "#d4d4d4",
28
+ "text": "#0a0a0a",
29
+ "muted": "#6b6b6b",
30
+ "accent": "#141414",
31
+ "positive": "#2e7d32",
32
+ "negative": "#c4242a",
33
+ "warning": "#92400e",
34
+ "chart": [
35
+ "#141414",
36
+ "#8a8a8a",
37
+ "#1d5fbf"
38
+ ],
39
+ "pills": {
40
+ "positive": [
41
+ "#dcfae5",
42
+ "#04250e"
43
+ ],
44
+ "negative": [
45
+ "#ffedea",
46
+ "#831c1e"
47
+ ],
48
+ "warning": [
49
+ "#fffbeb",
50
+ "#92400e"
51
+ ],
52
+ "neutral": [
53
+ "#eeeeee",
54
+ "#3d3d3d"
55
+ ]
56
+ },
57
+ "radius": {
58
+ "card": 8,
59
+ "control": 6
60
+ },
61
+ "font": {
62
+ "family": "Geist",
63
+ "second": "Geist Mono, for IDs and keys only",
64
+ "fallback": "Inter, system-ui, sans-serif",
65
+ "sizes": {
66
+ "title": 24,
67
+ "section": 16,
68
+ "kpi": 30,
69
+ "body": 14,
70
+ "small": 12
71
+ },
72
+ "weights": [
73
+ 400,
74
+ 500,
75
+ 700
76
+ ],
77
+ "note": "700 is for money figures only; every other number is 400-500."
78
+ },
79
+ "density": "sparse",
80
+ "rowHeight": 44,
81
+ "sidebarWidth": 256,
82
+ "gap": 12,
83
+ "pad": 24,
84
+ "controlHeight": 36
85
+ },
86
+ "shell": "open-plane",
87
+ "shellAlternatives": [
88
+ "icon-rail",
89
+ "no-sidebar"
90
+ ],
91
+ "signature": "No brand colour anywhere in the chrome: the one primary action is near-black (a grey pill, #e5e5e5, is the secondary), the main data element (today's series, the booked bars, the current period) takes the one chart hue, #1d5fbf, and everything else is drawn in ink with the comparison or the part after the cursor in grey, zero balances are set in grey, and the only hue on the screen is a small triangle or a short coloured number where a figure changed.",
92
+ "identity": [
93
+ "A ground from the product's world in place of #f8f8f8, one level off white and low in chroma: a stone (#f4f3f1) for a bakery or a shop, a sage (#f2f5f2) for a garden or a greenhouse, a blue-grey (#f2f4f7) for a ledger or a meter. Cards stay white; a warm tint stays under the cream check (saturation under about 15%).",
94
+ "The one chart hue (#1d5fbf, or the brand's own hue at 3:1 or more on white) on the screen's main data element: today's line, the booked bars, the current period's column, the margin that breaks. The chrome stays ink and the hue stays under 1% of the screen.",
95
+ "Every figure in Geist Mono, as the style's decision, so money and counts read as a ledger's columns while the text stays Geist. Lint and the inspector flag mono; give the reason in the report."
96
+ ],
97
+ "avoid": [
98
+ "a brand-coloured primary button",
99
+ "tinted cards or tinted KPI tiles",
100
+ "a coloured chart where one series in ink says it",
101
+ "bold on anything but money",
102
+ "a chart with no y-scale (the study's one example of this look hid magnitude behind hover and was flagged)",
103
+ "a grey pill as the only button for the screen's main job: in testing an Approve repeated in grey on every row left the screen without a primary"
104
+ ],
105
+ "notes": "The studied screens of this kind used 11-12px card radii, which §9.4 counts among the rare middle values; the library sets the tight pair (8 and 6) so the style lands on the bimodal rule. After testing, the chart hue moved from an unused third series colour onto the main data element: a screen whose only hue was a delta read as a kit."
106
+ },
107
+ {
108
+ "id": "framed-sheet",
109
+ "name": "Framed sheet",
110
+ "theme": "light",
111
+ "basis": "6 screens: a developer platform overview, an analytics overview, an events analytics tab, a list detail, a reports dashboard, a flow builder",
112
+ "suits": [
113
+ "analytics",
114
+ "devtools",
115
+ "builder",
116
+ "smb-admin",
117
+ "support",
118
+ "commerce",
119
+ "report"
120
+ ],
121
+ "idea": "The app chrome is one tinted L-shaped frame; the work sits on a white sheet with a hairline edge and soft corners, so depth comes from a single tone step and no shadow.",
122
+ "colourBudget": "under 3%; the brand shrinks to the logo and a 2px tab underline, the data carries the chroma",
123
+ "tokens": {
124
+ "ground": "#f9fbfc",
125
+ "surface": "#ffffff",
126
+ "raised": "#f4f6f8",
127
+ "active": "#ebedee",
128
+ "border": "#e8eaec",
129
+ "rule": "#f0f1f2",
130
+ "control": "#cdced1",
131
+ "text": "#131416",
132
+ "muted": "#5d5f60",
133
+ "accent": "#1b6c80",
134
+ "positive": "#1e7b4f",
135
+ "negative": "#c4242a",
136
+ "warning": "#92400e",
137
+ "chart": [
138
+ "#1b6c80",
139
+ "#2f70bb",
140
+ "#a86f0c"
141
+ ],
142
+ "pills": {
143
+ "positive": [
144
+ "#dcfae5",
145
+ "#04250e"
146
+ ],
147
+ "negative": [
148
+ "#ffedea",
149
+ "#831c1e"
150
+ ],
151
+ "warning": [
152
+ "#fffbeb",
153
+ "#92400e"
154
+ ],
155
+ "neutral": [
156
+ "#ebedee",
157
+ "#353736"
158
+ ]
159
+ },
160
+ "radius": {
161
+ "card": 8,
162
+ "control": 6,
163
+ "sheet": 16
164
+ },
165
+ "sheetInset": 8,
166
+ "font": {
167
+ "family": "IBM Plex Sans",
168
+ "second": "IBM Plex Mono, for IDs and keys only",
169
+ "fallback": "Inter, system-ui, sans-serif",
170
+ "sizes": {
171
+ "title": 22,
172
+ "section": 16,
173
+ "kpi": 28,
174
+ "body": 14,
175
+ "small": 12
176
+ },
177
+ "weights": [
178
+ 400,
179
+ 500,
180
+ 600
181
+ ],
182
+ "note": "KPI values at 400; the semibold goes on the label and the active tab."
183
+ },
184
+ "density": "medium",
185
+ "rowHeight": 48,
186
+ "sidebarWidth": 228,
187
+ "gap": 24,
188
+ "pad": 24,
189
+ "controlHeight": 32
190
+ },
191
+ "shell": "framed-sheet",
192
+ "shellAlternatives": [],
193
+ "signature": "One tinted frame holds the sidebar and the 48px top bar with no rule between them; the page is a white sheet inset 8px from the window's right and bottom edges, with a 1px edge, 16px corners and no shadow. The active tab is a 2px underline in ink or the accent; everything else in the chrome is grey.",
194
+ "identity": [
195
+ "The frame tinted from the product's colour in place of #f9fbfc: one low-chroma step of its hue (a green-grey for a climate or farm tool, a blue-grey for an observability tool, a stone for a print shop). The sheet stays white.",
196
+ "The brand's own hue from the brief as --chart-1 in place of the dealt teal, on the main series and the one selected state, at 3:1 or more on white, never violet or indigo.",
197
+ "IBM Plex Mono for IDs, keys and the figures in tables (one job): its figures have their own drawing, and a developer reads them as the product's."
198
+ ],
199
+ "avoid": [
200
+ "a border between the sidebar and the top bar",
201
+ "a shadow under the sheet",
202
+ "cards whose border is heavier than the sheet's (#cdcfcf on cards read as heavy in the study)",
203
+ "a fourth nesting level: frame, sheet and card are enough",
204
+ "different gutters for the KPI row and the chart row (20 against 24 was flagged)"
205
+ ],
206
+ "notes": "The study's second data hue in this style was an orange (#e88e46) that falls inside the house terracotta range; the third chart colour here is an amber moved out of that range and darkened to 3:1 on white."
207
+ },
208
+ {
209
+ "id": "accent-ladder",
210
+ "name": "Accent ladder",
211
+ "theme": "light",
212
+ "basis": "3 screens: a newsletter home, a network analytics overview, a cap-table company home",
213
+ "suits": [
214
+ "creator",
215
+ "smb-admin",
216
+ "community",
217
+ "analytics"
218
+ ],
219
+ "idea": "One brand hue at full strength only on small marks, and its pale tints doing all the area work: the active nav row, a plan card, badges and progress tracks.",
220
+ "colourBudget": "3-10%, nearly all of it as pale tints of the one hue",
221
+ "tokens": {
222
+ "ground": "#f9fafb",
223
+ "surface": "#ffffff",
224
+ "raised": "#f3f4f6",
225
+ "border": "#e5e7eb",
226
+ "rule": "#f2f2f2",
227
+ "control": "#d1d5db",
228
+ "text": "#111827",
229
+ "muted": "#5f6672",
230
+ "accent": "#b8336a",
231
+ "accentSoft": "#fdf2f7",
232
+ "accentTrack": "#f8dbe8",
233
+ "accentInk": "#6b1d3e",
234
+ "positive": "#247b50",
235
+ "negative": "#c4242a",
236
+ "warning": "#92400e",
237
+ "chart": [
238
+ "#b8336a",
239
+ "#6b7280",
240
+ "#d4618f"
241
+ ],
242
+ "pills": {
243
+ "positive": [
244
+ "#dcfce7",
245
+ "#14532d"
246
+ ],
247
+ "negative": [
248
+ "#ffedea",
249
+ "#831c1e"
250
+ ],
251
+ "warning": [
252
+ "#fffbeb",
253
+ "#92400e"
254
+ ],
255
+ "neutral": [
256
+ "#f3f4f6",
257
+ "#374151"
258
+ ],
259
+ "accent": [
260
+ "#fdf2f7",
261
+ "#6b1d3e"
262
+ ]
263
+ },
264
+ "radius": {
265
+ "card": 8,
266
+ "control": 6
267
+ },
268
+ "font": {
269
+ "family": "DM Sans",
270
+ "second": null,
271
+ "fallback": "Inter, system-ui, sans-serif",
272
+ "sizes": {
273
+ "title": 32,
274
+ "section": 18,
275
+ "kpi": 24,
276
+ "body": 14,
277
+ "small": 12
278
+ },
279
+ "weights": [
280
+ 400,
281
+ 500,
282
+ 600,
283
+ 700
284
+ ],
285
+ "note": "700 for the page title only."
286
+ },
287
+ "density": "sparse",
288
+ "rowHeight": 45,
289
+ "sidebarWidth": 230,
290
+ "gap": 24,
291
+ "pad": 24,
292
+ "controlHeight": 32
293
+ },
294
+ "shell": "open-plane",
295
+ "shellAlternatives": [
296
+ "ruled-t-frame"
297
+ ],
298
+ "signature": "The full hue goes only on small marks: the one filled-button style, the data series and the active nav icon. Its 50-200 tints carry every area: the active nav row (tint fill with the dark ink of the hue), the plan or trial card, badges and progress tracks. The primary action may instead be near-black, as on the study's newsletter home.",
299
+ "identity": [
300
+ "The ladder built from the brand's own hue (its logo, the brief's object) in place of the dealt raspberry: the full hue on small marks, its pale tints on areas, never violet or indigo.",
301
+ "The product's objects in the lead block: the newsletter's latest issue as its cover, the shop's products as 40px thumbnails, the course's lessons with their own art.",
302
+ "A ground one level toward the hue's palest tint (#fbf7f8 for the raspberry) in place of #f9fafb, so the page and the tints read as one family."
303
+ ],
304
+ "avoid": [
305
+ "the full hue on large areas",
306
+ "a second accent family (four families on one screen was flagged in the study)",
307
+ "a gradient on the trial chip or upgrade button",
308
+ "a left accent bar on the active nav row on top of the tint (seen once in 23 screens)",
309
+ "violet or indigo"
310
+ ],
311
+ "notes": "All three studied screens of this kind used violet, purple or pink as the one hue. The move does not depend on the hue, so the house's violet and indigo ban holds and the library deals a raspberry instead."
312
+ },
313
+ {
314
+ "id": "editorial-greeting",
315
+ "name": "Editorial greeting",
316
+ "theme": "light",
317
+ "basis": "2 screens: a team workspace home and a personal insights home",
318
+ "suits": [
319
+ "workspace",
320
+ "creator"
321
+ ],
322
+ "idea": "A personal or team home that opens with a typeset greeting in a centred column; every number below it is set at regular weight on tonal panels.",
323
+ "colourBudget": "under 2% for the accent; tonal panels carry the structure",
324
+ "tokens": {
325
+ "ground": "#ffffff",
326
+ "surface": "#f9f9f9",
327
+ "raised": "#ffffff",
328
+ "border": "#eaeaea",
329
+ "rule": "#f3f3f3",
330
+ "control": "#d9d9d6",
331
+ "text": "#1f201d",
332
+ "muted": "#636361",
333
+ "accent": "#1b6e66",
334
+ "positive": "#2e7d32",
335
+ "negative": "#b42318",
336
+ "warning": "#92400e",
337
+ "chart": [
338
+ "#1f201d",
339
+ "#1b6e66",
340
+ "#8c8c88"
341
+ ],
342
+ "pills": {
343
+ "positive": [
344
+ "#dcfae5",
345
+ "#04250e"
346
+ ],
347
+ "negative": [
348
+ "#fdecea",
349
+ "#7a1d14"
350
+ ],
351
+ "warning": [
352
+ "#fffbeb",
353
+ "#92400e"
354
+ ],
355
+ "neutral": [
356
+ "#f3f3f3",
357
+ "#3d3d3a"
358
+ ]
359
+ },
360
+ "radius": {
361
+ "card": 22,
362
+ "control": 999
363
+ },
364
+ "font": {
365
+ "family": "Instrument Sans",
366
+ "second": "Instrument Serif, for the greeting only",
367
+ "fallback": "Inter, system-ui, sans-serif",
368
+ "sizes": {
369
+ "title": 48,
370
+ "section": 14,
371
+ "kpi": 32,
372
+ "body": 14,
373
+ "small": 12
374
+ },
375
+ "weights": [
376
+ 400,
377
+ 500,
378
+ 600
379
+ ],
380
+ "note": "The 48px title is the serif greeting; set in the sans it is 24/400. Every figure is 400."
381
+ },
382
+ "density": "sparse",
383
+ "rowHeight": 63,
384
+ "sidebarWidth": 224,
385
+ "gap": 16,
386
+ "pad": 20,
387
+ "controlHeight": 38
388
+ },
389
+ "shell": "open-plane",
390
+ "shellAlternatives": [
391
+ "framed-sheet"
392
+ ],
393
+ "signature": "The greeting is the h1, in a centred 1100px column on a real 12-column grid (77px columns, 16px gutters), with spans that change by row but share column lines (3/3/3/3, then 9/3, then 6/6, so every internal edge meets one above it). Every figure below is set at regular weight on tonal panels, one layer each: a panel one step off white holds its title and its content directly; a white inner card is used once, for the main chart.",
394
+ "identity": [
395
+ "The greeting names this team or household and today's one fact, set from the data (\"Morning, Okoro house. The car is ready by 06:10.\"), never \"Welcome back\".",
396
+ "Each person's stable hue as a pale tint on their avatar and their own lane or column (a couple and their joint account as three lanes): identity, not data, so it stays out of the chart legends.",
397
+ "A surface from the product's world in place of #f9f9f9, one level toward its material (a sage for a garden, a stone for a kitchen, a blue-grey for a studio), with the page white kept."
398
+ ],
399
+ "avoid": [
400
+ "an emoji in the greeting",
401
+ "a tracked uppercase date above the greeting (put the date after it or in the grey line below)",
402
+ "a 624-864px column on a desktop screen (both were flagged as wasted width)",
403
+ "a tray around every card (a grey panel with a white card 6px inside it, on every block, read as a bento template in testing)",
404
+ "red as the accent: in testing red marked a record week of upgrades and read as an alarm; red is for the failing fact only"
405
+ ],
406
+ "notes": "One studied screen set its greeting in a serif at 48/700 and its counts in a mono; the other set the greeting at 24/400 in the sans. The red is the second screen's chart red moved two degrees of hue out of the house terracotta range. After testing, the studied red accent was replaced by a deep teal: red on good news read as an alarm."
407
+ },
408
+ {
409
+ "id": "pastel-consumer",
410
+ "name": "Pastel consumer",
411
+ "theme": "light",
412
+ "basis": "2 screens: a wallet home and a personal finance home",
413
+ "suits": [
414
+ "wallet",
415
+ "finance"
416
+ ],
417
+ "idea": "Categories are coded by pale tints whose ink is the dark of the same hue, all under one large radius, and each headline sum sits inside the card that explains it.",
418
+ "colourBudget": "5-8%, as pale tiles and data marks",
419
+ "tokens": {
420
+ "ground": "#f3f5f7",
421
+ "surface": "#ffffff",
422
+ "raised": "#f2f8fd",
423
+ "border": "#e6e6e6",
424
+ "rule": "#f4f4f4",
425
+ "control": "#d6d9dd",
426
+ "text": "#1b1d1f",
427
+ "muted": "#5c6064",
428
+ "accent": "#1d5fd6",
429
+ "accentSoft": "#dcf1ff",
430
+ "accentInk": "#0a3a80",
431
+ "positive": "#2f7a45",
432
+ "negative": "#c41c29",
433
+ "warning": "#92400e",
434
+ "chart": [
435
+ "#1d5fd6",
436
+ "#b45309",
437
+ "#2a8798"
438
+ ],
439
+ "pills": {
440
+ "positive": [
441
+ "#dcfae5",
442
+ "#04250e"
443
+ ],
444
+ "negative": [
445
+ "#ffedea",
446
+ "#831c1e"
447
+ ],
448
+ "warning": [
449
+ "#fffbeb",
450
+ "#92400e"
451
+ ],
452
+ "neutral": [
453
+ "#eef1f4",
454
+ "#3a3d40"
455
+ ],
456
+ "accent": [
457
+ "#dcf1ff",
458
+ "#0a3a80"
459
+ ]
460
+ },
461
+ "radius": {
462
+ "card": 20,
463
+ "control": 10
464
+ },
465
+ "font": {
466
+ "family": "Manrope",
467
+ "second": null,
468
+ "fallback": "Inter, system-ui, sans-serif",
469
+ "sizes": {
470
+ "title": 28,
471
+ "section": 20,
472
+ "kpi": 32,
473
+ "body": 16,
474
+ "small": 14
475
+ },
476
+ "weights": [
477
+ 400,
478
+ 500,
479
+ 600
480
+ ],
481
+ "note": "Money at 24-32px; card titles regular; semibold for net worth, bill amounts and actions."
482
+ },
483
+ "density": "medium",
484
+ "rowHeight": 72,
485
+ "sidebarWidth": 240,
486
+ "gap": 24,
487
+ "pad": 24,
488
+ "controlHeight": 40
489
+ },
490
+ "shell": "open-plane",
491
+ "shellAlternatives": [
492
+ "icon-rail"
493
+ ],
494
+ "signature": "Pale category tiles with the dark of their own hue as ink (#dcf1ff with #0a3a80), one large radius (20px on cards, stepping down to 10, 8 and 5 inside), and quiet money polarity: income green with a plus sign, spending in ink, no red on ordinary outgoings. Tints go on small tiles, avatars and chips; a panel that holds a list stays white. When the product has people (two partners, a family), each gets one hue, at least 60 degrees from the next.",
495
+ "identity": [
496
+ "The tile hues from the account's own colours (the card's colour, each pot's colour in the app) in place of the dealt cobalt, each tile pale with the dark of its own hue as ink.",
497
+ "The money's own objects: the card art at its real ratio, merchant marks at 24px in the rows, the goal's picture on its pot.",
498
+ "Manrope's figures carry the balance: 30-36px at 600 with tabular figures and the pence in a smaller grey, so the number itself is the face."
499
+ ],
500
+ "avoid": [
501
+ "a gradient balance card",
502
+ "two data palettes on one page (flagged in the study)",
503
+ "red on every outgoing amount",
504
+ "a 624px phone-width column on a desktop screen (flagged as a stretched phone screen)",
505
+ "a KPI strip on top: the sums belong in their cards",
506
+ "whole panels tinted per person or category beside white cards (two surface languages on one screen)"
507
+ ],
508
+ "notes": "The two studied screens used a pure #0000ff and an indigo #4723f5 as their brand colour, and pastels such as #7cbecf that fall under 3:1 on white. The library uses a cobalt that reads as blue rather than indigo, and data colours darkened to at least 3:1 on the card."
509
+ },
510
+ {
511
+ "id": "true-black-flat",
512
+ "name": "True-black flat",
513
+ "theme": "dark",
514
+ "basis": "5 screens: an events back office, an event analytics tab, a community overview, an artist studio home, an artist insights page",
515
+ "suits": [
516
+ "community",
517
+ "creator",
518
+ "markets"
519
+ ],
520
+ "idea": "Night mode on true black: sidebar, top bar and page share one ground, elevation is a lightness step alone, and colour is confined to data marks.",
521
+ "colourBudget": "at or under 3%; the accent never touches buttons, tabs or nav",
522
+ "tokens": {
523
+ "ground": "#000000",
524
+ "surface": "#111111",
525
+ "raised": "#2a2a2a",
526
+ "border": "#1a1a1a",
527
+ "rule": "#161616",
528
+ "control": "#444444",
529
+ "text": "#ffffff",
530
+ "muted": "#b4b4b4",
531
+ "faint": "#949494",
532
+ "accent": "#c6f24e",
533
+ "positive": "#c6f24e",
534
+ "negative": "#e5484d",
535
+ "warning": "#e5a93b",
536
+ "chart": [
537
+ "#c6f24e",
538
+ "#e6e6e6",
539
+ "#6b6b6b"
540
+ ],
541
+ "pills": {
542
+ "positive": [
543
+ "#222a10",
544
+ "#c6f24e"
545
+ ],
546
+ "negative": [
547
+ "#2c1a20",
548
+ "#e5566f"
549
+ ],
550
+ "warning": [
551
+ "#2b2414",
552
+ "#e5a93b"
553
+ ],
554
+ "neutral": [
555
+ "#222222",
556
+ "#ffffff"
557
+ ]
558
+ },
559
+ "radius": {
560
+ "card": 20,
561
+ "control": 999
562
+ },
563
+ "font": {
564
+ "family": "Inter",
565
+ "second": null,
566
+ "fallback": "system-ui, sans-serif",
567
+ "sizes": {
568
+ "title": 20,
569
+ "section": 16,
570
+ "kpi": 24,
571
+ "body": 14,
572
+ "small": 12
573
+ },
574
+ "weights": [
575
+ 400,
576
+ 500,
577
+ 600
578
+ ],
579
+ "note": "Nothing above 600; inactive nav labels #bbb, active #fff."
580
+ },
581
+ "density": "medium",
582
+ "rowHeight": 80,
583
+ "sidebarWidth": 210,
584
+ "gap": 14,
585
+ "pad": 22,
586
+ "controlHeight": 36
587
+ },
588
+ "shell": "ruled-t-frame",
589
+ "shellAlternatives": [
590
+ "no-sidebar"
591
+ ],
592
+ "signature": "Elevation by lightness alone (#000 ground, #111 card, #2a2a2a nested panel) with no borders or shadows on cards; the active nav item is marked only by its label going from #bbb to #fff; the primary control is made primary by inversion, a white 36px pill with black text.",
593
+ "identity": [
594
+ "The one data hue from the product's world in place of the dealt lime: a solar amber (#f2b33d) for an energy home, a sky blue (#4cb3f0) for water or weather, a lime only for sport. It is still the only hue on data and never touches buttons, tabs or nav. A green or yellow-green hue is also --positive; an amber that sits beside --warning leaves the warning to its pill pair.",
595
+ "A ground with the product's temperature: the studied #000 for media and events, a warm near-black (#0e0d0c) for a home, a cool one (#0c0d0f) for a monitor, with cards one lightness step above it (#181716, #15171a). Never navy or slate.",
596
+ "A signature element from the product's world as the lead: the energy home's power flow (sun, house, battery and grid with their live kW), an event's doors against capacity, an artist's release with its cover."
597
+ ],
598
+ "avoid": [
599
+ "a navy or slate dark theme",
600
+ "glow, neon borders or shadows",
601
+ "a hue per chart (five hues across four charts was flagged)",
602
+ "the accent on buttons, tabs or nav",
603
+ "a 64px top bar left empty across most of its width (flagged twice)"
604
+ ],
605
+ "notes": "The studied screens of this kind used a violet-magenta (#dd6cff) and an orange (#ff5500) as their one data hue. The library deals a lime, which keeps the move and stays clear of the violet ban; because the lime is a yellow-green, it is also the positive colour (a second, mint green beside it read as two greens). The greys are #b4b4b4 for secondary text and #949494 for meta, 32 levels apart rather than the 20 of the measured #aaa and #969696, which read as one grey; #949494 still holds 4.5:1 on the #2a2a2a nested panel."
606
+ },
607
+ {
608
+ "id": "data-terminal",
609
+ "name": "Data terminal",
610
+ "theme": "dark",
611
+ "basis": "1 screen: a stock research view. Keep it narrow.",
612
+ "suits": [
613
+ "markets",
614
+ "devtools"
615
+ ],
616
+ "idea": "A research or monitoring screen read in long sessions: cards darker than the ground, tabular digits that stack, signs instead of colour, and every selection marked by the same 1px accent line.",
617
+ "colourBudget": "under 3%; the accent is never more than a 1px line",
618
+ "tokens": {
619
+ "ground": "#171719",
620
+ "surface": "#131217",
621
+ "raised": "#212023",
622
+ "border": "#222224",
623
+ "rule": "#1b1a1f",
624
+ "control": "#3a3a3e",
625
+ "text": "#ffffff",
626
+ "muted": "#8a8c92",
627
+ "accent": "#4a8ad6",
628
+ "positive": "#44a282",
629
+ "negative": "#e5566f",
630
+ "warning": "#d9a441",
631
+ "chart": [
632
+ "#f2f2f3",
633
+ "#e5566f",
634
+ "#4a8ad6"
635
+ ],
636
+ "pills": {
637
+ "positive": [
638
+ "#1b2828",
639
+ "#5fc39c"
640
+ ],
641
+ "negative": [
642
+ "#2c1a20",
643
+ "#e5566f"
644
+ ],
645
+ "warning": [
646
+ "#2a2416",
647
+ "#d9a441"
648
+ ],
649
+ "neutral": [
650
+ "#212023",
651
+ "#bdbdc0"
652
+ ]
653
+ },
654
+ "shadow": "0 12px 28px rgba(0,0,0,.2)",
655
+ "radius": {
656
+ "card": 6,
657
+ "control": 999
658
+ },
659
+ "font": {
660
+ "family": "Public Sans",
661
+ "second": null,
662
+ "fallback": "Inter, system-ui, sans-serif",
663
+ "sizes": {
664
+ "title": 26,
665
+ "section": 20,
666
+ "kpi": 20,
667
+ "body": 13,
668
+ "small": 12
669
+ },
670
+ "weights": [
671
+ 400,
672
+ 500,
673
+ 600,
674
+ 700
675
+ ],
676
+ "note": "Section titles 20/400 in the muted grey; card titles 16/600; tabular figures everywhere."
677
+ },
678
+ "density": "dense",
679
+ "rowHeight": 42,
680
+ "sidebarWidth": 50,
681
+ "gap": 24,
682
+ "pad": 32,
683
+ "controlHeight": 34
684
+ },
685
+ "shell": "icon-rail",
686
+ "shellAlternatives": [],
687
+ "signature": "Every selection (tab, toggle, range, nav item) is a 1px accent line exactly as wide as its label, placed on the nearest existing edge; numbers stay white or grey and carry their sign in the text ('+$24,000,000').",
688
+ "identity": [
689
+ "Every figure in a monospace as the style's decision (IBM Plex Mono or JetBrains Mono for each price, count and time, digits that stack), with the text in Public Sans. Lint and the inspector flag mono; give the reason in the report.",
690
+ "The one accent line from the product's world in place of the dealt blue (the exchange's or the team's hue): still the only selection mark, never violet or indigo.",
691
+ "A signature of the market or the system as the lead: an order book's depth as two mirrored bar lists, an incident as a minute-by-minute strip, a region map with the list beside it."
692
+ ],
693
+ "avoid": [
694
+ "filled pill tabs or a coloured segmented control",
695
+ "a chart with no scale and no dates (the studied screen had none and was flagged)",
696
+ "tertiary text under 4.5:1 (#4c4c4f read at about 2:1 in the study)",
697
+ "lighter cards with borders and a glow",
698
+ "green and red on every number; the one column whose job is \"what moved today\" and a negative headline figure may carry the polarity colours"
699
+ ],
700
+ "notes": "The studied screen's muted grey #82848a and red #d4405d were lifted to #8a8c92 and #e5566f so text passes 4.5:1 on the card. Its card list rows sit on a 28px pitch and its table rows on 42px."
701
+ }
702
+ ],
703
+ "shells": [
704
+ {
705
+ "id": "open-plane",
706
+ "name": "Open plane",
707
+ "basis": "5 of 23 screens",
708
+ "suits": [
709
+ "finance",
710
+ "wallet",
711
+ "workspace",
712
+ "creator",
713
+ "analytics"
714
+ ],
715
+ "numbers": {
716
+ "sidebarWidth": "230-256 (230, 240, 256 in the study; 280 and 292 with a built-in icon rail)",
717
+ "separation": "none, or one 1px hairline; the sidebar sits on the page ground or within 1-2% of it",
718
+ "navPitch": 34,
719
+ "navRowHeight": 32,
720
+ "navIcon": "16px outline, about 1.5px stroke",
721
+ "navLabel": "14px, 400, grey or ink",
722
+ "activeItem": "neutral grey pill, radius 6-12, inset 8-12px from the sidebar edges (#e9e9e9-#ededed)",
723
+ "topBar": "none",
724
+ "canvas": "fluid with a 24-64px gutter, or a centred 1100px column"
725
+ },
726
+ "blueprint": "The labelled sidebar sits on the page ground with nothing or one hairline between it and the canvas; there is no top bar, and the page header and cards sit straight on the ground about 32-36px from the top. Workspace or account switcher at the top of the sidebar, primary nav on a 34px pitch, groups under 12-13px sentence-case grey labels with 22-56px of air above, utilities and the user row pushed to the bottom. Cards are white on the off-white ground (or the sidebar is white with a 1px border on a #f9fafb canvas). The canvas is fluid with one gutter value, or a centred column for personal homes.",
727
+ "phone": "The sidebar folds into a 48px top bar holding the screen's name, a menu button that opens a full-screen sheet with the nav and the switcher, and at most one action. Content takes the full width with 16px margins."
728
+ },
729
+ {
730
+ "id": "framed-sheet",
731
+ "name": "Tinted frame, white sheet",
732
+ "basis": "8 of 23 screens, in three variants",
733
+ "suits": [
734
+ "analytics",
735
+ "devtools",
736
+ "builder",
737
+ "smb-admin",
738
+ "support"
739
+ ],
740
+ "numbers": {
741
+ "chrome": "#f6f6f6-#f9fbfc (a warm #f7f6f2 once)",
742
+ "sheetInset": "8px from the window's right and bottom edges (12 and 16 once each)",
743
+ "sheetRadius": "10-16, median 16",
744
+ "sheetEdge": "1px #eaeaea-#ededed, no shadow",
745
+ "sidebarWidth": "220-263 (228 on two screens)",
746
+ "topBar": "48px on the chrome ground with no rule; search 548x32 centred on the window with a shortcut hint",
747
+ "contentPadding": 24,
748
+ "floatingVariant": "both panels inset 12px with a 12px gutter, radius 10"
749
+ },
750
+ "blueprint": "Sidebar and top bar share one tinted ground with no rule between them, forming an L; the page lives on a white sheet. Variant one: the sheet butts against the sidebar and the top bar and is inset 8px from the right and bottom edges, 16px radius, 1px edge. Variant two: a flush L-frame with no inset, the frame marked by one rule. Variant three: sidebar and content are two floating panels inset 12px from every edge with a 12px gutter. The top bar, when present, is 48px and holds a centred search, the account button and a help or AI icon. Inside the sheet the content has 24px padding and starts with the breadcrumb or title row.",
751
+ "phone": "The frame disappears: the sheet becomes the screen, with a 48px top bar (menu button, title, one action) on the chrome tint. The search moves into the menu sheet or behind an icon."
752
+ },
753
+ {
754
+ "id": "ruled-t-frame",
755
+ "name": "Ruled T-frame",
756
+ "basis": "4 of 23 screens (3 dark, 1 light)",
757
+ "suits": [
758
+ "community",
759
+ "creator",
760
+ "smb-admin"
761
+ ],
762
+ "numbers": {
763
+ "sidebarWidth": "210-240",
764
+ "topBar": "64px with a 1px bottom rule",
765
+ "rules": "1px; #1a1a1a on #000, #f2f2f2 on white",
766
+ "navPitch": "34 (dark) or 40 (light)",
767
+ "switcher": "at the top bar's right end, behind a full-height 1px divider",
768
+ "contentGutter": "29px from the sidebar rule and the window edge"
769
+ },
770
+ "blueprint": "A 210-240px sidebar and a 64px top bar share one ground, divided only by 1px rules. The workspace or community switcher sits at the right end of the top bar behind a full-height divider; the sidebar holds the wordmark and the nav on a 34px pitch with sentence-case group labels. On dark, the active item is its label going from #bbb to #fff. The top bar must carry something real (search, the back link and object name, the switcher): two studied screens left about 1070px of it blank and were flagged.",
771
+ "phone": "The top bar stays at 48-56px with the switcher reduced to its mark; the sidebar becomes a full-screen menu sheet or a bottom bar of four or five destinations."
772
+ },
773
+ {
774
+ "id": "icon-rail",
775
+ "name": "Icon rail",
776
+ "basis": "3 of 23 screens",
777
+ "suits": [
778
+ "markets",
779
+ "devtools",
780
+ "finance",
781
+ "wallet"
782
+ ],
783
+ "numbers": {
784
+ "railWidth": "50-60, median 55",
785
+ "icon": "15-18px outline",
786
+ "pitch": "34-49",
787
+ "active": "icon colour alone, or a full-bleed 50px band at a 2% tint, or a 1px accent bar on the rail's border",
788
+ "groups": "short 20px hairlines, no labels",
789
+ "utilities": "pushed to the bottom after a gap of about 200px"
790
+ },
791
+ "blueprint": "An unlabelled rail of 50-60px carries the brand mark at the top and 15-18px outline icons on a 34-49px pitch; groups are split by 20px hairlines, utilities sit at the bottom. The rail sits on the page ground with a 1px edge, or is white with a faint 4px shadow on a grey ground. It saves about 180px of width against a labelled sidebar, so it suits products with few destinations and screens that need the width. Icons need tooltips and an accessible name.",
792
+ "phone": "The rail becomes a bottom bar with the same four or five icons, each with a short label under it."
793
+ },
794
+ {
795
+ "id": "no-sidebar",
796
+ "name": "No sidebar",
797
+ "basis": "3 of 23 screens",
798
+ "suits": [
799
+ "report",
800
+ "creator",
801
+ "community"
802
+ ],
803
+ "numbers": {
804
+ "topBar": "46-48px on the page ground, no border",
805
+ "column": "centred, 1088-1208px",
806
+ "gutters": "152-212px at a 1512px window",
807
+ "logo": "on the column's left edge",
808
+ "links": "14-15px semibold grey"
809
+ },
810
+ "blueprint": "A 46-48px top bar on the page ground over a centred 1088-1208px column; the logo sits exactly on the column's left edge and the bar's right cluster ends near its right edge, so header and content share one column. Three to five text links, a 36px search, the account. Use it for generated reports, viewers and products with few destinations; with a sticky bar on the same ground, give it a 1px rule when content scrolls under it (the studied bar without one sliced content off).",
811
+ "phone": "The bar keeps the logo, a search icon and a menu button; the links move into the menu sheet. The column becomes the full width with 16px margins."
812
+ }
813
+ ],
814
+ "patterns": [
815
+ {
816
+ "id": "kpi-strip-chart-rail",
817
+ "name": "KPI strip, main chart and a side rail",
818
+ "screen": "overview",
819
+ "kinds": [
820
+ "creator",
821
+ "smb-admin",
822
+ "community",
823
+ "analytics"
824
+ ],
825
+ "basis": "a newsletter home; a community overview",
826
+ "blueprint": "Title row: a 24px noun or the product's name at 600-700, an optional 14-16px grey line under it, and the one primary action on the right, bottom-aligned with that line. 16-24px below, the scope row: section tabs and the date range in one row of 32-36px controls, or a 48px segmented track with the range select inside its right end. Then a grid of 1fr and a fixed 384px rail with a 24px gap. Main column: one KPI container split by 1px dividers into 3-5 equal cells (14px grey label, 24px value at 400-600, a 12px caption naming the baseline and window), then the main chart card, which is the largest thing on the screen, then the next card, all 16px apart. Rail: 16px headings outside their cards, 8px above each and 16px after the previous card; a recent-items list of 3-5 rows on a 45px pitch with 1px rules, closed by a 30px outlined 'View all' button instead of pagination. The rail starts level with the first card, not with the title.",
827
+ "phone": "The rail moves below the main column; the KPI container becomes a 2-column grid; tabs scroll inside their own row."
828
+ },
829
+ {
830
+ "id": "kpi-tabs-chart",
831
+ "name": "KPIs as the chart's tabs",
832
+ "screen": "overview",
833
+ "kinds": [
834
+ "finance",
835
+ "commerce"
836
+ ],
837
+ "basis": "a seller home",
838
+ "blueprint": "One card per subject, 8-16px apart: the main chart card runs full width, and any card holding a table of five columns or fewer, or a short list, pairs with its neighbour in two columns, the page header indented by the card padding so the title, the card titles, the numbers and the plot share one left edge. Balances that do not change during the day go first, in one container split by 1px dividers into equal columns; a zero balance is grey and its caption becomes the next step. In the main card, 2-4 KPIs sit in a row and act as the chart's series tabs: the selected one carries a 2px rule and an ink label, the others keep a grey label and their value in ink at a lighter weight (a grey value reads as disabled); when the tabs are the per-entity breakdown the brief asks for (takings by shop), nothing is greyed and the rule alone marks the selection. Choosing one swaps the series. Under them, one line chart as wide as the card's content (about 1136x220 in the study): 3-4 solid 1px gridlines, 4-6 round y ticks at 12px, a 2-3px line in ink with straight segments and no fill, an 8px hover dot with a 1px dashed guide and the line after the cursor in pale grey. Close with a 2-3 row comparison table on a 36px pitch, value and change columns right-aligned under a 14px grey header such as 'vs prior Monday'.",
839
+ "phone": "KPI tabs become a 2-up grid above the chart, with the selected cell marked by a fill (never an underline floating inside the grid) or a row of tabs that scrolls sideways; the chart is full width, 160-200px tall, with 4 x labels; the comparison table keeps its two right-aligned columns."
840
+ },
841
+ {
842
+ "id": "chart-pairs",
843
+ "name": "Per-period and running-total pairs",
844
+ "screen": "analytics",
845
+ "kinds": [
846
+ "community",
847
+ "smb-admin",
848
+ "analytics"
849
+ ],
850
+ "basis": "a network analytics overview",
851
+ "blueprint": "Title at 24-32px with one sentence under it saying what the filters do, then one filter row of 36-38px controls (one filled or near-black, the rest borderless or text, a reset link last) and 16-24px to the KPIs. KPI row: 3 equal cards in the content column (3 x 372 + 2 x 17 = 1152 in the study) or one divided container; a 16px label over the value with the change written as a phrase on the value's baseline ('+8 in the last 90 days'), grey when it is zero. Then one row per metric: the per-period column chart on the left and its cumulative line on the right, at equal width (2 x 568 + 16 = 1152) and with the same x ticks; square bars, a 2px straight line, integer ticks from zero, no legend because each chart has one series. One gap value horizontally and vertically.",
852
+ "phone": "Pairs stack, the cumulative chart directly under its per-period chart; KPI cards become a single column of label-value rows."
853
+ },
854
+ {
855
+ "id": "insights-share-tables",
856
+ "name": "Insights with share tables",
857
+ "screen": "analytics",
858
+ "kinds": [
859
+ "analytics",
860
+ "devtools",
861
+ "builder"
862
+ ],
863
+ "basis": "a per-agent insights page",
864
+ "blueprint": "No cards: sections are carried by whitespace and a 16/500 heading with one 14px grey sentence under it saying what the section shows. A row of up to 6 KPIs on a fixed pitch (12px grey label over a 30px tabular value, no boxes, no dividers), then one full-width time chart (about 218px plot, 5 hairline gridlines, 11-12px grey ticks, a dot legend under the title, a 'Compare to previous period' text button on the right). Then a 2 x 2 grid of small tables with a 24px gutter whose rows align across the two columns. Each table: a header of 12px grey labels with no fill and no rule, 44px rows with 2px gaps whose rounded fill (#f5f7f9, radius 8) is the data bar, its width the row's share divided by the largest share; Share in 12px grey and Count in 14px ink, both right-aligned. An empty table keeps its header and shows one dashed 1px box about 38px tall with one sentence ('No Slack channel usage in this range.').",
865
+ "phone": "KPIs become a 2 x 3 grid; the chart is full width; the share tables stack in one column and keep their row bars."
866
+ },
867
+ {
868
+ "id": "table-filter-bar",
869
+ "name": "Table with tabs and a filter bar",
870
+ "screen": "list",
871
+ "kinds": [
872
+ "community",
873
+ "devtools",
874
+ "commerce",
875
+ "support",
876
+ "smb-admin"
877
+ ],
878
+ "basis": "an events back office, a tracks studio, a sessions overview",
879
+ "blueprint": "Title row: an 18-24px title on the left, at most an outlined secondary and the one primary (36px) on the right. Underline tabs for the list's states on a full-width 1px rule with a 2px indicator as wide as the label; 22-32px below, the toolbar: a search of about 252-316 x 32-36 on the left, the count ('7 events') and the sort on the right. The table sits on the panel or page ground with no card around it: a header of 12-13px grey sentence-case labels with no fill and no rule, rows on a 48-56px pitch for one line or 72-92px with a thumbnail (media height plus 24-32px), 1px rules 3-7% darker than the ground or no rules at all, the identity column given the most width, numbers right-aligned in tabular figures with the unit muted ('5 /10'), one status mark per row and one kebab at the far right. Drop a column that is empty in every row (a blank co-host column left a 300px dead band). On an overview, cap the rows and link to the full list; on the full list, state the total and load more at the end.",
880
+ "phone": "Rows become two-line items: identity and the key number on line 1, the secondary fields in 13px grey on line 2, the kebab at the right. Tabs scroll in their own row; the search becomes a full-width field."
881
+ },
882
+ {
883
+ "id": "count-cards-filter",
884
+ "name": "Count cards that filter",
885
+ "screen": "list",
886
+ "kinds": [
887
+ "community",
888
+ "commerce",
889
+ "support"
890
+ ],
891
+ "basis": "an events back office",
892
+ "blueprint": "Above a list, 3-5 equal count cards (61px tall, 12px padding, a 13px grey label over a 16/600 value, 8px gap) are the type filter: the selected card gets a 1.5px accent border and a pale accent fill, and the list below shows that type only. Zero counts print as '0' in the same style; no deltas, no icons. This is one place where a row of identical small cards is right: the cards are peers and each one does work.",
893
+ "phone": "The count cards become a horizontally scrolling row of chips with the count inside each, or a select above the list."
894
+ },
895
+ {
896
+ "id": "settings-two-column",
897
+ "name": "Settings in two columns",
898
+ "screen": "settings",
899
+ "kinds": [
900
+ "devtools",
901
+ "smb-admin",
902
+ "support",
903
+ "workspace",
904
+ "commerce",
905
+ "analytics",
906
+ "finance",
907
+ "wallet",
908
+ "creator",
909
+ "community",
910
+ "builder",
911
+ "markets",
912
+ "report"
913
+ ],
914
+ "basis": "one settings page; stacking from a narrow rail card. The basis is thin.",
915
+ "blueprint": "A centred column of about 1152px. Each section is one row: a label column of about 450px (16/500 title, 14px grey description; the title's cap top 6-8px below the panel top, level with the panel's first line) beside a panel of about 700px with a #fafafa fill, 16px radius, 16px padding, no border and no shadow. Sections are split by a full-width 1px rule with 32px above and below. Inside a panel: field labels 14/500 above 40px white inputs (1px #e8e8e8, radius 10), 8px from label to field, 16px between fields, 24px from the description to the first label, 16px to the Save button; switch rows with a 14/500 title, a 20px status badge 8px after it, a 14px grey description and a 28x16 toggle 16px from the right edge, centred on the title line. A plan-gated feature shows a 48px tinted strip with a 32px button directly above its panel, and the panel stays readable. When a panel runs much taller than its label, put the section's help or a summary of the current values in the label column rather than 250px of nothing.",
916
+ "phone": "Each section stacks: title and description, then the panel at full width. Inside, label, 8-10px, field, 16-26px to the next pair; toggles stay on the right of their title."
917
+ },
918
+ {
919
+ "id": "settings-with-usage",
920
+ "name": "Settings with usage on top",
921
+ "screen": "settings",
922
+ "kinds": [
923
+ "devtools",
924
+ "smb-admin",
925
+ "support"
926
+ ],
927
+ "basis": "one settings page",
928
+ "blueprint": "Use this only when usage is the question of the view (a plan, billing or quota view), and show only numbers no section below repeats, at a size below the h1. When a settings screen also reports usage, put 3-4 usage numbers in one row on top (a 14px grey label, a 30px regular value, a 12px change pinned to the card bottom with its window in words, a grey dash where there is no comparison) and link out to the analytics screen ('View more') instead of drawing a chart. Below, the two-column settings rows. One dark primary per screen. Keep upsell to one surface: the studied settings page carried three nags (a top banner, a setup button and a gated strip) and was flagged for it.",
929
+ "phone": "The usage row becomes a 2-column grid of label-value pairs; settings rows stack."
930
+ },
931
+ {
932
+ "id": "wallet-balance-actions-assets",
933
+ "name": "Balance, actions and assets",
934
+ "screen": "wallet",
935
+ "kinds": [
936
+ "wallet",
937
+ "finance"
938
+ ],
939
+ "basis": "a wallet home",
940
+ "blueprint": "One column whose every element snaps to its two edges. A balance card (1px border, 16px radius, about 134px tall) holding one 32px figure and one line under it in which only the change is coloured ('-$0.09 in the last 30 days'); the title says what the figure is, so it needs no label. 32px below, 4 equal action tiles in a pale tint with dark same-hue icon and 12-14px label (4 x 144 + 3 x 16 = 624 in the study; scale the column and keep the arithmetic). 32-40px below, text tabs for the asset kinds on a 1px rule with a 2px ink indicator as wide as the word, a network or account select on the right of the same row. Then the asset table: 72px rows (48px round icon plus 24px), no dividers, two-line cells pairing a 16px value with a 14px grey unit amount, numeric columns right-aligned to shared edges, change as a small solid triangle and a coloured percentage, zero change grey, a missing share a grey em dash. On a desktop do not leave the column at phone width: the study's 624px column was flagged as a stretched phone screen; widen it to 864-1100 or give it a second column.",
941
+ "phone": "This pattern is phone-first: the same column at full width with 16px margins, the 4 tiles in one row, the table as two-line rows with the value right-aligned."
942
+ },
943
+ {
944
+ "id": "finance-home-pinned-rail",
945
+ "name": "Finance home with a pinned accounts column",
946
+ "screen": "overview",
947
+ "kinds": [
948
+ "finance",
949
+ "wallet"
950
+ ],
951
+ "basis": "a personal finance home",
952
+ "blueprint": "No page header and no KPI strip: cards start 36px from the top and each headline sum sits in the card that explains it. On the left, a 306px accounts card pinned at the viewport height minus the 36px margins opens with net worth (16/600 label left, value right) and holds the account tree with no dividers: groups 16px ink, categories 14px ink, leaves 14px grey indented 8px, values right-aligned, a 30px pitch and about 45px between groups; an empty group is a bordered box with an '+ Add account' link instead of $0.00. On the right, a 2-column grid with 24px gaps of cards that answer this month's questions, each with its own period caption: the plan (spanning both columns; a ring with an empty hole, a dot legend, the available figure beside it with a per-day line), recent spending as 61px two-line rows (payee over category, amount over date, right-aligned) and upcoming bills. Income is green with a plus sign; spending stays in ink.",
953
+ "phone": "Net worth becomes the first card; the account tree collapses to its groups with totals; the month cards stack."
954
+ },
955
+ {
956
+ "id": "builder-canvas",
957
+ "name": "Builder canvas",
958
+ "screen": "builder",
959
+ "kinds": [
960
+ "builder"
961
+ ],
962
+ "basis": "a flow builder in analytics mode",
963
+ "blueprint": "No global navigation: a 44px top bar on the window ground with no rule (an exit arrow, the object's name at 16/600 with a status pill, and on the right 16px icon buttons on a 40px pitch, a secondary and a near-black primary, split by 1px dividers). Below, two panels on the ground with 8px outer margins and a 12px gap, both with a 1px border, 16px radius and no shadow: a 232px palette (16px padding, groups under 14px labels, items on a 40px pitch with a small type tile, a label and a drag grip) and the canvas, a flat well one step darker than the ground (#f4f6f8 on #f9fbfc) with no dot grid. Nodes share one width (338px in the study), 12px radius, a 1px hairline, padding 16 on top and 12 at the sides, a type tile and a 16/600 title, and their metrics in a well as key-value rows on a 32px pitch with right-aligned tabular or mono values ('0% (0)'). Nodes stack on one spine 64px apart with a 38px round insert button centred in each gap; connectors are 1px orthogonal lines with 6px rounded elbows. Overlays (date range, zoom, minimap) are small white controls pinned 16px inside the canvas corners. Canvas content is one size larger than the chrome (16 against 14). Node-type tiles may be tinted, one pastel per type, the same in the palette and on the canvas: pass --allow icon-chips to the inspector and say why.",
964
+ "phone": "Editing a graph on a phone is rarely the job: show the flow read-only as a vertical list of nodes with their metrics, and the palette as a bottom sheet if editing is kept."
965
+ },
966
+ {
967
+ "id": "inbox-triage",
968
+ "name": "Inbox triage",
969
+ "screen": "inbox",
970
+ "kinds": [
971
+ "support",
972
+ "workspace"
973
+ ],
974
+ "basis": "assembled from the study's list, feed and rail measurements; no inbox screen was in the study",
975
+ "blueprint": "Three regions on one ground: the navigation (a 230px sidebar or a 55px rail), the list, and the open item with its details. The list column has a fixed width (the study's fixed columns are 306 and 384px) and its own toolbar: saved views as underline tabs or a select, a 32px search, the count. Rows are two-line, 64-80px: line 1 is who (14/600) with the time in words right-aligned in grey ('9 min', 'Yesterday'); line 2 is the subject or last message in 13-14px grey, truncated to one line with an ellipsis. Unread rows set the name at 600 and add a 6px dot or a 16px count circle; read rows keep the name and subject in ink at 400 (grey is for meta only, never for a row's identity: faded urgent rows were the top complaint in testing). One status mark per row (priority or SLA, as a pale pill or words, not both). The selected row takes the --active fill of the nav pill (optionally a 2px accent bar inside its left edge), so it is never confused with a hover or a focus ring; never a saturated fill. The row's meta sits in fixed right-aligned slots (assignee 20px, channel 14px, priority 14px) so it lines up as columns; priority is printed only above normal. The open item fills the remaining width; its details (customer, plan, history) sit in a fixed column of 306-384px as key-value rows on a 28-32px pitch.",
976
+ "phone": "One region at a time: the list fills the screen; choosing a row pushes the conversation; the details open from a button in its header; back returns to the list at the same scroll position."
977
+ },
978
+ {
979
+ "id": "workspace-home-greeting",
980
+ "name": "Workspace home with a greeting",
981
+ "screen": "home",
982
+ "kinds": [
983
+ "workspace",
984
+ "creator"
985
+ ],
986
+ "basis": "a team workspace home; a personal insights home",
987
+ "blueprint": "A centred column on a real 12-column grid (77px columns, 16px gutters, 1100px), about 72px from the top. The greeting is the h1 (48/700 in a serif, or 24/400 in the sans), with the date after it or in a grey line under it, never as a tracked eyebrow, and no emoji. 50px below, 4 count tiles spanning 3 columns each (128px tall, 16px padding): label, value at regular weight in tabular or mono figures, a plain caption ('Ready when you are'), no deltas. Then spans that change by row but share column lines (9 + 3, then 6 + 6, so each internal edge meets one above it) for the main objects: panels with 20px padding, a 14/600 title, a count chip and a 'View all' link, holding row cards 63px tall with 8px gaps, one step lighter than the panel with a border one step darker. Pale tints may code the panels, each in the hue of the tile that counts it. Only a floating composer, if there is one, carries a shadow, and it must not cover the last rows.",
988
+ "phone": "Greeting at 24-28px; tiles in a 2 x 2 grid; panels stack in reading order."
989
+ },
990
+ {
991
+ "id": "object-detail-header-grid",
992
+ "name": "Object header and a six-column grid",
993
+ "screen": "detail",
994
+ "kinds": [
995
+ "community",
996
+ "commerce",
997
+ "analytics"
998
+ ],
999
+ "basis": "an event's analytics tab",
1000
+ "blueprint": "The page header is the object itself: one card (88px, 14px padding) holding a 50x62 cover, the 18/600 name with 28px icon buttons beside it (open, copy, share), a 13px grey meta line (date, time, place) and outlined 36px actions on the right. Under it, underline tabs on a full-width 1px rule, then a 36px row with a segmented time range on the left and a refresh button on the right. The body is one 6-column grid with one gutter (14px) in both directions whose spans change by row while every edge lands on the same lines: 3 KPI tiles of 2 columns, the main chart in 4 columns beside a side chart in 2, two progress cards of 3, a full-width trend of 6. Give the widest card to the screen's question, and do not give 824px to one ring and one legend row (flagged).",
1001
+ "phone": "The header card keeps cover, name and meta, with actions in a kebab; every grid item takes the full width in the same order."
1002
+ },
1003
+ {
1004
+ "id": "generated-report",
1005
+ "name": "Generated report",
1006
+ "screen": "report",
1007
+ "kinds": [
1008
+ "report",
1009
+ "analytics"
1010
+ ],
1011
+ "basis": "a report generated from a CSV",
1012
+ "blueprint": "No sidebar; the only chrome is a 47-48px viewer bar with a 1px rule. A centred 1088px column 33px below it: a 24/600 title, a 12px grey line 4px under it naming the source and the load time, one outlined 30px action on the right ('Refresh view'). If the data is a snapshot, one quiet notice (#fffbeb fill, 1px #fde68a, 12px #92400e text, 34px tall). Then 4 stat cards with a 12px gap (4 x 263 + 3 x 12 = 1088), a 12px grey label over an 18/600 tabular value; put the date range in the subtitle, not in a lone fifth card. Two charts side by side at the same 12px gap so their edges meet the stat columns: a time chart on a real time axis with flat labels, and a histogram with equal bins and square bottoms. Then the records table in a card: a 256x30 search in its header, a 14/600 grey header row over a 1px #e5e7eb rule, 37px rows over lighter #f3f4f6 rules, numbers right-aligned, a sort glyph on the active column only.",
1013
+ "phone": "Stats in a 2 x 2 grid; charts stacked; the table as two-line rows, or scrolling inside its own frame with the first column fixed."
1014
+ },
1015
+ {
1016
+ "id": "tabbed-object-detail",
1017
+ "name": "Tabbed object detail in a sheet",
1018
+ "screen": "detail",
1019
+ "kinds": [
1020
+ "analytics",
1021
+ "smb-admin",
1022
+ "builder",
1023
+ "support"
1024
+ ],
1025
+ "basis": "a list's engagement tab; a reports dashboard",
1026
+ "blueprint": "Inside the sheet: a breadcrumb row at 16/600 (the parent in grey, the current page as the h1, a 24px grey type chip after it) with its actions on the right (a text button and an outlined 32px dropdown). Under it, the object's tabs at 14px with a 2px ink underline that runs 8px past the label, on a 1px rule that spans the sheet. 30px below, the filter row: a label above a 300x32 select on the left; the freshness stamp ('Last updated July 21, 2026') and a 40px refresh button on the right, centred on the select's line. Then 3 KPI cards (value 36/400, its label at 16/600 under it, the period in words) and 2 chart cards, all on one 24px gutter so the rows share column lines. Do not stretch a short card to its neighbour's height (it left 250px of dead white) and do not list legend series that have no data.",
1027
+ "phone": "Breadcrumb shortens to a back link and the h1; tabs scroll; KPI cards stack as label-value rows; charts full width."
1028
+ },
1029
+ {
1030
+ "id": "report-card-legend-table",
1031
+ "name": "Report card with a legend table",
1032
+ "screen": "analytics",
1033
+ "kinds": [
1034
+ "analytics",
1035
+ "smb-admin"
1036
+ ],
1037
+ "basis": "a campaign overview",
1038
+ "blueprint": "A report card (20/600 title, a kebab top right, a 32px select for the scope) whose body splits into a 390px left block and the chart. Left: the hero number at 24/400 with its label under it and one change pill with its window ('vs. previous period'), then the legend as a mini table of 2-4 metric rows on a 57px pitch: dot, name at 15/600, a benchmark pill, the value right-aligned, the change right-aligned. Right: the line chart with 4 gridlines at round values, a 2px baseline with ticks, y labels on the right and axis text no larger than the data (12-14px; 16px ticks were flagged as louder than the numbers). Under it, a detail table whose rate cells stack the count over a 12px grey percentage on one right edge. Use the same colour for a series in the legend dot and in the line.",
1039
+ "phone": "The legend table goes above the chart; the detail table becomes two-line rows."
1040
+ },
1041
+ {
1042
+ "id": "research-lists-table",
1043
+ "name": "Research lists and a long table",
1044
+ "screen": "analytics",
1045
+ "kinds": [
1046
+ "markets",
1047
+ "devtools"
1048
+ ],
1049
+ "basis": "a stock research view",
1050
+ "blueprint": "Header: a 26/700 title over a 20px grey date, quiet pill buttons on the right; a 1px rule about 44px below, with the tabs just under it and the active tab marked by a 1px accent line as wide as its label lying on that rule. 64px below, a 2-column row of cards at about 43/57 with a 24px gap: a ranked list on a 28px pitch (16px logo, bold ticker, grey name truncated, a right-aligned grey percentage and a white value, signs in the text) and a chart card with its legend in the header (5px dots, 13px grey labels), a text range selector under the baseline (1M 3M 6M YTD All, the active one marked by the same 1px accent segment) and 'Updated daily' in 11-12px grey. Then a 20/400 grey section title and a full-width table: a 38px header of 11-12px grey labels, 42px rows over 1px rules, ISO dates and every figure right-aligned in tabular numerals, white only for the identity and the total. Give the chart a y-scale and dates (the studied chart had neither and was flagged).",
1051
+ "phone": "Cards stack; the range selector stays as text under the chart; the table becomes two-line rows with the total on the right."
1052
+ },
1053
+ {
1054
+ "id": "platform-overview-tray",
1055
+ "name": "Platform overview with a usage tray",
1056
+ "screen": "overview",
1057
+ "kinds": [
1058
+ "devtools",
1059
+ "analytics"
1060
+ ],
1061
+ "basis": "a developer platform project overview",
1062
+ "blueprint": "Sections stacked in one column about 48px apart, each with an 18/500 title on the left and a quiet action on the right ('View all', an outlined Refresh, a date-range button), and freshness in 14px grey after the title with a small status dot. First, a getting-started strip: one container split by 1px dividers into 4 equal cells (16/500 title, a 14px description, a grey arrow top right), shown until setup is done. Then the recent items table, capped at 4-5 rows on a 49px pitch: IDs in mono truncated to 8 characters plus an ellipsis with a copy icon, relative expiry in grey, rules that bleed 8px past the text column. Then usage: a #fafafa tray with 6px padding holding a KPI strip of 5 equal cells (a 14/500 label over a 24/400 value with a 14px unit suffix, '5 mins') and, 6px below, a chart card whose metric is chosen by the KPI cells themselves (the selected cell marked by a 2px rule or the active fill), never a second control repeating the KPI labels; the chart takes two-thirds of the width when its line is flat for most of the window, with the next answer beside it. Durations and timestamps in tabular figures. A missing value is a grey dash at label size, not '--' at value size.",
1063
+ "phone": "The getting-started strip becomes a 2 x 2 grid or a list; the table becomes two-line rows; the KPI strip a 2-column grid."
1064
+ },
1065
+ {
1066
+ "id": "bar-list-ranking",
1067
+ "name": "Bar list and ranking",
1068
+ "screen": "analytics",
1069
+ "kinds": [
1070
+ "analytics",
1071
+ "smb-admin"
1072
+ ],
1073
+ "basis": "an AI-search visibility overview",
1074
+ "blueprint": "A 24/700 title with one factual stat chip beside the actions on the right; underline tabs on a 1px rule; a filter row of compound outlined groups that read as a sentence ('Date | Jun 14 - Jul 13 | Daily', 'Region | United States'), 28px tall and 8px apart. KPIs: as many equal columns as there are KPIs (four across, not four in a three-column grid that orphans one), tabular or mono values with fixed decimals. Then two equal panels, each with a 73px header (14/600 title, a 13px grey description, a dropdown that switches the panel's metric) over a full-bleed 1px rule: a sorted bar list (rows on a 64px pitch, a label line, then a 10px pill bar in one colour with no track, the value 5px after the bar's end, the longest bar about 88% of the width) and a ranking table (53px rows, rules inset to the padding, a rank, a 16px logo, a soft chip on the user's own row, values right-aligned). Do not fix a panel's height so its last row is cut off (flagged).",
1075
+ "phone": "KPIs in a 2 x 2 grid; panels stack; the bar list keeps its bars at full width."
1076
+ },
1077
+ {
1078
+ "id": "deploy-health-lead",
1079
+ "name": "Current deploy and health lead",
1080
+ "screen": "overview",
1081
+ "kinds": [
1082
+ "devtools"
1083
+ ],
1084
+ "basis": "house pattern from testing: built after a flat 24-hour chart filled a whole first screen and lost to a richer layout",
1085
+ "blueprint": "Title row: the project's name as the h1 with a status pill (Healthy, Degraded) and a breadcrumb of team and product above it; repository, branch and a freshness stamp in a 14px grey line under it; the one primary action (Redeploy, or View logs when the latest deploy failed) on the right. Then a full-width card for what is live now: the production deployment's commit message at 16/600, its branch, short SHA in mono, author and age on the left, and three or four facts in divided cells on the right (domain, live since, build time, regions). Then the health strip: three or four KPIs in one divided container, each with its change in words and in the polarity colour when it moved the wrong way. Then a two-column row: the 24-hour chart at two-thirds (deploy markers as 1px ticks with their short SHA, the budget or SLO as a dashed reference line) and, at one-third, the block that explains the worst number (the spike and what reverted it, the status codes behind the error rate). Then the deployments table capped at 6 rows, a failed row carrying its failing step and a View logs action, a building row its elapsed time.",
1086
+ "phone": "The live deployment card becomes a stack of label-value rows; the KPIs a 2x2 grid; the chart full width with its markers; the explanation under it; deployments as two-line rows with region and duration on line 2."
1087
+ },
1088
+ {
1089
+ "id": "power-flow",
1090
+ "name": "Power flow summary",
1091
+ "signature": true,
1092
+ "cues": [
1093
+ "energy",
1094
+ "solar",
1095
+ "battery",
1096
+ "kwh",
1097
+ "tariff",
1098
+ "heat pump",
1099
+ "electric car",
1100
+ "ev charger",
1101
+ "home charger"
1102
+ ],
1103
+ "basis": "house pattern from round-4 testing: a home-energy overview without it read as the stock dark dashboard; real energy apps lead with this flow",
1104
+ "blueprint": "A strip under the title row that answers \"where is the power going now?\": four nodes in one row (Sun, House, Battery, Grid), each a 14px label over its live figure at 20-24px with the unit as a grey suffix (2.4 kW), the battery's charge under its figure (88%). Between neighbours, a 2px connector only where power flows now, with its direction and amount in words above it (\"to battery 1.7 kW\"); an idle link is a 1px dashed rule in the grid colour. Solar and export carry the one data hue, import from the grid is grey, the house is ink. The flows balance and are built from one live-state object that also feeds the top bar and the charts: sun + grid import + battery out = house + battery in + export. A freshness stamp at the strip's right (\"Live · 20:34\").",
1105
+ "phone": "The four nodes become a 2x2 grid in the same order (Sun, House / Battery, Grid) with the flow sentence under it (\"Sun 2.4 kW: house 0.7, battery 1.7\"), no connectors."
1106
+ },
1107
+ {
1108
+ "id": "leave-timeline",
1109
+ "name": "Team timeline with kind encoding",
1110
+ "signature": true,
1111
+ "cues": [
1112
+ "leave",
1113
+ "holiday",
1114
+ "time off",
1115
+ "absence",
1116
+ "pto",
1117
+ "vacation",
1118
+ "rota",
1119
+ "roster",
1120
+ "shift",
1121
+ "booking"
1122
+ ],
1123
+ "basis": "house pattern from round-4 testing: a leave calendar that drew every booking in the same pale grey read as a loading state",
1124
+ "blueprint": "People down the left on a 160-220px column, grouped under 12px team subheaders; days across with weekends one tone step darker, faint 1px day lines, and today as a 1px line in the one data hue with its date in ink in the header. Each kind of booking has its own mark, drawn with `Charts.timeline(el, rows, kinds)`: holiday a pale fill, off sick a 1px diagonal hatch, long leave a darker grey step, working away an outline, a pending request a dashed outline. Full colour only for what needs a decision: a request that breaks cover is outlined and labelled in the negative colour. Bars 20-24px tall at radius 4; the label inside the bar, the kind's code when the bar is too short, then the label after the bar's end, never over the days before it. One-line names on a 32px pitch; a name with a subline (team, office) on 40-44px. A public holiday is a small dot under its date whose tooltip names the office. The legend is the one the helper returns, so each swatch is its mark scaled down and only kinds on screen are listed.",
1125
+ "phone": "One week at a time, with the week switch in the same control row as any office filter; names shorten to first name and initial; the legend sits in a 2-column grid."
1126
+ },
1127
+ {
1128
+ "id": "cover-matrix",
1129
+ "name": "Cover against the minimum",
1130
+ "signature": true,
1131
+ "cues": [
1132
+ "team cover",
1133
+ "cover by",
1134
+ "staffing",
1135
+ "rota",
1136
+ "roster",
1137
+ "shift",
1138
+ "coverage",
1139
+ "on call",
1140
+ "leave"
1141
+ ],
1142
+ "basis": "house pattern from round-4 testing: a grid of 120 absolute headcounts made the reader subtract each team's minimum in their head",
1143
+ "blueprint": "A team-by-day matrix of slack against each team's minimum (+2, +1, 0, −1) rather than headcounts, drawn with `Charts.matrix(el, rows, { cols, comfort })`: the team and its rule (\"needs 7 of 10\") in a 160-220px label column on a 40-44px pitch, one cell per working day with the signed slack in 12px tabular figures. Cells with room to spare stay plain; one hue ramps toward the negative colour as the slack runs out (tight a pale tint, at the minimum a stronger tint, short the full negative with white figures), and the headcount sits in the tooltip (\"6 in of 9, needs 7\"). Today's column has its date in ink. The days that go short are the finding in the title row, beside the request that causes them.",
1144
+ "phone": "The lowest slack per team for each week (four columns), with the days behind a tap; or one team at a time."
1145
+ },
1146
+ {
1147
+ "id": "sell-out-strip",
1148
+ "name": "Sell-out time strip",
1149
+ "signature": true,
1150
+ "cues": [
1151
+ "bakery",
1152
+ "cafe",
1153
+ "café",
1154
+ "kitchen",
1155
+ "restaurant",
1156
+ "sell-out",
1157
+ "sell out",
1158
+ "sold out",
1159
+ "deli",
1160
+ "menu",
1161
+ "bake"
1162
+ ],
1163
+ "basis": "house pattern from round-4 testing: six 4px black bars for sell-out times were the loudest marks on a bakery screen and drew no comparison",
1164
+ "blueprint": "One row per line that sold out, earliest first: the line and its shop on the left; a 2px grey track on a shared opening-to-closing axis with an ink dot at today's sell-out time and a hollow tick at the comparison day's (last Sunday), drawn with `Charts.timeStrip(el, rows, { open, close, compareLabel })`; the time on the right in ink with the gap under it in 12px grey, its baseline named (\"3 h 40 m before close\", \"45 m earlier than last Sunday\"). The lines that did not sell out are counted in one closing sentence, not drawn. Axis labels on one hourly step from opening; the legend (Today, Last Sunday) is the one the helper returns.",
1165
+ "phone": "The rows keep the full width with axis labels every two hours; the gap moves under the line's name."
1166
+ }
1167
+ ],
1168
+ "kinds": {
1169
+ "finance": {
1170
+ "note": "money homes, budgeting, accounting, seller balances",
1171
+ "styles": [
1172
+ "achromatic-ledger",
1173
+ "pastel-consumer"
1174
+ ],
1175
+ "screens": [
1176
+ "overview",
1177
+ "list",
1178
+ "settings"
1179
+ ]
1180
+ },
1181
+ "wallet": {
1182
+ "note": "consumer wallets, crypto, personal finance on the go",
1183
+ "styles": [
1184
+ "pastel-consumer",
1185
+ "achromatic-ledger"
1186
+ ],
1187
+ "screens": [
1188
+ "wallet",
1189
+ "list",
1190
+ "settings"
1191
+ ]
1192
+ },
1193
+ "commerce": {
1194
+ "note": "seller and shop back offices: orders, payouts, products",
1195
+ "styles": [
1196
+ "achromatic-ledger",
1197
+ "framed-sheet"
1198
+ ],
1199
+ "screens": [
1200
+ "overview",
1201
+ "list",
1202
+ "detail"
1203
+ ]
1204
+ },
1205
+ "analytics": {
1206
+ "note": "B2B analytics, marketing and growth reporting",
1207
+ "styles": [
1208
+ "framed-sheet",
1209
+ "achromatic-ledger",
1210
+ "accent-ladder"
1211
+ ],
1212
+ "screens": [
1213
+ "analytics",
1214
+ "list",
1215
+ "detail"
1216
+ ]
1217
+ },
1218
+ "devtools": {
1219
+ "note": "developer platforms: deploys, sessions, API keys, usage",
1220
+ "styles": [
1221
+ "framed-sheet",
1222
+ "data-terminal",
1223
+ "achromatic-ledger"
1224
+ ],
1225
+ "screens": [
1226
+ "overview",
1227
+ "list",
1228
+ "settings"
1229
+ ]
1230
+ },
1231
+ "builder": {
1232
+ "note": "flow, form, page and automation builders",
1233
+ "styles": [
1234
+ "framed-sheet",
1235
+ "achromatic-ledger"
1236
+ ],
1237
+ "screens": [
1238
+ "builder",
1239
+ "list",
1240
+ "settings"
1241
+ ]
1242
+ },
1243
+ "creator": {
1244
+ "note": "newsletters, creator studios, audience insights",
1245
+ "styles": [
1246
+ "accent-ladder",
1247
+ "editorial-greeting",
1248
+ "true-black-flat"
1249
+ ],
1250
+ "screens": [
1251
+ "overview",
1252
+ "analytics",
1253
+ "list"
1254
+ ]
1255
+ },
1256
+ "smb-admin": {
1257
+ "note": "small-business and SaaS admin with plans, onboarding and growth nudges",
1258
+ "styles": [
1259
+ "accent-ladder",
1260
+ "framed-sheet"
1261
+ ],
1262
+ "screens": [
1263
+ "overview",
1264
+ "list",
1265
+ "settings"
1266
+ ]
1267
+ },
1268
+ "workspace": {
1269
+ "note": "team hubs and personal homes",
1270
+ "styles": [
1271
+ "editorial-greeting",
1272
+ "achromatic-ledger"
1273
+ ],
1274
+ "screens": [
1275
+ "home",
1276
+ "inbox",
1277
+ "settings"
1278
+ ]
1279
+ },
1280
+ "community": {
1281
+ "note": "community, events and media back offices",
1282
+ "styles": [
1283
+ "true-black-flat",
1284
+ "accent-ladder"
1285
+ ],
1286
+ "screens": [
1287
+ "overview",
1288
+ "list",
1289
+ "detail"
1290
+ ]
1291
+ },
1292
+ "support": {
1293
+ "note": "support inboxes, queues, helpdesks",
1294
+ "styles": [
1295
+ "achromatic-ledger",
1296
+ "framed-sheet"
1297
+ ],
1298
+ "screens": [
1299
+ "inbox",
1300
+ "list",
1301
+ "settings"
1302
+ ]
1303
+ },
1304
+ "markets": {
1305
+ "note": "trading, research and monitoring read in long sessions",
1306
+ "styles": [
1307
+ "data-terminal",
1308
+ "true-black-flat"
1309
+ ],
1310
+ "screens": [
1311
+ "analytics",
1312
+ "list",
1313
+ "detail"
1314
+ ]
1315
+ },
1316
+ "report": {
1317
+ "note": "generated or exported reports with no app around them",
1318
+ "styles": [
1319
+ "achromatic-ledger",
1320
+ "framed-sheet"
1321
+ ],
1322
+ "screens": [
1323
+ "report"
1324
+ ]
1325
+ }
1326
+ }
1327
+ }