@design-intelligence/ghost 0.0.0-next-20260715121453

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 (327) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +89 -0
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +19 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/cli.d.ts +4 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +29 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/checks-command.d.ts +9 -0
  12. package/dist/commands/checks-command.d.ts.map +1 -0
  13. package/dist/commands/checks-command.js +52 -0
  14. package/dist/commands/checks-command.js.map +1 -0
  15. package/dist/commands/command-discovery.d.ts +57 -0
  16. package/dist/commands/command-discovery.d.ts.map +1 -0
  17. package/dist/commands/command-discovery.js +220 -0
  18. package/dist/commands/command-discovery.js.map +1 -0
  19. package/dist/commands/errors.d.ts +7 -0
  20. package/dist/commands/errors.d.ts.map +1 -0
  21. package/dist/commands/errors.js +19 -0
  22. package/dist/commands/errors.js.map +1 -0
  23. package/dist/commands/export-command.d.ts +3 -0
  24. package/dist/commands/export-command.d.ts.map +1 -0
  25. package/dist/commands/export-command.js +157 -0
  26. package/dist/commands/export-command.js.map +1 -0
  27. package/dist/commands/fingerprint-commands.d.ts +10 -0
  28. package/dist/commands/fingerprint-commands.d.ts.map +1 -0
  29. package/dist/commands/fingerprint-commands.js +69 -0
  30. package/dist/commands/fingerprint-commands.js.map +1 -0
  31. package/dist/commands/gather-command.d.ts +3 -0
  32. package/dist/commands/gather-command.d.ts.map +1 -0
  33. package/dist/commands/gather-command.js +214 -0
  34. package/dist/commands/gather-command.js.map +1 -0
  35. package/dist/commands/init-command.d.ts +3 -0
  36. package/dist/commands/init-command.d.ts.map +1 -0
  37. package/dist/commands/init-command.js +89 -0
  38. package/dist/commands/init-command.js.map +1 -0
  39. package/dist/commands/manifest-command.d.ts +9 -0
  40. package/dist/commands/manifest-command.d.ts.map +1 -0
  41. package/dist/commands/manifest-command.js +33 -0
  42. package/dist/commands/manifest-command.js.map +1 -0
  43. package/dist/commands/pull-command.d.ts +3 -0
  44. package/dist/commands/pull-command.d.ts.map +1 -0
  45. package/dist/commands/pull-command.js +230 -0
  46. package/dist/commands/pull-command.js.map +1 -0
  47. package/dist/commands/pulse-command.d.ts +3 -0
  48. package/dist/commands/pulse-command.d.ts.map +1 -0
  49. package/dist/commands/pulse-command.js +248 -0
  50. package/dist/commands/pulse-command.js.map +1 -0
  51. package/dist/commands/review-command.d.ts +3 -0
  52. package/dist/commands/review-command.d.ts.map +1 -0
  53. package/dist/commands/review-command.js +78 -0
  54. package/dist/commands/review-command.js.map +1 -0
  55. package/dist/commands/skill-command.d.ts +3 -0
  56. package/dist/commands/skill-command.d.ts.map +1 -0
  57. package/dist/commands/skill-command.js +96 -0
  58. package/dist/commands/skill-command.js.map +1 -0
  59. package/dist/fingerprint.d.ts +5 -0
  60. package/dist/fingerprint.d.ts.map +1 -0
  61. package/dist/fingerprint.js +3 -0
  62. package/dist/fingerprint.js.map +1 -0
  63. package/dist/ghost-core/catalog/assemble.d.ts +26 -0
  64. package/dist/ghost-core/catalog/assemble.d.ts.map +1 -0
  65. package/dist/ghost-core/catalog/assemble.js +29 -0
  66. package/dist/ghost-core/catalog/assemble.js.map +1 -0
  67. package/dist/ghost-core/catalog/closest.d.ts +16 -0
  68. package/dist/ghost-core/catalog/closest.d.ts.map +1 -0
  69. package/dist/ghost-core/catalog/closest.js +63 -0
  70. package/dist/ghost-core/catalog/closest.js.map +1 -0
  71. package/dist/ghost-core/catalog/index.d.ts +10 -0
  72. package/dist/ghost-core/catalog/index.d.ts.map +1 -0
  73. package/dist/ghost-core/catalog/index.js +9 -0
  74. package/dist/ghost-core/catalog/index.js.map +1 -0
  75. package/dist/ghost-core/catalog/menu.d.ts +28 -0
  76. package/dist/ghost-core/catalog/menu.d.ts.map +1 -0
  77. package/dist/ghost-core/catalog/menu.js +23 -0
  78. package/dist/ghost-core/catalog/menu.js.map +1 -0
  79. package/dist/ghost-core/catalog/types.d.ts +33 -0
  80. package/dist/ghost-core/catalog/types.d.ts.map +1 -0
  81. package/dist/ghost-core/catalog/types.js +2 -0
  82. package/dist/ghost-core/catalog/types.js.map +1 -0
  83. package/dist/ghost-core/check/index.d.ts +12 -0
  84. package/dist/ghost-core/check/index.d.ts.map +1 -0
  85. package/dist/ghost-core/check/index.js +12 -0
  86. package/dist/ghost-core/check/index.js.map +1 -0
  87. package/dist/ghost-core/check/lint.d.ts +9 -0
  88. package/dist/ghost-core/check/lint.d.ts.map +1 -0
  89. package/dist/ghost-core/check/lint.js +119 -0
  90. package/dist/ghost-core/check/lint.js.map +1 -0
  91. package/dist/ghost-core/check/load.d.ts +7 -0
  92. package/dist/ghost-core/check/load.d.ts.map +1 -0
  93. package/dist/ghost-core/check/load.js +44 -0
  94. package/dist/ghost-core/check/load.js.map +1 -0
  95. package/dist/ghost-core/check/parse.d.ts +12 -0
  96. package/dist/ghost-core/check/parse.d.ts.map +1 -0
  97. package/dist/ghost-core/check/parse.js +13 -0
  98. package/dist/ghost-core/check/parse.js.map +1 -0
  99. package/dist/ghost-core/check/source-ref.d.ts +27 -0
  100. package/dist/ghost-core/check/source-ref.d.ts.map +1 -0
  101. package/dist/ghost-core/check/source-ref.js +58 -0
  102. package/dist/ghost-core/check/source-ref.js.map +1 -0
  103. package/dist/ghost-core/check/types.d.ts +48 -0
  104. package/dist/ghost-core/check/types.d.ts.map +1 -0
  105. package/dist/ghost-core/check/types.js +4 -0
  106. package/dist/ghost-core/check/types.js.map +1 -0
  107. package/dist/ghost-core/errors.d.ts +30 -0
  108. package/dist/ghost-core/errors.d.ts.map +1 -0
  109. package/dist/ghost-core/errors.js +33 -0
  110. package/dist/ghost-core/errors.js.map +1 -0
  111. package/dist/ghost-core/glob.d.ts +5 -0
  112. package/dist/ghost-core/glob.d.ts.map +1 -0
  113. package/dist/ghost-core/glob.js +68 -0
  114. package/dist/ghost-core/glob.js.map +1 -0
  115. package/dist/ghost-core/glossary.d.ts +25 -0
  116. package/dist/ghost-core/glossary.d.ts.map +1 -0
  117. package/dist/ghost-core/glossary.js +69 -0
  118. package/dist/ghost-core/glossary.js.map +1 -0
  119. package/dist/ghost-core/index.d.ts +13 -0
  120. package/dist/ghost-core/index.d.ts.map +1 -0
  121. package/dist/ghost-core/index.js +19 -0
  122. package/dist/ghost-core/index.js.map +1 -0
  123. package/dist/ghost-core/markdown.d.ts +15 -0
  124. package/dist/ghost-core/markdown.d.ts.map +1 -0
  125. package/dist/ghost-core/markdown.js +30 -0
  126. package/dist/ghost-core/markdown.js.map +1 -0
  127. package/dist/ghost-core/material-transport.d.ts +43 -0
  128. package/dist/ghost-core/material-transport.d.ts.map +1 -0
  129. package/dist/ghost-core/material-transport.js +231 -0
  130. package/dist/ghost-core/material-transport.js.map +1 -0
  131. package/dist/ghost-core/materials.d.ts +14 -0
  132. package/dist/ghost-core/materials.d.ts.map +1 -0
  133. package/dist/ghost-core/materials.js +52 -0
  134. package/dist/ghost-core/materials.js.map +1 -0
  135. package/dist/ghost-core/node/index.d.ts +11 -0
  136. package/dist/ghost-core/node/index.d.ts.map +1 -0
  137. package/dist/ghost-core/node/index.js +11 -0
  138. package/dist/ghost-core/node/index.js.map +1 -0
  139. package/dist/ghost-core/node/parse.d.ts +16 -0
  140. package/dist/ghost-core/node/parse.d.ts.map +1 -0
  141. package/dist/ghost-core/node/parse.js +55 -0
  142. package/dist/ghost-core/node/parse.js.map +1 -0
  143. package/dist/ghost-core/node/schema.d.ts +17 -0
  144. package/dist/ghost-core/node/schema.d.ts.map +1 -0
  145. package/dist/ghost-core/node/schema.js +49 -0
  146. package/dist/ghost-core/node/schema.js.map +1 -0
  147. package/dist/ghost-core/node/serialize.d.ts +12 -0
  148. package/dist/ghost-core/node/serialize.d.ts.map +1 -0
  149. package/dist/ghost-core/node/serialize.js +39 -0
  150. package/dist/ghost-core/node/serialize.js.map +1 -0
  151. package/dist/ghost-core/node/steering.d.ts +19 -0
  152. package/dist/ghost-core/node/steering.d.ts.map +1 -0
  153. package/dist/ghost-core/node/steering.js +68 -0
  154. package/dist/ghost-core/node/steering.js.map +1 -0
  155. package/dist/ghost-core/node/types.d.ts +43 -0
  156. package/dist/ghost-core/node/types.d.ts.map +1 -0
  157. package/dist/ghost-core/node/types.js +2 -0
  158. package/dist/ghost-core/node/types.js.map +1 -0
  159. package/dist/ghost-core/package-manifest.d.ts +19 -0
  160. package/dist/ghost-core/package-manifest.d.ts.map +1 -0
  161. package/dist/ghost-core/package-manifest.js +24 -0
  162. package/dist/ghost-core/package-manifest.js.map +1 -0
  163. package/dist/ghost-core/skill-bundle-loader.d.ts +28 -0
  164. package/dist/ghost-core/skill-bundle-loader.d.ts.map +1 -0
  165. package/dist/ghost-core/skill-bundle-loader.js +51 -0
  166. package/dist/ghost-core/skill-bundle-loader.js.map +1 -0
  167. package/dist/index.d.ts +5 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +5 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/init-payloads/median/cliche.median.md +86 -0
  172. package/dist/init-payloads/median/median-tells.md +117 -0
  173. package/dist/init-payloads/skeleton/brand.md +23 -0
  174. package/dist/init-payloads/skeleton/context.conversation.md +24 -0
  175. package/dist/init-payloads/skeleton/foundation.color.md +39 -0
  176. package/dist/init-payloads/skeleton/foundation.composition.md +30 -0
  177. package/dist/init-payloads/skeleton/foundation.controls.md +29 -0
  178. package/dist/init-payloads/skeleton/foundation.layout.md +45 -0
  179. package/dist/init-payloads/skeleton/foundation.motion.md +34 -0
  180. package/dist/init-payloads/skeleton/foundation.type.md +44 -0
  181. package/dist/init-payloads/skeleton/foundation.voice.md +29 -0
  182. package/dist/init-payloads/skeleton/glossary.md +39 -0
  183. package/dist/init-payloads/vessel-light/anti-goal.median.md +86 -0
  184. package/dist/init-payloads/vessel-light/anti-goal.tells.md +38 -0
  185. package/dist/init-payloads/vessel-light/checks/conversation-grammar.md +20 -0
  186. package/dist/init-payloads/vessel-light/checks/median-tells.md +103 -0
  187. package/dist/init-payloads/vessel-light/checks/motion-restraint.md +20 -0
  188. package/dist/init-payloads/vessel-light/checks/relationships.md +33 -0
  189. package/dist/init-payloads/vessel-light/checks/shape-matches-job.md +43 -0
  190. package/dist/init-payloads/vessel-light/checks/values.md +51 -0
  191. package/dist/init-payloads/vessel-light/glossary.md +44 -0
  192. package/dist/init-payloads/vessel-light/grammar.color-roles.md +30 -0
  193. package/dist/init-payloads/vessel-light/grammar.conversation.md +30 -0
  194. package/dist/init-payloads/vessel-light/grammar.deletion.md +35 -0
  195. package/dist/init-payloads/vessel-light/grammar.hierarchy.md +58 -0
  196. package/dist/init-payloads/vessel-light/grammar.job.md +54 -0
  197. package/dist/init-payloads/vessel-light/grammar.motion.md +27 -0
  198. package/dist/init-payloads/vessel-light/grammar.rhythm.md +27 -0
  199. package/dist/init-payloads/vessel-light/grammar.surfaces.md +35 -0
  200. package/dist/init-payloads/vessel-light/index.md +33 -0
  201. package/dist/init-payloads/vessel-light/manifest.yml +3 -0
  202. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Black.woff2 +0 -0
  203. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Bold.woff2 +0 -0
  204. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-ExtraBold.woff2 +0 -0
  205. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Light.woff2 +0 -0
  206. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Medium.woff2 +0 -0
  207. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Regular.woff2 +0 -0
  208. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-SemiBold.woff2 +0 -0
  209. package/dist/init-payloads/vessel-light/materials/primitives.css +351 -0
  210. package/dist/init-payloads/vessel-light/materials/ref/composition.conversation.html +63 -0
  211. package/dist/init-payloads/vessel-light/materials/ref/composition.editorial.html +74 -0
  212. package/dist/init-payloads/vessel-light/materials/ref/composition.form.html +89 -0
  213. package/dist/init-payloads/vessel-light/materials/ref/composition.overlay.html +66 -0
  214. package/dist/init-payloads/vessel-light/materials/ref/composition.table.html +104 -0
  215. package/dist/init-payloads/vessel-light/materials/ref/email.html +80 -0
  216. package/dist/init-payloads/vessel-light/materials/tokens.css +191 -0
  217. package/dist/init-payloads/vessel-light/register.data-density.md +39 -0
  218. package/dist/init-payloads/vessel-light/register.editorial.md +41 -0
  219. package/dist/init-payloads/vessel-light/register.email.md +43 -0
  220. package/dist/init-payloads/vessel-light/signature.palette.md +45 -0
  221. package/dist/init-payloads/vessel-light/signature.shape.md +27 -0
  222. package/dist/init-payloads/vessel-light/signature.temperature.md +44 -0
  223. package/dist/init-payloads/vessel-light/signature.type.md +37 -0
  224. package/dist/internal/fs.d.ts +4 -0
  225. package/dist/internal/fs.d.ts.map +1 -0
  226. package/dist/internal/fs.js +24 -0
  227. package/dist/internal/fs.js.map +1 -0
  228. package/dist/observability-events.d.ts +34 -0
  229. package/dist/observability-events.d.ts.map +1 -0
  230. package/dist/observability-events.js +68 -0
  231. package/dist/observability-events.js.map +1 -0
  232. package/dist/package-version.d.ts +3 -0
  233. package/dist/package-version.d.ts.map +1 -0
  234. package/dist/package-version.js +10 -0
  235. package/dist/package-version.js.map +1 -0
  236. package/dist/review/baseline.d.ts +11 -0
  237. package/dist/review/baseline.d.ts.map +1 -0
  238. package/dist/review/baseline.js +35 -0
  239. package/dist/review/baseline.js.map +1 -0
  240. package/dist/review/diff.d.ts +7 -0
  241. package/dist/review/diff.d.ts.map +1 -0
  242. package/dist/review/diff.js +41 -0
  243. package/dist/review/diff.js.map +1 -0
  244. package/dist/review/glob.d.ts +2 -0
  245. package/dist/review/glob.d.ts.map +1 -0
  246. package/dist/review/glob.js +2 -0
  247. package/dist/review/glob.js.map +1 -0
  248. package/dist/review/probes.d.ts +13 -0
  249. package/dist/review/probes.d.ts.map +1 -0
  250. package/dist/review/probes.js +45 -0
  251. package/dist/review/probes.js.map +1 -0
  252. package/dist/review/resolve.d.ts +28 -0
  253. package/dist/review/resolve.d.ts.map +1 -0
  254. package/dist/review/resolve.js +90 -0
  255. package/dist/review/resolve.js.map +1 -0
  256. package/dist/review/review-packet.d.ts +41 -0
  257. package/dist/review/review-packet.d.ts.map +1 -0
  258. package/dist/review/review-packet.js +128 -0
  259. package/dist/review/review-packet.js.map +1 -0
  260. package/dist/scan/check-files.d.ts +23 -0
  261. package/dist/scan/check-files.d.ts.map +1 -0
  262. package/dist/scan/check-files.js +75 -0
  263. package/dist/scan/check-files.js.map +1 -0
  264. package/dist/scan/check-scaffold.d.ts +8 -0
  265. package/dist/scan/check-scaffold.d.ts.map +1 -0
  266. package/dist/scan/check-scaffold.js +53 -0
  267. package/dist/scan/check-scaffold.js.map +1 -0
  268. package/dist/scan/constants.d.ts +21 -0
  269. package/dist/scan/constants.d.ts.map +1 -0
  270. package/dist/scan/constants.js +21 -0
  271. package/dist/scan/constants.js.map +1 -0
  272. package/dist/scan/file-kind.d.ts +12 -0
  273. package/dist/scan/file-kind.d.ts.map +1 -0
  274. package/dist/scan/file-kind.js +114 -0
  275. package/dist/scan/file-kind.js.map +1 -0
  276. package/dist/scan/fingerprint-package-lint.d.ts +8 -0
  277. package/dist/scan/fingerprint-package-lint.d.ts.map +1 -0
  278. package/dist/scan/fingerprint-package-lint.js +284 -0
  279. package/dist/scan/fingerprint-package-lint.js.map +1 -0
  280. package/dist/scan/fingerprint-package-loader.d.ts +5 -0
  281. package/dist/scan/fingerprint-package-loader.d.ts.map +1 -0
  282. package/dist/scan/fingerprint-package-loader.js +78 -0
  283. package/dist/scan/fingerprint-package-loader.js.map +1 -0
  284. package/dist/scan/fingerprint-package.d.ts +66 -0
  285. package/dist/scan/fingerprint-package.d.ts.map +1 -0
  286. package/dist/scan/fingerprint-package.js +101 -0
  287. package/dist/scan/fingerprint-package.js.map +1 -0
  288. package/dist/scan/index.d.ts +3 -0
  289. package/dist/scan/index.d.ts.map +1 -0
  290. package/dist/scan/index.js +3 -0
  291. package/dist/scan/index.js.map +1 -0
  292. package/dist/scan/lint.d.ts +15 -0
  293. package/dist/scan/lint.d.ts.map +1 -0
  294. package/dist/scan/lint.js +2 -0
  295. package/dist/scan/lint.js.map +1 -0
  296. package/dist/scan/node-files.d.ts +25 -0
  297. package/dist/scan/node-files.d.ts.map +1 -0
  298. package/dist/scan/node-files.js +112 -0
  299. package/dist/scan/node-files.js.map +1 -0
  300. package/dist/scan/package-paths.d.ts +10 -0
  301. package/dist/scan/package-paths.d.ts.map +1 -0
  302. package/dist/scan/package-paths.js +49 -0
  303. package/dist/scan/package-paths.js.map +1 -0
  304. package/dist/scan/packed-payloads.d.ts +4 -0
  305. package/dist/scan/packed-payloads.d.ts.map +1 -0
  306. package/dist/scan/packed-payloads.js +55 -0
  307. package/dist/scan/packed-payloads.js.map +1 -0
  308. package/dist/scan/tarball.d.ts +23 -0
  309. package/dist/scan/tarball.d.ts.map +1 -0
  310. package/dist/scan/tarball.js +145 -0
  311. package/dist/scan/tarball.js.map +1 -0
  312. package/dist/scan/templates.d.ts +42 -0
  313. package/dist/scan/templates.d.ts.map +1 -0
  314. package/dist/scan/templates.js +375 -0
  315. package/dist/scan/templates.js.map +1 -0
  316. package/dist/skill-bundle/SKILL.md +146 -0
  317. package/dist/skill-bundle/references/adapting-a-starter.md +104 -0
  318. package/dist/skill-bundle/references/authoring-scenarios.md +184 -0
  319. package/dist/skill-bundle/references/blocks.md +179 -0
  320. package/dist/skill-bundle/references/brief.md +50 -0
  321. package/dist/skill-bundle/references/capture.md +392 -0
  322. package/dist/skill-bundle/references/concrete-tiers.md +95 -0
  323. package/dist/skill-bundle/references/recall.md +36 -0
  324. package/dist/skill-bundle/references/schema.md +114 -0
  325. package/dist/skill-bundle/references/self-check.md +65 -0
  326. package/dist/skill-bundle/references/steering-audit.md +60 -0
  327. package/package.json +79 -0
@@ -0,0 +1,66 @@
1
+ <!-- ghost ref annotations
2
+ normative-for: grammar.surfaces — the interrupting end of the elevation set: the modal tier (scrim, --shadow-modal, --radius-surface, compact header, clear footer) and the popover tier (an anchored menu floating above the flow with --shadow-popover). The card tier's home is composition.form.html and composition.table.html; together the three refs cover the closed elevation set. grammar.motion — the dialog reveal at --duration-normal with the one ease, opacity and small transform only. grammar.hierarchy — one primary confirm, ghost escape as button--icon close plus a cancel, menu items as ghost-weight actions; the info tone carrying a state-meaning note. signature.shape — surface radius on both overlay surfaces, the pill (--radius-control) on the icon close.
3
+ incidental: showing the popover and the modal in the same frame (a demonstration convenience — in a live UI the menu closes when the dialog interrupts); all copy and counts; the 512px dialog width; the specific menu items.
4
+ -->
5
+ <!doctype html>
6
+ <html lang="en">
7
+ <head>
8
+ <meta charset="utf-8" />
9
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
10
+ <title>Vessel Light — Overlay</title>
11
+ <link rel="stylesheet" href="../tokens.css" />
12
+ <link rel="stylesheet" href="../primitives.css" />
13
+ <style>
14
+ body { margin: 0; min-height: 100vh; padding: 24px; }
15
+ .page { width: min(100%, 720px); margin-inline: auto; position: relative; }
16
+ .menu { position: absolute; top: 48px; right: 0; width: 220px; }
17
+ .menu-item { justify-content: flex-start; width: 100%; height: 32px; padding: 6px 12px; }
18
+ .scrim { position: fixed; inset: 0; display: grid; place-items: center; padding: 16px; }
19
+ section[role="dialog"] { width: min(100%, 512px); }
20
+ /* dialog reveal: --duration-normal with the one ease, opacity + small transform */
21
+ section[role="dialog"] { animation: dialog-reveal var(--duration-normal) var(--ease-spring) both; }
22
+ @keyframes dialog-reveal { from { opacity: 0; transform: translateY(4px) scale(0.98); } }
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <main class="page stack stack--gap-lg">
27
+ <header class="stack stack--row stack--justify-between stack--align-center stack--gap-md">
28
+ <h1 class="text text--headline">Fingerprint</h1>
29
+ <button class="button button--outline button--size-sm" type="button" aria-haspopup="menu" aria-expanded="true">Actions</button>
30
+ </header>
31
+ <p class="text text--muted">Three nodes changed since the last publish. Review the diff, then publish from the actions menu.</p>
32
+
33
+ <!-- popover tier: anchored menu, floats above the flow -->
34
+ <nav class="menu surface surface--popover surface--pad-xs surface--radius-surface surface--border surface--elevation-popover stack stack--gap-none" role="menu" aria-label="Fingerprint actions">
35
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Review diff</button>
36
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Publish changes…</button>
37
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Export package</button>
38
+ </nav>
39
+ </main>
40
+
41
+ <!-- modal tier: scrim, interrupting dialog -->
42
+ <div class="scrim" role="presentation">
43
+ <section class="surface surface--popover surface--pad-lg surface--radius-surface surface--border surface--elevation-modal stack stack--gap-lg" role="dialog" aria-modal="true" aria-labelledby="dialog-title" aria-describedby="dialog-description">
44
+ <header class="stack stack--gap-sm">
45
+ <div class="stack stack--row stack--justify-between stack--align-center stack--gap-md">
46
+ <h2 class="text text--title" id="dialog-title">Publish fingerprint changes?</h2>
47
+ <button class="button button--ghost button--icon" type="button" aria-label="Close">&#215;</button>
48
+ </div>
49
+ <p class="text text--muted" id="dialog-description">This will make the selected brand truths available to agents working in this repo. Review the diff before confirming.</p>
50
+ </header>
51
+
52
+ <div class="surface surface--muted surface--pad-md surface--radius-surface stack stack--gap-xs">
53
+ <p class="text text--label">Included</p>
54
+ <p class="text">3 nodes, 2 material references, 1 review assertion</p>
55
+ </div>
56
+
57
+ <p class="text text--info">Publishing replaces the previous packet for every agent in this repo.</p>
58
+
59
+ <footer class="stack stack--row stack--justify-end stack--gap-sm stack--wrap">
60
+ <button class="button button--ghost" type="button">Cancel</button>
61
+ <button class="button button--primary" type="button">Confirm publish</button>
62
+ </footer>
63
+ </section>
64
+ </div>
65
+ </body>
66
+ </html>
@@ -0,0 +1,104 @@
1
+ <!-- ghost ref annotations
2
+ normative-for: register.data-density — the two smallest gap steps (--gap-xs, --gap-sm) as cell padding, mono tabular numerals right-aligned, muted-first hierarchy, hairline row borders with no zebra striping, small radius on the data surface (surface--radius-sm), status as a text label in one functional color family, hover confirmation at --duration-fast. grammar.hierarchy — label + title header pairing, secondary export action stepping down the ladder.
3
+ incidental: all customer names, emails, invoice ids, and amounts; the four-row count; the billing domain; the max content width.
4
+ -->
5
+ <!doctype html>
6
+ <html lang="en">
7
+ <head>
8
+ <meta charset="utf-8" />
9
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
10
+ <title>Vessel Light — Data Table</title>
11
+ <link rel="stylesheet" href="../tokens.css" />
12
+ <link rel="stylesheet" href="../primitives.css" />
13
+ <style>
14
+ body { margin: 0; min-height: 100vh; padding: var(--page-container-side-gutter); }
15
+ main { width: min(100%, calc(var(--page-container-side-gutter) * 56)); margin-inline: auto; }
16
+ .table-surface { overflow: hidden; }
17
+ table { width: 100%; border-collapse: collapse; }
18
+ th, td { padding: var(--gap-xs) var(--gap-sm); border-bottom: 1px solid var(--border); text-align: left; font-size: var(--text-body-size); line-height: 1.5; }
19
+ th { color: var(--muted-foreground); font-weight: 500; }
20
+ tbody tr { transition: background var(--duration-fast) var(--ease-spring); }
21
+ tbody tr:hover { background: var(--muted); }
22
+ tbody tr:last-child td { border-bottom: 0; }
23
+ .cell-secondary { color: var(--muted-foreground); }
24
+ .cell-number { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
25
+ .status { color: var(--success); font-size: 12px; font-weight: 600; line-height: 1.4; }
26
+ .align-right { text-align: right; }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <main class="stack stack--gap-lg">
31
+ <header class="stack stack--row stack--justify-between stack--align-end stack--gap-md stack--wrap">
32
+ <div class="stack stack--gap-xs">
33
+ <p class="text text--label text--muted">Billing console</p>
34
+ <h1 class="text text--title">Recent payments</h1>
35
+ </div>
36
+ <button class="button button--secondary button--size-sm" type="button">Export CSV</button>
37
+ </header>
38
+
39
+ <section class="surface surface--card surface--border surface--radius-sm table-surface" aria-label="Recent payments table">
40
+ <table>
41
+ <thead>
42
+ <tr>
43
+ <th scope="col">Customer</th>
44
+ <th scope="col">Plan</th>
45
+ <th scope="col">Invoice</th>
46
+ <th scope="col" class="align-right">Amount</th>
47
+ <th scope="col">Status</th>
48
+ </tr>
49
+ </thead>
50
+ <tbody>
51
+ <tr>
52
+ <td>
53
+ <div class="stack stack--gap-none">
54
+ <span>Northstar Studio</span>
55
+ <span class="cell-secondary">design@northstar.example</span>
56
+ </div>
57
+ </td>
58
+ <td class="cell-secondary">Team</td>
59
+ <td class="cell-secondary">VS-1048</td>
60
+ <td class="cell-number">$96.00</td>
61
+ <td><span class="status">Paid</span></td>
62
+ </tr>
63
+ <tr>
64
+ <td>
65
+ <div class="stack stack--gap-none">
66
+ <span>Common Room</span>
67
+ <span class="cell-secondary">ops@common.example</span>
68
+ </div>
69
+ </td>
70
+ <td class="cell-secondary">Business</td>
71
+ <td class="cell-secondary">VS-1047</td>
72
+ <td class="cell-number">$240.00</td>
73
+ <td><span class="status">Paid</span></td>
74
+ </tr>
75
+ <tr>
76
+ <td>
77
+ <div class="stack stack--gap-none">
78
+ <span>Field Notes Lab</span>
79
+ <span class="cell-secondary">admin@fieldnotes.example</span>
80
+ </div>
81
+ </td>
82
+ <td class="cell-secondary">Team</td>
83
+ <td class="cell-secondary">VS-1046</td>
84
+ <td class="cell-number">$96.00</td>
85
+ <td><span class="status">Paid</span></td>
86
+ </tr>
87
+ <tr>
88
+ <td>
89
+ <div class="stack stack--gap-none">
90
+ <span>Atlas Review</span>
91
+ <span class="cell-secondary">finance@atlas.example</span>
92
+ </div>
93
+ </td>
94
+ <td class="cell-secondary">Starter</td>
95
+ <td class="cell-secondary">VS-1045</td>
96
+ <td class="cell-number">$24.00</td>
97
+ <td><span class="status">Paid</span></td>
98
+ </tr>
99
+ </tbody>
100
+ </table>
101
+ </section>
102
+ </main>
103
+ </body>
104
+ </html>
@@ -0,0 +1,80 @@
1
+ <!doctype html>
2
+ <!-- ghost ref annotations
3
+ normative-for: register.email — the inverted material contract: table layout, 600px wrapper, inline styles, system font stack, hardcoded hex hand-transcribed from tokens.css (each annotated below with its source token), bulletproof pill button, surface radius on the card, exactly one expressive moment in one hue (the amber header band). signature.shape — the radius values (20px surface, 999px control) surviving without token names. signature.palette — monochrome spine, one hue, quiet factual copy, no celebration.
4
+ incidental: all copy, amounts, dates, and receipt numbers; the choice of amber for the one expressive moment (any single expression hue qualifies); the receipt subject matter.
5
+
6
+ hex transcription map (single source: materials/tokens.css — re-transcribe if a token changes):
7
+ #ffffff = --color-white (background)
8
+ #1a1a1a = --color-gray-900 (foreground / primary)
9
+ #999999 = --color-gray-500 (muted-foreground)
10
+ #e8e8e8 = --color-gray-200 (border)
11
+ #f6b44a = --expression-1 (amber)
12
+ border-radius 20px = --radius-surface; 999px = --radius-control
13
+ -->
14
+ <html lang="en">
15
+ <head>
16
+ <meta charset="utf-8" />
17
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
18
+ <title>Payment receipt</title>
19
+ </head>
20
+ <!-- #ffffff = --color-white; #1a1a1a = --color-gray-900 -->
21
+ <body style="margin:0; padding:0; background:#ffffff; color:#1a1a1a; font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;">
22
+ <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="width:100%; background:#ffffff;"><!-- #ffffff = --color-white -->
23
+ <tr>
24
+ <td align="center" style="padding:32px 16px;">
25
+ <table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="width:100%; max-width:600px;">
26
+ <tr>
27
+ <td style="padding:0 0 16px 0; font-size:11px; line-height:1.2; letter-spacing:0.12em; font-weight:600; text-transform:uppercase; color:#999999;">Vessel</td><!-- #999999 = --color-gray-500 -->
28
+ </tr>
29
+ <tr>
30
+ <!-- the one expressive moment: amber band (#f6b44a = --expression-1), one hue, nothing else colored; #e8e8e8 = --color-gray-200; 20px = --radius-surface -->
31
+ <td style="border:1px solid #e8e8e8; border-top:4px solid #f6b44a; border-radius:20px; padding:24px; background:#ffffff;">
32
+ <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
33
+ <tr>
34
+ <td style="padding:0 0 8px 0; font-size:24px; line-height:1.25; letter-spacing:-0.025em; font-weight:400; color:#1a1a1a;">Payment receipt</td><!-- #1a1a1a = --color-gray-900 -->
35
+ </tr>
36
+ <tr>
37
+ <td style="padding:0 0 24px 0; font-size:14px; line-height:1.625; color:#999999;">Your payment for the Team plan has been received. A copy of this receipt is available in billing settings.</td>
38
+ </tr>
39
+ <tr>
40
+ <td style="padding:0 0 24px 0;">
41
+ <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="border-top:1px solid #e8e8e8; border-bottom:1px solid #e8e8e8;"><!-- #e8e8e8 = --color-gray-200 -->
42
+ <tr>
43
+ <td style="padding:12px 0; font-size:14px; line-height:1.5; color:#999999;">Receipt number</td>
44
+ <td align="right" style="padding:12px 0; font-size:14px; line-height:1.5; color:#1a1a1a;">VS-1048</td>
45
+ </tr>
46
+ <tr>
47
+ <td style="padding:12px 0; border-top:1px solid #e8e8e8; font-size:14px; line-height:1.5; color:#999999;">Billing date</td>
48
+ <td align="right" style="padding:12px 0; border-top:1px solid #e8e8e8; font-size:14px; line-height:1.5; color:#1a1a1a;">July 7, 2026</td>
49
+ </tr>
50
+ <tr>
51
+ <td style="padding:12px 0; border-top:1px solid #e8e8e8; font-size:14px; line-height:1.5; color:#999999;">Amount paid</td>
52
+ <td align="right" style="padding:12px 0; border-top:1px solid #e8e8e8; font-size:14px; line-height:1.5; color:#1a1a1a;">$96.00</td>
53
+ </tr>
54
+ </table>
55
+ </td>
56
+ </tr>
57
+ <tr>
58
+ <td align="left" style="padding:0 0 24px 0;">
59
+ <table role="presentation" cellspacing="0" cellpadding="0" border="0">
60
+ <tr>
61
+ <!-- #1a1a1a = --color-gray-900 (primary); 999px = --radius-control -->
62
+ <td bgcolor="#1a1a1a" style="border-radius:999px; padding:10px 24px;">
63
+ <a href="https://example.com/billing" style="display:inline-block; font-size:14px; line-height:1; color:#ffffff; text-decoration:none;">View receipt</a>
64
+ </td>
65
+ </tr>
66
+ </table>
67
+ </td>
68
+ </tr>
69
+ <tr>
70
+ <td style="font-size:12px; line-height:1.4; color:#999999;">If you have billing questions, reply to this email and include the receipt number.</td>
71
+ </tr>
72
+ </table>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </td>
77
+ </tr>
78
+ </table>
79
+ </body>
80
+ </html>
@@ -0,0 +1,191 @@
1
+ /* Vessel Light materials contract: style only with these custom properties; never hardcode colors, shadows, or timing. */
2
+
3
+ @font-face {
4
+ font-family: "HK Grotesk";
5
+ src: url("fonts/HKGrotesk-Light.woff2") format("woff2");
6
+ font-weight: 300;
7
+ font-style: normal;
8
+ font-display: swap;
9
+ }
10
+
11
+ @font-face {
12
+ font-family: "HK Grotesk";
13
+ src: url("fonts/HKGrotesk-Regular.woff2") format("woff2");
14
+ font-weight: 400;
15
+ font-style: normal;
16
+ font-display: swap;
17
+ }
18
+
19
+ @font-face {
20
+ font-family: "HK Grotesk";
21
+ src: url("fonts/HKGrotesk-Medium.woff2") format("woff2");
22
+ font-weight: 500;
23
+ font-style: normal;
24
+ font-display: swap;
25
+ }
26
+
27
+ @font-face {
28
+ font-family: "HK Grotesk";
29
+ src: url("fonts/HKGrotesk-SemiBold.woff2") format("woff2");
30
+ font-weight: 600;
31
+ font-style: normal;
32
+ font-display: swap;
33
+ }
34
+
35
+ @font-face {
36
+ font-family: "HK Grotesk";
37
+ src: url("fonts/HKGrotesk-Bold.woff2") format("woff2");
38
+ font-weight: 700;
39
+ font-style: normal;
40
+ font-display: swap;
41
+ }
42
+
43
+ @font-face {
44
+ font-family: "HK Grotesk";
45
+ src: url("fonts/HKGrotesk-ExtraBold.woff2") format("woff2");
46
+ font-weight: 800;
47
+ font-style: normal;
48
+ font-display: swap;
49
+ }
50
+
51
+ @font-face {
52
+ font-family: "HK Grotesk";
53
+ src: url("fonts/HKGrotesk-Black.woff2") format("woff2");
54
+ font-weight: 900;
55
+ font-style: normal;
56
+ font-display: swap;
57
+ }
58
+
59
+ :root {
60
+ --font-sans: "HK Grotesk", system-ui, sans-serif;
61
+ --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
62
+
63
+ --color-white: #ffffff;
64
+
65
+ --color-gray-100: #f0f0f0;
66
+ --color-gray-200: #e8e8e8;
67
+ --color-gray-300: #e5e5e5;
68
+ --color-gray-400: #cccccc;
69
+ --color-gray-500: #999999;
70
+ --color-gray-900: #1a1a1a;
71
+
72
+ --color-red-200: #f94b4b;
73
+ --color-blue-200: #5c98f9;
74
+ --color-green-200: #91cb80;
75
+ --color-yellow-200: #fbcd44;
76
+
77
+ /* Radius dials: --radius-surface on what contains, --radius-control on what
78
+ you click. Everything else derives from these two answers. */
79
+ --radius-surface: 20px;
80
+ --radius-control: 999px;
81
+ --radius: var(--radius-surface);
82
+ --radius-sm: calc(var(--radius) - 4px);
83
+ --radius-md: calc(var(--radius) - 2px);
84
+ --radius-input: var(--radius-control);
85
+
86
+ --gap-xs: 4px;
87
+ --gap-sm: 8px;
88
+ --gap-md: 16px;
89
+ --gap-lg: 24px;
90
+ --gap-xl: 32px;
91
+
92
+ --text-body-size: 14px;
93
+ --text-body-line-height: 1.625;
94
+ --text-title-size: 18px;
95
+ --text-headline-size: 24px;
96
+ --text-heading-letter-spacing: -0.025em;
97
+
98
+ --control-height: 36px;
99
+
100
+ --background: var(--color-white);
101
+ --foreground: var(--color-gray-900);
102
+ --card: var(--background);
103
+ --card-foreground: var(--foreground);
104
+ --popover: var(--background);
105
+ --popover-foreground: var(--foreground);
106
+ --primary: var(--color-gray-900);
107
+ --primary-foreground: var(--color-white);
108
+ --secondary: var(--color-gray-100);
109
+ --secondary-foreground: var(--foreground);
110
+ --muted: var(--color-gray-100);
111
+ --muted-foreground: var(--color-gray-500);
112
+ --destructive: var(--color-red-200);
113
+ --destructive-foreground: var(--color-white);
114
+ --success: var(--color-green-200);
115
+ --warning: var(--color-yellow-200);
116
+ --info: var(--color-blue-200);
117
+ --border: var(--color-gray-200);
118
+ --input: var(--color-gray-300);
119
+ --ring: var(--color-gray-400);
120
+
121
+ --dark-40: rgba(26, 26, 26, 0.4);
122
+
123
+ /* Elevation is a closed set of three tiers (card, popover, modal);
124
+ --shadow-btn belongs to the button primitive, not the tiers. */
125
+ --shadow-btn: 0 2px 8px rgba(76, 76, 76, 0.15);
126
+ --shadow-card: 0 2px 8px rgba(76, 76, 76, 0.15);
127
+ --shadow-popover: 0 8px 30px rgba(0, 0, 0, 0.12);
128
+ --shadow-modal: 0 20px 60px rgba(0, 0, 0, 0.2);
129
+
130
+ --surface-dark: #0a0a0a;
131
+ --surface-dark-text: #f5f5f5;
132
+ --surface-dark-muted: rgba(255, 255, 255, 0.5);
133
+ --surface-dark-border: rgba(255, 255, 255, 0.08);
134
+
135
+ --heading-display-font-size: clamp(64px, 8vw, 96px);
136
+ --heading-display-line-height: 0.88;
137
+ --heading-display-letter-spacing: -0.05em;
138
+ --heading-display-font-weight: 900;
139
+ --heading-section-font-size: clamp(44px, 5vw, 64px);
140
+ --heading-section-line-height: 0.95;
141
+ --heading-section-letter-spacing: -0.035em;
142
+ --heading-section-font-weight: 700;
143
+ --heading-sub-font-size: clamp(28px, 3vw, 40px);
144
+ --heading-sub-line-height: 1;
145
+ --heading-sub-letter-spacing: -0.02em;
146
+ --heading-sub-font-weight: 700;
147
+
148
+ --body-reading-size: clamp(1rem, 1.3vw, 1.25rem);
149
+ --body-reading-line-height: 1.65;
150
+ --body-reading-letter-spacing: -0.01em;
151
+ --label-font-size: 11px;
152
+ --label-letter-spacing: 0.12em;
153
+ --label-font-weight: 600;
154
+ --label-line-height: 1.2;
155
+ --pullquote-size: clamp(1.5rem, 3vw, 2.5rem);
156
+ --pullquote-line-height: 1.3;
157
+ --pullquote-weight: 300;
158
+ --pullquote-letter-spacing: -0.02em;
159
+
160
+ --page-container-max-width: 1440px;
161
+ --page-container-side-gutter: 20px;
162
+ --section-padding-vertical: 100px;
163
+ --section-heading-margin-bottom: 75px;
164
+
165
+ --ease-spring: cubic-bezier(0.33, 1, 0.68, 1);
166
+ --duration-fast: 0.15s; /* hover and press — confirmation, not performance */
167
+ --duration-normal: 0.2s; /* reveals, fades, small state changes */
168
+ --duration-slow: 0.4s; /* spatial transitions only; editorial entrances */
169
+
170
+ /* Budgets — countable rules, checked per view, not moods.
171
+ A budget of one means at most one; zero is a valid spend. */
172
+ --primary-budget: 1; /* primary actions per view — and some views honestly earn none */
173
+ --expression-budget-product: 0; /* expression hues in product UI — charts only, never the chrome */
174
+ --expression-budget-email: 1; /* expressive moments per message, one hue */
175
+ --expression-budget-editorial: 2; /* expression hues per page, atmosphere allowed */
176
+
177
+ /* Numerals in data — tabular figures so columns align and deltas read. */
178
+ --numeric-tabular: "tnum" 1;
179
+
180
+ /* Expression palette — the brand's five hues, volume-gated by register.
181
+ Product: charts only. Data-density: one hue family for status.
182
+ Email: exactly one expressive moment. Editorial: atmosphere, max two
183
+ hues per page. Never on interactive controls in any register.
184
+ The refs demonstrate hues 1 and 2; hues 3-5 are declared inventory —
185
+ no register renders all five at once (see signature.palette). */
186
+ --expression-1: #f6b44a; /* amber */
187
+ --expression-2: #7585ff; /* periwinkle */
188
+ --expression-3: #d76a6a; /* clay */
189
+ --expression-4: #d185e0; /* orchid */
190
+ --expression-5: #91cb80; /* sage */
191
+ }
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: "Data-dense consoles — gather for tables, dashboards, logs, and monitoring; compresses product rhythm to the two smallest gap steps, mono numerals, muted-first."
3
+ materials:
4
+ - materials/ref/composition.table.html
5
+ - materials/primitives.css
6
+ ---
7
+
8
+ Condition: this node applies to data-dense surfaces — tables, dashboards,
9
+ transaction logs, and admin consoles.
10
+
11
+ Data density inverts the settings-page rhythm. Operators need scan speed
12
+ before they need breathing room.
13
+
14
+ Use the two smallest gap steps (`--gap-xs`, `--gap-sm`) where forms use the
15
+ medium step. Tight adjacency is meaning when rows compare against rows.
16
+
17
+ Numerals are mono so columns align. A ragged amount column is a broken
18
+ instrument.
19
+
20
+ Hierarchy is muted-first. Data is the default plane, labels are muted, and
21
+ emphasis is rare enough to stay useful.
22
+
23
+ Data surfaces take the small radius. A surface-radius table cell is costume —
24
+ the signature radius (see signature.shape) belongs on cards, not cells.
25
+
26
+ Status is a text label with at most one functional color family per view.
27
+
28
+ Charts inside a console follow the product carve-out from the palette
29
+ signature: expression hues live inside the plot area only. Outside the plot,
30
+ the one-status-hue cap holds — chart color never leaks into rows, badges, or
31
+ headers. More status color turns monitoring into confetti.
32
+
33
+ No zebra striping. Hairline borders carry rows with less noise and more
34
+ trust.
35
+
36
+ Hover confirmation uses the fast duration. It should acknowledge targeting,
37
+ not animate the table.
38
+
39
+ Generous whitespace is drift here. Wasted density makes operators scroll.
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: "Editorial and landing surfaces — gather for heroes, marketing pages, pull quotes, and full-bleed dark moments; inverts product type restraint."
3
+ materials:
4
+ - materials/ref/composition.editorial.html
5
+ - materials/tokens.css
6
+ ---
7
+
8
+ Condition: this node applies to marketing, landing, and editorial surfaces —
9
+ never to product UI.
10
+
11
+ Editorial surfaces invert the product type rules. Display scale is not an
12
+ indulgence here; it is the job.
13
+
14
+ Use the `--heading-display-*` tokens — size, line height, and weight — when
15
+ the words are the composition. The display tier belongs to this register (see
16
+ signature.type for the scale's character).
17
+
18
+ Section rhythm uses `--section-padding-vertical`, not a product stack
19
+ stretched until it looks important.
20
+
21
+ The sanctioned dramatic moment is the full-bleed dark section. Use the
22
+ `--surface-dark-*` family and let contrast carry the scene.
23
+
24
+ Pull quotes are visual punctuation for longform. They interrupt reading with
25
+ judgment, not decoration.
26
+
27
+ The tracked uppercase label is the kicker grammar. It gives the page a hard
28
+ editorial edge before the headline lands.
29
+
30
+ Monochrome remains the spine, but editorial is the loud end of the expression
31
+ ladder (see signature.palette): up to two expression hues per page as
32
+ atmosphere — a tinted dark section, a colored pull-quote accent, a duotone
33
+ image moment. Commit to few colors at scale; variety is where expression
34
+ collapses into decoration.
35
+
36
+ There is one primary action per page, and it keeps the control radius from
37
+ signature.shape. Editorial confidence does not excuse competing calls to
38
+ action.
39
+
40
+ A hero built at product scale reads as timid. Timidity is drift here, exactly
41
+ as spectacle is drift in product UI.
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: "Transactional email — gather ONLY for email; inverts the token contract: inline styles, hardcoded hex transcribed from tokens.css, table layout, system fonts."
3
+ materials:
4
+ - materials/ref/email.html
5
+ ---
6
+
7
+ Condition: this node applies only to email. In any other medium, everything
8
+ below is a violation.
9
+
10
+ Email clients do not honor the web contract. Custom properties, external
11
+ stylesheets, flex layout, and webfonts are unreliable materials here.
12
+
13
+ Email inverts the material contract deliberately. Transcribe token values by
14
+ hand instead of referencing tokens — every hex below is a transcription of
15
+ `materials/tokens.css`, which stays the single source; if a token changes,
16
+ re-transcribe.
17
+
18
+ Use `#1a1a1a` (`--color-gray-900`, foreground) for text, `#999999`
19
+ (`--color-gray-500`, muted) for muted text, and `#e8e8e8` (`--color-gray-200`,
20
+ border) for borders when the email needs the Vessel palette.
21
+
22
+ Keep the surface radius on cards and the control radius on buttons (see
23
+ signature.shape). The values survive even when the token names cannot travel.
24
+
25
+ Build with table layout, a 600px wrapper, predictable cells, and bulletproof
26
+ buttons. Email fidelity is made from boring structure.
27
+
28
+ HK Grotesk falls back to the system stack. The voice must survive without the
29
+ font file.
30
+
31
+ The soul survives the body swap: monochrome spine, quiet factual copy, one
32
+ primary action, no celebration.
33
+
34
+ Email gets exactly one expressive moment: a header band or the figure that
35
+ matters, in one expression hue, transcribed by hand like every value here —
36
+ amber is `#f6b44a` (`--expression-1`). One moment, one hue. A receipt is
37
+ allowed one degree of warmth; it is not allowed a palette.
38
+
39
+ Do not add further color to compensate for email constraints. Constraint is
40
+ not permission to perform.
41
+
42
+ Hardcoding hex here is fidelity, not drift. The check exemption is the
43
+ condition itself.
@@ -0,0 +1,45 @@
1
+ ---
2
+ description: "Gather whenever color beyond the base roles is in question, in any register. The palette dial: a monochrome spine plus a closed expression set whose volume rises with the register — this brand's current answer is gray plus five named hues."
3
+ materials:
4
+ - materials/tokens.css
5
+ ---
6
+
7
+ This is Vessel's answer to palette — it stands until you replace it.
8
+
9
+ The relationship is fixed: one brand at different volumes. A monochrome spine
10
+ is the default atmosphere in every medium — calm, legible, and resistant to
11
+ novelty — and a closed expression set supplies the atmosphere, with volume
12
+ set by register, never by taste.
13
+
14
+ Vessel's current answer: the base palette is monochrome gray, and the
15
+ expression palette is five named hues and only these — amber
16
+ (`--expression-1`), periwinkle (`--expression-2`), clay (`--expression-3`),
17
+ orchid (`--expression-4`), sage (`--expression-5`). Expressive color outside
18
+ this set is not expression; it is another brand. An invented hue is not a
19
+ bolder Vessel; it is a different brand.
20
+
21
+ The volume ladder, by register:
22
+
23
+ Product UI: expression lives only in data visualization. A chart may use the
24
+ hues; the interface around it stays monochrome.
25
+
26
+ Data-dense consoles: one hue family may mark status. Nothing atmospheric.
27
+ Charts inside a console keep the product carve-out — hues stay inside the
28
+ plot area and never leak into rows, badges, or headers.
29
+
30
+ Email: exactly one expressive moment per message — a header band or the
31
+ figure that matters. One hue, quiet everywhere else.
32
+
33
+ Editorial: expression is sanctioned atmosphere — a tinted dark section, a
34
+ colored pull-quote accent, a duotone moment. Never more than two hues per
35
+ page. Loudness comes from commitment to few colors at scale, not variety.
36
+
37
+ Two constants that outrank the ladder: expression never touches what you
38
+ click — buttons, inputs, and links stay monochrome in every register — and
39
+ the status roles are not expression; they keep their meanings everywhere and
40
+ never moonlight as atmosphere.
41
+
42
+ To adapt: edit the `--expression-*` values (and the gray ramp, if the spine
43
+ changes) in `materials/tokens.css` and restate this node's current answer.
44
+ The ladder — a quiet spine, a closed hue set, register-gated volume — is the
45
+ part worth keeping.
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: "Gather before setting any radius or corner treatment. The shape dial: controls take --radius-control, surfaces take --radius-surface — this brand's current answer is pills on controls and a 20px signature radius on surfaces."
3
+ materials:
4
+ - materials/tokens.css
5
+ - materials/primitives.css
6
+ ---
7
+
8
+ This is Vessel's answer to shape — it stands until you replace it.
9
+
10
+ The relationship is fixed: controls and surfaces carry different radius
11
+ roles, and the two never swap. Buttons and text inputs use
12
+ `--radius-control`; cards and other surfaces use `--radius-surface`.
13
+
14
+ Vessel's current answer: controls are pills (`--radius-control: 999px`) and
15
+ surfaces take the 20px signature radius (`--radius-surface: 20px`). The pill
16
+ is Vessel's most visible control signature; a rectangular button is not a
17
+ variant, it is a different design system. Never give a button the surface
18
+ radius — a rectangular button is the fastest tell that the output is not
19
+ Vessel.
20
+
21
+ 20px is a considered position: rounder than default shadcn, but not bubbly.
22
+ Use the radius system as restraint, not as decoration.
23
+
24
+ To adapt: edit the `--radius-control` and `--radius-surface` values in
25
+ `materials/tokens.css` and restate this node's current answer. The
26
+ role split — one radius for what you click, one for what contains — is the
27
+ part worth keeping.