@strategicnerds/slide-nerds 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 (101) hide show
  1. package/dist/cli/commands/analytics.d.ts +6 -0
  2. package/dist/cli/commands/analytics.d.ts.map +1 -0
  3. package/dist/cli/commands/analytics.js +44 -0
  4. package/dist/cli/commands/analytics.js.map +1 -0
  5. package/dist/cli/commands/create.d.ts +4 -0
  6. package/dist/cli/commands/create.d.ts.map +1 -0
  7. package/dist/cli/commands/create.js +87 -0
  8. package/dist/cli/commands/create.js.map +1 -0
  9. package/dist/cli/commands/export.d.ts +6 -0
  10. package/dist/cli/commands/export.d.ts.map +1 -0
  11. package/dist/cli/commands/export.js +109 -0
  12. package/dist/cli/commands/export.js.map +1 -0
  13. package/dist/cli/index.d.ts +3 -0
  14. package/dist/cli/index.d.ts.map +1 -0
  15. package/dist/cli/index.js +12 -0
  16. package/dist/cli/index.js.map +1 -0
  17. package/dist/cli/template-path.d.ts +4 -0
  18. package/dist/cli/template-path.d.ts.map +1 -0
  19. package/dist/cli/template-path.js +13 -0
  20. package/dist/cli/template-path.js.map +1 -0
  21. package/dist/runtime/export-api.d.ts +15 -0
  22. package/dist/runtime/export-api.d.ts.map +1 -0
  23. package/dist/runtime/export-api.js +21 -0
  24. package/dist/runtime/export-api.js.map +1 -0
  25. package/dist/runtime/index.d.ts +12 -0
  26. package/dist/runtime/index.d.ts.map +1 -0
  27. package/dist/runtime/index.js +8 -0
  28. package/dist/runtime/index.js.map +1 -0
  29. package/dist/runtime/light-table.d.ts +8 -0
  30. package/dist/runtime/light-table.d.ts.map +1 -0
  31. package/dist/runtime/light-table.js +104 -0
  32. package/dist/runtime/light-table.js.map +1 -0
  33. package/dist/runtime/presenter-view.d.ts +7 -0
  34. package/dist/runtime/presenter-view.d.ts.map +1 -0
  35. package/dist/runtime/presenter-view.js +62 -0
  36. package/dist/runtime/presenter-view.js.map +1 -0
  37. package/dist/runtime/slide-context.d.ts +16 -0
  38. package/dist/runtime/slide-context.d.ts.map +1 -0
  39. package/dist/runtime/slide-context.js +18 -0
  40. package/dist/runtime/slide-context.js.map +1 -0
  41. package/dist/runtime/slide-controls.d.ts +3 -0
  42. package/dist/runtime/slide-controls.d.ts.map +1 -0
  43. package/dist/runtime/slide-controls.js +177 -0
  44. package/dist/runtime/slide-controls.js.map +1 -0
  45. package/dist/runtime/slide-dom.d.ts +17 -0
  46. package/dist/runtime/slide-dom.d.ts.map +1 -0
  47. package/dist/runtime/slide-dom.js +89 -0
  48. package/dist/runtime/slide-dom.js.map +1 -0
  49. package/dist/runtime/slide-runtime.d.ts +7 -0
  50. package/dist/runtime/slide-runtime.d.ts.map +1 -0
  51. package/dist/runtime/slide-runtime.js +125 -0
  52. package/dist/runtime/slide-runtime.js.map +1 -0
  53. package/dist/runtime/slide-shape.d.ts +21 -0
  54. package/dist/runtime/slide-shape.d.ts.map +1 -0
  55. package/dist/runtime/slide-shape.js +115 -0
  56. package/dist/runtime/slide-shape.js.map +1 -0
  57. package/dist/runtime/types.d.ts +150 -0
  58. package/dist/runtime/types.d.ts.map +1 -0
  59. package/dist/runtime/types.js +38 -0
  60. package/dist/runtime/types.js.map +1 -0
  61. package/dist/runtime/use-presenter-mode.d.ts +14 -0
  62. package/dist/runtime/use-presenter-mode.d.ts.map +1 -0
  63. package/dist/runtime/use-presenter-mode.js +52 -0
  64. package/dist/runtime/use-presenter-mode.js.map +1 -0
  65. package/dist/runtime/use-slide-navigation.d.ts +13 -0
  66. package/dist/runtime/use-slide-navigation.d.ts.map +1 -0
  67. package/dist/runtime/use-slide-navigation.js +230 -0
  68. package/dist/runtime/use-slide-navigation.js.map +1 -0
  69. package/package.json +64 -0
  70. package/skills/accessibility/SKILL.md +236 -0
  71. package/skills/advanced-layouts/SKILL.md +429 -0
  72. package/skills/analytics/SKILL.md +97 -0
  73. package/skills/animation/SKILL.md +364 -0
  74. package/skills/brand/SKILL.md +200 -0
  75. package/skills/data-visualization/SKILL.md +533 -0
  76. package/skills/deck-templates/SKILL.md +93 -0
  77. package/skills/diagrams/SKILL.md +395 -0
  78. package/skills/export/SKILL.md +119 -0
  79. package/skills/interactive/SKILL.md +292 -0
  80. package/skills/layout/SKILL.md +178 -0
  81. package/skills/narrative-frameworks/SKILL.md +250 -0
  82. package/skills/react-component-embeds/SKILL.md +73 -0
  83. package/skills/slide-types/SKILL.md +384 -0
  84. package/skills/slidenerds-runtime/SKILL.md +163 -0
  85. package/skills/speaker-notes/SKILL.md +128 -0
  86. package/skills/strategic-frameworks/SKILL.md +392 -0
  87. package/skills/visual-design/SKILL.md +373 -0
  88. package/templates/analytics/custom.tsx.tmpl +20 -0
  89. package/templates/analytics/ga4.tsx.tmpl +15 -0
  90. package/templates/analytics/gtm.tsx.tmpl +9 -0
  91. package/templates/analytics/plausible.tsx.tmpl +10 -0
  92. package/templates/analytics/posthog.tsx.tmpl +14 -0
  93. package/templates/next-app/CLAUDE.md.tmpl +574 -0
  94. package/templates/next-app/README.md.tmpl +35 -0
  95. package/templates/next-app/app/globals.css.tmpl +274 -0
  96. package/templates/next-app/app/layout.tsx.tmpl +31 -0
  97. package/templates/next-app/app/page.tsx.tmpl +38 -0
  98. package/templates/next-app/brand.config.ts.tmpl +32 -0
  99. package/templates/next-app/package.json.tmpl +25 -0
  100. package/templates/next-app/postcss.config.mjs.tmpl +8 -0
  101. package/templates/next-app/tsconfig.json.tmpl +21 -0
@@ -0,0 +1,364 @@
1
+ ---
2
+ name: animation
3
+ description: Step-by-step reveal and transition patterns for slidenerds slides
4
+ ---
5
+
6
+ # Animation skill
7
+
8
+ Use this skill when a deck needs motion, sequencing, or narrative pacing. The runtime exposes one core control surface: `data-step`. Every animation in this skill maps to deterministic HTML, CSS, and step order.
9
+
10
+ ## Runtime contract
11
+
12
+ - Every slide is a `section` with `data-slide`.
13
+ - Every revealable element has `data-step`.
14
+ - The runtime toggles hidden and visible state by step index.
15
+ - The presenter controls pace through keyboard or click.
16
+
17
+ Do not rely on autoplay animation timelines for core meaning. If animation carries meaning, tie it to `data-step`.
18
+
19
+ ## Keynote-style animation support matrix
20
+
21
+ This table maps classic Apple Keynote patterns to reliable slidenerds implementations.
22
+
23
+ | Keynote family | Effects to support | slidenerds implementation |
24
+ | ---------------- | ---------------------------------------- | -------------------------------------------------------------- |
25
+ | Build in | Appear, Fade In, Move In, Scale In | `data-step` + CSS opacity, transform, scale transitions |
26
+ | Build out | Disappear, Fade Out, Move Out, Scale Out | Pair old/new layers across consecutive `data-step` wrappers |
27
+ | Action | Move, Rotate, Pulse, Color emphasis | `data-step` wrapper with CSS transitions on transform/color |
28
+ | Emphasis | Pulse, Highlight, Bounce | Short CSS keyframes triggered when step becomes visible |
29
+ | Slide transition | Dissolve, Push, Wipe style feel | Simulate with full-bleed transition elements on entering slide |
30
+ | Magic Move | Object morph between slides | Use the disciplined Magic Move emulation pattern below |
31
+
32
+ ## Animation primitives
33
+
34
+ Use these classes globally in deck CSS.
35
+
36
+ ```css
37
+ [data-step] {
38
+ visibility: hidden;
39
+ opacity: 0;
40
+ }
41
+
42
+ [data-step].step-fade {
43
+ transition:
44
+ opacity 280ms ease,
45
+ visibility 280ms ease;
46
+ }
47
+
48
+ [data-step].step-move-up {
49
+ transform: translateY(16px);
50
+ transition:
51
+ opacity 320ms ease,
52
+ transform 320ms ease,
53
+ visibility 320ms ease;
54
+ }
55
+
56
+ [data-step].step-scale-in {
57
+ transform: scale(0.96);
58
+ transition:
59
+ opacity 260ms ease,
60
+ transform 260ms ease,
61
+ visibility 260ms ease;
62
+ }
63
+
64
+ [data-step].step-emphasis {
65
+ animation: emphasis-pulse 360ms ease-out 1;
66
+ }
67
+
68
+ @keyframes emphasis-pulse {
69
+ 0% {
70
+ transform: scale(1);
71
+ }
72
+ 45% {
73
+ transform: scale(1.04);
74
+ }
75
+ 100% {
76
+ transform: scale(1);
77
+ }
78
+ }
79
+ ```
80
+
81
+ The runtime toggles the `.step-visible` class when the step is active. The visible state override:
82
+
83
+ ```css
84
+ [data-step].step-visible {
85
+ visibility: visible !important;
86
+ opacity: 1 !important;
87
+ transform: translateY(0) translateX(0) scale(1) !important;
88
+ }
89
+ ```
90
+
91
+ For emphasis entrance on big stats, combine with the `step-emphasis` class:
92
+
93
+ ```css
94
+ [data-step].step-emphasis.step-visible {
95
+ animation: emphasis-land 500ms cubic-bezier(0.16, 1, 0.3, 1) 1;
96
+ }
97
+
98
+ @keyframes emphasis-land {
99
+ 0% { transform: scale(0.85); opacity: 0; }
100
+ 60% { transform: scale(1.03); }
101
+ 100% { transform: scale(1); opacity: 1; }
102
+ }
103
+ ```
104
+
105
+ ## Build in patterns
106
+
107
+ ### Fade in list items
108
+
109
+ ```tsx
110
+ <ul className="space-y-3 text-xl">
111
+ <li data-step="" className="step-fade">
112
+ Problem is urgent
113
+ </li>
114
+ <li data-step="" className="step-fade">
115
+ Solution is differentiated
116
+ </li>
117
+ <li data-step="" className="step-fade">
118
+ Market timing is favorable
119
+ </li>
120
+ </ul>
121
+ ```
122
+
123
+ ### Move in diagram nodes
124
+
125
+ ```tsx
126
+ <div className="grid grid-cols-3 gap-6">
127
+ <div data-step="" className="step-move-up rounded-xl p-6">
128
+ Acquire
129
+ </div>
130
+ <div data-step="" className="step-move-up rounded-xl p-6">
131
+ Activate
132
+ </div>
133
+ <div data-step="" className="step-move-up rounded-xl p-6">
134
+ Expand
135
+ </div>
136
+ </div>
137
+ ```
138
+
139
+ ## Build out patterns
140
+
141
+ Use paired layers. First step shows current object, next step shows replacement object in target state.
142
+
143
+ ```tsx
144
+ <div className="relative h-48">
145
+ <div data-step="" className="step-fade absolute inset-0">
146
+ Current pricing: $49
147
+ </div>
148
+ <div data-step="" className="step-fade absolute inset-0">
149
+ New pricing: $99
150
+ </div>
151
+ </div>
152
+ ```
153
+
154
+ ## Action and emphasis patterns
155
+
156
+ ### Emphasize one metric without changing slide
157
+
158
+ ```tsx
159
+ <div data-step="" className="text-6xl font-bold step-emphasis">
160
+ 143%
161
+ </div>
162
+ ```
163
+
164
+ ### Animated chart reveal
165
+
166
+ ```tsx
167
+ <div data-step="" className="step-fade">
168
+ <ResponsiveContainer width="100%" height={360}>
169
+ <BarChart data={revenueData}>
170
+ <XAxis dataKey="quarter" />
171
+ <YAxis />
172
+ <Bar dataKey="arr" fill="var(--color-accent)" animationDuration={700} />
173
+ </BarChart>
174
+ </ResponsiveContainer>
175
+ </div>
176
+ ```
177
+
178
+ ## Magic Move (slide to slide)
179
+
180
+ The runtime performs automatic FLIP animation between slides for elements that share a `data-magic-id`. When navigating from one slide to the next, elements with matching IDs animate smoothly from their old position, size, and scale to their new position.
181
+
182
+ ### Protocol
183
+
184
+ 1. Give shared elements the same `data-magic-id` value on both slides.
185
+ 2. Keep typography tokens and brand colors identical across source and destination.
186
+ 3. Change geometry (position, size) between source and destination -- the runtime animates the difference.
187
+ 4. Put destination-only objects behind `data-step` on the destination slide.
188
+ 5. The FLIP animation runs at 500ms with a cubic-bezier(0.4, 0, 0.2, 1) easing.
189
+
190
+ ### Source slide
191
+
192
+ ```tsx
193
+ <section data-slide="">
194
+ <div className="relative min-h-screen" style={{ padding: 'var(--slide-padding)' }}>
195
+ <div data-magic-id="logo" className="absolute left-12 top-10">
196
+ Logo
197
+ </div>
198
+ <div data-magic-id="hero-chart" className="absolute left-20 top-28 w-[460px]">
199
+ Chart A
200
+ </div>
201
+ <h2 data-magic-id="headline" className="absolute left-20 bottom-24 text-5xl">
202
+ Before
203
+ </h2>
204
+ </div>
205
+ </section>
206
+ ```
207
+
208
+ ### Destination slide
209
+
210
+ ```tsx
211
+ <section data-slide="">
212
+ <div className="relative min-h-screen" style={{ padding: 'var(--slide-padding)' }}>
213
+ <div data-magic-id="logo" className="absolute right-12 top-10">
214
+ Logo
215
+ </div>
216
+ <div data-magic-id="hero-chart" className="absolute left-16 top-20 w-[760px]">
217
+ Chart B
218
+ </div>
219
+ <h2 data-magic-id="headline" className="absolute left-16 bottom-16 text-6xl">
220
+ After
221
+ </h2>
222
+ <p data-step="" className="step-fade absolute right-16 bottom-16">
223
+ Narration detail appears on click
224
+ </p>
225
+ </div>
226
+ </section>
227
+ ```
228
+
229
+ ### Magic Move quality checklist
230
+
231
+ - Same object names and semantic roles across both slides
232
+ - No random spacing changes outside intended movement
233
+ - Motion supports story progression, not decoration
234
+ - Presenter can explain the transform in one sentence
235
+
236
+ ## Transition overlays for slide changes
237
+
238
+ To mimic dissolve or wipe feeling, reveal a transition layer as the first step on the destination slide.
239
+
240
+ ```tsx
241
+ <section data-slide="">
242
+ <div data-step="" className="step-fade absolute inset-0 bg-black/20" />
243
+ <div style={{ padding: 'var(--slide-padding)' }}>
244
+ <h2 className="text-5xl">New section</h2>
245
+ </div>
246
+ </section>
247
+ ```
248
+
249
+ ## Auto-build animations
250
+
251
+ Auto-build animations trigger when a slide loads, with no click required. Use them for visual polish on slides where the content doesn't need pacing control.
252
+
253
+ ### Available classes
254
+
255
+ | Class | Effect | Duration |
256
+ |-------|--------|----------|
257
+ | `auto-fade` | Fade in | 350ms |
258
+ | `auto-pop` | Scale up with overshoot bounce | 400ms |
259
+ | `auto-wipe-right` | Clip-path reveal left to right | 500ms |
260
+ | `auto-slide-down` | Slide down from above + fade | 500ms |
261
+ | `auto-slide-up` | Slide up from below + fade | 500ms |
262
+
263
+ ### Staggering
264
+
265
+ Control stagger with inline `animationDelay`:
266
+
267
+ ```tsx
268
+ {items.map((item, i) => (
269
+ <div key={item.id} className="auto-pop card-surface p-5"
270
+ style={{ animationDelay: `${200 + i * 100}ms` }}>
271
+ {item.content}
272
+ </div>
273
+ ))}
274
+ ```
275
+
276
+ ### Directional grid pattern
277
+
278
+ For grids, use opposing directions by row for a "closing curtain" effect:
279
+
280
+ ```tsx
281
+ {items.map((item) => (
282
+ <div key={item.id}
283
+ className={`${item.row === 0 ? 'auto-slide-down' : 'auto-slide-up'} card-surface`}
284
+ style={{ animationDelay: '400ms' }}>
285
+ {item.content}
286
+ </div>
287
+ ))}
288
+ ```
289
+
290
+ ### When to use auto-build vs click-to-reveal
291
+
292
+ - **Auto-build**: KPI grids, case study cards, icon grids, badge lists, product cards. Slides where the visual entrance is the point, not the pacing.
293
+ - **Click-to-reveal**: Bullet lists, table rows, comparison reveals, any content where the presenter wants to control the narrative.
294
+ - **Hybrid**: Use `data-auto-step` for elements that auto-reveal, then `data-step` for elements that wait for clicks. Auto-steps play first, then manual steps take over.
295
+
296
+ ## Exit animations
297
+
298
+ Exit animations trigger when navigating away from a slide. The runtime adds `.exiting` to the slide and waits 400ms before transitioning.
299
+
300
+ ### Auto exits
301
+
302
+ Add exit classes directly to elements. They animate when the slide gets `.exiting`:
303
+
304
+ | Class | Effect | Duration |
305
+ |-------|--------|----------|
306
+ | `exit-fade` | Fade out | 400ms |
307
+ | `exit-scale-out` | Scale down + fade out | 400ms |
308
+ | `exit-slide-up` | Slide up + fade out | 400ms |
309
+ | `exit-slide-down` | Slide down + fade out | 400ms |
310
+ | `exit-wipe-left` | Clip-path collapse right to left | 400ms |
311
+
312
+ ### Author-controlled exits
313
+
314
+ Use `data-exit-step` for sequenced exits. After all entrance steps are revealed, subsequent clicks reveal exit steps (applying `exit-visible`), then transition to the next slide.
315
+
316
+ ```tsx
317
+ <h2 data-exit-step="" className="exit-fade">This fades out before slide transition</h2>
318
+ <div data-exit-step="" className="exit-slide-up">This slides up after the h2 fades</div>
319
+ ```
320
+
321
+ ## Auto-step sequencing
322
+
323
+ Use `data-auto-step="300ms"` for steps that reveal automatically on a timer. The value is the delay before revealing. Mix with `data-step` for hybrid sequences.
324
+
325
+ ```tsx
326
+ <div data-auto-step="200ms" className="step-fade">Reveals after 200ms</div>
327
+ <div data-auto-step="300ms" className="step-fade">Reveals 300ms after previous</div>
328
+ <div data-step="" className="step-move-up">Waits for click</div>
329
+ ```
330
+
331
+ ## Step groups
332
+
333
+ Use `data-step-group="name"` to reveal multiple elements with a single click. The runtime counts the group as one logical step.
334
+
335
+ ```tsx
336
+ <div data-step="" data-step-group="metrics" className="step-pop"
337
+ style={{ animationDelay: '0ms' }}>Revenue: $4.2M</div>
338
+ <div data-step="" data-step-group="metrics" className="step-pop"
339
+ style={{ animationDelay: '100ms' }}>Growth: 142%</div>
340
+ <div data-step="" data-step-group="metrics" className="step-pop"
341
+ style={{ animationDelay: '200ms' }}>Users: 50K</div>
342
+ ```
343
+
344
+ ## Animation QA checklist
345
+
346
+ - At least two distinct animation types in a deck: fade plus move, or fade plus scale
347
+ - At least one chart animation tied to `data-step`
348
+ - No animation duration above 800ms for presenter-controlled steps
349
+ - No infinite loops on content that appears in exports
350
+ - No clipping at common projector resolutions (1920x1080)
351
+
352
+ ## Image and logo motion rules
353
+
354
+ - Avoid animating full-bleed background images with large scale transforms
355
+ - Animate logo opacity or small position shifts only
356
+ - Keep logo animation under 250ms
357
+ - Preserve contrast at all animation states
358
+
359
+ ## What to avoid
360
+
361
+ - `backdrop-filter` and heavy blend modes, which degrade export reliability
362
+ - Delayed step transitions that make click timing ambiguous
363
+ - Parallel animations on more than 12 objects in one step
364
+ - Motion without narrative purpose
@@ -0,0 +1,200 @@
1
+ ---
2
+ name: brand
3
+ description: How to apply brand identity to a slidenerds deck by editing brand.config.ts and globals.css
4
+ ---
5
+
6
+ # Brand skill
7
+
8
+ Use this skill when creating a new deck, rebranding an existing deck, or applying a company's visual identity. This skill tells you exactly which files to edit and what values to set.
9
+
10
+ ## The branding system
11
+
12
+ Every slidenerds deck has two files that control brand:
13
+
14
+ 1. **`brand.config.ts`** at the project root. This is the single source of truth for colors, fonts, and spacing. The layout template reads this file and injects CSS custom properties on the `<html>` element at build time.
15
+ 2. **`app/globals.css`** for structural CSS, font imports, and derived color tokens. Add custom `@import` rules for web fonts here. Do not hardcode colors in slide content. Always use `var()` references.
16
+
17
+ Changing `brand.config.ts` rebrands the entire deck. No slide files need color or font edits.
18
+
19
+ ## brand.config.ts structure
20
+
21
+ ```typescript
22
+ import type { BrandConfig } from '@slidenerds/runtime'
23
+
24
+ export default {
25
+ colors: {
26
+ primary: '#0d0d0f',
27
+ accent: '#f59e0b',
28
+ background: '#111114',
29
+ surface: '#1a1a1f',
30
+ text: '#e8e6e3',
31
+ },
32
+ fonts: {
33
+ heading: 'Sora, system-ui, sans-serif',
34
+ body: 'DM Sans, system-ui, sans-serif',
35
+ mono: 'JetBrains Mono, ui-monospace, monospace',
36
+ },
37
+ spacing: {
38
+ slide: '5rem',
39
+ section: '2rem',
40
+ element: '1rem',
41
+ },
42
+ } satisfies BrandConfig
43
+ ```
44
+
45
+ ## How layout.tsx wires brand to CSS
46
+
47
+ The generated `app/layout.tsx` imports `brand.config.ts` and injects CSS custom properties:
48
+
49
+ ```tsx
50
+ import brandConfig from '../brand.config'
51
+
52
+ const brandVars = {
53
+ '--color-primary': brandConfig.colors.primary,
54
+ '--color-accent': brandConfig.colors.accent,
55
+ '--color-background': brandConfig.colors.background,
56
+ '--color-surface': brandConfig.colors.surface,
57
+ '--color-text': brandConfig.colors.text,
58
+ '--slide-padding': brandConfig.spacing.slide,
59
+ '--font-heading': brandConfig.fonts.heading,
60
+ '--font-body': brandConfig.fonts.body,
61
+ '--font-mono': brandConfig.fonts.mono,
62
+ } as React.CSSProperties
63
+
64
+ export default function RootLayout({ children }) {
65
+ return (
66
+ <html lang="en" style={brandVars}>
67
+ <body>
68
+ <SlideRuntime>{children}</SlideRuntime>
69
+ </body>
70
+ </html>
71
+ )
72
+ }
73
+ ```
74
+
75
+ This means every CSS `var()` reference resolves to the brand.config.ts values. No manual wiring needed.
76
+
77
+ ## What each color controls
78
+
79
+ | Token | CSS variable | Used by |
80
+ |---|---|---|
81
+ | `primary` | `--color-primary` | Section divider backgrounds, darkest surfaces |
82
+ | `accent` | `--color-accent` | Section labels, stat numbers, shape strokes, active indicators, chart fills, timeline dots, table highlights |
83
+ | `background` | `--color-background` | Slide canvas, body background |
84
+ | `surface` | `--color-surface` | Card backgrounds for charts, tables, code blocks |
85
+ | `text` | `--color-text` | Primary body text, headings |
86
+
87
+ ## Derived colors
88
+
89
+ Some slides need colors derived from the base palette. Define these in `globals.css`:
90
+
91
+ ```css
92
+ :root {
93
+ --color-accent-dim: rgba(245, 158, 11, 0.12);
94
+ --color-text-secondary: rgba(232, 230, 227, 0.6);
95
+ --color-text-tertiary: rgba(232, 230, 227, 0.4);
96
+ --color-border: rgba(255, 255, 255, 0.06);
97
+ --color-surface-elevated: #222228;
98
+ }
99
+ ```
100
+
101
+ When rebranding, extract the RGB values from the new accent and text colors and recompute these at the correct opacities.
102
+
103
+ ## How to rebrand step by step
104
+
105
+ ### Given a brand kit (colors + fonts)
106
+
107
+ 1. **Edit `brand.config.ts`**: Set the five core colors and three font stacks.
108
+ 2. **Update derived colors in `globals.css`**: Recompute accent-dim, text-secondary, text-tertiary, border, and surface-elevated using the new base values.
109
+ 3. **Add font imports in `globals.css`**: Add Google Fonts `@import` rules before the Tailwind import.
110
+ 4. **Done.** No slide files need editing.
111
+
112
+ ### Given only a logo or single brand color
113
+
114
+ Derive the full palette from one color:
115
+
116
+ - **accent**: The brand color itself.
117
+ - **background**: Near-black with a subtle hue tint toward the accent. Example: for amber accent, use `#111114` (neutral) or `#13120e` (warm).
118
+ - **surface**: One step lighter than background. Add 5-8% lightness.
119
+ - **primary**: Same as background or slightly darker.
120
+ - **text**: Off-white, not pure `#fff`. Use `#e8e6e3` or similar with a slight warm or cool bias matching the accent.
121
+
122
+ ### Light theme decks
123
+
124
+ Invert the relationships:
125
+
126
+ - **background**: Near-white (`#fafafa` to `#f5f5f5`)
127
+ - **surface**: White (`#ffffff`)
128
+ - **primary**: The brand's darkest color
129
+ - **text**: Near-black (`#1a1a1a` to `#2a2a2a`)
130
+ - **accent**: The brand color (ensure 4.5:1 contrast against background)
131
+ - Derived text opacities use the text color base, not white
132
+ - Change `--color-border` to `rgba(0, 0, 0, 0.06)` instead of white-based
133
+
134
+ ## Font pairing rules
135
+
136
+ - **Same family, weight contrast**: Use 800 heading, 400 body. Good for Inter, DM Sans, Plus Jakarta Sans.
137
+ - **Geometric heading + humanist body**: Sora or Space Grotesk headings, DM Sans or Source Sans body.
138
+ - **Serif heading + sans body**: Playfair Display or Fraunces headings, Inter or DM Sans body. For editorial or luxury brands.
139
+ - **Mono accent**: Always include a monospace font. JetBrains Mono, Fira Code, or Berkeley Mono.
140
+
141
+ Set all three in `brand.config.ts`. The layout injects them as `--font-heading`, `--font-body`, and `--font-mono`.
142
+
143
+ ## Where brand tokens appear in slide code
144
+
145
+ ```tsx
146
+ {/* Section label -- accent color, uppercase, wide tracking */}
147
+ <p className="section-label">Revenue</p>
148
+
149
+ {/* Title -- heading font inherited from body, tight tracking */}
150
+ <h2 className="text-[2.5rem] font-bold">ARR trajectory</h2>
151
+
152
+ {/* Body text -- secondary opacity */}
153
+ <p style={{ color: 'var(--color-text-secondary)' }}>Supporting detail</p>
154
+
155
+ {/* Stat number -- accent color with glow */}
156
+ <p className="stat-glow" style={{ color: 'var(--color-accent)' }}>$4.2M</p>
157
+
158
+ {/* Card surface for charts */}
159
+ <div className="card-surface p-8">...</div>
160
+
161
+ {/* Shape with brand colors */}
162
+ <SlideShape shape="hexagon" size={100}
163
+ fill="var(--color-surface)" stroke="var(--color-accent)" strokeWidth={1.5} />
164
+ ```
165
+
166
+ Never hardcode hex colors in slide content. Always use CSS variables.
167
+
168
+ ## Gradient mesh backgrounds
169
+
170
+ For atmospheric depth, use radial gradients with the accent at low opacity:
171
+
172
+ ```css
173
+ .bg-mesh-warm {
174
+ background:
175
+ radial-gradient(ellipse at 15% 60%, rgba(R, G, B, 0.07) 0%, transparent 50%),
176
+ radial-gradient(ellipse at 85% 25%, rgba(R, G, B, 0.03) 0%, transparent 40%),
177
+ var(--color-background);
178
+ }
179
+ ```
180
+
181
+ Replace R, G, B with the accent color's RGB components when rebranding.
182
+
183
+ ## Checklist after rebranding
184
+
185
+ - [ ] Five colors set in `brand.config.ts`
186
+ - [ ] Derived colors updated in `globals.css`
187
+ - [ ] Font imports added to `globals.css`
188
+ - [ ] Three font stacks set in `brand.config.ts`
189
+ - [ ] Gradient mesh backgrounds updated with new accent RGB
190
+ - [ ] No hardcoded hex values in slide content (search for `#` in page.tsx)
191
+ - [ ] Accent color has at least 4.5:1 contrast against background
192
+ - [ ] Text color has at least 7:1 contrast against background
193
+
194
+ ## Common mistakes
195
+
196
+ - Hardcoding `#f59e0b` instead of `var(--color-accent)` in slide files
197
+ - Editing `globals.css` colors instead of `brand.config.ts`
198
+ - Using pixel values for slide padding instead of `var(--slide-padding)`
199
+ - Using a font not declared in `brand.config.ts`
200
+ - Forgetting to update derived opacity colors after changing the base palette