stagecraft 0.1.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 (133) hide show
  1. package/AGENT.md +792 -0
  2. package/LICENSE +21 -0
  3. package/README.md +210 -0
  4. package/bin/cli.js +51 -0
  5. package/bin/export.js +137 -0
  6. package/bin/init.js +52 -0
  7. package/bin/lib/edit-ops.js +405 -0
  8. package/bin/serve.js +278 -0
  9. package/dist/stagecraft.bundle.css +4443 -0
  10. package/dist/stagecraft.bundle.js +7621 -0
  11. package/dist/themes/brand.bundle.css +5262 -0
  12. package/dist/themes/neon.bundle.css +5289 -0
  13. package/dist/themes/paper.bundle.css +5276 -0
  14. package/dist/themes/phosphor.bundle.css +4443 -0
  15. package/dist/themes/shopware.bundle.css +5850 -0
  16. package/examples/closing-card.js +74 -0
  17. package/examples/orchestration-graph.js +156 -0
  18. package/examples/terminal-log.js +109 -0
  19. package/examples/token-stream.js +96 -0
  20. package/examples/whoami.js +90 -0
  21. package/package.json +41 -0
  22. package/src/components/activity-list.js +75 -0
  23. package/src/components/agenda.js +79 -0
  24. package/src/components/bar-chart.js +162 -0
  25. package/src/components/before-after.js +135 -0
  26. package/src/components/bento.js +73 -0
  27. package/src/components/big-number.js +87 -0
  28. package/src/components/callout.js +75 -0
  29. package/src/components/checklist.js +81 -0
  30. package/src/components/code-block.js +141 -0
  31. package/src/components/code-diff.js +98 -0
  32. package/src/components/compare.js +85 -0
  33. package/src/components/counter.js +80 -0
  34. package/src/components/cta.js +69 -0
  35. package/src/components/cycle.js +146 -0
  36. package/src/components/definition.js +96 -0
  37. package/src/components/donut-chart.js +179 -0
  38. package/src/components/full-image.js +82 -0
  39. package/src/components/funnel.js +111 -0
  40. package/src/components/gauge.js +147 -0
  41. package/src/components/heatmap.js +141 -0
  42. package/src/components/image-grid.js +80 -0
  43. package/src/components/image-text.js +96 -0
  44. package/src/components/kinetic-text.js +72 -0
  45. package/src/components/kpi.js +106 -0
  46. package/src/components/line-chart.js +215 -0
  47. package/src/components/manifesto.js +104 -0
  48. package/src/components/marquee.js +63 -0
  49. package/src/components/matrix2x2.js +151 -0
  50. package/src/components/pillars.js +80 -0
  51. package/src/components/pricing.js +90 -0
  52. package/src/components/process-flow.js +133 -0
  53. package/src/components/progress.js +136 -0
  54. package/src/components/punchline.js +82 -0
  55. package/src/components/pyramid.js +107 -0
  56. package/src/components/qanda.js +60 -0
  57. package/src/components/quote.js +70 -0
  58. package/src/components/roadmap.js +130 -0
  59. package/src/components/section-card.js +45 -0
  60. package/src/components/shift-arrow.js +41 -0
  61. package/src/components/spark-line.js +147 -0
  62. package/src/components/spotlight.js +85 -0
  63. package/src/components/statement.js +106 -0
  64. package/src/components/stats.js +91 -0
  65. package/src/components/steps.js +83 -0
  66. package/src/components/swot.js +110 -0
  67. package/src/components/team-grid.js +87 -0
  68. package/src/components/testimonial.js +99 -0
  69. package/src/components/timeline.js +91 -0
  70. package/src/components/tip.js +63 -0
  71. package/src/components/venn.js +198 -0
  72. package/src/edit-mode.js +1256 -0
  73. package/src/engine.js +823 -0
  74. package/src/helpers.js +169 -0
  75. package/src/transitions.js +101 -0
  76. package/starter/index.html +40 -0
  77. package/starter/slides/00-title.js +12 -0
  78. package/starter/stagecraft.config.js +8 -0
  79. package/themes/brand/base.css +4 -0
  80. package/themes/brand/components-business.css +173 -0
  81. package/themes/brand/components-chart.css +65 -0
  82. package/themes/brand/components-content.css +126 -0
  83. package/themes/brand/components-data.css +162 -0
  84. package/themes/brand/components-diagram.css +115 -0
  85. package/themes/brand/components-layout.css +112 -0
  86. package/themes/brand/components.css +46 -0
  87. package/themes/brand/manifest.json +20 -0
  88. package/themes/brand/tokens.css +20 -0
  89. package/themes/brand/transitions.css +4 -0
  90. package/themes/neon/base.css +10 -0
  91. package/themes/neon/components-business.css +189 -0
  92. package/themes/neon/components-chart.css +70 -0
  93. package/themes/neon/components-content.css +112 -0
  94. package/themes/neon/components-data.css +160 -0
  95. package/themes/neon/components-diagram.css +109 -0
  96. package/themes/neon/components-layout.css +87 -0
  97. package/themes/neon/components.css +87 -0
  98. package/themes/neon/manifest.json +21 -0
  99. package/themes/neon/tokens.css +17 -0
  100. package/themes/neon/transitions.css +13 -0
  101. package/themes/paper/base.css +9 -0
  102. package/themes/paper/components-business.css +196 -0
  103. package/themes/paper/components-chart.css +74 -0
  104. package/themes/paper/components-content.css +108 -0
  105. package/themes/paper/components-data.css +168 -0
  106. package/themes/paper/components-diagram.css +89 -0
  107. package/themes/paper/components-layout.css +105 -0
  108. package/themes/paper/components.css +60 -0
  109. package/themes/paper/manifest.json +10 -0
  110. package/themes/paper/tokens.css +21 -0
  111. package/themes/paper/transitions.css +11 -0
  112. package/themes/phosphor/base.css +511 -0
  113. package/themes/phosphor/components-business.css +818 -0
  114. package/themes/phosphor/components-chart.css +415 -0
  115. package/themes/phosphor/components-content.css +530 -0
  116. package/themes/phosphor/components-data.css +824 -0
  117. package/themes/phosphor/components-diagram.css +427 -0
  118. package/themes/phosphor/components-layout.css +450 -0
  119. package/themes/phosphor/components.css +223 -0
  120. package/themes/phosphor/manifest.json +11 -0
  121. package/themes/phosphor/tokens.css +17 -0
  122. package/themes/phosphor/transitions.css +213 -0
  123. package/themes/shopware/base.css +94 -0
  124. package/themes/shopware/components-business.css +344 -0
  125. package/themes/shopware/components-chart.css +121 -0
  126. package/themes/shopware/components-content.css +169 -0
  127. package/themes/shopware/components-data.css +219 -0
  128. package/themes/shopware/components-diagram.css +129 -0
  129. package/themes/shopware/components-layout.css +166 -0
  130. package/themes/shopware/components.css +83 -0
  131. package/themes/shopware/manifest.json +21 -0
  132. package/themes/shopware/tokens.css +68 -0
  133. package/themes/shopware/transitions.css +22 -0
package/AGENT.md ADDED
@@ -0,0 +1,792 @@
1
+ # Stagecraft — Slides for Creative Directors
2
+
3
+ You're not filling a template. You're directing a scene.
4
+
5
+ If your slide is fewer than three lines, it's probably boring. The components below are anchors, not cages. Take them apart. Add particles, typewriters, glitch transitions, SVG. The Web Animations API is your friend.
6
+
7
+ ## 1. The rule
8
+
9
+ - A deck is a collection of `.js` files registered via `Stage.register({...})`.
10
+ - Each slide owns its DOM, its animation, its lifecycle.
11
+ - The engine handles navigation, the storyboard, and transitions.
12
+ - If you copy-paste a component call and don't customize it, you've wasted the opportunity.
13
+
14
+ ## 2. The toolbox (Layer-2 components)
15
+
16
+ Components have spare defaults on purpose. Adding animation is opt-in.
17
+
18
+ ### Stage.KineticText — multi-line staggered reveal (workhorse, ~50% of slides)
19
+ ```js
20
+ Stage.register(Stage.KineticText({
21
+ section: 2,
22
+ title: '02 · The shift',
23
+ pace: 800,
24
+ lines: [
25
+ { text: 'You start with a sentence.', color: 'fg' },
26
+ { text: 'You end with the sentence', color: 'dim' },
27
+ { text: 'rewritten.', color: 'accent', pause: 800 }
28
+ ]
29
+ }));
30
+ ```
31
+ Colors: `fg` `dim` `accent` `amber` `blue`. `pause` is extra ms before that line.
32
+
33
+ ### Stage.SectionCard — section divider
34
+ ```js
35
+ Stage.register(Stage.SectionCard({
36
+ section: 3, number: '03',
37
+ title: 'Where the work goes',
38
+ tag: 'time and attention'
39
+ }));
40
+ ```
41
+
42
+ ### Stage.ActivityList — numbered items (num · name · description)
43
+ ```js
44
+ Stage.register(Stage.ActivityList({
45
+ section: 3,
46
+ items: [
47
+ { num: '01', name: 'Problem framing', desc: 'understand the actual ask' },
48
+ { num: '02', name: 'Architecture', desc: 'pick the shape' }
49
+ ],
50
+ reveal: 'staggered' // 'staggered' | 'per-click' | 'instant'
51
+ }));
52
+ ```
53
+
54
+ ### Stage.Compare — two-column comparison
55
+ ```js
56
+ Stage.register(Stage.Compare({
57
+ section: 4,
58
+ left: { heading: 'OLD', items: ['type', 'compile'], style: 'strikethrough' },
59
+ right: { heading: 'NEW', items: ['describe', 'review'], style: 'accent' },
60
+ reveal: 'staggered'
61
+ }));
62
+ ```
63
+
64
+ ### Stage.Counter — live numeric counters
65
+ ```js
66
+ Stage.register(Stage.Counter({
67
+ section: 4,
68
+ blocks: [
69
+ { label: 'Lines written', start: 0, perSecond: 47, color: 'accent' },
70
+ { label: 'Bugs introduced', start: 0, perSecond: 3, color: 'amber' }
71
+ ],
72
+ footer: 'Both numbers are wrong.'
73
+ }));
74
+ ```
75
+
76
+ ### Stage.ShiftArrow — `from → to` mental model
77
+ ```js
78
+ Stage.register(Stage.ShiftArrow({
79
+ section: 6, from: 'writing code', to: 'reviewing code'
80
+ }));
81
+ ```
82
+
83
+ ### Layout family
84
+
85
+ #### Stage.ImageText — image one side, text the other
86
+ ```js
87
+ Stage.register(Stage.ImageText({
88
+ section: 3,
89
+ image: { src: 'assets/photo.jpg', alt: '...' },
90
+ side: 'left', // or 'right'
91
+ heading: 'The thing',
92
+ body: 'First sentence.\nSecond sentence.', // \n staggers per line
93
+ caption: 'optional small dim line',
94
+ reveal: 'staggered'
95
+ }));
96
+ ```
97
+
98
+ #### Stage.FullImage — full-bleed image with optional overlay
99
+ ```js
100
+ Stage.register(Stage.FullImage({
101
+ section: 4,
102
+ image: { src: 'assets/landscape.jpg', alt: '...' },
103
+ overlay: { position: 'bottom-left', headline: 'BIG IDEA', body: 'small subtitle' }
104
+ }));
105
+ ```
106
+ Without `overlay`: subtle ken-burns drift. Positions: `center`, `top`, `bottom-left`, `bottom-right`.
107
+
108
+ #### Stage.Quote — large quote with attribution
109
+ ```js
110
+ Stage.register(Stage.Quote({
111
+ section: 2,
112
+ quote: 'The best way to predict the future is to invent it.',
113
+ author: 'Alan Kay',
114
+ role: 'computer scientist',
115
+ source: '1971'
116
+ }));
117
+ ```
118
+
119
+ #### Stage.BigNumber — one huge number + label
120
+ ```js
121
+ Stage.register(Stage.BigNumber({
122
+ section: 4,
123
+ number: 47, unit: 'x',
124
+ label: 'productivity multiplier',
125
+ caption: 'observed on a focused refactor'
126
+ }));
127
+ ```
128
+ Counts up from 0 to target on init.
129
+
130
+ #### Stage.Stats — grid of statistic cards
131
+ ```js
132
+ Stage.register(Stage.Stats({
133
+ section: 4,
134
+ blocks: [
135
+ { number: 12, unit: 'k', label: 'commits', color: 'accent' },
136
+ { number: 47, unit: 'x', label: 'speedup', color: 'amber' },
137
+ { number: 99, unit: '%', label: 'caffeine', color: 'blue' }
138
+ ],
139
+ columns: 3
140
+ }));
141
+ ```
142
+
143
+ #### Stage.Bento — 2026 modular grid
144
+ ```js
145
+ Stage.register(Stage.Bento({
146
+ section: 5,
147
+ cells: [
148
+ { span: 2, heading: 'Hero', body: 'wide cell', color: 'accent' },
149
+ { heading: 'Stat', body: '...', image: { src: 'a.jpg' } },
150
+ { heading: 'Quote', body: '...' },
151
+ { span: 2, heading: 'Note', body: 'wide cell' }
152
+ ]
153
+ }));
154
+ ```
155
+
156
+ ### Diagram family
157
+
158
+ #### Stage.Pillars — N columns with material icons
159
+ ```js
160
+ Stage.register(Stage.Pillars({
161
+ section: 5,
162
+ intro: 'Three pillars',
163
+ pillars: [
164
+ { icon: 'bolt', heading: 'Speed', body: 'iterate fast' },
165
+ { icon: 'shield', heading: 'Safety', body: 'never break prod' },
166
+ { icon: 'visibility', heading: 'Clarity', body: 'see what you ship' }
167
+ ],
168
+ reveal: 'staggered' // | 'per-click' | 'instant'
169
+ }));
170
+ ```
171
+ Icons are Material Symbols Outlined names. See https://fonts.google.com/icons.
172
+
173
+ #### Stage.Timeline — milestones along a line
174
+ ```js
175
+ Stage.register(Stage.Timeline({
176
+ section: 5,
177
+ orientation: 'horizontal', // or 'vertical'
178
+ events: [
179
+ { date: '2024 Q1', heading: 'idea', icon: 'lightbulb' },
180
+ { date: '2024 Q3', heading: 'prototype', icon: 'science' },
181
+ { date: '2025 Q1', heading: 'launch', icon: 'rocket_launch', color: 'accent' }
182
+ ],
183
+ reveal: 'per-click'
184
+ }));
185
+ ```
186
+
187
+ #### Stage.Pyramid — stacked tiers
188
+ ```js
189
+ Stage.register(Stage.Pyramid({
190
+ section: 6,
191
+ layers: [
192
+ { label: 'Vision', body: 'where to' },
193
+ { label: 'Strategy', body: 'how to' },
194
+ { label: 'Tactics', body: 'do what' }
195
+ ],
196
+ orientation: 'up', // narrowest layer on top
197
+ reveal: 'staggered'
198
+ }));
199
+ ```
200
+
201
+ #### Stage.Cycle — circular arrangement
202
+ ```js
203
+ Stage.register(Stage.Cycle({
204
+ section: 6,
205
+ items: [
206
+ { label: 'Plan', icon: 'edit_note' },
207
+ { label: 'Build', icon: 'construction' },
208
+ { label: 'Measure', icon: 'monitor_heart' },
209
+ { label: 'Learn', icon: 'school' }
210
+ ],
211
+ reveal: 'rotate' // spins in on entry
212
+ }));
213
+ ```
214
+
215
+ #### Stage.Funnel — narrowing stages
216
+ ```js
217
+ Stage.register(Stage.Funnel({
218
+ section: 6,
219
+ stages: [
220
+ { label: 'Visitors', value: '10,000' },
221
+ { label: 'Trials', value: '1,200' },
222
+ { label: 'Customers', value: '180', color: 'accent' }
223
+ ],
224
+ reveal: 'staggered'
225
+ }));
226
+ ```
227
+
228
+ ### Chart family
229
+
230
+ #### Stage.Matrix2x2 — quadrant chart (Eisenhower-style)
231
+ ```js
232
+ Stage.register(Stage.Matrix2x2({
233
+ section: 7,
234
+ axes: {
235
+ x: { label: 'Effort', low: 'low', high: 'high' },
236
+ y: { label: 'Impact', low: 'low', high: 'high' }
237
+ },
238
+ quadrants: [
239
+ { x: 'low', y: 'high', label: 'Quick wins', color: 'accent' },
240
+ { x: 'high', y: 'high', label: 'Big bets', color: 'blue' },
241
+ { x: 'low', y: 'low', label: 'Fill-ins' },
242
+ { x: 'high', y: 'low', label: 'Time sinks', color: 'red' }
243
+ ],
244
+ reveal: 'per-click'
245
+ }));
246
+ ```
247
+
248
+ #### Stage.BarChart — simple bars
249
+ ```js
250
+ Stage.register(Stage.BarChart({
251
+ section: 7,
252
+ orientation: 'horizontal', // or 'vertical'
253
+ bars: [
254
+ { label: 'A', value: 42, color: 'accent' },
255
+ { label: 'B', value: 78, color: 'amber' },
256
+ { label: 'C', value: 31 }
257
+ ],
258
+ unit: 'h',
259
+ reveal: 'animated' // 0 → value tween
260
+ }));
261
+ ```
262
+
263
+ #### Stage.Progress — stacked progress bars
264
+ ```js
265
+ Stage.register(Stage.Progress({
266
+ section: 7,
267
+ items: [
268
+ { label: 'Coverage', value: 87 }, // /100
269
+ { label: 'Refactor', value: 3, total: 5 }, // /5
270
+ { label: 'Migration', value: 42, total: 100, color: 'amber' }
271
+ ],
272
+ reveal: 'animated'
273
+ }));
274
+ ```
275
+
276
+ #### Stage.ProcessFlow — N → N → N with arrows
277
+ ```js
278
+ Stage.register(Stage.ProcessFlow({
279
+ section: 7,
280
+ orientation: 'horizontal', // or 'vertical'
281
+ steps: [
282
+ { icon: 'edit', label: 'Draft' },
283
+ { icon: 'visibility', label: 'Review' },
284
+ { icon: 'check', label: 'Ship', color: 'accent' }
285
+ ],
286
+ reveal: 'per-click'
287
+ }));
288
+ ```
289
+
290
+ #### Stage.Venn — 2 or 3 overlapping circles
291
+ ```js
292
+ Stage.register(Stage.Venn({
293
+ section: 7,
294
+ sets: [
295
+ { label: 'speed', color: 'accent' },
296
+ { label: 'quality', color: 'amber' },
297
+ { label: 'cost', color: 'blue' }
298
+ ],
299
+ overlaps: [
300
+ { ids: [0, 1], label: 'real eng' },
301
+ { ids: [0, 2], label: 'hack' },
302
+ { ids: [1, 2], label: 'craft' },
303
+ { ids: [0, 1, 2], label: 'unicorn' }
304
+ ],
305
+ reveal: 'staggered'
306
+ }));
307
+ ```
308
+
309
+ ### Data-viz family (10)
310
+
311
+ #### Stage.KPI — hero metric card
312
+ ```js
313
+ Stage.register(Stage.KPI({
314
+ section: 8, value: 42_300, unit: '€',
315
+ label: 'monthly recurring revenue',
316
+ change: { value: 18, direction: 'up', period: 'QoQ' },
317
+ color: 'accent', icon: 'trending_up'
318
+ }));
319
+ ```
320
+
321
+ #### Stage.DonutChart — pie/donut with segments
322
+ ```js
323
+ Stage.register(Stage.DonutChart({
324
+ section: 8,
325
+ segments: [
326
+ { label: 'Engineering', value: 12, color: 'accent' },
327
+ { label: 'Sales', value: 7, color: 'amber' },
328
+ { label: 'Ops', value: 3, color: 'blue' }
329
+ ],
330
+ centerLabel: 'headcount',
331
+ reveal: 'animated'
332
+ }));
333
+ ```
334
+
335
+ #### Stage.LineChart — multi-series line/area chart
336
+ ```js
337
+ Stage.register(Stage.LineChart({
338
+ section: 8,
339
+ xLabels: ['Q1','Q2','Q3','Q4'],
340
+ series: [
341
+ { label: 'Revenue', color: 'accent', points: [12, 18, 24, 32] },
342
+ { label: 'Cost', color: 'amber', points: [8, 11, 14, 17] }
343
+ ],
344
+ area: true,
345
+ reveal: 'animated'
346
+ }));
347
+ ```
348
+
349
+ #### Stage.Gauge — semi-circular progress meter
350
+ ```js
351
+ Stage.register(Stage.Gauge({
352
+ section: 8, value: 73, max: 100,
353
+ label: 'capacity used', color: 'amber', ticks: 5
354
+ }));
355
+ ```
356
+
357
+ #### Stage.SparkLine — number + tiny inline trend
358
+ ```js
359
+ Stage.register(Stage.SparkLine({
360
+ section: 8, value: 1247, label: 'daily signups',
361
+ points: [820, 880, 910, 1050, 1100, 1180, 1247],
362
+ color: 'accent', period: 'past 7 days'
363
+ }));
364
+ ```
365
+
366
+ #### Stage.Heatmap — calendar-style intensity grid
367
+ ```js
368
+ Stage.register(Stage.Heatmap({
369
+ section: 8, rows: 7, cols: 12,
370
+ data: [[1,3,5,...], [2,4,6,...], ...],
371
+ color: 'accent',
372
+ xLabels: ['Jan','Feb','Mar', ...],
373
+ yLabels: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
374
+ }));
375
+ ```
376
+
377
+ #### Stage.Roadmap — quarterly swimlanes
378
+ ```js
379
+ Stage.register(Stage.Roadmap({
380
+ section: 8,
381
+ months: ['Q1','Q2','Q3','Q4'],
382
+ lanes: [
383
+ { label: 'Platform', color: 'accent', bars: [{start:0, end:2, label:'auth'}, {start:2, end:4, label:'billing'}] },
384
+ { label: 'Growth', color: 'amber', bars: [{start:1, end:3, label:'onboarding'}] }
385
+ ],
386
+ reveal: 'staggered'
387
+ }));
388
+ ```
389
+
390
+ #### Stage.SWOT — strengths/weaknesses/opportunities/threats
391
+ ```js
392
+ Stage.register(Stage.SWOT({
393
+ section: 8,
394
+ strengths: ['fast iteration', 'small team'],
395
+ weaknesses: ['no enterprise sales'],
396
+ opportunities: ['LLM tailwind', 'market shift'],
397
+ threats: ['incumbents catching up'],
398
+ reveal: 'per-click'
399
+ }));
400
+ ```
401
+
402
+ #### Stage.CodeBlock — syntax-highlighted code
403
+ ```js
404
+ Stage.register(Stage.CodeBlock({
405
+ section: 8,
406
+ language: 'javascript',
407
+ fileName: 'engine.js',
408
+ code: `function go(idx) {\n if (idx < 0) return;\n current = idx;\n}`,
409
+ highlight: [2],
410
+ reveal: 'typewriter'
411
+ }));
412
+ ```
413
+
414
+ #### Stage.CodeDiff — unified diff with +/- lines
415
+ ```js
416
+ Stage.register(Stage.CodeDiff({
417
+ section: 8, fileName: 'engine.js',
418
+ lines: [
419
+ { type: 'context', text: 'function go(idx) {' },
420
+ { type: 'remove', text: ' if (idx < 0) return;' },
421
+ { type: 'add', text: ' if (idx < 0 || idx >= slides.length) return;' },
422
+ { type: 'context', text: ' current = idx;' },
423
+ { type: 'context', text: '}' }
424
+ ],
425
+ reveal: 'staggered'
426
+ }));
427
+ ```
428
+
429
+ ### Business family (10)
430
+
431
+ #### Stage.Pricing — N tiers with features
432
+ ```js
433
+ Stage.register(Stage.Pricing({
434
+ section: 9,
435
+ tiers: [
436
+ { name: 'Free', price: '$0', period: '/mo', features: ['1 deck', 'public sharing'] },
437
+ { name: 'Pro', price: '$12', period: '/mo', features: ['unlimited decks', 'edit mode', 'all themes'], featured: true, ctaLabel: 'Start trial' },
438
+ { name: 'Team', price: '$48', period: '/mo', features: ['everything Pro', '5 seats', 'analytics'] }
439
+ ],
440
+ reveal: 'staggered'
441
+ }));
442
+ ```
443
+
444
+ #### Stage.Testimonial — quote with photo + logo
445
+ ```js
446
+ Stage.register(Stage.Testimonial({
447
+ section: 9,
448
+ quote: 'It cut our deck-prep time by 80%.',
449
+ author: { name: 'Jane Doe', role: 'VP Product', company: 'Acme', photo: 'photo.jpg', logo: 'logo.svg' }
450
+ }));
451
+ ```
452
+
453
+ #### Stage.TeamGrid — N people cards
454
+ ```js
455
+ Stage.register(Stage.TeamGrid({
456
+ section: 9, columns: 3,
457
+ people: [
458
+ { name: 'Ada Lovelace', role: 'Founder', photo: 'ada.jpg', bio: 'wrote the first program' },
459
+ { name: 'Alan Turing', role: 'CTO', photo: 'alan.jpg', social: { linkedin: '…' } }
460
+ ]
461
+ }));
462
+ ```
463
+
464
+ #### Stage.Agenda — timed schedule
465
+ ```js
466
+ Stage.register(Stage.Agenda({
467
+ section: 9,
468
+ items: [
469
+ { time: '09:00', label: 'Kickoff', duration: '30m', icon: 'flag' },
470
+ { time: '09:30', label: 'Deep dive', duration: '90m', icon: 'psychology' },
471
+ { time: '11:00', label: 'Demo', duration: '20m', icon: 'play_arrow' }
472
+ ],
473
+ reveal: 'per-click'
474
+ }));
475
+ ```
476
+
477
+ #### Stage.Checklist — checked/unchecked items
478
+ ```js
479
+ Stage.register(Stage.Checklist({
480
+ section: 9,
481
+ items: [
482
+ { text: 'set up project', done: true },
483
+ { text: 'wire up auth', done: true },
484
+ { text: 'write tests', done: false, body: 'integration first' },
485
+ { text: 'ship it' }
486
+ ],
487
+ reveal: 'staggered'
488
+ }));
489
+ ```
490
+
491
+ #### Stage.Steps — numbered tutorial steps
492
+ ```js
493
+ Stage.register(Stage.Steps({
494
+ section: 9,
495
+ steps: [
496
+ { number: 1, label: 'install', icon: 'download', body: 'npm i stagecraft' },
497
+ { number: 2, label: 'init', icon: 'create', body: 'npx stagecraft init' },
498
+ { number: 3, label: 'present', icon: 'play_arrow', body: 'open index.html' }
499
+ ],
500
+ orientation: 'horizontal',
501
+ reveal: 'per-click'
502
+ }));
503
+ ```
504
+
505
+ #### Stage.CTA — call to action
506
+ ```js
507
+ Stage.register(Stage.CTA({
508
+ section: 9,
509
+ headline: 'Start building today',
510
+ body: 'No credit card required.',
511
+ action: { label: 'Sign up', hint: '→' },
512
+ accent: true
513
+ }));
514
+ ```
515
+
516
+ #### Stage.Callout — colored sidebar box
517
+ ```js
518
+ Stage.register(Stage.Callout({
519
+ section: 9,
520
+ kind: 'warning', // 'info' | 'tip' | 'warning' | 'danger' | 'success'
521
+ icon: 'warning',
522
+ heading: 'Heads up',
523
+ body: 'Don\'t run this in production without backing up the database.'
524
+ }));
525
+ ```
526
+
527
+ #### Stage.Tip — compact emphasis box
528
+ ```js
529
+ Stage.register(Stage.Tip({
530
+ section: 9, kind: 'tip',
531
+ icon: 'lightbulb',
532
+ body: 'Combining BarChart with reveal: per-click makes a great explainer.'
533
+ }));
534
+ ```
535
+
536
+ #### Stage.BeforeAfter — split comparison
537
+ ```js
538
+ Stage.register(Stage.BeforeAfter({
539
+ section: 9,
540
+ before: { label: 'BEFORE', image: { src: 'old.jpg' } },
541
+ after: { label: 'AFTER', image: { src: 'new.jpg' } },
542
+ reveal: 'slider' // 'slider' animates the divider from 0 → 50%
543
+ }));
544
+ ```
545
+
546
+ ### Content / typography family (8)
547
+
548
+ #### Stage.Statement — single massive declarative
549
+ ```js
550
+ Stage.register(Stage.Statement({
551
+ section: 10,
552
+ text: 'We are not in the widget business. We are in the trust business.',
553
+ emphasis: ['trust']
554
+ }));
555
+ ```
556
+
557
+ #### Stage.QandA — question + answer
558
+ ```js
559
+ Stage.register(Stage.QandA({
560
+ section: 10,
561
+ question: 'What slows teams down most?',
562
+ answer: 'Unclear ownership.',
563
+ attribution: 'observed across 47 projects'
564
+ }));
565
+ ```
566
+
567
+ #### Stage.Manifesto — numbered "We believe…"
568
+ ```js
569
+ Stage.register(Stage.Manifesto({
570
+ section: 10,
571
+ intro: 'We believe...',
572
+ declarations: [
573
+ { text: 'Software should be honest.', emphasis: ['honest'] },
574
+ { text: 'Defaults should be excellent.', emphasis: ['excellent'] },
575
+ { text: 'Customers should never wait.', emphasis: ['never wait'] }
576
+ ],
577
+ reveal: 'per-click'
578
+ }));
579
+ ```
580
+
581
+ #### Stage.Punchline — buildup + payoff
582
+ ```js
583
+ Stage.register(Stage.Punchline({
584
+ section: 10,
585
+ buildup: [
586
+ 'We tried scaling the team.',
587
+ 'We tried adding tools.',
588
+ 'We tried more meetings.'
589
+ ],
590
+ payoff: 'What worked was deleting code.',
591
+ reveal: 'manual'
592
+ }));
593
+ ```
594
+
595
+ #### Stage.Definition — dictionary-style entry
596
+ ```js
597
+ Stage.register(Stage.Definition({
598
+ section: 10,
599
+ term: 'stagecraft',
600
+ definition: 'a small JavaScript library for cinematic, agent-authored presentations.',
601
+ etymology: 'from "stage" + "-craft"',
602
+ examples: ['Stagecraft handled the keynote deck beautifully.']
603
+ }));
604
+ ```
605
+
606
+ #### Stage.ImageGrid — gallery
607
+ ```js
608
+ Stage.register(Stage.ImageGrid({
609
+ section: 10, columns: 3,
610
+ images: [
611
+ { src: 'a.jpg', caption: 'one' },
612
+ { src: 'b.jpg', caption: 'two' },
613
+ { src: 'c.jpg' }
614
+ ],
615
+ reveal: 'cascade'
616
+ }));
617
+ ```
618
+
619
+ #### Stage.Spotlight — focus + context strip
620
+ ```js
621
+ Stage.register(Stage.Spotlight({
622
+ section: 10,
623
+ focus: { heading: 'The big one', body: 'this is what matters', icon: 'star' },
624
+ context: ['supporting fact 1', 'supporting fact 2', 'supporting fact 3'],
625
+ reveal: 'staggered'
626
+ }));
627
+ ```
628
+
629
+ #### Stage.Marquee — scrolling ticker
630
+ ```js
631
+ Stage.register(Stage.Marquee({
632
+ section: 10,
633
+ items: ['shipped 2024-01', 'shipped 2024-02', 'shipped 2024-03', 'shipped 2024-04'],
634
+ direction: 'left', speed: 'medium', double: true
635
+ }));
636
+ ```
637
+
638
+ ## 3. The toolbox (Layer-1 primitives)
639
+
640
+ Available globally as `Stage.<name>`. Use them in any slide's `init()` to build bespoke motion.
641
+
642
+ | Primitive | Signature | What |
643
+ |---|---|---|
644
+ | `staggerIn` | `(nodes, step=200, initial=100) → cleanup` | Add `.in` class to nodes one after another. Pairs with `.stagger > *` CSS. |
645
+ | `typewriter` | `(el, text, {speed, jitter, onDone}) → cleanup` | Character-by-character text reveal. |
646
+ | `emitParticle` | `(parent, x1, y1, x2, y2, dur=800) → cleanup` | SVG particle traveling between two points. |
647
+ | `revealByDataStep` | `(el, step)` | Show `[data-step=N]` elements where N ≤ step. Pass as `onStep`. |
648
+ | `blinkCaret` | `(el) → cleanup` | Attach a blinking caret. |
649
+ | `sessionElapsedClock` | `({start}) → {el, stop}` | Live MM:SS clock element. |
650
+ | `assignStageKeys` | `(root)` | Auto-assigns `data-stage-key` for edit-mode pins (engine calls this). |
651
+
652
+ ## 4. The cookbook
653
+
654
+ When you need motion that the components don't cover, **read these first** — they're the ceiling, not the floor. All in `examples/`:
655
+
656
+ - `examples/token-stream.js` — interleaved word-fill across a split panel, particle emit.
657
+ - `examples/orchestration-graph.js` — SVG hex-graph with particles flowing from satellites to center.
658
+ - `examples/terminal-log.js` — streaming colored log lines with a human realization reveal.
659
+ - `examples/whoami.js` — terminal prompt cycling through identity strings.
660
+ - `examples/closing-card.js` — QR + dedication + underline.
661
+
662
+ Don't copy them verbatim. Take the technique (the interleaved queue, the SVG particle pattern, the streaming type) and apply it to your own content.
663
+
664
+ ## 5. The step model
665
+
666
+ A slide may declare `steps: N`. The engine:
667
+
668
+ - Tracks `currentStep` (starts at 0).
669
+ - On `→`: if `currentStep < N-1`, increment and call `onStep(el, currentStep)`. Otherwise advance to next slide.
670
+ - On `←`: mirror.
671
+ - On `R`: reset to step 0, re-run `init`.
672
+
673
+ ```js
674
+ Stage.register({
675
+ section: 5, title: 'reveal each',
676
+ steps: 3,
677
+ render(el) {
678
+ el.innerHTML = `
679
+ <ul>
680
+ <li data-step="1">First insight</li>
681
+ <li data-step="2">Second insight</li>
682
+ <li data-step="3">Third insight</li>
683
+ </ul>`;
684
+ },
685
+ onStep: Stage.revealByDataStep
686
+ });
687
+ ```
688
+
689
+ For trivial cases use `Stage.revealByDataStep`. For anything richer (glow transitions, particle emit, typewriter on each step) write `onStep` yourself — that's the point.
690
+
691
+ ## 6. The transition library
692
+
693
+ In `stagecraft.config.js`, the `transition` on each slide controls how it enters:
694
+
695
+ ```js
696
+ Stage.deck({
697
+ theme: 'phosphor',
698
+ slides: [
699
+ { src: 'slides/00-title.js' },
700
+ { src: 'slides/01-shift.js', transition: 'fade' },
701
+ { src: 'slides/02-impact.js', transition: 'glitch' }
702
+ ]
703
+ });
704
+ ```
705
+
706
+ Built-in (14):
707
+
708
+ | | | |
709
+ |---|---|---|
710
+ | `cut` — hard, instant | `fade` — crossfade | `slide` — push from right |
711
+ | `dissolve` — slow blur fade | `glitch` — scanlines + RGB shift | `wipe` — masked sweep |
712
+ | `zoom-in` — scale up from small | `zoom-out` — start large, shrink | `flip` — 3D Y-axis rotate |
713
+ | `iris` — circular reveal | `shutter` — horizontal bands | `push` — strong horizontal push |
714
+ | `typewriter` — scaleX 0 → 1 | `shatter` — pixelated resolve | |
715
+
716
+ Themes override visuals. Unknown → falls back to `fade`.
717
+
718
+ ## 7. Edit mode (you-might-not-see-it, but: it exists)
719
+
720
+ When the human runs `npx stagecraft serve`, they get a browser-based editor that writes back to source. They might leave notes in slides:
721
+
722
+ ```js
723
+ // @note: too text-heavy, split into two slides
724
+ // @note[stage-key="KineticText/line[2]"]: this line is dishonest
725
+ Stage.register(Stage.KineticText({ ... }));
726
+ ```
727
+
728
+ When they say "process my notes":
729
+ 1. `grep -rn '@note' slides/`
730
+ 2. Read each note + the slide it's attached to
731
+ 3. Edit the slide accordingly
732
+ 4. **Delete the `@note:` lines** (absence ⇔ resolved)
733
+
734
+ Notes don't get a "resolved" state. Deleting them is how you mark them done.
735
+
736
+ ## 8. When to register a custom slide vs. use a component
737
+
738
+ Use a component when:
739
+ - It's truly a list of bullets / a comparison / a section divider — boring is fine for these.
740
+ - The visual you want is achievable with one component + minor styling.
741
+
742
+ Write a custom slide (just `Stage.register({section, title, render, init, ...})`) when:
743
+ - The animation is core to the message (token-stream, orchestration graph, terminal log).
744
+ - You're combining motion patterns no component covers.
745
+ - The slide is the centerpiece of a section — it deserves the attention.
746
+
747
+ The split should be roughly: ~40% workhorse components (KineticText, SectionCard, Quote, BigNumber), ~30% structural (ImageText, Bento, Compare, Pillars, Timeline), ~15% chart/diagram for data-heavy moments (BarChart, Matrix2x2, Pyramid, Funnel, Venn, ProcessFlow, Cycle), ~15% bespoke. If the bespoke share goes below 10%, the deck has gone flat.
748
+
749
+ ## 9. The full component catalog at a glance
750
+
751
+ | Family | Components |
752
+ |---|---|
753
+ | **Core (6)** | KineticText · SectionCard · ActivityList · Compare · Counter · ShiftArrow |
754
+ | **Layout (6)** | ImageText · FullImage · Quote · BigNumber · Stats · Bento |
755
+ | **Diagram (5)** | Pillars · Timeline · Pyramid · Cycle · Funnel |
756
+ | **Chart (5)** | Matrix2x2 · BarChart · Progress · ProcessFlow · Venn |
757
+ | **Data-viz (10)** | KPI · DonutChart · LineChart · Gauge · SparkLine · Heatmap · Roadmap · SWOT · CodeBlock · CodeDiff |
758
+ | **Business (10)** | Pricing · Testimonial · TeamGrid · Agenda · Checklist · Steps · CTA · Callout · Tip · BeforeAfter |
759
+ | **Content (8)** | Statement · QandA · Manifesto · Punchline · Definition · ImageGrid · Spotlight · Marquee |
760
+ | **Bespoke (5)** | TokenStream · OrchestrationGraph · TerminalLog · Whoami · ClosingCard (cookbook in `examples/`) |
761
+
762
+ **50 anchored components + 5 cookbook bespoke patterns + 15 transitions.** Pick the closest anchor, then customize. Animate. Pace. **Direct the scene.**
763
+
764
+ ## 10. Speaker notes
765
+
766
+ Slides take an optional second arg to `Stage.register` for metadata. The most common field is `notes`:
767
+
768
+ ```js
769
+ Stage.register(Stage.KineticText({...}), {
770
+ notes: 'Pause after the third line. The audience needs the beat.'
771
+ });
772
+ ```
773
+
774
+ Notes show only in the **Presenter View** (`P` opens a second window with current + next + notes + timer). They're editable via the 🎙 button on each storyboard tile.
775
+
776
+ ## 11. Themes (5)
777
+
778
+ | | |
779
+ |---|---|
780
+ | `phosphor` (default) | dark, JetBrains Mono, phosphor-green |
781
+ | `paper` | light, Inter + Source Serif 4, navy |
782
+ | `neon` | dark, magenta + cyan, heavy glow |
783
+ | `brand` | dark, Inter, blue, schlicht |
784
+ | `shopware` | light, Inter, brand-blue `#0870ff` — sourced from Shopware's Meteor design tokens |
785
+
786
+ Switch live from the storyboard, or set `data-theme="..."` on `<html>` and link the matching CSS bundle.
787
+
788
+ ## 12. Keyboard cheat sheet
789
+
790
+ `→ ← Space` navigate · `1-9` jump to section · `R` replay · `F` fullscreen
791
+ `S` storyboard · `P` presenter window · `E` toggle edit mode · `N` slide-level note
792
+ `?` show hint · `Esc` close overlay