wand-kit 0.3.3 → 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 (159) hide show
  1. package/PROMPT.md +182 -16
  2. package/SKILL.md +91 -18
  3. package/START-HERE.md +12 -1
  4. package/brands/interim/assets/avatar.svg +1 -0
  5. package/brands/interim/assets/closing-art.png +0 -0
  6. package/brands/interim/assets/cover-art.png +0 -0
  7. package/brands/interim/assets/cover-portrait-art.png +0 -0
  8. package/brands/interim/assets/divider-art.png +0 -0
  9. package/brands/interim/assets/glyphs/README.md +29 -0
  10. package/brands/interim/assets/glyphs/activity.svg +15 -0
  11. package/brands/interim/assets/glyphs/atom.svg +17 -0
  12. package/brands/interim/assets/glyphs/badge-check.svg +16 -0
  13. package/brands/interim/assets/glyphs/bell.svg +16 -0
  14. package/brands/interim/assets/glyphs/blocks.svg +16 -0
  15. package/brands/interim/assets/glyphs/book-open.svg +16 -0
  16. package/brands/interim/assets/glyphs/bot.svg +20 -0
  17. package/brands/interim/assets/glyphs/boxes.svg +26 -0
  18. package/brands/interim/assets/glyphs/brain.svg +23 -0
  19. package/brands/interim/assets/glyphs/briefcase.svg +16 -0
  20. package/brands/interim/assets/glyphs/building-2.svg +21 -0
  21. package/brands/interim/assets/glyphs/calendar.svg +18 -0
  22. package/brands/interim/assets/glyphs/chart-column.svg +18 -0
  23. package/brands/interim/assets/glyphs/chart-line.svg +16 -0
  24. package/brands/interim/assets/glyphs/chart-pie.svg +16 -0
  25. package/brands/interim/assets/glyphs/circle-check.svg +16 -0
  26. package/brands/interim/assets/glyphs/clipboard-check.svg +17 -0
  27. package/brands/interim/assets/glyphs/clock.svg +16 -0
  28. package/brands/interim/assets/glyphs/cloud.svg +15 -0
  29. package/brands/interim/assets/glyphs/code.svg +15 -0
  30. package/brands/interim/assets/glyphs/coins.svg +18 -0
  31. package/brands/interim/assets/glyphs/compass.svg +16 -0
  32. package/brands/interim/assets/glyphs/cpu.svg +24 -0
  33. package/brands/interim/assets/glyphs/database.svg +17 -0
  34. package/brands/interim/assets/glyphs/eye.svg +16 -0
  35. package/brands/interim/assets/glyphs/file-check.svg +17 -0
  36. package/brands/interim/assets/glyphs/filter.svg +15 -0
  37. package/brands/interim/assets/glyphs/fingerprint.svg +23 -0
  38. package/brands/interim/assets/glyphs/flag.svg +16 -0
  39. package/brands/interim/assets/glyphs/gauge.svg +16 -0
  40. package/brands/interim/assets/glyphs/gavel.svg +19 -0
  41. package/brands/interim/assets/glyphs/git-branch.svg +18 -0
  42. package/brands/interim/assets/glyphs/globe.svg +17 -0
  43. package/brands/interim/assets/glyphs/graduation-cap.svg +17 -0
  44. package/brands/interim/assets/glyphs/handshake.svg +19 -0
  45. package/brands/interim/assets/glyphs/hexagon.svg +15 -0
  46. package/brands/interim/assets/glyphs/index.json +177 -0
  47. package/brands/interim/assets/glyphs/infinity.svg +15 -0
  48. package/brands/interim/assets/glyphs/key.svg +17 -0
  49. package/brands/interim/assets/glyphs/landmark.svg +20 -0
  50. package/brands/interim/assets/glyphs/layers.svg +17 -0
  51. package/brands/interim/assets/glyphs/lightbulb.svg +17 -0
  52. package/brands/interim/assets/glyphs/link.svg +16 -0
  53. package/brands/interim/assets/glyphs/list-checks.svg +19 -0
  54. package/brands/interim/assets/glyphs/lock.svg +16 -0
  55. package/brands/interim/assets/glyphs/map.svg +17 -0
  56. package/brands/interim/assets/glyphs/megaphone.svg +16 -0
  57. package/brands/interim/assets/glyphs/message-square.svg +15 -0
  58. package/brands/interim/assets/glyphs/milestone.svg +17 -0
  59. package/brands/interim/assets/glyphs/network.svg +19 -0
  60. package/brands/interim/assets/glyphs/orbit.svg +19 -0
  61. package/brands/interim/assets/glyphs/package.svg +18 -0
  62. package/brands/interim/assets/glyphs/plug.svg +18 -0
  63. package/brands/interim/assets/glyphs/puzzle.svg +15 -0
  64. package/brands/interim/assets/glyphs/radar.svg +22 -0
  65. package/brands/interim/assets/glyphs/receipt.svg +17 -0
  66. package/brands/interim/assets/glyphs/refresh-cw.svg +18 -0
  67. package/brands/interim/assets/glyphs/rocket.svg +18 -0
  68. package/brands/interim/assets/glyphs/route.svg +17 -0
  69. package/brands/interim/assets/glyphs/scale.svg +19 -0
  70. package/brands/interim/assets/glyphs/search.svg +16 -0
  71. package/brands/interim/assets/glyphs/server.svg +18 -0
  72. package/brands/interim/assets/glyphs/settings.svg +16 -0
  73. package/brands/interim/assets/glyphs/share-2.svg +19 -0
  74. package/brands/interim/assets/glyphs/shield-check.svg +16 -0
  75. package/brands/interim/assets/glyphs/shuffle.svg +19 -0
  76. package/brands/interim/assets/glyphs/sparkles.svg +19 -0
  77. package/brands/interim/assets/glyphs/square-stack.svg +17 -0
  78. package/brands/interim/assets/glyphs/target.svg +17 -0
  79. package/brands/interim/assets/glyphs/trending-up.svg +16 -0
  80. package/brands/interim/assets/glyphs/triangle-alert.svg +17 -0
  81. package/brands/interim/assets/glyphs/trophy.svg +20 -0
  82. package/brands/interim/assets/glyphs/users.svg +18 -0
  83. package/brands/interim/assets/glyphs/wallet.svg +16 -0
  84. package/brands/interim/assets/glyphs/wand-sparkles.svg +22 -0
  85. package/brands/interim/assets/glyphs/workflow.svg +17 -0
  86. package/brands/interim/assets/glyphs/zap.svg +15 -0
  87. package/brands/interim/assets/mark.svg +1 -0
  88. package/brands/interim/assets/social/composition.json +6833 -0
  89. package/brands/interim/assets/spark-lavender.png +0 -0
  90. package/brands/interim/assets/spark-violet.png +0 -0
  91. package/brands/interim/assets/statement-art.png +0 -0
  92. package/brands/interim/assets/story/agent-alpha.png +0 -0
  93. package/brands/interim/assets/story/agent.png +0 -0
  94. package/brands/interim/assets/story/economy-alpha.png +0 -0
  95. package/brands/interim/assets/story/economy.png +0 -0
  96. package/brands/interim/assets/story/index.json +214 -0
  97. package/brands/interim/assets/story/learning-alpha.png +0 -0
  98. package/brands/interim/assets/story/learning.png +0 -0
  99. package/brands/interim/assets/story/organization-alpha.png +0 -0
  100. package/brands/interim/assets/story/organization.png +0 -0
  101. package/brands/interim/assets/story/worker-alpha.png +0 -0
  102. package/brands/interim/assets/story/worker-light.png +0 -0
  103. package/brands/interim/assets/story/worker.png +0 -0
  104. package/brands/interim/assets/wordmark-on-dark.png +0 -0
  105. package/brands/interim/assets/wordmark-on-dark.svg +1 -0
  106. package/brands/interim/assets/wordmark-on-light.png +0 -0
  107. package/brands/interim/assets/wordmark-on-light.svg +1 -0
  108. package/brands/interim/fonts/Geist-Book.ttf +0 -0
  109. package/brands/interim/fonts/Geist-Medium.ttf +0 -0
  110. package/brands/interim/fonts/Geist-Regular.ttf +0 -0
  111. package/brands/interim/fonts/Geist-SemiBold.ttf +0 -0
  112. package/brands/interim/fonts/Newsreader-Italic.ttf +0 -0
  113. package/brands/interim/fonts/Newsreader-Medium.ttf +0 -0
  114. package/brands/interim/fonts/Newsreader-MediumItalic.ttf +0 -0
  115. package/brands/interim/fonts/Newsreader-Regular.ttf +0 -0
  116. package/brands/interim/fonts/OFL-Geist.txt +93 -0
  117. package/brands/interim/fonts/OFL-Newsreader.txt +93 -0
  118. package/brands/interim/fonts/faces.json +12 -0
  119. package/brands/interim/lib/composition.js +169 -0
  120. package/brands/interim/lib/composition.mjs +101 -0
  121. package/brands/interim/lib/glyphs.js +89 -0
  122. package/brands/interim/lib/measure.js +121 -0
  123. package/brands/interim/lib/pdf.js +597 -0
  124. package/brands/interim/lib/ttf.py +169 -0
  125. package/brands/interim/lib/wandxml.py +37 -0
  126. package/brands/interim/tokens.json +299 -0
  127. package/examples/social/social.json +23 -0
  128. package/lib/audit.js +142 -0
  129. package/lib/brand.js +12 -7
  130. package/lib/components.js +13 -8
  131. package/lib/engine.js +55 -9
  132. package/lib/library.js +180 -0
  133. package/lib/pptx.js +1 -1
  134. package/lib/social.js +366 -0
  135. package/library/index.json +629 -0
  136. package/library/interim/avatar-800x800.png +0 -0
  137. package/library/interim/icons/apple-touch-icon.png +0 -0
  138. package/library/interim/icons/favicon-16.png +0 -0
  139. package/library/interim/icons/favicon-32.png +0 -0
  140. package/library/interim/icons/favicon-48.png +0 -0
  141. package/library/interim/icons/favicon.ico +0 -0
  142. package/library/interim/icons/favicon.svg +1 -0
  143. package/library/interim/icons/icon-192.png +0 -0
  144. package/library/interim/icons/icon-512.png +0 -0
  145. package/library/interim/icons/icon-tags.html +5 -0
  146. package/library/interim/icons/site.webmanifest +19 -0
  147. package/library/interim/linkedin-banner-1584x396.png +0 -0
  148. package/library/interim/linkedin-company-1128x191.png +0 -0
  149. package/library/interim/open-agent-discovery-share-1200x630.png +0 -0
  150. package/library/interim/open-agent-discovery-share-head-tags.html +17 -0
  151. package/library/interim/wand-ai-share-1200x630.png +0 -0
  152. package/library/interim/wand-ai-share-head-tags.html +17 -0
  153. package/library/interim/x-header-1500x500.png +0 -0
  154. package/package.json +2 -2
  155. package/templates/card.mjs +6 -2
  156. package/templates/page.mjs +1 -1
  157. package/templates/slide.mjs +1 -1
  158. package/templates/storyboard.mjs +1 -1
  159. package/wand.js +64 -5
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
 
@@ -88,6 +92,15 @@ violets as grounds, beige as paper); see `brand-next/tokens.json`. Its
88
92
  `second` is a quiet tone, not gold (7B7B79 on light, 9D99A8 on dark, large
89
93
  type only; `secondSm`, the text grey, below that size).
90
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`.
103
+
91
104
  **Rules.**
92
105
  - One accent. The accent phrase in a title is the single most recognisable
93
106
  device in the system: one per title, never two, the sentence period in ink.
@@ -98,6 +111,20 @@ type only; `secondSm`, the text grey, below that size).
98
111
  wand.ai rebuild (October 2026) read as a template while every heading's
99
112
  second line was gold: when gold is everywhere it means nothing. On the
100
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.
101
128
  - One emphasis card per row, at most one or two per page.
102
129
  - Light pages carry no art. Dark pages carry art on the cover, the closing and
103
130
  a statement; a dark content page is flat.
@@ -112,11 +139,16 @@ Three face roles per brand: `display` (titles, figures, the lockup), `body`
112
139
  Tracking and leading travel with the face in `tokens.json`; the CSS sets them
113
140
  from the same values.
114
141
 
115
- | Role | current | next |
116
- |---|---|---|
117
- | display | Geist SemiBold, −0.02em | FK Roman Standard Light, −0.07em, 1.06 |
118
- | body | Geist Regular | Overused Grotesk, −0.02em |
119
- | 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.
120
152
 
121
153
  **Weight carries no hierarchy on the next brand** (the serif ships one weight);
122
154
  the face does. Components therefore never rely on bold to separate levels, and
@@ -131,7 +163,8 @@ Figures are tabular (`font-variant-numeric: tabular-nums` on the page).
131
163
  ## 4. Chrome
132
164
 
133
165
  Drawn by `c.page()` on every page: eyebrow (`job.tag | eyebrow`), mark, footer
134
- (`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
135
168
  `c.closing()`, which place the brand art and the lockup; a job gives them
136
169
  words, never styling. Every piece of chrome is `.deco` or chrome-classed, so
137
170
  the gates know what is content and what is frame.
@@ -175,6 +208,14 @@ decide, and that make or break a page:
175
208
  ground.
176
209
  - **Short lines in cards.** One sentence and an outcome. The card's body is
177
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.
178
219
  - **Equal heights in a row** (`stretch`), titles at one height, and the empty
179
220
  space at the foot of a page shared by its sections, never left under one.
180
221
  - **One arc.** Night, then day, then first light: the dark cover with its
@@ -246,13 +287,17 @@ new ─▶ argue ─▶ content ─▶ compose ─▶ build ─▶ review ─▶
246
287
  | pdf text | the PDF's text misses a line, or carries an em dash | |
247
288
  | contrast (warn) | text under WCAG AA against its background, chrome excepted | |
248
289
  | measure (warn) | a paragraph over the surface's characters-per-line | |
249
- | 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 |
250
293
  | media | a demo, a clip or its poster is missing | a demo that loads and misbehaves |
251
294
  | console | a page error | |
252
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 |
253
296
  | timing (warn, boards) | the board is more than 10% off its `target` | the real voiceover's pace |
254
297
  | frames (warn, boards) | a frame is still to draw | a frame that is drawn and wrong |
255
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 |
256
301
 
257
302
  The gates read the DOM Chromium laid out for the PDF; nothing is inferred from
258
303
  the spec. What no gate sees: the argument, the pacing, and whether the right
@@ -306,7 +351,9 @@ component was chosen. That is the review.
306
351
  4. **A scratch voice.** The Wand OS film timed its board against a voice from
307
352
  macOS `say`; the chat sandbox has none, so timing here is words at `wpm`.
308
353
  A recorded voiceover passed as `audio` leads the player.
309
- 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.
310
357
 
311
358
  ## 12. Talks: motion and the presenter
312
359
 
@@ -378,3 +425,122 @@ direction (the line, camera, motion, on screen, sound, into next).
378
425
  - **Both brands:** the board is one job; `--brand next` builds it on the
379
426
  website's brand beside the first. Frames drawn as sketches or on brand roles
380
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.3"
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`:
@@ -97,6 +124,11 @@ beside the first. Nothing in the job changes.
97
124
  at `out/sheet.png`. Open a page only where something looks off. Then answer
98
125
  the review questions the build prints under the gates, as a creative
99
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`.
100
132
  5. `node wand.js ship work/<name>/job.mjs --pptx` for a deck; without `--pptx`
101
133
  for a document. Deliver the PDF (and the .pptx, and the .html) with the
102
134
  review note.
@@ -109,7 +141,9 @@ review reads the argument instead. Three sections a page, not four.
109
141
 
110
142
  On the next brand, a title's phrase is its quiet second tone and gold is kept
111
143
  for the cover, a statement, the close and the figures; photographs go through
112
- `c.photo("walk")` (the brand's set, graded), large or not at all.
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.
113
147
 
114
148
  ### Make it generic (an industry version of a client piece)
115
149
 
@@ -151,10 +185,45 @@ talk adds:
151
185
  HTML with its player. Say in the note that timing is scratch timing at the
152
186
  `wpm` given until a real read exists, and which frames are still to draw.
153
187
 
154
- ### Social cards
155
-
156
- `--surface square` or `og`; one `c.page()` per card; `out/pages/pNN.png` are
157
- 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.
158
227
 
159
228
  ### Older Wand work
160
229
 
@@ -172,11 +241,15 @@ two kits, or `edit --set`; none of it applies to anything else.
172
241
  Which brand it is on; what was changed from the source and why (every edit,
173
242
  every cut); the gate table as printed; what a human still has to decide (a figure to confirm, a
174
243
  quote to clear, a claim legal should see). A file delivered without the gate
175
- 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.
176
247
 
177
248
  ## Available scripts
178
249
 
179
- - **`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
180
253
  - **`lib/engine.js`** — the render and the gates
181
254
  - **`lib/components.js`** — the vocabulary and its CSS
182
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.
@@ -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>
@@ -0,0 +1,29 @@
1
+ # Glyphs — Lucide
2
+
3
+ 75 icons from [Lucide](https://lucide.dev) v0.469.0, **ISC licensed** (permissive:
4
+ use, modify and redistribute, keep the notice). They replace the numbered PNGs
5
+ that were reverse-extracted from a reference deck.
6
+
7
+ Two problems they fix, both of which were standing known gaps:
8
+
9
+ **Polarity.** The old glyphs were baked white or baked accent, so a white one on
10
+ a light-theme `surface` tile was invisible. These are single-colour stroke SVGs
11
+ with `stroke="currentColor"`, and the kit substitutes the theme's ink colour at
12
+ build time. There is no variant to pick and nothing to get wrong.
13
+
14
+ **Meaning.** They have names. A spec says `icon: "shield-check"`, not
15
+ `icon: "icon-17.png"`. `index.json` groups them by what a deck actually needs —
16
+ governance, workforce, platform, process, outcome, signal.
17
+
18
+ ## How they reach the deck
19
+
20
+ As vector. pptxgenjs writes the OOXML `asvg:svgBlip` extension with a raster
21
+ fallback, so PowerPoint 2016+ renders the SVG and anything older gets the PNG.
22
+ Nothing is rasterised at build time, so the kit still needs no native
23
+ dependency.
24
+
25
+ ## The old set
26
+
27
+ `../icons/*.png` is still there and still works — every existing spec references
28
+ those filenames. New specs should use glyph names. The two sets can coexist
29
+ indefinitely; `iconTile` resolves a name first and falls back to a filename.
@@ -0,0 +1,15 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-activity"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2" />
15
+ </svg>
@@ -0,0 +1,17 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-atom"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <circle cx="12" cy="12" r="1" />
15
+ <path d="M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z" />
16
+ <path d="M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z" />
17
+ </svg>
@@ -0,0 +1,16 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-badge-check"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" />
15
+ <path d="m9 12 2 2 4-4" />
16
+ </svg>
@@ -0,0 +1,16 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-bell"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="M10.268 21a2 2 0 0 0 3.464 0" />
15
+ <path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" />
16
+ </svg>
@@ -0,0 +1,16 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-blocks"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <rect width="7" height="7" x="14" y="3" rx="1" />
15
+ <path d="M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3" />
16
+ </svg>
@@ -0,0 +1,16 @@
1
+ <!-- @license lucide-static v0.469.0 - ISC -->
2
+ <svg
3
+ class="lucide lucide-book-open"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ stroke-width="2"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ >
14
+ <path d="M12 7v14" />
15
+ <path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
16
+ </svg>