wand-kit 0.3.2 → 0.5.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 (162) hide show
  1. package/PROMPT.md +221 -19
  2. package/SKILL.md +100 -20
  3. package/START-HERE.md +12 -1
  4. package/brands/current/tokens.json +10 -2
  5. package/brands/interim/assets/avatar.svg +1 -0
  6. package/brands/interim/assets/closing-art.png +0 -0
  7. package/brands/interim/assets/cover-art.png +0 -0
  8. package/brands/interim/assets/cover-portrait-art.png +0 -0
  9. package/brands/interim/assets/divider-art.png +0 -0
  10. package/brands/interim/assets/glyphs/README.md +29 -0
  11. package/brands/interim/assets/glyphs/activity.svg +15 -0
  12. package/brands/interim/assets/glyphs/atom.svg +17 -0
  13. package/brands/interim/assets/glyphs/badge-check.svg +16 -0
  14. package/brands/interim/assets/glyphs/bell.svg +16 -0
  15. package/brands/interim/assets/glyphs/blocks.svg +16 -0
  16. package/brands/interim/assets/glyphs/book-open.svg +16 -0
  17. package/brands/interim/assets/glyphs/bot.svg +20 -0
  18. package/brands/interim/assets/glyphs/boxes.svg +26 -0
  19. package/brands/interim/assets/glyphs/brain.svg +23 -0
  20. package/brands/interim/assets/glyphs/briefcase.svg +16 -0
  21. package/brands/interim/assets/glyphs/building-2.svg +21 -0
  22. package/brands/interim/assets/glyphs/calendar.svg +18 -0
  23. package/brands/interim/assets/glyphs/chart-column.svg +18 -0
  24. package/brands/interim/assets/glyphs/chart-line.svg +16 -0
  25. package/brands/interim/assets/glyphs/chart-pie.svg +16 -0
  26. package/brands/interim/assets/glyphs/circle-check.svg +16 -0
  27. package/brands/interim/assets/glyphs/clipboard-check.svg +17 -0
  28. package/brands/interim/assets/glyphs/clock.svg +16 -0
  29. package/brands/interim/assets/glyphs/cloud.svg +15 -0
  30. package/brands/interim/assets/glyphs/code.svg +15 -0
  31. package/brands/interim/assets/glyphs/coins.svg +18 -0
  32. package/brands/interim/assets/glyphs/compass.svg +16 -0
  33. package/brands/interim/assets/glyphs/cpu.svg +24 -0
  34. package/brands/interim/assets/glyphs/database.svg +17 -0
  35. package/brands/interim/assets/glyphs/eye.svg +16 -0
  36. package/brands/interim/assets/glyphs/file-check.svg +17 -0
  37. package/brands/interim/assets/glyphs/filter.svg +15 -0
  38. package/brands/interim/assets/glyphs/fingerprint.svg +23 -0
  39. package/brands/interim/assets/glyphs/flag.svg +16 -0
  40. package/brands/interim/assets/glyphs/gauge.svg +16 -0
  41. package/brands/interim/assets/glyphs/gavel.svg +19 -0
  42. package/brands/interim/assets/glyphs/git-branch.svg +18 -0
  43. package/brands/interim/assets/glyphs/globe.svg +17 -0
  44. package/brands/interim/assets/glyphs/graduation-cap.svg +17 -0
  45. package/brands/interim/assets/glyphs/handshake.svg +19 -0
  46. package/brands/interim/assets/glyphs/hexagon.svg +15 -0
  47. package/brands/interim/assets/glyphs/index.json +177 -0
  48. package/brands/interim/assets/glyphs/infinity.svg +15 -0
  49. package/brands/interim/assets/glyphs/key.svg +17 -0
  50. package/brands/interim/assets/glyphs/landmark.svg +20 -0
  51. package/brands/interim/assets/glyphs/layers.svg +17 -0
  52. package/brands/interim/assets/glyphs/lightbulb.svg +17 -0
  53. package/brands/interim/assets/glyphs/link.svg +16 -0
  54. package/brands/interim/assets/glyphs/list-checks.svg +19 -0
  55. package/brands/interim/assets/glyphs/lock.svg +16 -0
  56. package/brands/interim/assets/glyphs/map.svg +17 -0
  57. package/brands/interim/assets/glyphs/megaphone.svg +16 -0
  58. package/brands/interim/assets/glyphs/message-square.svg +15 -0
  59. package/brands/interim/assets/glyphs/milestone.svg +17 -0
  60. package/brands/interim/assets/glyphs/network.svg +19 -0
  61. package/brands/interim/assets/glyphs/orbit.svg +19 -0
  62. package/brands/interim/assets/glyphs/package.svg +18 -0
  63. package/brands/interim/assets/glyphs/plug.svg +18 -0
  64. package/brands/interim/assets/glyphs/puzzle.svg +15 -0
  65. package/brands/interim/assets/glyphs/radar.svg +22 -0
  66. package/brands/interim/assets/glyphs/receipt.svg +17 -0
  67. package/brands/interim/assets/glyphs/refresh-cw.svg +18 -0
  68. package/brands/interim/assets/glyphs/rocket.svg +18 -0
  69. package/brands/interim/assets/glyphs/route.svg +17 -0
  70. package/brands/interim/assets/glyphs/scale.svg +19 -0
  71. package/brands/interim/assets/glyphs/search.svg +16 -0
  72. package/brands/interim/assets/glyphs/server.svg +18 -0
  73. package/brands/interim/assets/glyphs/settings.svg +16 -0
  74. package/brands/interim/assets/glyphs/share-2.svg +19 -0
  75. package/brands/interim/assets/glyphs/shield-check.svg +16 -0
  76. package/brands/interim/assets/glyphs/shuffle.svg +19 -0
  77. package/brands/interim/assets/glyphs/sparkles.svg +19 -0
  78. package/brands/interim/assets/glyphs/square-stack.svg +17 -0
  79. package/brands/interim/assets/glyphs/target.svg +17 -0
  80. package/brands/interim/assets/glyphs/trending-up.svg +16 -0
  81. package/brands/interim/assets/glyphs/triangle-alert.svg +17 -0
  82. package/brands/interim/assets/glyphs/trophy.svg +20 -0
  83. package/brands/interim/assets/glyphs/users.svg +18 -0
  84. package/brands/interim/assets/glyphs/wallet.svg +16 -0
  85. package/brands/interim/assets/glyphs/wand-sparkles.svg +22 -0
  86. package/brands/interim/assets/glyphs/workflow.svg +17 -0
  87. package/brands/interim/assets/glyphs/zap.svg +15 -0
  88. package/brands/interim/assets/mark.svg +1 -0
  89. package/brands/interim/assets/social/composition.json +6833 -0
  90. package/brands/interim/assets/spark-lavender.png +0 -0
  91. package/brands/interim/assets/spark-violet.png +0 -0
  92. package/brands/interim/assets/statement-art.png +0 -0
  93. package/brands/interim/assets/story/agent-alpha.png +0 -0
  94. package/brands/interim/assets/story/agent.png +0 -0
  95. package/brands/interim/assets/story/economy-alpha.png +0 -0
  96. package/brands/interim/assets/story/economy.png +0 -0
  97. package/brands/interim/assets/story/index.json +214 -0
  98. package/brands/interim/assets/story/learning-alpha.png +0 -0
  99. package/brands/interim/assets/story/learning.png +0 -0
  100. package/brands/interim/assets/story/organization-alpha.png +0 -0
  101. package/brands/interim/assets/story/organization.png +0 -0
  102. package/brands/interim/assets/story/worker-alpha.png +0 -0
  103. package/brands/interim/assets/story/worker-light.png +0 -0
  104. package/brands/interim/assets/story/worker.png +0 -0
  105. package/brands/interim/assets/wordmark-on-dark.png +0 -0
  106. package/brands/interim/assets/wordmark-on-dark.svg +1 -0
  107. package/brands/interim/assets/wordmark-on-light.png +0 -0
  108. package/brands/interim/assets/wordmark-on-light.svg +1 -0
  109. package/brands/interim/fonts/Geist-Book.ttf +0 -0
  110. package/brands/interim/fonts/Geist-Medium.ttf +0 -0
  111. package/brands/interim/fonts/Geist-Regular.ttf +0 -0
  112. package/brands/interim/fonts/Geist-SemiBold.ttf +0 -0
  113. package/brands/interim/fonts/Newsreader-Italic.ttf +0 -0
  114. package/brands/interim/fonts/Newsreader-Medium.ttf +0 -0
  115. package/brands/interim/fonts/Newsreader-MediumItalic.ttf +0 -0
  116. package/brands/interim/fonts/Newsreader-Regular.ttf +0 -0
  117. package/brands/interim/fonts/OFL-Geist.txt +93 -0
  118. package/brands/interim/fonts/OFL-Newsreader.txt +93 -0
  119. package/brands/interim/fonts/faces.json +12 -0
  120. package/brands/interim/lib/composition.js +169 -0
  121. package/brands/interim/lib/composition.mjs +101 -0
  122. package/brands/interim/lib/glyphs.js +89 -0
  123. package/brands/interim/lib/measure.js +121 -0
  124. package/brands/interim/lib/pdf.js +597 -0
  125. package/brands/interim/lib/ttf.py +169 -0
  126. package/brands/interim/lib/wandxml.py +37 -0
  127. package/brands/interim/tokens.json +299 -0
  128. package/brands/next/tokens.json +14 -2
  129. package/examples/social/social.json +23 -0
  130. package/lib/audit.js +142 -0
  131. package/lib/brand.js +12 -7
  132. package/lib/components.js +42 -10
  133. package/lib/engine.js +72 -9
  134. package/lib/library.js +180 -0
  135. package/lib/pptx.js +1 -1
  136. package/lib/social.js +366 -0
  137. package/lib/talk.js +37 -4
  138. package/library/index.json +629 -0
  139. package/library/interim/avatar-800x800.png +0 -0
  140. package/library/interim/icons/apple-touch-icon.png +0 -0
  141. package/library/interim/icons/favicon-16.png +0 -0
  142. package/library/interim/icons/favicon-32.png +0 -0
  143. package/library/interim/icons/favicon-48.png +0 -0
  144. package/library/interim/icons/favicon.ico +0 -0
  145. package/library/interim/icons/favicon.svg +1 -0
  146. package/library/interim/icons/icon-192.png +0 -0
  147. package/library/interim/icons/icon-512.png +0 -0
  148. package/library/interim/icons/icon-tags.html +5 -0
  149. package/library/interim/icons/site.webmanifest +19 -0
  150. package/library/interim/linkedin-banner-1584x396.png +0 -0
  151. package/library/interim/linkedin-company-1128x191.png +0 -0
  152. package/library/interim/open-agent-discovery-share-1200x630.png +0 -0
  153. package/library/interim/open-agent-discovery-share-head-tags.html +17 -0
  154. package/library/interim/wand-ai-share-1200x630.png +0 -0
  155. package/library/interim/wand-ai-share-head-tags.html +17 -0
  156. package/library/interim/x-header-1500x500.png +0 -0
  157. package/package.json +2 -2
  158. package/templates/card.mjs +6 -2
  159. package/templates/page.mjs +1 -1
  160. package/templates/slide.mjs +1 -1
  161. package/templates/storyboard.mjs +1 -1
  162. package/wand.js +65 -6
package/PROMPT.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # Wand Power Prompt — Studio (v0.1)
2
2
 
3
3
  One design surface for every material a sales or marketing team needs, on
4
- either Wand brand. The page is HTML; it is composed from a component library on
4
+ any of the three Wand brands. The page is HTML; it is composed from a component library on
5
5
  brand tokens; Chromium renders it; every gate measures that render; and every
6
6
  export (PDF, PNG, PowerPoint, a one-file HTML) is read from it, so nothing can
7
7
  drift from what was reviewed on screen.
8
8
 
9
9
  This document is the design system and the pipeline, and the source of truth
10
- on every design question. `brand/BRAND.md` and `brand-next/BRAND.md` win on
10
+ on every design question. `brand/BRAND.md`, `brand-next/BRAND.md` and
11
+ `brand-interim/BRAND.md` win on
11
12
  values (a hex, a face, an asset); `STATUS.md` is state; `SKILL.md` is procedure.
12
13
 
13
14
  **Why this exists.** The outputs that reviewed best in October 2026 (the
@@ -22,24 +23,27 @@ components, gates, exports.
22
23
 
23
24
  ## 0. Ground truth
24
25
 
25
- Two brands, one component set.
26
+ Three brands, one component set.
26
27
 
27
28
  | Brand | Directory | Faces | Guideline |
28
29
  |---|---|---|---|
29
30
  | `current` | `brand/` | Geist | the Kearney leadership deck; `brand/BRAND.md` |
30
- | `next` | `brand-next/` | FK Roman Standard Light, Overused Grotesk | the website, read 2026-10-05; `brand-next/BRAND.md` |
31
+ | `next` | `brand-next/` | FK Roman Standard Light, Overused Grotesk | the staging website, read 2026-10-05; `brand-next/BRAND.md` |
32
+ | `interim` | `brand-interim/` | Geist, Newsreader | the live wand.ai, read 2026-10-21, and the social design approved on it 2026-10-22, which wins where they differ; `brand-interim/BRAND.md` |
31
33
 
32
34
  Each directory's `tokens.json` carries the brand as values a kit can draw with:
33
35
  `swatch` (the measured hexes), `roles` (what each value is for, once per
34
36
  ground), `faces` (the files and their PowerPoint names), `shape` (radius,
35
- strokes) and `art` (which file plays which role). A component asks for a role
37
+ strokes, and `artShade`, the shade the kit lays over a dark page's art, 0.3
38
+ unless a brand says otherwise) and `art` (which file plays which role). A component asks for a role
36
39
  (`--ink`, `--accent`, `--emph`) and never for a hex. Where a hex in
37
40
  `tokens.json` and `BRAND.md` differ, `BRAND.md` is right and `tokens.json` has
38
41
  drifted.
39
42
 
40
- `current` is the default while the two overlap; a job is on `next` when the
41
- user asks for the new brand. The default is one constant, `DEFAULT_BRAND` in
42
- `kit/lib/brand.js`, and `doctor` prints the rule from it. The FK Roman
43
+ `current` is the default while the brands overlap; a job is on `next` when the
44
+ user asks for the new brand and on `interim` when they ask for the interim
45
+ brand or the live site's look. The default is one constant, `DEFAULT_BRAND`
46
+ in `kit/lib/brand.js`, and `doctor` prints the rule from it. The FK Roman
43
47
  Standard licence for documents is still to be confirmed
44
48
  (`brand-next/fonts/LICENSE-FONTS.md`).
45
49
 
@@ -80,13 +84,47 @@ the ground's values, so one component draws on both.
80
84
  | `label` | 6C5CE7 | A78BFA | tags, section numbers |
81
85
  | `emph` / `emphInk` / `emphText` / `emphAccent` | 251C63 / FFF / DCD6F5 / AA9BFF | 4D2E8C / FFF / DCD6F5 / C4B5F4 | the emphasis card and what sits on it |
82
86
  | `stroke` / `rule` / `track` / `surface` | E4E0F2 / E4E0F2 / E9E6F5 / EBE8F8 | 5B4BB0 / 3A2E63 / 1A1033 / 1A1033 | card strokes, hairlines, meter tracks, tiles |
87
+ | `second` / `secondSm` | 6C5CE7 / 6C5CE7 | 9481FF / 9481FF | a title's phrase, large / small (on this brand, the accent itself) |
88
+ | `gradeLow` / `gradeHigh` | 240F48 / F8F6FB | the same | the photograph grade: where blacks lift to, where highlights settle |
83
89
 
84
90
  The next brand fills the same roles from the website (gold the one accent,
85
- violets as grounds, beige as paper); see `brand-next/tokens.json`.
91
+ violets as grounds, beige as paper); see `brand-next/tokens.json`. Its
92
+ `second` is a quiet tone, not gold (7B7B79 on light, 9D99A8 on dark, large
93
+ type only; `secondSm`, the text grey, below that size).
94
+
95
+ The interim brand fills them from the live site and the social design
96
+ approved on it (2026-10-22), which wins where they differ: the approved
97
+ ground (`14101C`) is the dark ground, with ink `F7F5F9` and lavender
98
+ (`D4BCE8`) the accent for what is drawn; stone (`F5F3EF`) the light ground
99
+ with strong violet (`6D41B3`) the accent; a title's phrase is `violet`
100
+ (`C2A1EF`) on dark, on every page including the art pages (`accentText`), and
101
+ `765098` on light, the site's own `h1 em` colours; the spark takes the
102
+ phrase's colour. See `brand-interim/BRAND.md`.
86
103
 
87
104
  **Rules.**
88
105
  - One accent. The accent phrase in a title is the single most recognisable
89
106
  device in the system: one per title, never two, the sentence period in ink.
107
+ - **On the next brand a title has two tones and gold is rare.** The phrase
108
+ takes `second`, a quieter tone of the ink; gold stays for the pages that
109
+ carry the brand's art (the cover, a statement, the close), for figures and
110
+ for the spark. The website's own headings carry no gold at all, and the
111
+ wand.ai rebuild (October 2026) read as a template while every heading's
112
+ second line was gold: when gold is everywhere it means nothing. On the
113
+ current brand `second` is the accent, so nothing changes there.
114
+ - **On the interim brand a title's phrase changes face, not weight.** `<em>`
115
+ sets in Newsreader at the display's weight, the site's own `h1 em`; on the
116
+ pages that carry the art (the cover, a statement, the close) it is the
117
+ italic, as the hero's and the approved lockup's are. Its colour is one
118
+ violet on dark, the art pages too, as the approved banners set it; the
119
+ lavender accent stays for what is drawn, the figures and nothing else.
120
+ - **On the interim brand the cover is the approved composition.** The planet's
121
+ rim, four trails sweeping under the title to their dots and up through the
122
+ hero's oval, drawn unshaded (`shape.artShade` 0) with the title untracked
123
+ (`faces.display.coverTracking` 0). The composition itself
124
+ (`brand-interim/assets/social/composition.json`, drawn by
125
+ `brand-interim/lib/composition.mjs`) is what a link preview or a social
126
+ banner on this brand is cut from: a window of it at one scale, never its
127
+ parts re-proportioned.
90
128
  - One emphasis card per row, at most one or two per page.
91
129
  - Light pages carry no art. Dark pages carry art on the cover, the closing and
92
130
  a statement; a dark content page is flat.
@@ -101,11 +139,16 @@ Three face roles per brand: `display` (titles, figures, the lockup), `body`
101
139
  Tracking and leading travel with the face in `tokens.json`; the CSS sets them
102
140
  from the same values.
103
141
 
104
- | Role | current | next |
105
- |---|---|---|
106
- | display | Geist SemiBold, −0.02em | FK Roman Standard Light, −0.07em, 1.06 |
107
- | body | Geist Regular | Overused Grotesk, −0.02em |
108
- | label | Geist SemiBold, +0.18em, caps | FK Roman Standard Light, caps |
142
+ | Role | current | next | interim |
143
+ |---|---|---|---|
144
+ | display | Geist SemiBold, −0.02em | FK Roman Standard Light, −0.07em, 1.06 | Geist Medium (500), untracked, 1.025 |
145
+ | body | Geist Regular | Overused Grotesk, −0.02em | Geist Regular |
146
+ | label | Geist SemiBold, +0.18em, caps | FK Roman Standard Light, caps | Geist Medium, +0.11em, caps |
147
+ | phrase | the display face | the display face | Newsreader Medium (500, optical size 72), untracked; italic on the art pages |
148
+
149
+ A brand that sets a title's phrase in another face declares `faces.phrase`;
150
+ the CSS reads it as `--face-phrase` and friends, and a brand without it leaves
151
+ the phrase in the title's face, unchanged.
109
152
 
110
153
  **Weight carries no hierarchy on the next brand** (the serif ships one weight);
111
154
  the face does. Components therefore never rely on bold to separate levels, and
@@ -120,7 +163,8 @@ Figures are tabular (`font-variant-numeric: tabular-nums` on the page).
120
163
  ## 4. Chrome
121
164
 
122
165
  Drawn by `c.page()` on every page: eyebrow (`job.tag | eyebrow`), mark, footer
123
- (`job.footer`, page number). The cover and closing pages are `c.cover()` and
166
+ (`job.footer`, page number; a page's own `footer` replaces the line, for a
167
+ source note such as "Illustrative operating sequence"). The cover and closing pages are `c.cover()` and
124
168
  `c.closing()`, which place the brand art and the lockup; a job gives them
125
169
  words, never styling. Every piece of chrome is `.deco` or chrome-classed, so
126
170
  the gates know what is content and what is frame.
@@ -142,6 +186,7 @@ The components (`node wand.js components`; `kit/lib/components.js`):
142
186
  | `quote({ text, by, emph })`, `who` | testimonial cards, name over role, no photographs |
143
187
  | `stats`, `delta(from, to)` | figures, before-and-after |
144
188
  | `steps(items)` | next steps with arrows |
189
+ | `photo(name, { pos })` | a brand photograph filling its box, with the brand's grade |
145
190
  | `callout`, `list`, `chapter`, `img`, `icon`, `tile` | the rest |
146
191
  | `enter(kind, i)`, `step(n, html)`, `countup(text)`, `stat({ count })` | motion in a talk (§12) |
147
192
  | `video({ src, poster })`, `demo({ src, poster })` | a clip or a live page on a slide (§12) |
@@ -163,8 +208,30 @@ decide, and that make or break a page:
163
208
  ground.
164
209
  - **Short lines in cards.** One sentence and an outcome. The card's body is
165
210
  never the place for the argument.
211
+ - **Two lines a paragraph on a slide, at most** (Carlos, 2026-10-27: past two
212
+ "it breaks a lot", in PowerPoint and Google Slides above all). Keep the
213
+ words and give them room: two by two instead of four across, a ruled row
214
+ (the title left, the line right) instead of a narrow column, a band for a
215
+ unit, a lead under its title. The `lines` gate counts each block's lines
216
+ from the browser's own line boxes; it warns on every deck and fails a job
217
+ that sets `maxLines`. Titles balance and paragraphs wrap pretty
218
+ (`text-wrap`), so no word sits alone on a line.
166
219
  - **Equal heights in a row** (`stretch`), titles at one height, and the empty
167
220
  space at the foot of a page shared by its sections, never left under one.
221
+ - **One arc.** Night, then day, then first light: the dark cover with its
222
+ art, the argument on light pages, one dark statement where the piece turns,
223
+ and the close. A piece that switches ground on every page reads as a
224
+ slideshow of boxes.
225
+ - **No composition three pages running.** The same heading, then the same
226
+ three cards, page after page, is what makes a set of pages read as a
227
+ template; the variety gate names the run. Vary it: a statement set large,
228
+ a split with a photograph, a figure, a page that is one exhibit.
229
+ - **Photographs large or not at all**, through `photo()`: full bleed or a full
230
+ column, never a thumbnail; architecture and light from the brand's set,
231
+ never stock (a person at a desk, a stethoscope, a form, a highway). Every
232
+ photograph takes the brand's one grade, so they read as one shoot.
233
+ - **An exhibit on hairlines, not in a box.** A diagram or a flow sits on the
234
+ ground with rules; a frame around it reads as a dashboard widget.
168
235
  - **A slide balances and sizes itself.** Its body sits in the space under the
169
236
  title, not in the top quarter; a slide whose content fills under 55% of it
170
237
  takes the type scale a step up (`.big`) when that still fits, and the space
@@ -191,7 +258,12 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
191
258
  per page, the contact sheet. `watch` does this on every save in under a
192
259
  second with the browser kept warm.
193
260
  6. **review** — look at `out/sheet.png`, then at any page the gates named.
194
- Read the pages as the reader will: does each carry its claim?
261
+ Read the pages as the reader will: does each carry its claim? Then read
262
+ the sheet as a creative director would, the questions the build prints
263
+ under it: is one page memorable, and which; is the accent rare;
264
+ are photographs large or absent; are hairlines and type doing the
265
+ separating. A piece where no page would stop someone who has seen a
266
+ hundred decks is not finished: make one page that does.
195
267
  7. **ship** — `node wand.js ship <job> [--pptx]`: the build, the one-file HTML,
196
268
  the PowerPoint. A deck's HTML is a talk (§12), a storyboard's plays (§13),
197
269
  and either runtime is driven before it ships. `--brand next` (or `current`)
@@ -204,6 +276,7 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
204
276
  |---|---|---|
205
277
  | fit | anything in the content box runs past it, under the footer, or off the sides | a page that fits and reads badly |
206
278
  | space (warn, slides) | a slide still uses under 40% of its content area after sizing itself | whether the content deserves the slide |
279
+ | variety (warn) | three pages running share one composition (the same blocks in the same order) | two pages composed alike but far apart |
207
280
  | coverage | a line of `content.txt` is not on the page (whole, or in its declared parts), less the `cut` lines | a line that is present and in the wrong place |
208
281
  | overlap | one text box sits on another | text on art |
209
282
  | brand | a computed colour, border or fill that is not a token or a declared theme colour | gradients and images |
@@ -214,13 +287,17 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
214
287
  | pdf text | the PDF's text misses a line, or carries an em dash | |
215
288
  | contrast (warn) | text under WCAG AA against its background, chrome excepted | |
216
289
  | measure (warn) | a paragraph over the surface's characters-per-line | |
217
- | images | an image did not load | an image that loaded and is the wrong one |
290
+ | lines (warn; hard with `maxLines`) | a block of text on a slide that sets in more than two lines (or the job's `maxLines`), counted from its line boxes; autosizing never steps a slide up past it | a two-line paragraph that reads badly |
291
+ | crop (warn, og) | a share image's words leave the centre square, which Slack and WhatsApp cut as their thumbnail | the chrome, and how the image reads at 128pt |
292
+ | images | an image did not load, or is drawn at another shape than its own (stretched or squeezed past 2%; only `object-fit` cover, contain or none may change a box's shape) | an image that loaded and is the wrong one |
218
293
  | media | a demo, a clip or its poster is missing | a demo that loads and misbehaves |
219
294
  | console | a page error | |
220
295
  | runtime (ship, decks) | a slide or step the keyboard cannot reach, the overview or notes not opening, the presenter view out of step, a demo that never loads | how the motion feels |
221
296
  | timing (warn, boards) | the board is more than 10% off its `target` | the real voiceover's pace |
222
297
  | frames (warn, boards) | a frame is still to draw | a frame that is drawn and wrong |
223
298
  | player (ship, boards) | the player does not run, scrub, or caption | |
299
+ | social (each image) | the lockup leaves its place or the centre square, the ring is cut, type under the floor, a share image over 300 KB | how it reads at 128pt: the review questions |
300
+ | library (`--check`) | a library file is not the one approved, or the kit no longer draws it within its tolerance | a file that was approved and is wrong |
224
301
 
225
302
  The gates read the DOM Chromium laid out for the PDF; nothing is inferred from
226
303
  the spec. What no gate sees: the argument, the pacing, and whether the right
@@ -274,7 +351,9 @@ component was chosen. That is the review.
274
351
  4. **A scratch voice.** The Wand OS film timed its board against a voice from
275
352
  macOS `say`; the chat sandbox has none, so timing here is words at `wpm`.
276
353
  A recorded voiceover passed as `audio` leads the player.
277
- 4. **Email and banner surfaces**: declared in §1's spirit, not yet in the table.
354
+ 5. **Email surfaces**: declared in §1's spirit, not yet in the table. Banners
355
+ exist on the interim brand, drawn from its composition (§14); on the other
356
+ brands they are still to come.
278
357
 
279
358
  ## 12. Talks: motion and the presenter
280
359
 
@@ -293,7 +372,11 @@ figure final, every poster.
293
372
  - **Kinds.** `rise` (the default), `fade`, `pop` for a mark or a figure,
294
373
  `grow` for a bar going up, `widen` for a bar going across, `draw` for a
295
374
  line that tells a trend (an SVG path with `pathLength="1"`), `count` for a
296
- figure the room should watch arrive (`stat({ count: true })`, `countup()`).
375
+ figure the room should watch arrive (`stat({ count: true })`, `countup()`),
376
+ `words` for a title whose words rise out of their lines (every title does
377
+ this under `motion: "auto"`), `lit` for a statement that lights word by
378
+ word, `window` for a photograph that opens like a window. A page's art
379
+ (the cover's light, a statement, the close) comes up like first light.
297
380
  - **Steps** when the order of the argument is the point: `step(1, html)`, then
298
381
  2, then 3. Never more than four on a slide. Going back undoes the last step.
299
382
  - **Notes on every slide of a talk**, and `seconds` on each when the talk has a
@@ -342,3 +425,122 @@ direction (the line, camera, motion, on screen, sound, into next).
342
425
  - **Both brands:** the board is one job; `--brand next` builds it on the
343
426
  website's brand beside the first. Frames drawn as sketches or on brand roles
344
427
  follow; an image frame is per brand when it shows the brand.
428
+
429
+ ## 14. Social images
430
+
431
+ A brand that carries an approved composition draws its social images from it
432
+ (`node wand.js social <social.json>`, `kit/lib/social.js`), not from a page.
433
+ The interim brand does: its X header, LinkedIn banner, LinkedIn company
434
+ banner and avatar (approved 2026-10-22) measured into one artwork in master
435
+ units (`brand-interim/assets/social/composition.json`: the planet and its
436
+ glow, four trails with their tint and fade, eight dots, the hero's oval, the
437
+ lockup, the marks), drawn by `brand-interim/lib/composition.js`. Every format
438
+ is a window onto it at one scale (`formats`), so a part never changes its
439
+ proportion to the others. Redrawn from it, the three approved banners match
440
+ their exports within 2.5 to 3.8 levels in 255.
441
+
442
+ | Kind | Size (export) | How it sits on the composition |
443
+ |---|---|---|
444
+ | `linkedin-banner` | 1584 × 396 (2x) | the approved banner's window |
445
+ | `x-header` | 1500 × 500 (2x) | the approved header's: lockup 28 higher, ring 38 left |
446
+ | `linkedin-company` | 1128 × 191 (2x) | the approved company banner's |
447
+ | `share` | 1200 × 630 | the art from the planet's rim to past the ring; the lockup set on its own in the centre square |
448
+ | `square` | 1080 × 1080 | the art's right half on its diagonal; the lockup in the corner it leaves |
449
+ | `avatar` | 800 × 800 | `avatar.svg` full bleed; every platform cuts its own circle |
450
+ | `profile-photo` | 800 × 800 | the banner's art behind the profile photo's circle, continued below the banner's edge, a cut-out of the person over it in the brand's photo grade |
451
+ | `icons` | 16, 32, 48, 180, 192, 512 | `avatar.svg` set at each size: the favicons as the disc on transparent, the apple-touch and manifest icons full bleed (iOS and Android cut their own shape); `favicon.ico` (16, 32, 48), `favicon.svg`, `site.webmanifest` |
452
+
453
+ **Start from what is live.** Before redrawing a page's preview, read it as
454
+ the feeds do: `node wand.js social --audit <url> [more urls]` reads each
455
+ page's og: and twitter: tags and its image, and shows that image in
456
+ LinkedIn's compact card, Slack's square, X's 2:1 and WhatsApp's thumbnail,
457
+ with the centre square outlined (`audit/audit.png`). Its rows name what the
458
+ 2026-10-23 fix found by hand: no image, missing tags, an em dash, an
459
+ og:title that repeats the image, one image for every page, a file over 300
460
+ KB or off 1.91:1. A chat without web access is told so and passes a saved
461
+ page and its image instead (`--image`). A share card's `before` (the image
462
+ live now) puts the old image above the new one in the preview.
463
+
464
+ **A share image (og:image) is seen small and cut** (Hope Frank's feedback,
465
+ 2026-10-23, on Rotem Alaluf's post and a Slack unfurl; `runs/2026-10-23-wand-og-fix`):
466
+
467
+ - Slack and WhatsApp show a square cut from the image's centre, so the
468
+ wordmark and the words sit inside the centre square (x 285 to 915 of 1200),
469
+ 24px clear of it; the composition's gate and, on a page, the crop row hold
470
+ it. The banners' wide, stepped lockup does not survive that cut: the share
471
+ image sets it left-aligned without the step.
472
+ - LinkedIn shows a link in a post with text as a compact card, the whole
473
+ image about 128pt wide: the words as large as the square allows (64px for
474
+ the site's line), the wordmark at 1.5x the lockup's ratio, and no small
475
+ print at all.
476
+ - One image per page. An article carries its own headline, verbatim (X now
477
+ shows a link card's image with only the domain over it). The site's own
478
+ image carries its line.
479
+ - The `og:title` does not repeat the image's words (the site's became
480
+ `Wand AI`), and nothing in the tags carries an em dash. `head-tags.html`
481
+ holds each page's block: the image's absolute https URL, type, size and alt,
482
+ and one `twitter:card` with the X tags.
483
+ - Every upload goes to a new file name or folder, since every platform caches
484
+ an image by its URL; then LinkedIn Post Inspector, and Slack after its
485
+ cache (about 30 minutes). A post made before keeps its old preview.
486
+
487
+ **The hand-over carries its own instructions.** Every `social` job writes
488
+ `INSTALL.md` beside the images: where each file goes (the banner's pencil,
489
+ the company page's header, the upload folder), the Post Inspector and Sharing
490
+ Debugger links for each page, the cache to wait out, and that nothing is
491
+ verified until it is live. With the PNGs, `head-tags.html` and `preview.png`,
492
+ it goes into one zip (`<name>-<date>.zip`), which is what a web developer or
493
+ a social lead receives. The build prints review questions under the preview,
494
+ the ones that settled the 2026-10-23 cards: does the lockup read at 128pt,
495
+ does Slack's square keep it whole, does the phrase end where the dots meet
496
+ it, is the ring whole and clear, is the banner's lockup clear of the photo.
497
+
498
+ **A profile photo that continues the banner** needs a cut-out of the person
499
+ (a PNG with a transparent ground): Photos or Preview on a Mac lift a subject
500
+ in one step. The kit does not cut a person out itself; from a plain photo it
501
+ asks for the cut-out rather than guess an edge. Its circle is placed where
502
+ LinkedIn's desktop profile puts it; on mobile the photo sits elsewhere and the
503
+ art lines up only roughly, which the dark ground hides.
504
+
505
+ On a brand without a composition, social cards are pages on the `square` and
506
+ `og` surfaces; the crop row warns when a share image's words leave the
507
+ centre square.
508
+
509
+
510
+ ## 15. The library: approved files, handed out as they are
511
+
512
+ Most asks for a Wand file are not design jobs: "send me the LinkedIn
513
+ banner", "the logo on dark", "the favicon set for the site". The answer is
514
+ the file a person approved, not a new drawing of it. The kit carries those
515
+ files in `library/` (`kit/library/index.json`): on the interim brand the
516
+ LinkedIn banner, the X header, the company banner, the avatar, the share
517
+ images for wand.ai and the NandaIndex article with their tags, and the
518
+ site's icons; on both live brands the wordmark, the mark and the slide art,
519
+ which it names inside the brand folders rather than copying.
520
+
521
+ - **List, then hand over.** `node wand.js library [words]` lists what there
522
+ is; `node wand.js library get <id> --to <folder>` copies it and prints where
523
+ each file goes and who approved it. It needs no browser. A bare name
524
+ (`wordmark`) resolves on the brand the rule gives; a vague one lists the
525
+ candidates.
526
+ - **Never redraw an approved file** to hand it over, never re-export or
527
+ recompress it, never retouch it. If the file asked for is not in the
528
+ library, say so and offer to make it (`social`, or a page): what the kit
529
+ makes is a candidate until a person approves it.
530
+ - **One file, one record.** Each carries its size, use, approval and
531
+ sha256; `get` refuses a copy that does not match.
532
+ - **The library and the kit cannot drift.** `node wand.js library --check`
533
+ proves every file is the one approved (its sha256), then draws again every
534
+ file the kit can draw, from the recipes in the index, and compares: within
535
+ its tolerance it passes; a visible difference warns (a 2px move of the
536
+ share image's lockup does); past 4 levels in 255 or 2% of pixels visibly
537
+ off it fails (a 6px move does). The share images are the files delivered
538
+ on 2026-10-23, drawn at 2x and reduced, which the kit's 1x redraw matches
539
+ within 0.75 levels; every other file is the kit's own, matched exactly.
540
+ - **A file enters only once approved**, through `tools/library.mjs` in the
541
+ repo (`add` for a file, `build` to draw the recipes and rewrite each
542
+ record). A changed sha256 is a changed approved file: the CHANGELOG says so.
543
+
544
+ What is deliberately not in it: the square card and the light-ground
545
+ versions (never approved), profile photos (one person's), and the next
546
+ brand (no approved social design, and its face's licence is open).
package/SKILL.md CHANGED
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: wand-design
3
- description: Rebrand or create Wand material on the current or new brand - decks and talks, documents, case studies, storyboards from a script, social cards. Use when a file is attached or branded work is wanted.
3
+ description: Rebrand or create Wand decks, documents, storyboards and social images on any Wand brand, or hand out approved Wand files (logos, banners, link previews, icons). Use for branded work or a Wand asset.
4
4
  compatibility: Requires Node.js 18+, code execution enabled in claude.ai (Settings > Features), and a Chromium the kit can find (Playwright's cache or the system). No network needed once installed. Python 3 embeds fonts in the .pptx; without it the deck ships with the faces named, not embedded.
5
5
  license: Proprietary - Wand AI
6
6
  metadata:
7
- version: "0.3.2"
7
+ version: "0.5.0"
8
8
  ---
9
9
 
10
10
 
@@ -25,7 +25,9 @@ node wand.js doctor
25
25
 
26
26
  Every row must be clear, and `chromium` must name a binary. If it does not,
27
27
  **stop and say so**: nothing renders without a browser, and never report checks
28
- you did not run. Every path below is relative to the kit folder.
28
+ you did not run. The one exception is handing over an approved file
29
+ (`library`, below), which needs no browser. Every path below is relative to
30
+ the kit folder.
29
31
 
30
32
  ## Whichever Wand skill brought you here
31
33
 
@@ -57,31 +59,56 @@ page. `node wand.js components` lists the vocabulary.
57
59
 
58
60
  ## Which brand
59
61
 
60
- Two brands, one kit: `current` (Geist) and `next` (the website's). `doctor`
61
- ends with the brand rule: which one is the default, and the words that ask
62
- for the other. Follow it as printed. When the user names no brand, build on
63
- the default without asking; when their words ask for the other, pass
62
+ Three brands, one kit: `current` (Geist), `next` (the staging website's) and
63
+ `interim` (the live wand.ai's as its approved social design sets it: Geist
64
+ and Newsreader on a near-black ground, the metallic oval and its trails). `doctor` ends
65
+ with the brand rule: which one is the default, and the words that ask for
66
+ each of the others. Follow it as printed. When the user names no brand, build
67
+ on the default without asking; when their words ask for another, pass
64
68
  `--brand` to `new`. One brand per piece, never a mix, and the review note
65
69
  says which. The rule lives in the kit, not here, so it can change without
66
70
  anyone reinstalling the skill.
67
71
 
68
- **The same piece on the other brand:** `node wand.js ship <job> --brand next`
69
- (or `current`) builds the job again on that brand, into `out-<brand>/`
70
- beside the first. Nothing in the job changes.
72
+ **The same piece on another brand:** `node wand.js ship <job> --brand next`
73
+ (or `interim`, or `current`) builds the job again on that brand, into
74
+ `out-<brand>/` beside the first. Nothing in the job changes.
71
75
 
72
76
  ## Read only what the job needs
73
77
 
74
78
  | Job | Read |
75
79
  |---|---|
80
+ | An existing Wand file: a logo, a banner, a link preview, the icons, slide art | nothing: `node wand.js library` (PROMPT.md §15 if in doubt) |
76
81
  | A document, a two-pager, a case study | `PROMPT.md` §5 and `templates/page.mjs`; `examples/overview/job.mjs` for a finished one |
77
82
  | A deck | §5 and `templates/slide.mjs` |
78
83
  | An animated deck, a talk, a live demo | §12 and `templates/slide.mjs`; `examples/talk/job.mjs` for a finished one |
79
84
  | A storyboard from a script | §13 and `templates/storyboard.mjs`; `examples/storyboard/job.mjs` |
80
- | Social cards, a banner | `templates/card.mjs` |
85
+ | Social images on the interim brand: banners, link previews, icons, a profile photo | PROMPT.md §14 and `examples/social/social.json` |
86
+ | Social cards on another brand | `templates/card.mjs` |
81
87
  | Edit a job this kit built | the job's `job.mjs` only, then `build` |
82
88
 
83
89
  ## The jobs
84
90
 
91
+ ### Ask for an existing file (the cheapest job: start here when it fits)
92
+
93
+ "The LinkedIn banner", "our logo on dark", "the favicon for the site", "the
94
+ image wand.ai shares as": these are approved files, and the library hands
95
+ them over as they are (PROMPT.md §15).
96
+
97
+ 1. `node wand.js library <words>` (for example `library banner`, `library
98
+ logo`) lists what matches; `node wand.js library` lists everything.
99
+ 2. `node wand.js library get <id> --to <folder>`: the folder the chat
100
+ delivers files from (in claude.ai, `/mnt/user-data/outputs`). A bare
101
+ `wordmark`, `mark` or `slide-art` takes the brand the rule gives; if it
102
+ names several, pick by the brand rule or ask which.
103
+ 3. Deliver the files with the `use` line it prints (where each goes) and its
104
+ size. For a share image, its tags file goes with it and the install steps
105
+ of PROMPT.md §14 apply.
106
+
107
+ Never redraw, re-export, resize or recompress a library file to hand it over.
108
+ If what they ask for is not there, say so and offer to make it (the social
109
+ job below, or a page); what you make is a draft until someone approves it,
110
+ and the note says so.
111
+
85
112
  ### Rebuild from a source they attached (a .pptx, .docx, .pdf, .html)
86
113
 
87
114
  1. Dump the source's strings verbatim, one per line, into `content.txt`:
@@ -94,7 +121,14 @@ beside the first. Nothing in the job changes.
94
121
  in `edits` (no em dashes: swap them for commas or semicolons there) and
95
122
  every line left out in `cut`.
96
123
  4. `node wand.js build work/<name>/job.mjs` until every hard gate is ok. Look
97
- at `out/sheet.png`. Open a page only where something looks off.
124
+ at `out/sheet.png`. Open a page only where something looks off. Then answer
125
+ the review questions the build prints under the gates, as a creative
126
+ director would; if the variety row names a run of pages, recompose it.
127
+ On a deck, no paragraph sets in more than two lines: the lines row names
128
+ any that do. Re-lay, never reword: two by two instead of four across, a
129
+ ruled row (title left, line right) instead of a narrow column. Set
130
+ `maxLines: 2` in the job to make it a hard gate. A source note under one
131
+ slide goes in that page's `footer`.
98
132
  5. `node wand.js ship work/<name>/job.mjs --pptx` for a deck; without `--pptx`
99
133
  for a document. Deliver the PDF (and the .pptx, and the .html) with the
100
134
  review note.
@@ -105,6 +139,12 @@ Skip `content.txt` (delete the `content:` line in the job). Write the page list
105
139
  with its claims first, then the pages. Coverage is skipped and says so; the
106
140
  review reads the argument instead. Three sections a page, not four.
107
141
 
142
+ On the next brand, a title's phrase is its quiet second tone and gold is kept
143
+ for the cover, a statement, the close and the figures; photographs go through
144
+ `c.photo("walk")` (the brand's set, graded), large or not at all. On the
145
+ interim brand the phrase changes face instead: `<em>` sets in Newsreader, the
146
+ italic only on the pages that carry the art.
147
+
108
148
  ### Make it generic (an industry version of a client piece)
109
149
 
110
150
  Author from the client piece: remove the client's figures, names, quotes and
@@ -120,8 +160,9 @@ talk adds:
120
160
  1. Notes on every slide, and `seconds` on each when the talk has a slot.
121
161
  2. Motion where it carries the argument (PROMPT.md §12): `step(n, html)` for
122
162
  a reveal in order, `stat({ count: true })` for a figure to watch arrive,
123
- `enter("draw")` on a trend line, `enter("grow", i)` on bars. Restraint: one
124
- moment a slide.
163
+ `enter("draw")` on a trend line, `enter("grow", i)` on bars, `enter("lit")`
164
+ on a statement, `enter("window")` on a photograph. Titles rise word by word
165
+ on their own. Restraint: one moment a slide.
125
166
  3. A live demo: one self-contained HTML file, then its poster on the deck's
126
167
  brand: `node wand.js poster demo.html --play 3 --brand <brand>`, and
127
168
  `c.demo({ src, poster })` on the slide. A clip: `c.video({ src, poster })`.
@@ -144,10 +185,45 @@ talk adds:
144
185
  HTML with its player. Say in the note that timing is scratch timing at the
145
186
  `wpm` given until a real read exists, and which frames are still to draw.
146
187
 
147
- ### Social cards
148
-
149
- `--surface square` or `og`; one `c.page()` per card; `out/pages/pNN.png` are
150
- the deliverables.
188
+ ### Social images
189
+
190
+ **First, is it already approved?** `node wand.js library <words>`: if the
191
+ file exists, hand it over (the job above) instead of drawing it again.
192
+
193
+ **On the interim brand** the banners, link previews, square, avatar and site
194
+ icons are the approved design itself, drawn from the brand's composition
195
+ (PROMPT.md §14):
196
+
197
+ 1. For a link preview that is live and wrong (someone sent a screenshot of a
198
+ bad unfurl), read it first: `node wand.js social --audit <url> [more]`.
199
+ Its rows and `audit/audit.png` show what the feeds do to it; say what is
200
+ wrong in the note. Without web access it says so: ask for the saved page
201
+ and its image and pass them (`--audit page.html --image og.png`).
202
+ 2. Copy `examples/social/social.json` beside the work and set `line` (the
203
+ words), the `cards` wanted, and for each share image its page's `url`,
204
+ `title`, `description` and `alt`, plus `upload` (where the images will
205
+ live: a new folder each time) and `before` (the image live now, if any).
206
+ An article's share image takes its headline verbatim as `lead` and
207
+ `phrase`. `{ "kind": "icons", "upload": "/assets/<date>/" }` adds the
208
+ favicons, app icons and manifest.
209
+ 3. `node wand.js social work/<name>/social.json`. Every image has a row; a
210
+ share image fails if its words leave the centre square or its type falls
211
+ under the floor. Look at `out/preview.png`: each image as the profile, the
212
+ LinkedIn compact card, Slack, X and WhatsApp show it, the live image above
213
+ the new one. Then answer the review questions printed under it.
214
+ 4. Deliver the zip (`out/<name>-<date>.zip`: the images, `head-tags.html`,
215
+ `INSTALL.md`, the preview). `INSTALL.md` already says where each file goes
216
+ and how to check it; the note adds that nothing is verified until it is
217
+ live, and that what you drew is a draft until approved.
218
+
219
+ A profile photo that continues the LinkedIn banner is a `profile-photo` card
220
+ with `photo`, a cut-out of the person (transparent ground). If they gave a
221
+ plain photo, ask for the cut-out (Photos or Preview: lift the subject) rather
222
+ than cutting it yourself.
223
+
224
+ **On another brand**: `--surface square` or `og`; one `c.page()` per card;
225
+ `out/pages/pNN.png` are the deliverables. The crop row warns when a share
226
+ image's words leave the centre square: keep them there.
151
227
 
152
228
  ### Older Wand work
153
229
 
@@ -165,11 +241,15 @@ two kits, or `edit --set`; none of it applies to anything else.
165
241
  Which brand it is on; what was changed from the source and why (every edit,
166
242
  every cut); the gate table as printed; what a human still has to decide (a figure to confirm, a
167
243
  quote to clear, a claim legal should see). A file delivered without the gate
168
- table has been checked by nobody.
244
+ table has been checked by nobody. A library file is the exception: it was
245
+ checked when it was approved, so its note is the `use` and `approved` lines
246
+ `get` prints.
169
247
 
170
248
  ## Available scripts
171
249
 
172
- - **`wand.js`** — doctor, new, build, check, ship, watch, poster, gallery, components, brands
250
+ - **`wand.js`** — doctor, new, build, check, ship, watch, poster, social, library, gallery, components, brands
251
+ - **`lib/library.js`**, **`library/`** — the approved files, their records and the check
252
+ - **`lib/social.js`** — the social set from a brand's approved composition; **`lib/audit.js`** — a live page's link preview, read
173
253
  - **`lib/engine.js`** — the render and the gates
174
254
  - **`lib/components.js`** — the vocabulary and its CSS
175
255
  - **`lib/pptx.js`**, **`tools/embed_fonts.py`** — the PowerPoint export
package/START-HERE.md CHANGED
@@ -6,9 +6,20 @@ node wand.js new work/acme --surface letter # the default brand; doct
6
6
  # write work/acme/job.mjs (pages(c)) and, for a rebuild, work/acme/content.txt
7
7
  node wand.js build work/acme/job.mjs # gates, PDF, a PNG per page, out/sheet.png
8
8
  node wand.js ship work/acme/job.mjs --pptx # + one-file HTML, PowerPoint
9
- node wand.js ship work/acme/job.mjs --brand next # the same job on the other brand, in out-next/
9
+ node wand.js ship work/acme/job.mjs --brand next # the same job on another brand (next, interim), in out-<brand>/
10
10
  ```
11
11
 
12
+ Asked for a file that already exists (the logo, a banner, a link preview, the
13
+ icons), hand over the approved one: `node wand.js library banner`, then
14
+ `node wand.js library get linkedin-banner --to <folder>`. PROMPT.md §15.
15
+
16
+ On the interim brand, `node wand.js social examples/social/social.json` draws
17
+ the approved social set (banners, link previews with their tags, square,
18
+ avatar, a profile photo that continues the banner, the site's icons) from the
19
+ brand's own composition, with `INSTALL.md` and a zip of the hand-over;
20
+ `node wand.js social --audit <url>` reads a live page's preview first.
21
+ PROMPT.md §14 has the rules.
22
+
12
23
  A deck's HTML is a talk: entrances, steps, a presenter view (P). A demo needs
13
24
  a poster: `node wand.js poster demo.html --play 3`. A storyboard starts from
14
25
  `node wand.js new work/film --surface storyboard`; its HTML plays the board.
@@ -54,7 +54,11 @@
54
54
  "rule": "E4E0F2",
55
55
  "track": "E9E6F5",
56
56
  "surface": "EBE8F8",
57
- "emphLabel": "AA9BFF"
57
+ "emphLabel": "AA9BFF",
58
+ "second": "6C5CE7",
59
+ "secondSm": "6C5CE7",
60
+ "gradeLow": "240F48",
61
+ "gradeHigh": "F8F6FB"
58
62
  },
59
63
  "dark": {
60
64
  "bg": "240F48",
@@ -74,7 +78,11 @@
74
78
  "rule": "3A2E63",
75
79
  "track": "1A1033",
76
80
  "surface": "1A1033",
77
- "emphLabel": "C4B5F4"
81
+ "emphLabel": "C4B5F4",
82
+ "second": "9481FF",
83
+ "secondSm": "9481FF",
84
+ "gradeLow": "240F48",
85
+ "gradeHigh": "F8F6FB"
78
86
  }
79
87
  },
80
88
  "faces": {
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" role="img" aria-label="Wand"><circle cx="400" cy="400" r="400" fill="#261d3d"/><g transform="translate(180.48 300.24) scale(0.187233) translate(0 -512)"><path d="M0 530A18 18 0 0 1 18 512L352.5 512A18 18 0 0 1 370.5 530L370.5 1347A278 278 0 0 0 926.5 1347L926.5 530A18 18 0 0 1 944.5 512L1279 512A18 18 0 0 1 1297 530L1297 1347A278 278 0 0 0 1853 1347L1853 734A18 18 0 0 1 1871 716L1873 716Q1882 716 1888.13 722.59L1940.35 778.75A134.03 134.03 0 0 0 2136.65 778.75L2188.87 722.59Q2195 716 2204 716L2205.5 716A18 18 0 0 1 2223.5 734L2223.5 1347A648.5 648.5 0 0 1 1125.96 1814.89Q1111.75 1800.82 1097.54 1814.89A648.5 648.5 0 0 1 0 1347Z" fill="#ffffff"/><path d="M2021.58 -300.31A16.61 16.61 0 0 1 2055.42 -300.31A426.81 426.81 0 0 0 2465.31 109.58A16.61 16.61 0 0 1 2465.31 143.42A426.81 426.81 0 0 0 2055.42 553.31A16.61 16.61 0 0 1 2021.58 553.31A426.81 426.81 0 0 0 1611.69 143.42A16.61 16.61 0 0 1 1611.69 109.58A426.81 426.81 0 0 0 2021.58 -300.31Z" fill="#c2a1ef"/></g></svg>