@design-intelligence/ghost 0.20.0 → 0.22.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 +47 -33
  2. package/dist/commands/checks-command.d.ts.map +1 -1
  3. package/dist/commands/checks-command.js +8 -1
  4. package/dist/commands/checks-command.js.map +1 -1
  5. package/dist/commands/fingerprint-commands.d.ts.map +1 -1
  6. package/dist/commands/fingerprint-commands.js +1 -6
  7. package/dist/commands/fingerprint-commands.js.map +1 -1
  8. package/dist/commands/gather-command.d.ts.map +1 -1
  9. package/dist/commands/gather-command.js +26 -30
  10. package/dist/commands/gather-command.js.map +1 -1
  11. package/dist/commands/init-command.d.ts.map +1 -1
  12. package/dist/commands/init-command.js +23 -13
  13. package/dist/commands/init-command.js.map +1 -1
  14. package/dist/commands/pull-command.d.ts.map +1 -1
  15. package/dist/commands/pull-command.js +12 -19
  16. package/dist/commands/pull-command.js.map +1 -1
  17. package/dist/commands/pulse-command.js +1 -10
  18. package/dist/commands/pulse-command.js.map +1 -1
  19. package/dist/commands/review-command.d.ts.map +1 -1
  20. package/dist/commands/review-command.js +1 -0
  21. package/dist/commands/review-command.js.map +1 -1
  22. package/dist/ghost-core/catalog/assemble.d.ts +0 -4
  23. package/dist/ghost-core/catalog/assemble.d.ts.map +1 -1
  24. package/dist/ghost-core/catalog/assemble.js +0 -10
  25. package/dist/ghost-core/catalog/assemble.js.map +1 -1
  26. package/dist/ghost-core/catalog/index.d.ts +1 -1
  27. package/dist/ghost-core/catalog/index.d.ts.map +1 -1
  28. package/dist/ghost-core/catalog/index.js +1 -1
  29. package/dist/ghost-core/catalog/index.js.map +1 -1
  30. package/dist/ghost-core/catalog/menu.d.ts +1 -11
  31. package/dist/ghost-core/catalog/menu.d.ts.map +1 -1
  32. package/dist/ghost-core/catalog/menu.js +1 -6
  33. package/dist/ghost-core/catalog/menu.js.map +1 -1
  34. package/dist/ghost-core/catalog/types.d.ts +0 -6
  35. package/dist/ghost-core/catalog/types.d.ts.map +1 -1
  36. package/dist/ghost-core/glossary.d.ts +0 -13
  37. package/dist/ghost-core/glossary.d.ts.map +1 -1
  38. package/dist/ghost-core/glossary.js +0 -7
  39. package/dist/ghost-core/glossary.js.map +1 -1
  40. package/dist/ghost-core/index.d.ts +2 -2
  41. package/dist/ghost-core/index.d.ts.map +1 -1
  42. package/dist/ghost-core/index.js +1 -1
  43. package/dist/ghost-core/index.js.map +1 -1
  44. package/dist/ghost-core/package-manifest.d.ts +7 -0
  45. package/dist/ghost-core/package-manifest.d.ts.map +1 -1
  46. package/dist/ghost-core/package-manifest.js +10 -0
  47. package/dist/ghost-core/package-manifest.js.map +1 -1
  48. package/dist/init-payloads/median/cliche.median.md +86 -0
  49. package/dist/init-payloads/median/median-tells.md +117 -0
  50. package/dist/init-payloads/skeleton/brand.md +22 -0
  51. package/dist/init-payloads/skeleton/context.conversation.md +24 -0
  52. package/dist/init-payloads/skeleton/foundation.color.md +39 -0
  53. package/dist/init-payloads/skeleton/foundation.composition.md +30 -0
  54. package/dist/init-payloads/skeleton/foundation.controls.md +29 -0
  55. package/dist/init-payloads/skeleton/foundation.layout.md +45 -0
  56. package/dist/init-payloads/skeleton/foundation.motion.md +34 -0
  57. package/dist/init-payloads/skeleton/foundation.type.md +44 -0
  58. package/dist/init-payloads/skeleton/foundation.voice.md +29 -0
  59. package/dist/init-payloads/skeleton/glossary.md +39 -0
  60. package/dist/init-payloads/vessel-light/anti-goal.median.md +86 -0
  61. package/dist/init-payloads/vessel-light/anti-goal.tells.md +38 -0
  62. package/dist/init-payloads/vessel-light/checks/conversation-grammar.md +20 -0
  63. package/dist/init-payloads/vessel-light/checks/median-tells.md +103 -0
  64. package/dist/init-payloads/vessel-light/checks/motion-restraint.md +20 -0
  65. package/dist/init-payloads/vessel-light/checks/relationships.md +33 -0
  66. package/dist/init-payloads/vessel-light/checks/shape-matches-job.md +43 -0
  67. package/dist/init-payloads/vessel-light/checks/values.md +51 -0
  68. package/dist/init-payloads/vessel-light/glossary.md +44 -0
  69. package/dist/init-payloads/vessel-light/grammar.color-roles.md +30 -0
  70. package/dist/init-payloads/vessel-light/grammar.conversation.md +30 -0
  71. package/dist/init-payloads/vessel-light/grammar.deletion.md +35 -0
  72. package/dist/init-payloads/vessel-light/grammar.hierarchy.md +58 -0
  73. package/dist/init-payloads/vessel-light/grammar.job.md +54 -0
  74. package/dist/init-payloads/vessel-light/grammar.motion.md +27 -0
  75. package/dist/init-payloads/vessel-light/grammar.rhythm.md +27 -0
  76. package/dist/init-payloads/vessel-light/grammar.surfaces.md +35 -0
  77. package/dist/init-payloads/vessel-light/index.md +33 -0
  78. package/dist/init-payloads/vessel-light/manifest.yml +3 -0
  79. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Black.woff2 +0 -0
  80. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Bold.woff2 +0 -0
  81. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-ExtraBold.woff2 +0 -0
  82. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Light.woff2 +0 -0
  83. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Medium.woff2 +0 -0
  84. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Regular.woff2 +0 -0
  85. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-SemiBold.woff2 +0 -0
  86. package/dist/init-payloads/vessel-light/materials/primitives.css +351 -0
  87. package/dist/init-payloads/vessel-light/materials/ref/composition.conversation.html +63 -0
  88. package/dist/init-payloads/vessel-light/materials/ref/composition.editorial.html +74 -0
  89. package/dist/init-payloads/vessel-light/materials/ref/composition.form.html +89 -0
  90. package/dist/init-payloads/vessel-light/materials/ref/composition.overlay.html +66 -0
  91. package/dist/init-payloads/vessel-light/materials/ref/composition.table.html +104 -0
  92. package/dist/init-payloads/vessel-light/materials/ref/email.html +80 -0
  93. package/dist/init-payloads/vessel-light/materials/tokens.css +191 -0
  94. package/dist/init-payloads/vessel-light/register.data-density.md +39 -0
  95. package/dist/init-payloads/vessel-light/register.editorial.md +41 -0
  96. package/dist/init-payloads/vessel-light/register.email.md +43 -0
  97. package/dist/init-payloads/vessel-light/signature.palette.md +45 -0
  98. package/dist/init-payloads/vessel-light/signature.shape.md +27 -0
  99. package/dist/init-payloads/vessel-light/signature.temperature.md +44 -0
  100. package/dist/init-payloads/vessel-light/signature.type.md +37 -0
  101. package/dist/observability-events.d.ts +0 -3
  102. package/dist/observability-events.d.ts.map +1 -1
  103. package/dist/observability-events.js.map +1 -1
  104. package/dist/review/resolve.d.ts +3 -4
  105. package/dist/review/resolve.d.ts.map +1 -1
  106. package/dist/review/resolve.js +12 -9
  107. package/dist/review/resolve.js.map +1 -1
  108. package/dist/review/review-packet.d.ts +2 -1
  109. package/dist/review/review-packet.d.ts.map +1 -1
  110. package/dist/review/review-packet.js +9 -20
  111. package/dist/review/review-packet.js.map +1 -1
  112. package/dist/scan/check-files.d.ts.map +1 -1
  113. package/dist/scan/check-files.js +0 -15
  114. package/dist/scan/check-files.js.map +1 -1
  115. package/dist/scan/check-scaffold.d.ts +1 -0
  116. package/dist/scan/check-scaffold.d.ts.map +1 -1
  117. package/dist/scan/check-scaffold.js +17 -1
  118. package/dist/scan/check-scaffold.js.map +1 -1
  119. package/dist/scan/fingerprint-package-lint.d.ts +8 -0
  120. package/dist/scan/fingerprint-package-lint.d.ts.map +1 -0
  121. package/dist/scan/fingerprint-package-lint.js +284 -0
  122. package/dist/scan/fingerprint-package-lint.js.map +1 -0
  123. package/dist/scan/fingerprint-package-loader.d.ts.map +1 -1
  124. package/dist/scan/fingerprint-package-loader.js +2 -29
  125. package/dist/scan/fingerprint-package-loader.js.map +1 -1
  126. package/dist/scan/fingerprint-package.d.ts +16 -8
  127. package/dist/scan/fingerprint-package.d.ts.map +1 -1
  128. package/dist/scan/fingerprint-package.js +41 -241
  129. package/dist/scan/fingerprint-package.js.map +1 -1
  130. package/dist/scan/node-files.d.ts.map +1 -1
  131. package/dist/scan/node-files.js +1 -3
  132. package/dist/scan/node-files.js.map +1 -1
  133. package/dist/scan/packed-payloads.d.ts +4 -0
  134. package/dist/scan/packed-payloads.d.ts.map +1 -0
  135. package/dist/scan/packed-payloads.js +55 -0
  136. package/dist/scan/packed-payloads.js.map +1 -0
  137. package/dist/scan/templates.d.ts +20 -2
  138. package/dist/scan/templates.d.ts.map +1 -1
  139. package/dist/scan/templates.js +106 -26
  140. package/dist/scan/templates.js.map +1 -1
  141. package/dist/skill-bundle/SKILL.md +16 -13
  142. package/dist/skill-bundle/references/adapting-a-starter.md +104 -0
  143. package/dist/skill-bundle/references/authoring-scenarios.md +42 -5
  144. package/dist/skill-bundle/references/blocks.md +1 -1
  145. package/dist/skill-bundle/references/brief.md +5 -6
  146. package/dist/skill-bundle/references/capture.md +52 -41
  147. package/dist/skill-bundle/references/concrete-tiers.md +95 -0
  148. package/dist/skill-bundle/references/recall.md +6 -12
  149. package/dist/skill-bundle/references/schema.md +15 -24
  150. package/dist/skill-bundle/references/self-check.md +2 -2
  151. package/dist/skill-bundle/references/steering-audit.md +7 -10
  152. package/package.json +2 -2
  153. package/dist/scan/steering-template.d.ts +0 -8
  154. package/dist/scan/steering-template.d.ts.map +0 -1
  155. package/dist/scan/steering-template.js +0 -266
  156. package/dist/scan/steering-template.js.map +0 -1
  157. package/dist/skill-bundle/references/wild.md +0 -30
@@ -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.
@@ -0,0 +1,44 @@
1
+ ---
2
+ description: "Gather for any copy and for motion character. The temperature dial: how the brand sounds and how it moves — this brand's current answer is factual, quiet, never celebratory, with resolved spring motion."
3
+ materials:
4
+ - materials/tokens.css
5
+ ---
6
+
7
+ This is Vessel's answer to temperature — it stands until you replace it.
8
+
9
+ The relationship is fixed: voice and motion carry the same temperature. Copy
10
+ states what happened, what is possible, or what the user must decide — it
11
+ does not perform personality — and motion confirms rather than entertains.
12
+
13
+ Vessel's current answer in words: product UI is the default register —
14
+ factual, quiet, sentence case, and free of applause. No exclamation marks;
15
+ celebration is not reassurance. Confirmations are quiet: "Changes saved",
16
+ never "Awesome!" The system should sound reliable, not excited by basic
17
+ competence. Errors name the problem and the fix in the place where the user
18
+ can act; a vague failure banner is evasion. Buttons name the act — "Delete
19
+ account", "Save changes", "Invite member", not "Do it" or "Let's go".
20
+ Destructive copy is direct because the risk is direct; softening the verb
21
+ makes the interface less honest. Vessel never celebrates at the user. Trust
22
+ comes from precision, restraint, and naming the truth plainly.
23
+
24
+ The voice is a mechanical edit, not a mood — apply it as transformations:
25
+ "Sorry, nothing here yet!" → "Nothing yet". "Awesome, your changes have been
26
+ saved!" → "Changes saved". "Oops! Something went wrong" → "Payment failed —
27
+ card expired". "You might want to consider updating your billing info" →
28
+ "Update your billing info". Strip the apology, the applause, and the hedge;
29
+ keep the fact and the fix.
30
+
31
+ Vessel's current answer in motion: three durations — `--duration-fast`,
32
+ `--duration-normal`, `--duration-slow` — and one ease, `--ease-spring`, which
33
+ should feel resolved without feeling elastic. Hover confirms with color and
34
+ background shifts at the fast duration, not levitation.
35
+
36
+ Condition: editorial surfaces switch register. Short declarative confident
37
+ fragments are correct in heroes and section headings. That same editorial
38
+ confidence is wrong in a settings form — product copy serves the task before
39
+ it serves the voice. Email copy uses the product voice: factual, not
40
+ campaign-like.
41
+
42
+ To adapt: rewrite this node's current answers in your brand's voice and edit
43
+ the duration and ease values in `materials/tokens.css`. The coupling — words
44
+ and motion sharing one temperature — is the part worth keeping.
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: "Gather for any text, and for heroes, landing pages, and editorial moments. The type dial: one voice typeface plus a mono for machine detail, with an editorial heading scale kept separate from product text — this brand's current answer is HK Grotesk."
3
+ materials:
4
+ - materials/tokens.css
5
+ - materials/fonts/*.woff2
6
+ ---
7
+
8
+ This is Vessel's answer to type — it stands until you replace it.
9
+
10
+ The relationship is fixed: one typeface is the voice of the interface,
11
+ everywhere, with a mono variant only for code, tool detail, and machine
12
+ output. The heading scale is editorial — its tokens exist for pages composed
13
+ outside the text variants — and product UI never mixes the two vocabularies
14
+ in one view.
15
+
16
+ Vessel's current answer: HK Grotesk. vessel-light ships it as its embedded
17
+ voice — here, `tokens.css` is canonical.
18
+
19
+ The heading scale is editorial: display, section, and sub each carry their
20
+ own rhythm (`--heading-display-*`, `--heading-section-*`, `--heading-sub-*`).
21
+ Display sizes use tight tracking and sub-1 line heights because the words
22
+ behave like composition, not paragraph text. Card-level headings inside
23
+ editorial features use the product `title` variant — the scale does not reach
24
+ below sub.
25
+
26
+ Labels are small, semibold, and tracked wide. They should feel precise, never
27
+ loud. Body text keeps the established reading sizes with relaxed line height;
28
+ do not shrink important prose until it becomes legal copy.
29
+
30
+ Condition: display and section scale are for editorial or hero moments.
31
+ Product UI lives in headline, title, body, label, and mono. A modal title is
32
+ not a poster. When in doubt, make type quieter and layout clearer.
33
+
34
+ To adapt: swap the font files, edit `--font-sans`, `--font-mono`, and the
35
+ heading tokens in `materials/tokens.css`, and restate this node's current
36
+ answer. The one-voice rule and the editorial/product vocabulary split are the
37
+ parts worth keeping.