@design-intelligence/ghost 0.20.0 → 0.21.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 (95) hide show
  1. package/dist/commands/checks-command.d.ts.map +1 -1
  2. package/dist/commands/checks-command.js +8 -1
  3. package/dist/commands/checks-command.js.map +1 -1
  4. package/dist/commands/init-command.d.ts.map +1 -1
  5. package/dist/commands/init-command.js +23 -8
  6. package/dist/commands/init-command.js.map +1 -1
  7. package/dist/commands/review-command.d.ts.map +1 -1
  8. package/dist/commands/review-command.js +1 -0
  9. package/dist/commands/review-command.js.map +1 -1
  10. package/dist/init-payloads/median/anti-goal.median.md +86 -0
  11. package/dist/init-payloads/median/median-tells.md +117 -0
  12. package/dist/init-payloads/skeleton/glossary.md +44 -0
  13. package/dist/init-payloads/skeleton/grammar.color-roles.md +26 -0
  14. package/dist/init-payloads/skeleton/grammar.conversation.md +23 -0
  15. package/dist/init-payloads/skeleton/grammar.hierarchy.md +39 -0
  16. package/dist/init-payloads/skeleton/grammar.motion.md +24 -0
  17. package/dist/init-payloads/skeleton/grammar.rhythm.md +23 -0
  18. package/dist/init-payloads/skeleton/grammar.surfaces.md +26 -0
  19. package/dist/init-payloads/skeleton/index.md +27 -0
  20. package/dist/init-payloads/skeleton/signature.palette.md +24 -0
  21. package/dist/init-payloads/skeleton/signature.shape.md +19 -0
  22. package/dist/init-payloads/skeleton/signature.temperature.md +20 -0
  23. package/dist/init-payloads/skeleton/signature.type.md +22 -0
  24. package/dist/init-payloads/vessel-light/anti-goal.median.md +86 -0
  25. package/dist/init-payloads/vessel-light/anti-goal.tells.md +37 -0
  26. package/dist/init-payloads/vessel-light/checks/conversation-grammar.md +20 -0
  27. package/dist/init-payloads/vessel-light/checks/median-tells.md +103 -0
  28. package/dist/init-payloads/vessel-light/checks/motion-restraint.md +20 -0
  29. package/dist/init-payloads/vessel-light/checks/relationships.md +33 -0
  30. package/dist/init-payloads/vessel-light/checks/values.md +51 -0
  31. package/dist/init-payloads/vessel-light/glossary.md +45 -0
  32. package/dist/init-payloads/vessel-light/grammar.color-roles.md +30 -0
  33. package/dist/init-payloads/vessel-light/grammar.conversation.md +30 -0
  34. package/dist/init-payloads/vessel-light/grammar.hierarchy.md +48 -0
  35. package/dist/init-payloads/vessel-light/grammar.motion.md +27 -0
  36. package/dist/init-payloads/vessel-light/grammar.rhythm.md +27 -0
  37. package/dist/init-payloads/vessel-light/grammar.surfaces.md +35 -0
  38. package/dist/init-payloads/vessel-light/index.md +37 -0
  39. package/dist/init-payloads/vessel-light/manifest.yml +2 -0
  40. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Black.woff2 +0 -0
  41. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Bold.woff2 +0 -0
  42. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-ExtraBold.woff2 +0 -0
  43. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Light.woff2 +0 -0
  44. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Medium.woff2 +0 -0
  45. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-Regular.woff2 +0 -0
  46. package/dist/init-payloads/vessel-light/materials/fonts/HKGrotesk-SemiBold.woff2 +0 -0
  47. package/dist/init-payloads/vessel-light/materials/primitives.css +388 -0
  48. package/dist/init-payloads/vessel-light/materials/ref/composition.conversation.html +63 -0
  49. package/dist/init-payloads/vessel-light/materials/ref/composition.editorial.html +69 -0
  50. package/dist/init-payloads/vessel-light/materials/ref/composition.form.html +89 -0
  51. package/dist/init-payloads/vessel-light/materials/ref/composition.overlay.html +60 -0
  52. package/dist/init-payloads/vessel-light/materials/ref/composition.table.html +104 -0
  53. package/dist/init-payloads/vessel-light/materials/ref/email.html +80 -0
  54. package/dist/init-payloads/vessel-light/materials/tokens.css +242 -0
  55. package/dist/init-payloads/vessel-light/register.data-density.md +39 -0
  56. package/dist/init-payloads/vessel-light/register.editorial.md +41 -0
  57. package/dist/init-payloads/vessel-light/register.email.md +43 -0
  58. package/dist/init-payloads/vessel-light/signature.palette.md +45 -0
  59. package/dist/init-payloads/vessel-light/signature.shape.md +27 -0
  60. package/dist/init-payloads/vessel-light/signature.temperature.md +37 -0
  61. package/dist/init-payloads/vessel-light/signature.type.md +36 -0
  62. package/dist/review/resolve.d.ts +2 -2
  63. package/dist/review/resolve.d.ts.map +1 -1
  64. package/dist/review/resolve.js +8 -4
  65. package/dist/review/resolve.js.map +1 -1
  66. package/dist/review/review-packet.d.ts +2 -0
  67. package/dist/review/review-packet.d.ts.map +1 -1
  68. package/dist/review/review-packet.js +9 -1
  69. package/dist/review/review-packet.js.map +1 -1
  70. package/dist/scan/check-scaffold.d.ts +1 -0
  71. package/dist/scan/check-scaffold.d.ts.map +1 -1
  72. package/dist/scan/check-scaffold.js +17 -1
  73. package/dist/scan/check-scaffold.js.map +1 -1
  74. package/dist/scan/fingerprint-package.d.ts +7 -1
  75. package/dist/scan/fingerprint-package.d.ts.map +1 -1
  76. package/dist/scan/fingerprint-package.js +25 -12
  77. package/dist/scan/fingerprint-package.js.map +1 -1
  78. package/dist/scan/packed-payloads.d.ts +4 -0
  79. package/dist/scan/packed-payloads.d.ts.map +1 -0
  80. package/dist/scan/packed-payloads.js +55 -0
  81. package/dist/scan/packed-payloads.js.map +1 -0
  82. package/dist/scan/templates.d.ts +20 -2
  83. package/dist/scan/templates.d.ts.map +1 -1
  84. package/dist/scan/templates.js +83 -11
  85. package/dist/scan/templates.js.map +1 -1
  86. package/dist/skill-bundle/SKILL.md +1 -0
  87. package/dist/skill-bundle/references/adapting-a-starter.md +102 -0
  88. package/dist/skill-bundle/references/authoring-scenarios.md +40 -1
  89. package/dist/skill-bundle/references/blocks.md +1 -1
  90. package/dist/skill-bundle/references/capture.md +5 -5
  91. package/package.json +2 -2
  92. package/dist/scan/steering-template.d.ts +0 -8
  93. package/dist/scan/steering-template.d.ts.map +0 -1
  94. package/dist/scan/steering-template.js +0 -266
  95. package/dist/scan/steering-template.js.map +0 -1
@@ -0,0 +1,89 @@
1
+ <!-- ghost ref annotations
2
+ normative-for: grammar.hierarchy — the complete control emphasis ladder (primary, secondary, outline, ghost, link) working one coherent view with one primary; destructive as a meaning, not a rung; field/label/error anatomy; the product text variants headline, title, body, label, mono; the warning and destructive tones. grammar.rhythm — column stacks with named gap steps, rows only for controls and paired label/value moments. grammar.surfaces — card tier with structural border. signature.shape — --radius-control on every control, --radius-surface on the card.
3
+ incidental: all copy, field values, and key strings; the 560px column width; which specific action occupies each ladder rung; the settings domain itself.
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 — Settings Form</title>
11
+ <link rel="stylesheet" href="../tokens.css" />
12
+ <link rel="stylesheet" href="../primitives.css" />
13
+ <style>
14
+ body { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 24px; }
15
+ main { width: min(100%, 560px); }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <main class="stack stack--gap-lg">
20
+ <header class="stack stack--row stack--justify-between stack--align-end stack--gap-md stack--wrap">
21
+ <div class="stack stack--gap-xs">
22
+ <h1 class="text text--headline">Workspace settings</h1>
23
+ <p class="text text--muted">Tune the defaults your team sees when Vessel drafts interface work.</p>
24
+ </div>
25
+ <button class="button button--secondary button--size-sm" type="button">Invite member</button>
26
+ </header>
27
+
28
+ <section class="surface surface--card surface--pad-lg surface--radius-surface surface--border surface--elevation-card">
29
+ <form class="stack stack--gap-lg">
30
+ <header class="stack stack--gap-sm">
31
+ <h2 class="text text--title">Profile</h2>
32
+ <p class="text text--muted">These values appear on receipts, invites, and review packets.</p>
33
+ </header>
34
+
35
+ <section class="stack stack--gap-md">
36
+ <div class="field">
37
+ <label class="label" for="workspace-name">Workspace name</label>
38
+ <input class="input" id="workspace-name" value="Ghost Studio" />
39
+ </div>
40
+
41
+ <div class="field">
42
+ <label class="label" for="reply-email">Reply email</label>
43
+ <input class="input" id="reply-email" value="design@ghost.example" aria-invalid="true" />
44
+ <p class="field-error">Use a verified sender before inviting collaborators.</p>
45
+ </div>
46
+
47
+ <div class="field">
48
+ <span class="label">Default density</span>
49
+ <div class="input input--select" role="button" tabindex="0" aria-label="Default density">
50
+ <span>Comfortable</span>
51
+ <span aria-hidden="true">⌄</span>
52
+ </div>
53
+ </div>
54
+
55
+ <label class="stack stack--row stack--gap-sm stack--align-center">
56
+ <input class="input input--checkbox" type="checkbox" checked />
57
+ <span class="text">Send weekly review summaries</span>
58
+ </label>
59
+ </section>
60
+
61
+ <section class="stack stack--gap-sm">
62
+ <span class="text text--label text--muted">API access</span>
63
+ <div class="surface surface--muted surface--pad-sm surface--radius-surface stack stack--row stack--justify-between stack--align-center stack--gap-sm stack--wrap">
64
+ <code class="text text--mono text--muted">vsl_live_4f8a…03c2</code>
65
+ <button class="button button--outline button--size-sm" type="button">Regenerate key</button>
66
+ </div>
67
+ <p class="text text--warning">Regenerating invalidates the key currently in use by integrations.</p>
68
+ </section>
69
+
70
+ <section class="stack stack--row stack--justify-between stack--align-center stack--gap-md stack--wrap">
71
+ <div class="stack stack--gap-none">
72
+ <span class="text">Delete this workspace</span>
73
+ <span class="text text--destructive">Removes every fingerprint and review record immediately.</span>
74
+ </div>
75
+ <button class="button button--destructive button--size-sm" type="button">Delete workspace</button>
76
+ </section>
77
+
78
+ <footer class="stack stack--row stack--justify-between stack--align-center stack--gap-sm stack--wrap">
79
+ <a class="button button--link button--size-sm" href="#audit-log">View audit log</a>
80
+ <div class="stack stack--row stack--justify-end stack--gap-sm">
81
+ <button class="button button--ghost" type="button">Cancel</button>
82
+ <button class="button button--primary" type="submit">Save settings</button>
83
+ </div>
84
+ </footer>
85
+ </form>
86
+ </section>
87
+ </main>
88
+ </body>
89
+ </html>
@@ -0,0 +1,60 @@
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.hierarchy — one primary confirm, ghost escape, menu items as ghost-weight actions; the info tone carrying a state-meaning note. signature.shape — surface radius on both overlay surfaces.
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
+ </style>
21
+ </head>
22
+ <body>
23
+ <main class="page stack stack--gap-lg">
24
+ <header class="stack stack--row stack--justify-between stack--align-center stack--gap-md">
25
+ <h1 class="text text--headline">Fingerprint</h1>
26
+ <button class="button button--outline button--size-sm" type="button" aria-haspopup="menu" aria-expanded="true">Actions</button>
27
+ </header>
28
+ <p class="text text--muted">Three nodes changed since the last publish. Review the diff, then publish from the actions menu.</p>
29
+
30
+ <!-- popover tier: anchored menu, floats above the flow -->
31
+ <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">
32
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Review diff</button>
33
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Publish changes…</button>
34
+ <button class="button button--ghost menu-item" type="button" role="menuitem">Export package</button>
35
+ </nav>
36
+ </main>
37
+
38
+ <!-- modal tier: scrim, interrupting dialog -->
39
+ <div class="scrim" role="presentation">
40
+ <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">
41
+ <header class="stack stack--gap-sm">
42
+ <h2 class="text text--title" id="dialog-title">Publish fingerprint changes?</h2>
43
+ <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>
44
+ </header>
45
+
46
+ <div class="surface surface--muted surface--pad-md surface--radius-surface stack stack--gap-xs">
47
+ <p class="text text--label">Included</p>
48
+ <p class="text">3 nodes, 2 material references, 1 review assertion</p>
49
+ </div>
50
+
51
+ <p class="text text--info">Publishing replaces the previous packet for every agent in this repo.</p>
52
+
53
+ <footer class="stack stack--row stack--justify-end stack--gap-sm stack--wrap">
54
+ <button class="button button--ghost" type="button">Cancel</button>
55
+ <button class="button button--primary" type="button">Confirm publish</button>
56
+ </footer>
57
+ </section>
58
+ </div>
59
+ </body>
60
+ </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, 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; border-radius: var(--radius-sm); }
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 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,242 @@
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
+ --color-black: #000000;
65
+
66
+ --color-gray-50: #f5f5f5;
67
+ --color-gray-100: #f0f0f0;
68
+ --color-gray-200: #e8e8e8;
69
+ --color-gray-300: #e5e5e5;
70
+ --color-gray-400: #cccccc;
71
+ --color-gray-500: #999999;
72
+ --color-gray-600: #666666;
73
+ --color-gray-700: #333333;
74
+ --color-gray-800: #232323;
75
+ --color-gray-900: #1a1a1a;
76
+
77
+ --color-red-100: #ff6b6b;
78
+ --color-red-200: #f94b4b;
79
+ --color-blue-100: #7cacff;
80
+ --color-blue-200: #5c98f9;
81
+ --color-green-100: #a3d795;
82
+ --color-green-200: #91cb80;
83
+ --color-yellow-100: #ffd966;
84
+ --color-yellow-200: #fbcd44;
85
+
86
+ --radius: 20px;
87
+ --radius-sm: calc(var(--radius) - 4px);
88
+ --radius-md: calc(var(--radius) - 2px);
89
+ --radius-lg: var(--radius);
90
+ --radius-surface: 20px;
91
+ --radius-control: 999px;
92
+ --radius-input: 999px;
93
+
94
+ --gap-xs: 4px;
95
+ --gap-sm: 8px;
96
+ --gap-md: 16px;
97
+ --gap-lg: 24px;
98
+ --gap-xl: 32px;
99
+
100
+ --text-body-size: 14px;
101
+ --text-title-size: 18px;
102
+ --text-headline-size: 24px;
103
+
104
+ --control-height: 36px;
105
+
106
+ --background: var(--color-white);
107
+ --foreground: var(--color-gray-900);
108
+ --card: var(--background);
109
+ --card-foreground: var(--foreground);
110
+ --popover: var(--background);
111
+ --popover-foreground: var(--foreground);
112
+ --primary: var(--color-gray-900);
113
+ --primary-foreground: var(--color-white);
114
+ --secondary: var(--color-gray-100);
115
+ --secondary-foreground: var(--foreground);
116
+ --muted: var(--color-gray-100);
117
+ --muted-foreground: var(--color-gray-500);
118
+ --accent: var(--color-gray-100);
119
+ --accent-foreground: var(--foreground);
120
+ --destructive: var(--color-red-200);
121
+ --destructive-foreground: var(--color-white);
122
+ --success: var(--color-green-200);
123
+ --success-foreground: var(--color-gray-900);
124
+ --warning: var(--color-yellow-200);
125
+ --warning-foreground: var(--color-gray-900);
126
+ --info: var(--color-blue-200);
127
+ --info-foreground: var(--color-gray-900);
128
+ --border: var(--color-gray-200);
129
+ --input: var(--color-gray-300);
130
+ --ring: var(--color-gray-400);
131
+
132
+ --dark-10: rgba(26, 26, 26, 0.1);
133
+ --dark-40: rgba(26, 26, 26, 0.4);
134
+ --dark-04: rgba(26, 26, 26, 0.04);
135
+
136
+ --shadow-mini: 0 2px 8px rgba(76, 76, 76, 0.15);
137
+ --shadow-mini-inset: 0 1px 4px rgba(76, 76, 76, 0.1) inset;
138
+ --shadow-btn: 0 2px 8px rgba(76, 76, 76, 0.15);
139
+ --shadow-card: 0 2px 8px rgba(76, 76, 76, 0.15);
140
+ --shadow-elevated: 0 3px 12px rgba(76, 76, 76, 0.22);
141
+ --shadow-popover: 0 8px 30px rgba(0, 0, 0, 0.12);
142
+ --shadow-modal: 0 20px 60px rgba(0, 0, 0, 0.2);
143
+ --shadow-kbd: 0 2px 8px rgba(76, 76, 76, 0.15);
144
+
145
+ --surface-dark: #0a0a0a;
146
+ --surface-dark-text: #f5f5f5;
147
+ --surface-dark-muted: rgba(255, 255, 255, 0.5);
148
+ --surface-dark-border: rgba(255, 255, 255, 0.08);
149
+
150
+ --heading-display-font-size: clamp(64px, 8vw, 96px);
151
+ --heading-display-line-height: 0.88;
152
+ --heading-display-letter-spacing: -0.05em;
153
+ --heading-display-font-weight: 900;
154
+ --heading-section-font-size: clamp(44px, 5vw, 64px);
155
+ --heading-section-line-height: 0.95;
156
+ --heading-section-letter-spacing: -0.035em;
157
+ --heading-section-font-weight: 700;
158
+ --heading-sub-font-size: clamp(28px, 3vw, 40px);
159
+ --heading-sub-line-height: 1;
160
+ --heading-sub-letter-spacing: -0.02em;
161
+ --heading-sub-font-weight: 700;
162
+ --heading-card-font-size: clamp(20px, 2vw, 28px);
163
+ --heading-card-line-height: 1.1;
164
+ --heading-card-letter-spacing: -0.01em;
165
+ --heading-card-font-weight: 600;
166
+
167
+ --display-size: clamp(3rem, 12vw, 12rem);
168
+ --display-line-height: 0.85;
169
+ --display-letter-spacing: -0.05em;
170
+ --body-reading-size: clamp(1rem, 1.3vw, 1.25rem);
171
+ --body-reading-line-height: 1.65;
172
+ --body-reading-letter-spacing: -0.01em;
173
+ --label-font-size: 11px;
174
+ --label-letter-spacing: 0.12em;
175
+ --label-font-weight: 600;
176
+ --label-line-height: 1.2;
177
+ --pullquote-size: clamp(1.5rem, 3vw, 2.5rem);
178
+ --pullquote-line-height: 1.3;
179
+ --pullquote-weight: 300;
180
+ --pullquote-letter-spacing: -0.02em;
181
+
182
+ --page-container-max-width: 1440px;
183
+ --page-container-side-gutter: 20px;
184
+ --section-padding-vertical: 100px;
185
+ --section-heading-margin-bottom: 75px;
186
+
187
+ --ease-spring: cubic-bezier(0.33, 1, 0.68, 1);
188
+ --duration-fast: 0.15s;
189
+ --duration-normal: 0.2s;
190
+ --duration-slow: 0.4s;
191
+
192
+ /* Expression palette — the brand's five hues, volume-gated by register.
193
+ Product: charts only. Data-density: one hue family for status.
194
+ Email: exactly one expressive moment. Editorial: atmosphere, max two
195
+ hues per page. Never on interactive controls in any register. */
196
+ --expression-1: #f6b44a; /* amber */
197
+ --expression-2: #7585ff; /* periwinkle */
198
+ --expression-3: #d76a6a; /* clay */
199
+ --expression-4: #d185e0; /* orchid */
200
+ --expression-5: #91cb80; /* sage */
201
+ }
202
+
203
+ .dark {
204
+ --background: var(--color-black);
205
+ --foreground: var(--color-white);
206
+ --card: var(--color-gray-800);
207
+ --card-foreground: var(--foreground);
208
+ --popover: var(--color-gray-800);
209
+ --popover-foreground: var(--foreground);
210
+ --primary: var(--color-white);
211
+ --primary-foreground: var(--color-black);
212
+ --secondary: var(--color-gray-700);
213
+ --secondary-foreground: var(--foreground);
214
+ --muted: var(--color-gray-800);
215
+ --muted-foreground: var(--color-gray-500);
216
+ --accent: var(--color-gray-800);
217
+ --accent-foreground: var(--foreground);
218
+ --destructive: var(--color-red-100);
219
+ --destructive-foreground: var(--color-black);
220
+ --success: var(--color-green-100);
221
+ --success-foreground: var(--color-black);
222
+ --warning: var(--color-yellow-100);
223
+ --warning-foreground: var(--color-black);
224
+ --info: var(--color-blue-100);
225
+ --info-foreground: var(--color-black);
226
+ --border: var(--color-gray-700);
227
+ --input: var(--color-gray-700);
228
+ --ring: var(--color-gray-400);
229
+
230
+ --dark-10: rgba(242, 242, 242, 0.1);
231
+ --dark-40: rgba(242, 242, 242, 0.4);
232
+ --dark-04: rgba(242, 242, 242, 0.04);
233
+
234
+ --shadow-mini: 0 2px 8px rgba(0, 0, 0, 0.4);
235
+ --shadow-mini-inset: 0 1px 4px rgba(0, 0, 0, 0.5) inset;
236
+ --shadow-btn: 0 2px 8px rgba(0, 0, 0, 0.3);
237
+ --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.4);
238
+ --shadow-elevated: 0 3px 12px rgba(0, 0, 0, 0.5);
239
+ --shadow-popover: 0 8px 30px rgba(0, 0, 0, 0.4);
240
+ --shadow-modal: 0 20px 60px rgba(0, 0, 0, 0.6);
241
+ --shadow-kbd: 0 2px 8px rgba(0, 0, 0, 0.4);
242
+ }
@@ -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.