Convert any content into a stunning Apple Keynote-style HTML presentation. Takes markdown, text descriptions, or structured data and generates a single self-contained .html file with cinematic animations, glassmorphism, and premium design. Inspired by ChronicleHQ.
Scanned 5/27/2026
Install via CLI
openskills install sacredvoid/presentation-chef---
name: presentation-chef
description: "Convert any content into a stunning Apple Keynote-style HTML presentation. Takes markdown, text descriptions, or structured data and generates a single self-contained .html file with cinematic animations, glassmorphism, and premium design. Inspired by ChronicleHQ."
---
# Presentation Chef
Generate cinematic, Apple Keynote-style HTML presentations from any content. Single self-contained .html file with zero dependencies.
<HARD-GATE>
You MUST gather all inputs interactively using AskUserQuestion before generating any HTML. Do NOT skip the input gathering phase. Do NOT generate a presentation without knowing the content, theme, and design preferences.
</HARD-GATE>
## Process
Follow these steps exactly:
### Pre-Step: Initialize Task Pipeline
Before starting Step 1, create tasks to give the user visibility into the full workflow:
```
TaskCreate:
subject: "Gather content source"
description: "Ask the user for their presentation content — paste, file, or topic"
activeForm: "Gathering content source"
TaskCreate:
subject: "Select theme & customize design"
description: "Analyze content, recommend a theme, and gather design customization preferences"
activeForm: "Selecting theme and design preferences"
TaskCreate:
subject: "Plan slide structure"
description: "Map content to slide types and confirm the structure with user"
activeForm: "Planning slide structure"
TaskCreate:
subject: "Build presentation"
description: "Generate the complete HTML presentation with slides, navigation, and effects"
activeForm: "Building presentation"
```
Update each task to `in_progress` when starting that phase, and `completed` when done:
- **"Gather content source"** → covers Step 1
- **"Select theme & customize design"** → covers Steps 2-3
- **"Plan slide structure"** → covers Step 4
- **"Build presentation"** → covers Steps 5-6
### Step 1: Gather Content
**TaskUpdate:** Mark "Gather content source" → `in_progress`
Ask the user for their content source using AskUserQuestion:
```
AskUserQuestion:
question: "What content should I turn into a presentation?"
header: "Content"
options:
- label: "Paste or describe it"
description: "I'll type/paste content or describe what I want in the presentation"
- label: "Read from a file"
description: "I have a markdown file, text file, or other document to convert"
- label: "Generate from topic"
description: "Give me a topic and I'll create both content and design"
multiSelect: false
```
If the user selects "Read from a file", ask for the file path and use the Read tool to get the content.
If the user selects "Generate from topic", ask what the topic is and what audience/purpose it serves.
If the user pastes content, analyze it to understand its structure.
**TaskUpdate:** Mark "Gather content source" → `completed`
### Step 2: Analyze Content & Suggest Theme
**TaskUpdate:** Mark "Select theme & customize design" → `in_progress`
After receiving content, analyze it to determine:
- **Content type**: pitch deck, portfolio, product launch, educational, report, personal story, etc.
- **Tone**: professional, creative, technical, casual, dramatic
- **Slide count**: how many slides the content naturally breaks into
Then present theme options interactively:
```
AskUserQuestion:
question: "What visual theme should the presentation use?"
header: "Theme"
options:
- label: "Dark Cinematic (Recommended)"
description: "[AI reasoning why this fits the content]. Pure black bg, ambient orbs, glassmorphism cards, Apple blue/purple accents"
markdown: |
DARK CINEMATIC
──────────────────────────────
Background: #000000 (pure black)
Text: #ffffff / #86868b
Accent 1: #0071e3 (Apple blue)
Accent 2: #a855f7 (purple)
Warm: #ff6723 (orange)
Success: #30d158 (green)
Effects: Ambient orbs, grain overlay
Glassmorphism cards
Gradient text on headlines
Font: SF Pro / system sans-serif
Animations: Cinematic (900ms, spring easing)
- label: "Light Minimal"
description: "Clean, Chronicle-style white canvas with bold typography and single accent color"
markdown: |
LIGHT MINIMAL
──────────────────────────────
Background: #ffffff / #fafafa
Text: #1d1d1f / #86868b
Accent: #0071e3 (or content-matched)
Border: #e5e5e5
Effects: Subtle shadows, no orbs
Clean card borders
Understated elegance
Font: Geist / clean geometric sans
Animations: Smooth (600ms, ease-out)
- label: "Warm Editorial"
description: "Magazine-style warmth with serif typography and rich earth tones"
markdown: |
WARM EDITORIAL
──────────────────────────────
Background: #1a1210 / #f5efe8
Text: #f5efe8 / #a89585
Accent: #e8734a (coral)
Secondary: #c4956a (warm gold)
Effects: Warm ambient glow
Paper-like texture
Editorial layouts
Font: Playfair Display + Source Sans
Animations: Elegant (800ms, smooth)
- label: "Neon Cyberpunk"
description: "High-energy tech aesthetic with neon accents on deep dark backgrounds"
markdown: |
NEON CYBERPUNK
──────────────────────────────
Background: #0a0a1a / #0d1117
Text: #e0e0ff / #6b7280
Accent 1: #00f0ff (cyan)
Accent 2: #ff00aa (magenta)
Glow: #7c3aed (purple)
Effects: Neon glow borders
Scanline overlay
Matrix-style grid bg
Font: JetBrains Mono + Space Grotesk
Animations: Snappy (500ms, sharp easing)
multiSelect: false
```
**IMPORTANT**: Customize the recommendation text based on the actual content analyzed. Don't use generic descriptions. For example: "Since this is a startup pitch, Dark Cinematic will make your numbers feel impactful and your product feel premium."
### Step 3: Customize Design
Ask about specific design preferences:
```
AskUserQuestion:
question: "Any design customizations?"
header: "Customize"
options:
- label: "Use defaults"
description: "The theme preset looks great as-is, no changes needed"
- label: "Custom accent color"
description: "I want to use a specific brand color as the primary accent"
- label: "Custom fonts"
description: "I want specific fonts (e.g., Google Fonts or system fonts)"
- label: "Multiple customizations"
description: "I have specific requirements for colors, fonts, or effects"
multiSelect: false
```
If the user wants customizations, ask follow-up questions one at a time about each customization.
**TaskUpdate:** Mark "Select theme & customize design" → `completed`
### Step 4: Map Content to Slides
**TaskUpdate:** Mark "Plan slide structure" → `in_progress`
Analyze the content and map it to the appropriate slide types. Present the slide plan:
```
AskUserQuestion:
question: "Here's my proposed slide structure. Does this look right?"
header: "Structure"
options:
- label: "Looks perfect"
description: "Generate the presentation with this structure"
- label: "Adjust order"
description: "I want to reorder some slides"
- label: "Add/remove slides"
description: "I want to add or remove specific slides"
- label: "Different approach"
description: "I want a different overall structure"
multiSelect: false
```
Before asking, present the slide plan as a numbered list in your message text. Example:
```
Slide 1: Hero — "Company Name" + tagline
Slide 2: Stats — 3 key metrics with count-up
Slide 3: Chapter — "The Problem"
Slide 4: Content Card — Problem description
...
```
**TaskUpdate:** Mark "Plan slide structure" → `completed`
### Step 5: Ask Output Location
```
AskUserQuestion:
question: "Where should I save the presentation?"
header: "Output"
options:
- label: "Current directory"
description: "Save as presentation.html in the current working directory"
- label: "Custom path"
description: "I'll specify the exact file path and name"
- label: "Desktop"
description: "Save to ~/Desktop/ for easy access"
multiSelect: false
```
### Step 6: Generate the Presentation (Batched with Progress Tracking)
When entering this step, mark the "Build presentation" high-level task as `in_progress`.
#### 6a: Create Build Sub-Tasks
Based on the confirmed slide plan, create granular build tasks. Group slides into batches of 3-4:
```
TaskCreate:
subject: "Set up HTML structure & CSS theme"
description: "Create HTML skeleton, CSS reset, theme variables, effects (grain/orbs), slide system, reveal animations, typography, responsive breakpoints, print styles"
activeForm: "Setting up document structure and CSS"
# For each batch of 3-4 slides, create a task:
TaskCreate:
subject: "Build slides [X]-[Y]: [slide types]"
description: "Generate HTML for: Slide X ([type] — [title]), Slide X+1 ([type] — [title]), ..."
activeForm: "Building slides [X] through [Y]"
# Example for a 12-slide presentation:
# "Build slides 1-4: Hero, Stats, Chapter, Content Card"
# "Build slides 5-8: Feature Grid, Timeline, Comparison, Quote"
# "Build slides 9-12: Data, Split Screen, List, CTA"
TaskCreate:
subject: "Add navigation, controls & speaker notes"
description: "Progress bar, nav dots, keyboard hints, speaker notes sidebar with talking points for every slide, controls bar"
activeForm: "Adding navigation and speaker notes"
TaskCreate:
subject: "Wire up JavaScript engine"
description: "Slide navigation, reveal animations, count-up, data bars, keyboard/mouse/touch handlers, parallax, loading screen, notes toggle, PDF export"
activeForm: "Wiring up JavaScript engine"
TaskCreate:
subject: "Run quality checklist & save file"
description: "Verify all 23 quality checks pass, then write the final .html file"
activeForm: "Running quality checklist and saving"
```
#### 6b: Execute Build Pipeline
Work through each task sequentially. For **every** task:
1. `TaskUpdate` → `in_progress` before you start working on it
2. Generate that section of the presentation
3. `TaskUpdate` → `completed` when done
4. Move to the next task
**Slide batch details:** When building a slide batch, generate the HTML for all slides in that batch. Each slide must include:
- The slide container `<div>` with correct `data-slide` index
- Background variant class
- Ambient orbs (if dark theme)
- All content elements wrapped in `reveal-element` with sequential delays
- Proper slide type pattern from the Design System Reference below
#### 6c: Assemble & Write
After all build tasks are complete, assemble the full HTML document in this order:
1. Document structure (head, meta, `<style>` open)
2. All CSS (reset, theme, effects, slides, typography, responsive, print)
3. `<body>` open, loading screen, grain overlay (if dark theme)
4. Progress bar, nav dots, keyboard hint
5. Speaker notes sidebar (all slides)
6. Controls bar
7. `<div class="slide-container">` with **all slide batches** in order
8. `<script>` with full JS engine
9. Close body/html
Use the **Write** tool to save the assembled HTML to the confirmed output path.
Mark the "Build presentation" high-level task as `completed`, then mark "Run quality checklist & save file" as `completed`.
Tell the user the file path and suggest opening it in a browser.
---
## Design System Reference
When generating the HTML presentation, follow these specifications exactly.
### Document Structure
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[Presentation Title]</title>
<style>/* ALL CSS INLINE */</style>
</head>
<body>
<!-- Loading Screen -->
<!-- Grain Overlay (if dark theme) -->
<!-- Progress Bar -->
<!-- Navigation Dots -->
<!-- Keyboard Hint -->
<!-- Speaker Notes Sidebar -->
<!-- Controls Bar (Notes T, PDF P) -->
<!-- Slide Container -->
<script>/* ALL JS INLINE */</script>
</body>
</html>
```
Everything must be inline. Zero external dependencies. No CDN links. No Google Fonts links (use system font stacks or embed @font-face with base64 only if absolutely necessary for a specific requested font).
### CSS Foundation
#### Reset & Base
```css
*, *::before, *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
:root {
/* Theme tokens - set these per theme */
--bg-primary: #000000;
--bg-secondary: #0a1628;
--text-primary: #ffffff;
--text-secondary: #86868b;
--text-muted: #6e6e73;
--accent-1: #0071e3;
--accent-1-light: #2997ff;
--accent-2-start: #6e3aff;
--accent-2-end: #a855f7;
--accent-warm: #ff6723;
--accent-pink: #ff375f;
--accent-green: #30d158;
--accent-teal: #64d2ff;
--gray-100: #f5f5f7;
--gray-200: #d2d2d7;
--gray-400: #86868b;
--gray-600: #6e6e73;
--gray-800: #1d1d1f;
--card-bg: rgba(255, 255, 255, 0.04);
--card-border: rgba(255, 255, 255, 0.08);
--card-blur: 40px;
--transition-smooth: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--transition-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
--transition-cinematic: cubic-bezier(0.16, 1, 0.3, 1);
--slide-duration: 900ms;
--reveal-stagger: 150ms;
}
html { scroll-behavior: auto; overflow: hidden; background: var(--bg-primary); }
body {
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Inter', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
overflow: hidden;
height: 100vh;
width: 100vw;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
```
#### Light Theme Override
For light themes, override:
```css
:root {
--bg-primary: #ffffff;
--bg-secondary: #fafafa;
--text-primary: #1d1d1f;
--text-secondary: #86868b;
--text-muted: #aeaeb2;
--card-bg: rgba(0, 0, 0, 0.03);
--card-border: rgba(0, 0, 0, 0.08);
/* Adjust accent colors for contrast on light */
}
```
### Effects
#### Grain Overlay (dark themes only)
```css
.grain-overlay {
position: fixed;
top: -50%; left: -50%;
width: 200%; height: 200%;
pointer-events: none;
z-index: 9998;
opacity: 0.035;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
animation: grainShift 0.5s steps(3) infinite;
}
@keyframes grainShift {
0% { transform: translate(0, 0); }
33% { transform: translate(-2px, 1px); }
66% { transform: translate(1px, -1px); }
100% { transform: translate(0, 0); }
}
```
#### Ambient Orbs (dark themes)
```css
.ambient-orb {
position: absolute;
border-radius: 50%;
filter: blur(120px);
opacity: 0.15;
pointer-events: none;
animation: orbFloat 12s ease-in-out infinite alternate;
}
@keyframes orbFloat {
0% { transform: translate(0, 0) scale(1); }
100% { transform: translate(30px, -20px) scale(1.1); }
}
```
Create 2-3 orbs per slide with different colors matching the theme. Vary sizes (400-600px), positions, animation delays.
#### Hero Glow Ring
```css
.hero-glow {
position: absolute;
width: 600px; height: 600px;
border-radius: 50%;
background: radial-gradient(circle, rgba(accent1, 0.08) 0%, rgba(accent2, 0.04) 40%, transparent 70%);
pointer-events: none;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
animation: glowPulse 6s ease-in-out infinite alternate;
}
```
### Slide System
#### Container & Transitions
```css
.slide-container {
position: fixed; inset: 0;
width: 100vw; height: 100vh;
}
.slide {
position: absolute; inset: 0;
width: 100%; height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
opacity: 0;
visibility: hidden;
transform: scale(0.95) translateY(30px);
transition: opacity var(--slide-duration) var(--transition-cinematic),
transform var(--slide-duration) var(--transition-cinematic),
visibility 0s linear var(--slide-duration);
will-change: opacity, transform;
overflow-y: auto;
overflow-x: hidden;
}
.slide.active {
opacity: 1;
visibility: visible;
transform: scale(1) translateY(0);
transition: opacity var(--slide-duration) var(--transition-cinematic),
transform var(--slide-duration) var(--transition-cinematic),
visibility 0s linear 0s;
}
.slide.exiting-up {
opacity: 0; visibility: hidden;
transform: scale(1.05) translateY(-50px);
}
.slide.exiting-down {
opacity: 0; visibility: hidden;
transform: scale(0.9) translateY(50px);
}
```
#### Slide Background Variants
For dark themes, create gradient backgrounds per slide:
```css
.slide--dark { background: var(--bg-primary); }
.slide--gradient-blue { background: linear-gradient(145deg, #000 0%, #0a1628 40%, #0d2137 70%, #0a0a2e 100%); }
.slide--gradient-purple { background: linear-gradient(145deg, #000 0%, #1a0a2e 40%, #2d1b4e 60%, #0a0a2e 100%); }
.slide--gradient-warm { background: linear-gradient(145deg, #000 0%, #2e1a0a 40%, #3d1f0f 60%, #1a0a00 100%); }
```
For light themes, use subtle gradients:
```css
.slide--light { background: var(--bg-primary); }
.slide--gradient-soft { background: linear-gradient(145deg, #fff 0%, #f8f9fa 50%, #f0f0f5 100%); }
```
### Reveal Animations
```css
.reveal-element {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.8s var(--transition-cinematic),
transform 0.8s var(--transition-cinematic);
}
.reveal-element.revealed {
opacity: 1; transform: translateY(0);
}
/* Staggered delays */
.reveal-element[data-delay="1"] { transition-delay: 0.15s; }
.reveal-element[data-delay="2"] { transition-delay: 0.3s; }
.reveal-element[data-delay="3"] { transition-delay: 0.45s; }
/* Continue up to data-delay="12" at 0.15s increments */
```
Wrap every content element in a `<div class="reveal-element" data-delay="N">` with sequential delay values per slide.
### Slide Types — HTML Patterns
#### 1. Hero Slide
```html
<div class="slide slide--dark active" data-slide="0">
<div class="hero-glow"></div>
<div class="reveal-element" data-delay="0">
<h1 class="hero-name">[Title]</h1>
</div>
<div class="reveal-element" data-delay="2">
<p class="hero-subtitle">[Subtitle with separator spans]</p>
</div>
<div class="reveal-element" data-delay="4">
<div class="divider-line"></div>
</div>
<div class="reveal-element" data-delay="5">
<p class="hero-location">[Location or tagline]</p>
</div>
</div>
```
Typography:
```css
.hero-name {
font-size: clamp(48px, 10vw, 120px);
font-weight: 700;
letter-spacing: -0.03em;
line-height: 1;
text-align: center;
background: linear-gradient(135deg, var(--text-primary) 0%, var(--gray-200) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: clamp(18px, 3vw, 32px);
font-weight: 400;
color: var(--text-secondary);
text-align: center;
margin-top: 24px;
letter-spacing: 0.02em;
}
```
#### 2. Stats Slide
```html
<div class="slide slide--gradient-blue" data-slide="N">
<div class="ambient-orb ambient-orb--accent1"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label text]</p>
</div>
<div class="stats-grid">
<div class="stat-item reveal-element" data-delay="1">
<div class="stat-number mega-number--accent1"><span class="count-up" data-target="[N]">0</span>[suffix]</div>
<div class="stat-label">[Label]</div>
</div>
<!-- Repeat for each stat (2-4 stats ideal) -->
</div>
</div>
```
Stats grid: `grid-template-columns: repeat(2, 1fr)`, gap `48px 64px`, max-width `900px`.
Mega numbers: `font-size: clamp(48px, 8vw, 96px)`, weight 800, gradient text with matching glow.
Count-up JS animates from 0 to target with ease-out cubic easing over 1200ms.
#### 3. Chapter Divider Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="ambient-orb"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Small label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Big title with gradient text]</h2>
</div>
<div class="reveal-element" data-delay="2">
<p class="section-subtitle">[Supporting text, max 2 lines]</p>
</div>
</div>
```
Section title: `font-size: clamp(36px, 7vw, 96px)`, weight 700, tight tracking.
#### 4. Content Card Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="ambient-orb"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Context label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title" style="font-size: clamp(28px, 5vw, 56px);">[Title]</h2>
</div>
<div class="experience-card reveal-element" data-delay="2">
<div class="card-title">[Title]</div>
<div class="card-subtitle">[Subtitle in accent color]</div>
<div class="card-meta">[Date/location/metadata]</div>
<div class="card-body">
<ul>
<li>[Point 1]</li>
<li>[Point 2]</li>
</ul>
</div>
</div>
</div>
```
Card: `background: var(--card-bg)`, `backdrop-filter: blur(var(--card-blur))`, `border: 1px solid var(--card-border)`, `border-radius: 24px`, padding `clamp(32px, 4vw, 56px)`.
Top highlight: `::before` pseudo-element with gradient line.
Bullet points: custom dot (6px circle in accent color) via `::before`.
#### 5. Feature Grid Slide
```html
<div class="slide slide--gradient-deep" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="tech-grid">
<div class="tech-chip tech-chip--[category] reveal-element" data-delay="2">
[Item name]
<span class="tech-category-label">[Category]</span>
</div>
<!-- Repeat -->
</div>
</div>
```
Grid: `repeat(auto-fit, minmax(120px, 1fr))`, gap 16px. Chips have hover lift + scale, radial gradient glow on hover.
#### 6. Timeline Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="timeline">
<div class="timeline-item reveal-element" data-delay="2">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-date">[Date]</div>
<div class="timeline-title">[Title]</div>
<div class="timeline-desc">[Description]</div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
```
Timeline: vertical line (2px, accent gradient) with circular markers (12px). Content cards to the right. Alternating layout on desktop.
```css
.timeline {
position: relative;
max-width: 800px;
width: 100%;
margin-top: 32px;
padding-left: 40px;
}
.timeline::before {
content: '';
position: absolute;
left: 16px;
top: 0;
bottom: 0;
width: 2px;
background: linear-gradient(to bottom, var(--accent-1), var(--accent-2-end));
}
.timeline-item {
position: relative;
margin-bottom: 32px;
padding-left: 24px;
}
.timeline-marker {
position: absolute;
left: -32px;
top: 6px;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-1);
border: 2px solid var(--bg-primary);
box-shadow: 0 0 0 4px rgba(var(--accent-1-rgb), 0.2);
}
```
#### 7. Comparison Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="comparison-grid">
<div class="comparison-col reveal-element" data-delay="2">
<h3 class="comparison-heading">[Side A]</h3>
<ul class="comparison-list">
<li>[Point]</li>
</ul>
</div>
<div class="comparison-divider reveal-element" data-delay="3"></div>
<div class="comparison-col reveal-element" data-delay="4">
<h3 class="comparison-heading">[Side B]</h3>
<ul class="comparison-list">
<li>[Point]</li>
</ul>
</div>
</div>
</div>
```
Two-column grid with vertical divider. Cards have frosted glass background.
#### 8. Quote Slide
```html
<div class="slide slide--dark" data-slide="N">
<div class="hero-glow" style="opacity: 0.3;"></div>
<div class="reveal-element" data-delay="0">
<blockquote class="quote-text">"[Quote text]"</blockquote>
</div>
<div class="reveal-element" data-delay="2">
<p class="quote-attribution">— [Name], [Title]</p>
</div>
</div>
```
Quote: `font-size: clamp(24px, 4vw, 48px)`, weight 400, italic, line-height 1.4. Center aligned with max-width 800px.
#### 9. Image Slide
```html
<div class="slide slide--image" data-slide="N" style="background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.8)), url('[base64 or path]') center/cover;">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Overlay text]</h2>
</div>
</div>
```
Note: For truly self-contained files, images should be base64-encoded inline if the user provides them. Otherwise use descriptive gradient backgrounds as visual stand-ins.
#### 10. Data Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="data-bars">
<div class="data-bar-item reveal-element" data-delay="2">
<div class="data-bar-label">[Label]</div>
<div class="data-bar-track">
<div class="data-bar-fill" style="--bar-width: [N]%;" data-value="[N]%"></div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
```
CSS-only animated bars. Fill animates width from 0 to `--bar-width` on reveal. Gradient fill matching theme accent.
```css
.data-bar-track {
height: 8px;
background: var(--card-bg);
border-radius: 4px;
overflow: hidden;
flex: 1;
}
.data-bar-fill {
height: 100%;
width: 0;
background: linear-gradient(90deg, var(--accent-1), var(--accent-2-end));
border-radius: 4px;
transition: width 1.2s var(--transition-cinematic);
}
.data-bar-fill.revealed { width: var(--bar-width); }
```
#### 11. Split Screen Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="split-layout">
<div class="split-text reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
<h2 class="section-title" style="text-align: left; font-size: clamp(28px, 5vw, 56px);">[Title]</h2>
<p class="section-subtitle" style="text-align: left;">[Description]</p>
</div>
<div class="split-visual reveal-element" data-delay="2">
<!-- Visual content: card, graphic, or placeholder -->
</div>
</div>
</div>
```
```css
.split-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 64px;
max-width: 1100px;
width: 100%;
align-items: center;
}
@media (max-width: 768px) {
.split-layout { grid-template-columns: 1fr; gap: 32px; }
}
```
#### 12. List / Achievements Slide
```html
<div class="slide slide--dark" data-slide="N">
<div class="reveal-element" data-delay="0">
<h2 class="section-title">[Title]</h2>
</div>
<div class="achievements-list">
<div class="achievement-item reveal-element" data-delay="1">
<div class="achievement-icon">[emoji or icon]</div>
<div class="achievement-content">
<div class="achievement-title">[Title]</div>
<div class="achievement-desc">[Description]</div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
```
Icon container: 48x48, rounded 12px, frosted glass bg. Flex row with 20px gap.
#### 13. CTA / Contact Slide
```html
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<div class="available-badge">
<span class="available-pulse"></span>
[Status text]
</div>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[CTA headline]</h2>
</div>
<div class="reveal-element" data-delay="2">
<p class="section-subtitle">[Supporting text]</p>
</div>
<div class="contact-links reveal-element" data-delay="3">
<a href="[url]" class="contact-link contact-link--primary">
<svg>...</svg> [Label]
</a>
<a href="[url]" class="contact-link">
<svg>...</svg> [Label]
</a>
</div>
</div>
```
Pill-shaped links: `border-radius: 100px`, frosted glass bg, hover lift.
Available badge: green pulse animation, pill shape, green tint bg.
### Navigation Components
#### Progress Bar
```css
.progress-bar {
position: fixed; top: 0; left: 0;
height: 2px;
background: linear-gradient(90deg, var(--accent-1), var(--accent-2-end));
z-index: 200;
transition: width 0.6s var(--transition-cinematic);
box-shadow: 0 0 10px rgba(accent1, 0.5);
}
```
#### Navigation Dots
Fixed right side, vertical, 8px circles. Active dot: white, scale 1.4, glow shadow. Hover shows label via `::before` content.
#### Keyboard Hint
Fixed bottom center. Shows arrow keys and space. Hidden class after first interaction. Bounce arrow animation.
### JavaScript Engine
The JS engine handles:
1. **Slide navigation** — `goToSlide(index, direction)` with transition locking
2. **Reveal animations** — trigger `.revealed` class on active slide elements
3. **Count-up animations** — `requestAnimationFrame` with ease-out cubic
4. **Data bar animations** — trigger fill width on reveal
5. **Dot/progress updates** — sync with current slide
6. **Keyboard navigation** — arrows, space, page up/down, home/end, escape, T (notes), P (pdf)
7. **Mouse wheel** — debounced with accumulator (threshold 50, debounce 80ms)
8. **Touch** — swipe detection with 50px threshold
9. **Parallax** — mousemove on hero glow and ambient orbs
10. **Loading screen** — fade out after 600ms on window load
11. **Speaker notes toggle** — `toggleNotes()` opens/closes sidebar, `updateNotes()` syncs content to current slide
12. **PDF export** — `exportPdf()` snaps all count-up numbers to `data-target` values and data bars to full width before calling `window.print()`, ensuring animated values render correctly in the PDF
Key constants:
```js
const TOTAL_SLIDES = [number];
const TRANSITION_DURATION = 900;
const DEBOUNCE_MS = 80;
const COUNT_DURATION = 1200;
const WHEEL_THRESHOLD = 50;
```
Use an IIFE wrapper. No external dependencies. All event listeners with proper passive flags.
### Responsive Breakpoints
- **768px**: Single columns, reduced gaps, hidden dot labels, smaller padding
- **480px**: Further simplified grids, hidden keyboard hints
- **Touch devices**: Disable hover transforms via `@media (hover: none)`
### Speaker Notes Sidebar (Press T)
Every presentation MUST include a speaker notes sidebar. The sidebar:
- Slides in from the left when pressing `T` key or clicking the Notes button
- Frosted glass panel (`rgba(10,10,20,0.92)` bg, `backdrop-filter: blur(30px)`, 340px wide)
- Has a sticky header with "Talking Points" title, close button, and "Slide X of N" label
- Contains a `<div class="note-content" data-note="N">` for each slide with talking points
- Only the `.note-content.active` matching current slide is shown (display block/none)
- When open, the main slide container shifts right and scales down: `transform: translateX(170px) scale(0.88)`
- Progress bar left offset adjusts: `left: 340px`
- Toggle via `body.notes-open` class
**Talking points content**: Write 2-3 paragraphs per slide with:
- **Bold opener** — what to emphasize on this slide
- Key talking points in natural speaking language (not bullet points)
- A `.note-tip` callout for delivery tips (when to pause, make eye contact, etc.)
**Important**: Call `updateNotes()` inside `goToSlide()` when `notesOpen` is true.
### Controls Bar
Fixed bottom-right, two buttons:
```html
<div class="controls-bar">
<button class="control-btn" id="btnNotes">
<svg><!-- document icon --></svg> Notes <span class="key-badge">T</span>
</button>
<button class="control-btn" id="btnPdf">
<svg><!-- download icon --></svg> PDF <span class="key-badge">P</span>
</button>
</div>
```
Buttons: `border-radius: 10px`, frosted glass bg, 12px font. Key badge: 20x20 rounded square.
Hide controls bar on mobile (`@media (max-width: 480px) { .controls-bar { display: none; } }`).
### PDF / Print Export (Press P)
Every presentation MUST include PDF export via `window.print()` with a print stylesheet.
**Critical: Count-up number fix.** Before printing, the `exportPdf()` function MUST:
1. Snap ALL `.count-up` elements to their `data-target` values (set `textContent = getAttribute('data-target')`)
2. Add `.revealed` class to ALL `.data-bar-fill` elements so bars show at full width
3. Close speaker notes if open
4. Call `window.print()` after a 100ms delay to let CSS settle
```js
function exportPdf() {
document.querySelectorAll('.count-up').forEach(function(el) {
el.textContent = el.getAttribute('data-target');
});
document.querySelectorAll('.data-bar-fill').forEach(function(el) {
el.classList.add('revealed');
});
var wasNotesOpen = notesOpen;
if (notesOpen) toggleNotes();
setTimeout(function() {
window.print();
if (wasNotesOpen) setTimeout(toggleNotes, 300);
}, 100);
}
```
**Print stylesheet** (`@media print`):
```css
@media print {
*, *::before, *::after { animation: none !important; transition: none !important; }
html, body { overflow: visible !important; height: auto !important; width: auto !important; }
.loading-screen, .grain-overlay, .progress-bar, .nav-dots,
.keyboard-hint, .controls-bar, .speaker-notes,
.ambient-orb, .hero-glow { display: none !important; }
.slide-container { position: static !important; transform: none !important; }
.slide {
position: relative !important;
opacity: 1 !important; visibility: visible !important; transform: none !important;
width: 100% !important; height: 100vh !important;
page-break-after: always; break-after: page;
page-break-inside: avoid; break-inside: avoid;
overflow: hidden !important;
}
.slide:last-child { page-break-after: auto; }
.reveal-element { opacity: 1 !important; transform: none !important; }
.data-bar-fill { width: var(--bar-width) !important; }
}
@page { size: landscape; margin: 0; }
```
### Typography Scale
| Element | Size | Weight | Tracking |
|---------|------|--------|----------|
| Hero name | clamp(48px, 10vw, 120px) | 700 | -0.03em |
| Section title | clamp(36px, 7vw, 96px) | 700 | -0.03em |
| Mega number | clamp(64px, 15vw, 180px) | 800 | -0.04em |
| Section label | clamp(14px, 1.5vw, 18px) | 600 | 0.15em, uppercase |
| Body text | clamp(14px, 1.8vw, 18px) | 400 | normal |
| Subtitle | clamp(16px, 2.5vw, 28px) | 400 | normal |
| Chip text | clamp(12px, 1.4vw, 15px) | 500 | normal |
### Quality Checklist
Before outputting the final HTML, verify:
- [ ] All CSS is inline in a single `<style>` tag
- [ ] All JS is inline in a single `<script>` tag
- [ ] No external dependencies or CDN links
- [ ] Every content element wrapped in `reveal-element` with sequential delays
- [ ] Navigation dots count matches total slides
- [ ] `TOTAL_SLIDES` constant matches actual slide count
- [ ] Progress bar gradient matches theme
- [ ] All `data-slide` attributes are sequential from 0
- [ ] Count-up elements have `data-target` set
- [ ] Cards have `::before` top highlight gradient
- [ ] Responsive styles handle 768px and 480px breakpoints
- [ ] Touch prevention (`touchmove` preventDefault) is included
- [ ] Loading screen included and auto-hides
- [ ] `will-change` hints on slide elements
- [ ] Grain overlay included (dark themes) or omitted (light themes)
- [ ] Ambient orbs have varied positions, sizes, and animation delays
- [ ] Speaker notes sidebar included with talking points for EVERY slide
- [ ] Each `.note-content[data-note="N"]` matches a slide (0-indexed)
- [ ] Controls bar with Notes (T) and PDF (P) buttons is included
- [ ] `exportPdf()` snaps count-up values to targets before `window.print()`
- [ ] `@media print` stylesheet hides UI chrome and shows all slides as pages
- [ ] `@page { size: landscape; margin: 0; }` is set
- [ ] `updateNotes()` is called in `goToSlide()` when notes are open
- [ ] T key toggles notes, P key triggers PDF export, Escape closes notes
### Common SVG Icons for Contact Links
Include these inline SVGs as needed:
- **Email**: `<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>`
- **LinkedIn**: `<path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.79M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77z"/>`
- **GitHub**: `<path d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z"/>`
- **Twitter/X**: `<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>`
- **Website**: `<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>`
All SVGs use `viewBox="0 0 24 24"` and `fill="currentColor"` at 18x18px.
---
## Theme Definitions
When the user selects a theme, apply these complete variable sets:
### Dark Cinematic
```
--bg-primary: #000000
--text-primary: #ffffff
--text-secondary: #86868b
--accent-1: #0071e3
--accent-1-light: #2997ff
--accent-2-start: #6e3aff
--accent-2-end: #a855f7
--accent-warm: #ff6723
--accent-green: #30d158
--card-bg: rgba(255, 255, 255, 0.04)
--card-border: rgba(255, 255, 255, 0.08)
Font: -apple-system, BlinkMacSystemFont, SF Pro, system
Effects: grain overlay, ambient orbs, hero glow
```
### Light Minimal
```
--bg-primary: #ffffff
--bg-secondary: #fafafa
--text-primary: #1d1d1f
--text-secondary: #86868b
--text-muted: #aeaeb2
--accent-1: #0071e3
--card-bg: rgba(0, 0, 0, 0.03)
--card-border: rgba(0, 0, 0, 0.08)
Font: 'Geist', -apple-system, system
Effects: subtle shadows, no grain, no orbs
```
### Warm Editorial
```
--bg-primary: #1a1210
--text-primary: #f5efe8
--text-secondary: #a89585
--accent-1: #e8734a
--accent-2-end: #c4956a
--card-bg: rgba(245, 239, 232, 0.04)
--card-border: rgba(245, 239, 232, 0.08)
Font: 'Playfair Display', Georgia, serif (headings) + 'Source Sans 3', system (body)
Effects: warm grain, warm orbs, paper texture
```
### Neon Cyberpunk
```
--bg-primary: #0a0a1a
--text-primary: #e0e0ff
--text-secondary: #6b7280
--accent-1: #00f0ff
--accent-2-end: #ff00aa
--accent-warm: #7c3aed
--card-bg: rgba(0, 240, 255, 0.04)
--card-border: rgba(0, 240, 255, 0.12)
Font: 'JetBrains Mono', monospace (headings) + 'Space Grotesk', system (body)
Effects: neon glow borders, scanline overlay, grid background
```
### Earth Organic
```
--bg-primary: #faf8f5
--text-primary: #2d2a26
--text-secondary: #7a7470
--accent-1: #2d6a4f
--accent-2-end: #b07d62
--card-bg: rgba(45, 106, 79, 0.04)
--card-border: rgba(45, 106, 79, 0.1)
Font: 'DM Sans', system (headings + body)
Effects: no grain, organic blob shapes instead of orbs, warm shadows
```
---
## Content-Aware AI Decisions
When analyzing content, use these heuristics to suggest themes and slide types:
| Content Type | Suggested Theme | Typical Slides |
|-------------|-----------------|----------------|
| Startup pitch | Dark Cinematic | Hero, Stats, Chapter, Content Card, Feature Grid, CTA |
| Portfolio | Dark Cinematic or Light Minimal | Hero, Stats, Chapter, Content Card x N, Feature Grid, List, CTA |
| Product launch | Neon Cyberpunk or Dark Cinematic | Hero, Chapter, Split, Feature Grid, Comparison, Stats, CTA |
| Educational | Light Minimal or Earth Organic | Hero, Chapter, Content Card, Data, Timeline, List, CTA |
| Report / research | Light Minimal | Hero, Stats, Data, Content Card, Comparison, List, CTA |
| Personal story | Warm Editorial | Hero, Timeline, Quote, Content Card, List, CTA |
| Company overview | Dark Cinematic | Hero, Stats, Chapter, Content Card, Feature Grid, Timeline, CTA |
Always tell the user WHY you're recommending a specific theme. Be specific about the content, not generic.
---
## Narrative Arc Guidelines
Structure slides to follow a story arc:
1. **Hook** — Hero slide that grabs attention
2. **Context** — Stats or chapter that establishes credibility
3. **Body** — The core content (cards, grids, timelines, comparisons)
4. **Surprise** — A "one more thing" moment or unexpected highlight
5. **Close** — CTA or contact slide
Each slide should communicate ONE idea. If a slide has too much content, split it into multiple slides.
Keep total slide count between 8-15 for optimal pacing. Fewer than 8 feels thin; more than 15 feels long.
No comments yet. Be the first to comment!