octocode-cli 1.3.1 → 1.5.1

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 (102) hide show
  1. package/README.md +193 -34
  2. package/out/chunks/chunk-7476PETK.js +309 -0
  3. package/out/chunks/chunk-CVNNNSMQ.js +26 -0
  4. package/out/chunks/chunk-OQBJTZWK.js +60 -0
  5. package/out/chunks/chunk-UCZCF3BQ.js +9 -0
  6. package/out/chunks/command-help-specs-JZXVSLZ5.js +8 -0
  7. package/out/chunks/commands-XBFPLHSQ.js +8 -0
  8. package/out/chunks/help-P7TCOYAJ.js +10 -0
  9. package/out/chunks/main-help-ULF5PAQY.js +10 -0
  10. package/out/chunks/prompts-5E6VKRX5.js +8 -0
  11. package/out/chunks/spinner-URV2OX6O.js +8 -0
  12. package/out/chunks/tool-command-M6VA7P2F.js +8 -0
  13. package/out/octocode-cli.js +1 -1
  14. package/package.json +5 -3
  15. package/skills/README.md +13 -1
  16. package/skills/agentic-flow-best-practices/SKILL.md +280 -0
  17. package/skills/agentic-flow-best-practices/references/agent-collaboration-patterns.md +75 -0
  18. package/skills/agentic-flow-best-practices/references/pr-review-agent-example.md +47 -0
  19. package/skills/agentic-flow-best-practices/references/resources.md +112 -0
  20. package/skills/octocode-chrome-devtools/README.md +541 -0
  21. package/skills/octocode-chrome-devtools/SKILL.md +197 -0
  22. package/skills/octocode-chrome-devtools/agents/openai.yaml +7 -0
  23. package/skills/octocode-chrome-devtools/references/CDP_AGENT_REFERENCE.md +401 -0
  24. package/skills/octocode-chrome-devtools/references/CHROME_FLAGS.md +234 -0
  25. package/skills/octocode-chrome-devtools/references/INTENTS.md +108 -0
  26. package/skills/octocode-chrome-devtools/references/INTENTS_AUTH.md +179 -0
  27. package/skills/octocode-chrome-devtools/references/INTENTS_AUTOMATION.md +214 -0
  28. package/skills/octocode-chrome-devtools/references/INTENTS_DEBUG.md +329 -0
  29. package/skills/octocode-chrome-devtools/references/INTENTS_ENVIRONMENT.md +237 -0
  30. package/skills/octocode-chrome-devtools/references/INTENTS_INSPECT.md +263 -0
  31. package/skills/octocode-chrome-devtools/references/INTENTS_STORAGE_CONSENT.md +214 -0
  32. package/skills/octocode-chrome-devtools/references/RECOVERY.md +39 -0
  33. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS.md +43 -0
  34. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_ASYNC_WORKERS.md +345 -0
  35. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_BROWSER.md +403 -0
  36. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_OBSERVE.md +275 -0
  37. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_SPECIAL.md +18 -0
  38. package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +503 -0
  39. package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +123 -0
  40. package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +81 -0
  41. package/skills/octocode-chrome-devtools/scripts/octocode-chrome-devtools.vpn.example.json +8 -0
  42. package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +362 -0
  43. package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +193 -0
  44. package/skills/octocode-chrome-devtools/scripts/undercover.mjs +226 -0
  45. package/skills/octocode-design/README.md +2 -2
  46. package/skills/octocode-documentation-writer/README.md +1 -1
  47. package/skills/octocode-engineer/README.md +1 -1
  48. package/skills/octocode-engineer/SKILL.md +4 -2
  49. package/skills/octocode-engineer/references/output-files.md +3 -3
  50. package/skills/octocode-engineer/scripts/run.js +136 -136
  51. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +48 -0
  52. package/skills/octocode-engineer/src/reporting/summary-md.ts +43 -2
  53. package/skills/octocode-install/SKILL.md +1 -1
  54. package/skills/octocode-pull-request-reviewer/README.md +5 -5
  55. package/skills/octocode-pull-request-reviewer/SKILL.md +1 -1
  56. package/skills/octocode-research/AGENTS.md +1 -1
  57. package/skills/octocode-research/README.md +2 -2
  58. package/skills/octocode-research/docs/ARCHITECTURE.md +1 -1
  59. package/skills/octocode-research/scripts/server.js +191 -246
  60. package/skills/octocode-research/src/routes/github.ts +4 -21
  61. package/skills/octocode-research/src/routes/local.ts +4 -21
  62. package/skills/octocode-research/src/utils/fileContentTransform.ts +44 -0
  63. package/skills/octocode-search-skill/SKILL.md +245 -229
  64. package/skills/octocode-search-skill/references/agent-skills-guide.md +177 -0
  65. package/skills/octocode-search-skill/references/discovery-surfaces.md +162 -0
  66. package/skills/octocode-search-skill/references/fetch-and-create-locally.md +57 -0
  67. package/skills/octocode-search-skill/references/install-reference.md +130 -0
  68. package/skills/octocode-search-skill/references/references-template.md +27 -0
  69. package/skills/octocode-search-skill/references/references.md +62 -0
  70. package/skills/octocode-slides/README.md +307 -0
  71. package/skills/octocode-slides/SKILL.md +410 -0
  72. package/skills/octocode-slides/references/01-brief.md +156 -0
  73. package/skills/octocode-slides/references/02-research.md +149 -0
  74. package/skills/octocode-slides/references/03-outline.md +172 -0
  75. package/skills/octocode-slides/references/04-design.md +301 -0
  76. package/skills/octocode-slides/references/05-implementation.md +213 -0
  77. package/skills/octocode-slides/references/06-review.md +258 -0
  78. package/skills/octocode-slides/references/animation.md +281 -0
  79. package/skills/octocode-slides/references/design-system.md +316 -0
  80. package/skills/octocode-slides/references/html-templates.md +673 -0
  81. package/skills/octocode-slides/references/image-generation.md +448 -0
  82. package/skills/octocode-slides/references/resources.md +840 -0
  83. package/skills/octocode-slides/references/slide-rules.md +541 -0
  84. package/skills/octocode-slides/references/wireframes.md +727 -0
  85. package/skills/octocode-slides/scripts/animation.js +182 -0
  86. package/skills/octocode-slides/scripts/base.css +353 -0
  87. package/skills/octocode-slides/scripts/base.html +655 -0
  88. package/skills/octocode-slides/scripts/generate_image.py +221 -0
  89. package/skills/octocode-slides/scripts/navbridge.js +79 -0
  90. package/skills/octocode-slides/scripts/presenter.js +316 -0
  91. package/skills/octocode-slides/scripts/slide.html +248 -0
  92. package/skills/octocode-stats/SKILL.md +73 -0
  93. package/skills/octocode-stats/assets/template.html +1332 -0
  94. package/skills/octocode-stats/scripts/build_dashboard.mjs +407 -0
  95. package/assets/example.png +0 -0
  96. package/out/chunks/chunk-QCY7Q7YW.js +0 -389
  97. package/out/chunks/command-help-specs-CQ3RBLP6.js +0 -8
  98. package/out/chunks/commands-OCTZP2TO.js +0 -51
  99. package/out/chunks/help-XPXP46ZT.js +0 -10
  100. package/out/chunks/main-help-35HX2UDQ.js +0 -10
  101. package/out/chunks/tool-command-HOSMVLNK.js +0 -8
  102. package/skills/octocode-search-skill/INSTALL_REFERENCE.md +0 -112
@@ -0,0 +1,673 @@
1
+ # HTML Templates Reference — Octocode Slides
2
+
3
+ Read during Phase 5 implementation, and consult during Phase 4 when a design choice depends on available layout patterns.
4
+
5
+ ---
6
+
7
+ ## Canonical slide skeleton
8
+
9
+ A slide can use up to **four regions** in this order. Only `.slide-content` is required — every other region is opt-in per slide. The skeleton is a contract for **where things go when present**, not a recipe forcing every slide into the same shape.
10
+
11
+ | Region | Class | Optional? | Purpose |
12
+ |---|---|---|---|
13
+ | Logo | `.slide-logo` | Optional | Brand mark, anchored top-right (absolute) |
14
+ | Header | `.slide-header` | Optional | `.title` + `.description` (muted subtitle) |
15
+ | Content | `.slide-content` | **Required** | Smart flex body — bullets, grid, chart, image, etc. |
16
+ | Footer | `.slide-footer` | Optional | Source line, page number, link, attribution |
17
+
18
+ **Use what serves the slide; omit the rest.** A title hero may only need `.slide-content`. A data slide may use all four. Variety across slides is good — what matters is that *when* a region appears, it sits in the same place and uses the same class.
19
+
20
+ ```html
21
+ <div class="slide slide--{{TYPE}}">
22
+ <!-- optional: brand mark, top-right -->
23
+ <header class="slide-logo">
24
+ <img src="../assets/logo.svg" alt="{{Brand}}">
25
+ </header>
26
+
27
+ <!-- optional: title + description -->
28
+ <header class="slide-header">
29
+ <h2 class="title">{{Slide title — claim sentence}}</h2>
30
+ <p class="description">{{One-line description (optional)}}</p>
31
+ </header>
32
+
33
+ <!-- required: the body. Smart flex column by default. -->
34
+ <main class="slide-content">
35
+ {{body markup — see per-type templates below}}
36
+ </main>
37
+
38
+ <!-- optional: source / context / page / link -->
39
+ <footer class="slide-footer">
40
+ <span>{{Source or context}}</span>
41
+ <span>{{Page or link}}</span>
42
+ </footer>
43
+ </div>
44
+ ```
45
+
46
+ `.slide-content` defaults to `display: flex; flex-direction: column; flex: 1; gap: var(--sp-3)`. Use these modifier classes when the default isn't right:
47
+
48
+ | Modifier | Effect | Use for |
49
+ |---|---|---|
50
+ | `slide-content--center` | Center along both axes + text-align center | Single number, single sentence, hero block |
51
+ | `slide-content--middle` | Center vertically only | Tall body that should sit in the middle |
52
+ | `slide-content--row` | Switch to flex-row, align stretched | Text + image side-by-side |
53
+ | `slide-content--grid-2` | Two equal columns | Comparisons, two-up cards |
54
+ | `slide-content--grid-3` | Three equal columns | KPI grid, three icons + labels |
55
+
56
+ Centered slide types (`title`, `section`, `quote`, `closing`) automatically center the entire stack — no modifier needed.
57
+
58
+ ---
59
+
60
+ ## Naming convention — classes and IDs
61
+
62
+ Every element targeted by animation, JS control, or external overrides must have a precise, unambiguous selector. Vague class names collide across slides when scripts run in `index.html` context or when a future deck reuses a component.
63
+
64
+ ### Class rules for repetitive components
65
+
66
+ | Pattern | Use | Example |
67
+ |---------|-----|---------|
68
+ | `{component}-list` | Wrapping container for a group | `bullets`, `agenda-list`, `stat-grid`, `timeline` |
69
+ | `{component}-item` | Individual member of a list | `stat-item`, `tl-item`, `bar-row` |
70
+ | `{component}-{part}` | Named sub-part of an item | `stat-value`, `stat-label`, `tl-dot`, `tl-label`, `bar-label` |
71
+ | `{context}-col {context}-{role}` | Layout column scoped to a slide type | `cmp-col cmp-before` · `col two-col-left` · `col two-col-right` |
72
+ | `{slide-type}-{role}` | Unique element within one slide type | `closing-links`, `image-caption`, `chart-insight`, `code-caption` |
73
+
74
+ **Never use bare, context-free class names** — `col`, `item`, `panel`, `row` alone — as the sole identifier. Always pair them with a context qualifier (e.g. `col two-col-left`) so animation selectors stay unambiguous across a multi-slide deck.
75
+
76
+ ### ID rules
77
+
78
+ Assign `id` only when:
79
+
80
+ - An animation counter needs a direct DOM target (`document.getElementById(...)` in `onUpdate`)
81
+ - A chart or diagram library initializes by element ID
82
+ - JS needs a reliable, unique anchor (focus management, presenter note jump target)
83
+
84
+ **Format: `{slide-slug}-{role}`** — e.g. `id="stats-kpi-1"`, `id="perf-chart"`, `id="timeline-root"`.
85
+
86
+ Never use bare numeric IDs (`id="1"`) or generic IDs (`id="chart"`, `id="kpi"`). They collide when a slide is scripted from the parent `index.html` or reused across decks.
87
+
88
+ ---
89
+
90
+ ## Slide file shell
91
+
92
+ Every `slides/slug.html` uses this shell. Slides fill the iframe 100%×100% — the stage in `index.html` handles all scaling. Add CDN `<link>` / `<script>` tags inside `<head>` only when the slide needs them.
93
+
94
+ **`js/navbridge.js` is required in every slide.** It propagates arrow-key events from the iframe back to the parent navigation controller via `postMessage`, so keyboard navigation keeps working after the user clicks inside a slide. The `<script>` tag is already included at the end of `scripts/slide.html` — do not remove it.
95
+
96
+ ```html
97
+ <!DOCTYPE html>
98
+ <html lang="en">
99
+ <head>
100
+ <meta charset="UTF-8">
101
+ <title>{{Slide Title}}</title>
102
+ <link rel="stylesheet" href="../css/base.css">
103
+ <link rel="stylesheet" href="../css/theme.css">
104
+ <!-- Optional: add CDN libraries only when the slide needs them -->
105
+ </head>
106
+ <body>
107
+ <div class="slide slide--{{TYPE}}">
108
+ <!-- Up to four regions: .slide-logo, .slide-header, .slide-content, .slide-footer -->
109
+ <!-- Only .slide-content is required. -->
110
+ </div>
111
+ <aside class="speaker-notes">{{Speaker notes}}</aside>
112
+ <script src="../js/navbridge.js"></script>
113
+ </body>
114
+ </html>
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Slide type templates
120
+
121
+ All templates below use the **canonical 4-region skeleton**. Logo and footer regions are shown commented-out: include them when the deck calls for them and stay consistent about it. Description lines are shown as `{{Description (optional)}}` — fill them when the title needs reinforcement, leave the line out when it doesn't. Don't pad slides with descriptions just because the slot exists.
122
+
123
+ ### title
124
+
125
+ Centered hero. The deck's first impression. `.slide-header` carries the display heading; `.slide-content` carries supporting copy.
126
+
127
+ ```html
128
+ <div class="slide slide--title">
129
+ <!-- <header class="slide-logo"><img src="../assets/logo.svg" alt="Brand"></header> -->
130
+ <header class="slide-header">
131
+ <p class="eyebrow fade-in">{{Event or tagline}}</p>
132
+ <h1 class="display slide-up">{{Main Title}}</h1>
133
+ <p class="description slide-up delay-1">{{Subtitle / description}}</p>
134
+ </header>
135
+ <main class="slide-content">
136
+ <p class="meta fade-in delay-2">{{Author}} · {{Date}}</p>
137
+ </main>
138
+ </div>
139
+ ```
140
+
141
+ ### agenda
142
+
143
+ ```html
144
+ <div class="slide slide--agenda">
145
+ <header class="slide-header">
146
+ <h2 class="title fade-in">{{Agenda}}</h2>
147
+ <!-- optional: <p class="description">{{One-line promise}}</p> -->
148
+ </header>
149
+ <main class="slide-content">
150
+ <ol class="agenda-list">
151
+ <li class="slide-up delay-1"><span class="num">01</span>{{Topic One}}</li>
152
+ <li class="slide-up delay-2"><span class="num">02</span>{{Topic Two}}</li>
153
+ <li class="slide-up delay-3"><span class="num">03</span>{{Topic Three}}</li>
154
+ </ol>
155
+ </main>
156
+ </div>
157
+ ```
158
+
159
+ ### section-header
160
+
161
+ ```html
162
+ <div class="slide slide--section">
163
+ <header class="slide-header">
164
+ <p class="section-num fade-in">{{01}}</p>
165
+ <h2 class="display slide-up">{{Section Title}}</h2>
166
+ <p class="description slide-up delay-1">{{One supporting line}}</p>
167
+ </header>
168
+ </div>
169
+ ```
170
+
171
+ `.slide-header` is the only region used; the centered slide type vertically centers it.
172
+
173
+ ### content
174
+
175
+ Header above, smart-flex body below.
176
+
177
+ ```html
178
+ <div class="slide slide--content">
179
+ <header class="slide-header">
180
+ <h2 class="title fade-in">{{Action title}}</h2>
181
+ <!-- optional: <p class="description">{{Why this matters}}</p> -->
182
+ </header>
183
+ <main class="slide-content">
184
+ <ul class="bullets">
185
+ <li class="slide-up delay-1">{{Point one — max 12 words}}</li>
186
+ <li class="slide-up delay-2">{{Point two}}</li>
187
+ <li class="slide-up delay-3">{{Point three}}</li>
188
+ <!-- max 4 bullets -->
189
+ </ul>
190
+ </main>
191
+ </div>
192
+ ```
193
+
194
+ ### two-column
195
+
196
+ ```html
197
+ <div class="slide slide--two-col">
198
+ <header class="slide-header">
199
+ <h2 class="title fade-in">{{Heading}}</h2>
200
+ </header>
201
+ <main class="slide-content slide-content--grid-2">
202
+ <!-- `col` keeps base.css styling; `two-col-left` gives animation/JS a precise target -->
203
+ <div class="col two-col-left slide-up delay-1">
204
+ <h3 class="col-heading two-col-heading">{{Left heading}}</h3>
205
+ <ul class="two-col-bullets"><li>{{Point}}</li><li>{{Point}}</li></ul>
206
+ </div>
207
+ <div class="col two-col-right slide-up delay-2">
208
+ <h3 class="col-heading two-col-heading">{{Right heading}}</h3>
209
+ <ul class="two-col-bullets"><li>{{Point}}</li><li>{{Point}}</li></ul>
210
+ </div>
211
+ </main>
212
+ </div>
213
+ ```
214
+
215
+ ### quote
216
+
217
+ ```html
218
+ <div class="slide slide--quote">
219
+ <main class="slide-content">
220
+ <p class="quote-mark fade-in" aria-hidden="true">"</p>
221
+ <blockquote class="quote-text slide-up">{{Quote — max 30 words}}</blockquote>
222
+ <cite class="quote-attr fade-in delay-2">— {{Name, Title}}</cite>
223
+ </main>
224
+ </div>
225
+ ```
226
+
227
+ ### code (with highlight.js)
228
+
229
+ ```html
230
+ <!DOCTYPE html>
231
+ <html lang="en">
232
+ <head>
233
+ <meta charset="UTF-8">
234
+ <title>{{Slide Title}}</title>
235
+ <link rel="stylesheet" href="../css/base.css">
236
+ <link rel="stylesheet" href="../css/theme.css">
237
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css">
238
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
239
+ </head>
240
+ <body>
241
+ <div class="slide slide--code">
242
+ <header class="slide-header">
243
+ <h2 class="title fade-in">{{Heading}}</h2>
244
+ </header>
245
+ <main class="slide-content">
246
+ <pre class="code-block slide-up delay-1"><code class="language-{{js|python|typescript|bash|go}}">{{
247
+ // code here — max 20 lines
248
+ }}</code></pre>
249
+ <p class="code-caption fade-in delay-2">{{One-line insight}}</p>
250
+ </main>
251
+ </div>
252
+ <aside class="speaker-notes">{{Speaker notes}}</aside>
253
+ <script>hljs.highlightAll();</script>
254
+ <script src="../js/navbridge.js"></script>
255
+ </body>
256
+ </html>
257
+ ```
258
+
259
+ ### chart (HTML+CSS bar chart — no JS library)
260
+
261
+ ```html
262
+ <div class="slide slide--chart">
263
+ <header class="slide-header">
264
+ <h2 class="title fade-in">{{Heading}}</h2>
265
+ </header>
266
+ <main class="slide-content">
267
+ <div class="bar-chart slide-up delay-1" role="img" aria-label="{{description}}">
268
+ <div class="bar-row">
269
+ <span class="bar-label">{{Label A}}</span>
270
+ <div class="bar" style="--pct:80%"><span>{{Value}}</span></div>
271
+ </div>
272
+ <div class="bar-row">
273
+ <span class="bar-label">{{Label B}}</span>
274
+ <div class="bar" style="--pct:55%"><span>{{Value}}</span></div>
275
+ </div>
276
+ <div class="bar-row">
277
+ <span class="bar-label">{{Label C}}</span>
278
+ <div class="bar" style="--pct:35%"><span>{{Value}}</span></div>
279
+ </div>
280
+ </div>
281
+ <p class="chart-insight fade-in delay-3">{{Key takeaway}}</p>
282
+ </main>
283
+ </div>
284
+ ```
285
+
286
+ ### timeline
287
+
288
+ ```html
289
+ <div class="slide slide--timeline">
290
+ <header class="slide-header">
291
+ <h2 class="title fade-in">{{Heading}}</h2>
292
+ </header>
293
+ <main class="slide-content">
294
+ <ol class="timeline">
295
+ <li class="tl-item slide-up delay-1">
296
+ <span class="tl-dot"></span>
297
+ <div><strong class="tl-label">{{2022 / Q1}}</strong> {{Description}}</div>
298
+ </li>
299
+ <li class="tl-item slide-up delay-2"><!-- repeat --></li>
300
+ </ol>
301
+ </main>
302
+ </div>
303
+ ```
304
+
305
+ ### comparison
306
+
307
+ ```html
308
+ <div class="slide slide--comparison">
309
+ <header class="slide-header">
310
+ <h2 class="title fade-in">{{Before / After}}</h2>
311
+ </header>
312
+ <main class="slide-content">
313
+ <div class="comparison">
314
+ <div class="cmp-col cmp-before slide-up delay-1">
315
+ <h3>{{Before}}</h3>
316
+ <ul><li>{{Point}}</li><li>{{Point}}</li></ul>
317
+ </div>
318
+ <div class="cmp-divider fade-in delay-2"></div>
319
+ <div class="cmp-col cmp-after slide-up delay-3">
320
+ <h3>{{After}}</h3>
321
+ <ul><li>{{Point}}</li><li>{{Point}}</li></ul>
322
+ </div>
323
+ </div>
324
+ </main>
325
+ </div>
326
+ ```
327
+
328
+ ### closing
329
+
330
+ ```html
331
+ <div class="slide slide--closing">
332
+ <header class="slide-header">
333
+ <h2 class="display slide-up">{{Thank You / Key Takeaway}}</h2>
334
+ <p class="description fade-in delay-1">{{Call to action}}</p>
335
+ </header>
336
+ <main class="slide-content">
337
+ <div class="closing-links fade-in delay-2">
338
+ <a href="{{URL}}">{{Link text}}</a>
339
+ </div>
340
+ </main>
341
+ </div>
342
+ ```
343
+
344
+ ### stats (KPI / big numbers)
345
+
346
+ Use for 1–3 key metrics. Add a Motion counter animation when numbers should count up.
347
+
348
+ ```html
349
+ <div class="slide slide--stats">
350
+ <header class="slide-header">
351
+ <h2 class="title fade-in">{{Heading — claim sentence}}</h2>
352
+ </header>
353
+ <main class="slide-content">
354
+ <div class="stat-grid">
355
+ <!-- id="{slide-slug}-kpi-{n}" — required for animation counter targeting -->
356
+ <div class="stat-item pop-in delay-1">
357
+ <span class="stat-value" id="{{slide-slug}}-kpi-1">{{Number or symbol}}</span>
358
+ <span class="stat-label">{{Label}}</span>
359
+ </div>
360
+ <div class="stat-item pop-in delay-2">
361
+ <span class="stat-value" id="{{slide-slug}}-kpi-2">{{Number or symbol}}</span>
362
+ <span class="stat-label">{{Label}}</span>
363
+ </div>
364
+ <div class="stat-item pop-in delay-3">
365
+ <span class="stat-value" id="{{slide-slug}}-kpi-3">{{Number or symbol}}</span>
366
+ <span class="stat-label">{{Label}}</span>
367
+ </div>
368
+ </div>
369
+ <p class="stat-caption fade-in delay-4">{{Source or context}}</p>
370
+ </main>
371
+ </div>
372
+ ```
373
+
374
+ ### image (full-bleed background)
375
+
376
+ Full-bleed slides are special: they bypass the standard regions and use absolute layering.
377
+
378
+ ```html
379
+ <div class="slide slide--image">
380
+ <img src="{{path/to/image.jpg}}" alt="{{Descriptive alt text}}">
381
+ <div class="image-overlay" aria-hidden="true"></div>
382
+ <div class="image-caption slide-up delay-1">
383
+ <p class="display">{{Short headline}}</p>
384
+ <p class="description">{{Supporting line}}</p>
385
+ </div>
386
+ </div>
387
+ ```
388
+
389
+ ### image-placeholder (inline — user will provide image later)
390
+
391
+ Use for `content`, `two-col`, or `chart` slides that need an inline image the user hasn't provided yet. Replace `.image-ph` with `<img>` once the file is available.
392
+
393
+ ```html
394
+ <div class="slide slide--content">
395
+ <header class="slide-header">
396
+ <h2 class="title fade-in">{{Heading}}</h2>
397
+ </header>
398
+ <main class="slide-content">
399
+ <!-- IMAGE PLACEHOLDER — replace with <img src="PATH" alt="ALT"> when provided -->
400
+ <div class="image-ph slide-up delay-1" data-expected="{{image description}}">
401
+ <div class="image-ph-inner">
402
+ <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true" style="opacity:0.5">
403
+ <rect x="1" y="1" width="42" height="42" rx="5" stroke="currentColor" stroke-width="1.5" stroke-dasharray="5 3"/>
404
+ <circle cx="16" cy="17" r="4" stroke="currentColor" stroke-width="1.5"/>
405
+ <path d="M3 33l10-8 7 6 7-7 14 9" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>
406
+ </svg>
407
+ <p class="image-ph-label">PLACEHOLDER: {{image description}}</p>
408
+ </div>
409
+ </div>
410
+ </main>
411
+ </div>
412
+ ```
413
+
414
+ ### image-placeholder (full-bleed — for slide--image type when image not yet provided)
415
+
416
+ ```html
417
+ <div class="slide slide--image">
418
+ <div class="image-ph-bleed" aria-label="Image placeholder: {{image description}}">
419
+ [ PLACEHOLDER: {{image description}} ]
420
+ </div>
421
+ <div class="image-overlay" aria-hidden="true"></div>
422
+ <div class="image-caption slide-up delay-1">
423
+ <p class="display">{{Short headline}}</p>
424
+ <p class="description">{{Supporting line}}</p>
425
+ </div>
426
+ </div>
427
+ ```
428
+
429
+ ### markdown-content (renders .md source via marked.js)
430
+
431
+ ```html
432
+ <!DOCTYPE html>
433
+ <html lang="en">
434
+ <head>
435
+ <meta charset="UTF-8">
436
+ <title>{{Slide Title}}</title>
437
+ <link rel="stylesheet" href="../css/base.css">
438
+ <link rel="stylesheet" href="../css/theme.css">
439
+ <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
440
+ <style>
441
+ .md-body h1, .md-body h2 { font-family: var(--font-head); color: var(--accent); margin-bottom: var(--sp-3); }
442
+ .md-body h1 { font-size: var(--t-title); }
443
+ .md-body h2 { font-size: var(--t-sub); }
444
+ .md-body p { font-size: var(--t-body); color: var(--text); margin-bottom: var(--sp-2); }
445
+ .md-body ul, .md-body ol { padding-left: var(--sp-4); font-size: var(--t-body); }
446
+ .md-body li { margin-bottom: var(--sp-1); }
447
+ .md-body code { font-family: var(--font-mono); font-size: var(--t-code); background: var(--code-bg); padding: 0.1em 0.4em; border-radius: var(--r-sm); }
448
+ .md-body blockquote { border-left: 3px solid var(--accent); padding-left: var(--sp-3); color: var(--muted); font-style: italic; }
449
+ .md-body strong { color: var(--accent); font-weight: 700; }
450
+ </style>
451
+ </head>
452
+ <body>
453
+ <div class="slide slide--content">
454
+ <header class="slide-header">
455
+ <h2 class="title fade-in">{{Heading}}</h2>
456
+ </header>
457
+ <main class="slide-content">
458
+ <div class="md-body slide-up delay-1" data-md>
459
+ {{Paste raw Markdown content here — agent fills this from source files}}
460
+ </div>
461
+ </main>
462
+ </div>
463
+ <aside class="speaker-notes">{{Speaker notes}}</aside>
464
+ <script>
465
+ marked.setOptions({ breaks: true, gfm: true });
466
+ document.querySelectorAll('[data-md]').forEach(el => {
467
+ el.innerHTML = marked.parse(el.textContent.trim());
468
+ });
469
+ </script>
470
+ <script src="../js/navbridge.js"></script>
471
+ </body>
472
+ </html>
473
+ ```
474
+
475
+ ---
476
+
477
+ ## Region usage — guidelines, not rules
478
+
479
+ - **Logo / footer rhythm is usually deck-wide, but exceptions are fine.** Pick a posture in Phase 4 (always-on, always-off, or "everywhere except hero/section breaks") and stick to it. Don't sprinkle them onto random slides — that creates noise rather than rhythm.
480
+ - **Header is per-slide.** Use `.display` for hero/section/closing slides, `.title` for content/code/chart/etc. If the slide's *whole point* is the body — a single quote, one giant number, a full-bleed image — omit the header.
481
+ - **Description is optional.** Reach for it when the title needs a "why this matters" line. Skip it when the title already lands.
482
+ - **Footer carries facts about the slide, not the message of the slide.** Sources, page numbers, links, attribution — yes. Extra bullets or claims — no.
483
+ - **The four classes are how you stay consistent. The *content* of each region is up to the slide.** Two slides using `.slide-content--grid-2` can look completely different — different visuals, different rhythm, different focus. Same skeleton, different shape.
484
+
485
+ ---
486
+
487
+ ## Motion animation patterns
488
+
489
+ Use these `<script type="module">` blocks at the bottom of a slide's `<body>`. They replace or augment the CSS animation classes from `base.css`.
490
+
491
+ ### Staggered entrance (lists, bullets, cards)
492
+ ```html
493
+ <script type="module">
494
+ import { animate, stagger } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
495
+ animate(
496
+ '.bullets li, .agenda-list li, .stat-item, .tl-item',
497
+ { opacity: [0, 1], y: [16, 0] },
498
+ { delay: stagger(0.12), duration: 0.45, easing: [0.22, 1, 0.36, 1] }
499
+ );
500
+ </script>
501
+ ```
502
+
503
+ ### Title + description sequence
504
+ ```html
505
+ <script type="module">
506
+ import { timeline } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
507
+ timeline([
508
+ ['.display', { opacity: [0, 1], y: [-14, 0] }, { duration: 0.5 }],
509
+ ['.description', { opacity: [0, 1] }, { duration: 0.35, at: '+0.1' }],
510
+ ['.meta', { opacity: [0, 1] }, { duration: 0.3, at: '+0.08' }],
511
+ ]);
512
+ </script>
513
+ ```
514
+
515
+ ### Animated counter (stat / KPI slides)
516
+ ```html
517
+ <script type="module">
518
+ import { animate } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
519
+ // Use the slide-slug-scoped ID from the stats template (e.g. 'results-kpi-1')
520
+ animate(0, {{TARGET_NUMBER}}, {
521
+ duration: 1.4,
522
+ easing: [0.22, 1, 0.36, 1],
523
+ onUpdate(v) {
524
+ document.getElementById('{{slide-slug}}-kpi-1').textContent =
525
+ Math.round(v).toLocaleString();
526
+ }
527
+ });
528
+ </script>
529
+ ```
530
+
531
+ ### Bar chart fill animation (augments CSS .bar::after)
532
+ ```html
533
+ <script type="module">
534
+ import { animate, stagger } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
535
+ document.querySelectorAll('.bar').forEach((bar, i) => {
536
+ const target = bar.style.getPropertyValue('--pct');
537
+ bar.style.setProperty('--pct', '0%');
538
+ setTimeout(() => {
539
+ animate(0, parseFloat(target), {
540
+ duration: 0.8,
541
+ delay: i * 0.1,
542
+ easing: [0.22, 1, 0.36, 1],
543
+ onUpdate(v) { bar.style.setProperty('--pct', v + '%'); }
544
+ });
545
+ }, 200);
546
+ });
547
+ </script>
548
+ ```
549
+
550
+ ### In-view reveal (for timelines / diagrams that still fit on one slide)
551
+ ```html
552
+ <script type="module">
553
+ import { animate, inView } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
554
+ inView('.tl-item', ({ target }) => {
555
+ animate(target, { opacity: [0, 1], x: [-20, 0] }, { duration: 0.4 });
556
+ }, { margin: '-10% 0px' });
557
+ </script>
558
+ ```
559
+
560
+ **Rules:**
561
+ - Motion loads from ESM CDN — always `type="module"`.
562
+ - Prefer `timeline()` for multi-step sequences; `animate()` + `stagger()` for lists.
563
+ - Don't combine Motion entrance animations with CSS `.fade-in`/`.slide-up` on the same element — pick one.
564
+ - Respect `prefers-reduced-motion` — wrap Motion calls in `if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches)`.
565
+
566
+ ---
567
+
568
+
569
+ ## `css/base.css` source
570
+
571
+ **Copy `scripts/base.css` verbatim to `css/base.css` at the deck root.** Do not paraphrase, do not regenerate from memory — `scripts/base.css` is the canonical source of truth for layout primitives, type scale, slide-type rules, component classes, animations, and the print/PDF media query.
572
+
573
+ Override the override surface in `css/theme.css` only — colors, fonts, and the type-scale `clamp()` ranges if the design calls for it. Never edit `css/base.css` after the copy.
574
+
575
+ **The override surface (defined in `:root` in `scripts/base.css`):**
576
+
577
+ ```css
578
+ /* css/theme.css overrides any of these; do not redefine layout rules. */
579
+ :root {
580
+ /* Colors */
581
+ --bg --surface --border --accent --text --muted --code-bg --code-text
582
+ /* Fonts */
583
+ --font-head --font-body --font-mono
584
+ /* Type scale (clamp ranges) */
585
+ --t-display --t-title --t-sub --t-body --t-small --t-code
586
+ /* Spacing (8px grid) */
587
+ --sp-1 --sp-2 --sp-3 --sp-4 --sp-6 --sp-8 --pad
588
+ /* Radius */
589
+ --r-sm --r-md --r-lg
590
+ /* Motion */
591
+ --fast --base --slow --ease
592
+ }
593
+ ```
594
+
595
+ **What `scripts/base.css` provides (do not duplicate elsewhere):**
596
+ - Reset + slide canvas (1280×720, `overflow: hidden`)
597
+ - Canonical 4-region skeleton (`.slide-logo`, `.slide-header`, `.slide-content`, `.slide-footer`)
598
+ - Smart-flex modifiers (`--center`, `--middle`, `--row`, `--grid-2`, `--grid-3`)
599
+ - Typography classes (`.display`, `.title`, `.description`, `.subtitle`, `.eyebrow`, `.meta`)
600
+ - Slide-type rules (`.slide--title`, `.slide--section`, `.slide--quote`, `.slide--closing`, `.slide--stats`, `.slide--agenda`, `.slide--image`)
601
+ - Component classes (`.bullets`, `.agenda-list`, `.code-block`, `.bar-chart`, `.timeline`, `.comparison`, `.stat-grid`, `.image-ph`, `.image-ph-bleed`, `.image-overlay`, `.image-caption`)
602
+ - Animations (`.fade-in`, `.slide-up`, `.pop-in`, `.delay-1` … `.delay-4`) + `prefers-reduced-motion`
603
+ - `@media print` for 1280×720 PDF export
604
+
605
+ If a class is missing for a one-off layout, add it to the slide's local `<style>` — do not edit `scripts/base.css` or `css/base.css` after the copy.
606
+
607
+ ---
608
+
609
+ ## `index.html` — navigation controller
610
+
611
+ **Always copy from `scripts/base.html`** — it is the canonical source of truth. The condensed reference below shows the key patterns; use the full template for actual implementation.
612
+
613
+ ### Slide manifest format
614
+
615
+ ```javascript
616
+ const slides = [
617
+ // Each entry: { path, hidden, name }
618
+ // path – slide HTML file relative to index.html
619
+ // name – unique slug for URL hash (e.g. 'problem' → #problem)
620
+ // Do NOT use numbers — playback order is controlled by this array.
621
+ // hidden – true = skip during playback AND hide from overview grid
622
+ { path: 'slides/title.html', hidden: false, name: 'title' },
623
+ { path: 'slides/problem.html', hidden: false, name: 'problem' },
624
+ { path: 'slides/solution.html', hidden: false, name: 'solution' },
625
+ { path: 'slides/closing.html', hidden: false, name: 'closing' },
626
+ ];
627
+ ```
628
+
629
+ Key rules for the manifest:
630
+ - **Filename numbers do NOT control order** — the array position does. Files can be named `slides/title.html` without a numeric prefix.
631
+ - **`name` must be unique** across all visible (non-hidden) slides.
632
+ - **`hidden: true`** skips the slide during playback and hides it from the overview grid, but keeps the file in the deck (useful for draft slides or extended-edition content).
633
+ - **Name-based hash navigation**: `#problem` jumps to the slide where `name === 'problem'`. Legacy numeric hashes (`#5`) still work for backwards compatibility.
634
+
635
+ ### Navbridge integration
636
+
637
+ The parent `index.html` uses a **single `handleKey()` function** as the sole navigation handler:
638
+
639
+ - When the **parent window** has focus → `document.addEventListener('keydown', handleKey, true)` fires directly. Step-aware nav keys (`→`, `↓`, Space, `←`, `↑`) are first posted into the active iframe as `{ type: 'octocode-slides:key', key }`, so `animation.js` can reveal or hide a step before slide navigation happens.
640
+ - When the **iframe** has focus (user clicked inside a slide) → `js/navbridge.js` inside the slide posts `{ type: 'octocode-slides:nav', key }` only after the slide has no step left to consume in that direction.
641
+ - The parent's message listener calls `handleKey({ key, passthrough: true })`; `passthrough:true` means the key already passed through the active iframe and should now advance or retreat the deck.
642
+
643
+ Do NOT attach a second `keydown` listener to the iframe — that would double-fire and advance two slides per key press.
644
+
645
+ ```javascript
646
+ window.addEventListener('message', function (event) {
647
+ var data = event.data;
648
+ if (!data || typeof data !== 'object') return;
649
+ if (data.type === 'octocode-slides:nav' && data.key) {
650
+ handleKey({ key: data.key, passthrough: true, preventDefault: function () {} });
651
+ } else if (data.type === 'octocode-slides:activity') {
652
+ showHud();
653
+ } else if (data.type === 'octocode-slides:presenter-goto') {
654
+ go(clampIndex(data.index));
655
+ }
656
+ });
657
+ ```
658
+
659
+ ### HUD (keyboard hint pill)
660
+
661
+ The HUD fades in on mouse move / key press, fades out after 1.6 s:
662
+
663
+ ```javascript
664
+ let hudTimer;
665
+ function showHud() {
666
+ hud.classList.add('show');
667
+ clearTimeout(hudTimer);
668
+ hudTimer = setTimeout(() => hud.classList.remove('show'), 1600);
669
+ }
670
+ window.addEventListener('mousemove', showHud);
671
+ ```
672
+
673
+ **After generating all slides:** fill `const slides = [...]` with every `{ path, hidden, name }` entry in presentation order.