# CLAUDE.md — HTML Presentation Builder

This file governs how you build presentations in this repository. Read it fully before generating or editing any deck. The standard is **not** "a working slideshow." The standard is **a deck a consultant would put in front of a board** — precise, restrained, data-forward, and unmistakably intentional. If an output looks like a generic Bootstrap/Tailwind template, it has failed.

---

## 1. Mission

Build **single-file, self-contained, presentation-ready HTML decks** that are:

- **Corporate-friendly** — safe in front of executives, clients, and investors. Conservative structure, confident typography, zero gimmicks.
- **Data-oriented** — numbers are the hero. Charts, KPIs, and tables are first-class citizens, formatted to a strict standard.
- **Interactive where it earns its place** — incremental builds, hover detail, toggles, animated chart entrances. Never animation for its own sake.
- **Self-contained** — one `.html` file that opens by double-clicking. No build step, no `npm install`, no bundler.
- **Genuinely professional** — the difference between "looks like AI made it" and "looks like a design studio made it" is the bar.

Every decision below serves those five goals. When a request conflicts with them, surface the tension and recommend the professional choice.

---

## 2. Non-negotiable constraints

1. **One file.** The entire deck — markup, styles, scripts, data — lives in a single `.html` file unless the user explicitly asks for a multi-file project. Charts read from inline JS data objects, not external files.
2. **No build tooling.** Everything loads from CDN or is inlined. The file must work when opened directly from disk (`file://`) with an internet connection.
3. **Offline-capable mode on request.** If the user needs a deck that works with *no* internet (air-gapped boardroom, conference wifi you can't trust), vendor the libraries: download Tailwind's compiled CSS, Reveal.js, and Chart.js into the file or a `/vendor` folder and reference locally. Default is CDN; ask if unsure for a high-stakes live presentation.
4. **16:9 by default.** 1280×720 logical resolution. This is the universal projector/Zoom/Google-Meet aspect ratio. Only deviate (4:3, A4-portrait one-pager) on explicit request.
5. **PDF export must work.** The deck must print cleanly to PDF (one slide per page, no clipping, charts rendered). This is how decks get emailed. Test mentally against the print rules in §11.
6. **Never invent data.** If the user gives numbers, use them exactly. If they don't, use **clearly labeled placeholder data** (`// PLACEHOLDER — replace with real figures`) and tell the user in your summary which numbers are fabricated. A professional deck with fake numbers presented as real is a liability, not a deliverable.

---

## 3. Tech stack (fixed)

Use this stack unless the user overrides. Do not swap libraries on a whim — consistency across decks is part of the product.

| Layer | Choice | Why |
|---|---|---|
| **Deck engine** | **Reveal.js 5.x** (CDN) | Battle-tested keyboard nav, fragments (incremental builds), overview mode, speaker notes, and `?print-pdf` export — all for free. Reinventing this per deck produces bugs. |
| **Styling** | **Tailwind CSS** via Play CDN + a small inline `<style>` block | Utility-first speed *plus* a custom design-token layer. Reveal's built-in themes are **disabled**. |
| **Data viz** | **Chart.js 4.x** (primary) | Clean, lightweight, professional defaults once restyled. Covers 90% of corporate charts. |
| **Data viz (advanced)** | **ECharts 5.x** (only when needed) | For dense dashboards, treemaps, sankey, geo maps, or large datasets. Don't load it unless a slide genuinely needs it. |
| **Icons** | **Lucide** (inline SVG, copy the path) | Crisp, consistent, neutral. Never use emoji as iconography in a corporate deck. |
| **Fonts** | Google Fonts (or brand fonts) | See §6. |

### Canonical CDN block

```html
<!-- Reveal core -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.css">
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5/dist/reveal.js"></script>
<!-- NOTE: deliberately NOT loading any reveal theme (e.g. black.css). We style everything ourselves. -->

<!-- Tailwind Play CDN -->
<script src="https://cdn.tailwindcss.com"></script>

<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<!-- Optional, load ONLY if a slide needs it -->
<!-- <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> -->

<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Inter+Tight:wght@600;700;800&display=swap" rel="stylesheet">
```

> **Tailwind Play CDN caveat:** it ships the full engine and compiles in-browser. That's fine for decks (not a public high-traffic site). Configure it via the inline `tailwind.config` script *before* using custom classes (see §6).

### Why Reveal.js and not a custom engine

A custom slide engine re-implements navigation, fragments, PDF export, and aspect-ratio scaling every single time — and gets at least one of them subtly wrong. Reveal handles all of it. We treat Reveal as a **headless** engine: it provides behavior, Tailwind + our tokens provide 100% of the look. If a deck must be zero-dependency single-file with no Reveal, see the fallback engine in **Appendix A**.

---

## 4. File structure & boilerplate

### Single-file layout (default)

```
deck-name.html
└─ <head>
   ├─ meta + title
   ├─ CDN links (§3)
   ├─ tailwind.config inline script (§6 tokens)
   └─ <style> — design tokens as CSS vars, Reveal overrides, print rules, animations
└─ <body>
   └─ <div class="reveal"><div class="slides">
      ├─ <section> … one per slide … </section>
   └─ ...
   └─ <script> Reveal.initialize({...}) + all chart instances </script>
```

### Multi-file (only if requested)

```
/deck
  index.html          ← markup + Reveal init
  /assets
    theme.css         ← tokens, overrides, print
    charts.js         ← chart factory functions + data
    /img              ← logos, photos (prefer SVG/optimized)
  /vendor             ← only for offline mode
```

### Required `<head>` skeleton

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>[Deck title] — [Company]</title>
  <!-- CDN block from §3 -->
  <script>
    tailwind.config = { /* tokens — see §6 */ };
  </script>
  <style>/* CSS vars, Reveal overrides, print, motion — see §6, §11 */</style>
</head>
```

### Reveal init (baseline)

```js
Reveal.initialize({
  width: 1280,
  height: 720,
  margin: 0,              // we control padding ourselves
  hash: true,             // shareable per-slide URLs
  slideNumber: 'c/t',     // "3 / 18"
  transition: 'fade',     // see §8 — fade or none, never zoom/cube/flip
  transitionSpeed: 'fast',
  controls: true,
  progress: true,
  overview: true,         // press Esc for grid
  pdfSeparateFragments: false,
});
```

---

## 5. Slide architecture & navigation

**Anatomy of every content slide** (consistency is what reads as "professional"):

```
┌────────────────────────────────────────────────────────┐
│ EYEBROW / SECTION LABEL                       ● ● ● ●    │  ← kicker + section progress dots
│ Slide headline — one clear claim                         │  ← H1, the assertion the slide proves
│ ──────────────────────────────────────────────────────  │  ← hairline rule (optional)
│                                                          │
│            [ body: chart / KPIs / table / text ]         │  ← the evidence
│                                                          │
│ Source: … | Footnote                          Logo  03/18│  ← footer band
└────────────────────────────────────────────────────────┘
```

Rules:
- **Headlines are assertions, not topics.** "Revenue grew 34% on enterprise expansion" — not "Revenue." The audience should be able to read only the headlines and get the argument. This is the single most important rule in the file.
- **One idea per slide.** If a slide needs two charts to make two points, it's two slides.
- **Persistent chrome:** every content slide carries the eyebrow, footer logo, slide number, and (where used) the source line. Title and section-divider slides are the only exceptions.
- **Generous, consistent margins.** A fixed safe-area inset (≈64px sides, 48px top/bottom). Never let content touch the edge.

**Standard navigation/affordances** (Reveal gives these; expose them):
- Arrow keys / space / on-screen controls for next/prev.
- `Esc` → overview grid. `F` → fullscreen. `S` → speaker notes view.
- Visible progress bar + `c/t` counter.
- Optional: a thin **section progress indicator** (dots or a stepped bar) showing position within the current section.

---

## 6. Design system

> The fastest way to look AI-generated is to accept defaults. Pick tokens deliberately, derive every color and size from them, and never hardcode a stray hex in markup.

### 6.1 The look: "Corporate, confident, quiet"

Avoid the three AI-default aesthetics: (1) cream + serif + terracotta, (2) near-black + acid-green, (3) broadsheet hairlines everywhere. The target here is closer to a **modern management-consulting / fintech investor deck**: lots of calm whitespace, one disciplined accent, immaculate type, and charts that carry the energy. **Spend boldness in exactly one place per slide** — usually the data.

### 6.2 Color tokens (default — override with brand colors first)

```js
// tailwind.config theme.extend.colors
const tokens = {
  ink:      '#0F172A',  // near-black slate — primary text
  body:     '#334155',  // secondary text
  muted:    '#64748B',  // captions, axis labels, footnotes
  hairline: '#E2E8F0',  // rules, gridlines, borders
  surface:  '#FFFFFF',  // slide background
  subtle:   '#F8FAFC',  // alt panels / cards
  accent:   '#1D4ED8',  // ONE brand accent — CTAs, key data, active state
  accentInk:'#1E3A8A',  // accent text on light
  positive: '#059669',  // up / good — use sparingly, only with meaning
  negative: '#DC2626',  // down / risk — use sparingly, only with meaning
};
```

**Color discipline:**
- **Accent is rare.** It marks the *one* thing that matters on a slide (the key bar, the headline number, the recommended option). If everything is accent-colored, nothing is.
- **positive/negative encode meaning, never decoration.** Green = up/good, red = down/risk. Don't paint a neutral chart green because it "looks nice."
- **Brand first.** If the user gives brand colors, replace `accent` (and derive a tint/shade scale) and check contrast. Brand color must hit **WCAG AA (4.5:1)** against its background for text; if it doesn't, use it for fills only and keep text in `ink`.
- **Dark mode** is available but **not default** for corporate decks — light reads as more formal and prints better. Offer it; don't assume it.

### 6.3 Categorical data palette (for multi-series charts)

A fixed, colorblind-considerate, ordered sequence. **Always assign in order** so the same category gets the same color across the deck:

```js
const dataColors = ['#1D4ED8','#0891B2','#7C3AED','#DB2777','#D97706','#65A30D','#475569'];
// Sequential (heatmaps/ramps): light #DBEAFE → dark #1E3A8A
// Diverging (variance vs target): #DC2626 ↔ #E2E8F0 ↔ #059669
```
Rules: max **6 categories** before you switch to grouping/"Other"; never rely on color alone (use direct labels, patterns, or position too).

### 6.4 Typography

```js
// tailwind.config
fontFamily: {
  display: ['"Inter Tight"', 'system-ui', 'sans-serif'], // headlines, big numbers
  sans:    ['Inter', 'system-ui', 'sans-serif'],          // body, labels
}
```
- **Brand fonts win.** If the company has a typeface, use it. Inter / Inter Tight is the safe, professional fallback.
- **Type scale** (px, for 1280×720): display headline 44–56 / slide H1 36 / subhead 24 / body 18–20 / caption 14 / eyebrow 13 uppercase tracked. Big "hero numbers": 72–120, weight 800, **tight leading**.
- **Tabular figures everywhere numbers appear.** Set `font-variant-numeric: tabular-nums;` on data, tables, KPIs, axes. Misaligned digit columns scream amateur.
- Headlines: weight 700–800, leading-tight (1.05–1.15), no orphans. Body: weight 400–500, leading-relaxed (1.5). **Sentence case** for headlines and labels — Title Case Everywhere Reads Dated.
- Eyebrows/kickers: 12–13px, uppercase, letter-spacing ~0.08em, color `muted`.

### 6.5 Spacing, grid, shape

- **8px spacing scale.** Everything snaps to multiples of 8 (or 4 for fine work). No magic numbers.
- **12-column mental grid** inside the safe area for aligning charts, columns, and KPI rows.
- **Border radius:** subtle (`rounded-lg`, 8px) on cards; **0** on chart plot areas and tables. Avoid pill-shaped everything.
- **Elevation:** prefer **hairline borders** (`border border-hairline`) over heavy shadows. If a shadow is used, make it soft and single (`shadow-sm`). No glassmorphism, no neon glows.
- **Whitespace is the budget.** When in doubt, remove an element and add space. (Chanel rule: take one accessory off before leaving the house.)

### 6.6 Reveal overrides (kill the framework look)

```css
.reveal { font-family: 'Inter', system-ui, sans-serif; color: var(--ink); }
.reveal .slides { text-align: left; }                 /* never center-align everything */
.reveal .slides section { padding: 48px 64px; }       /* safe area */
.reveal h1,.reveal h2,.reveal h3 { text-transform: none; font-family:'Inter Tight'; letter-spacing:-0.01em; }
.reveal .progress { color: var(--accent); height: 3px; }
.reveal .controls { color: var(--muted); }
.reveal ::selection { background: color-mix(in srgb, var(--accent) 20%, transparent); }
```

---

## 7. Slide templates (the building blocks)

Build decks by composing these. Each is a `<section>`. Keep markup semantic; style with Tailwind utilities mapped to tokens.

1. **Title slide** — deck title (display, large), subtitle/tagline, presenter/date/confidentiality line, logo. One restrained signature element (a thin accent rule, a single key metric, or a subtle background motif). No clip-art.
2. **Agenda / contents** — numbered list *only because an agenda genuinely is a sequence*. Current section can highlight in accent. Keep to 3–6 items.
3. **Section divider** — large section number + section title on a `subtle` or inverted (ink) background. Resets attention. Optionally shows "Section 2 of 5."
4. **Statement / thesis** — one sentence, large, lots of air. For the single most important claim. Use sparingly (1–2 per deck max).
5. **KPI dashboard** — 3–4 metric cards in a row: big number (tabular, weight 800), label above, delta below with ▲/▼ and `positive`/`negative` color, tiny sparkline optional. This is the workhorse "data-oriented" slide.
6. **Single chart + insight** — chart fills ~65% width, a short **insight callout** (the "so what") in the remaining space. Headline states the conclusion; chart proves it. Direct-label the key series.
7. **Two-up comparison** — two columns (before/after, us/them, option A/B). Symmetric. Highlight the recommended/winning side in accent.
8. **Data table** — clean financial-style table: right-aligned tabular numbers, zebra via `subtle` (subtle!), bold totals row with a top border, units in the header, no vertical gridlines. Heatmap-shade cells only to reveal a real pattern.
9. **Process / timeline** — horizontal stepped flow *only when order carries meaning*. Numbered nodes, connecting rule, accent on the current/critical step.
10. **Quote / testimonial** — short pull quote, attribution with name/title/company, optional small logo. No giant decorative quotation marks unless they're typographically deliberate.
11. **Matrix / 2×2** — classic consulting quadrant (axes labeled, items plotted, recommended quadrant tinted).
12. **Closing / CTA** — the ask, next steps (3 max), contact block. Mirrors the title slide's styling for bookends.

> When the user gives content that doesn't fit a template, compose a new layout from the same tokens and grid — don't force the content into the wrong template.

---

## 8. Interactivity & motion

Interactivity must **aid comprehension or pacing**, never perform. Default to restraint; over-animation is a top signal of AI-generated work.

**Use:**
- **Fragments (incremental builds)** — reveal bullets, chart series, or table rows one step at a time so the presenter controls the narrative. `<li class="fragment">`. This is the highest-value interaction in a deck — use it on dense slides.
- **Animated chart entrance** — bars grow / lines draw **once** when the slide becomes active (hook Reveal's `slidechanged` event to `chart.update()`), 400–700ms, ease-out. Disable Chart.js animation on subsequent interactions.
- **Hover detail** — chart tooltips (clean, see §9), and hover states on interactive elements. Cursor `pointer` only on truly clickable things.
- **Toggles / tabs / scenario sliders** — e.g., switch a chart between "Actual / Forecast," toggle scenarios, or a small input that recomputes a projected figure live. Excellent for finance/what-if decks. Keep controls obvious and labeled with plain verbs.
- **Slide transitions:** `fade` (or `none`). **Never** zoom, cube, flip, slide-spin — they read as PowerPoint-2007.

**Motion rules:**
- Durations 200–600ms, ease-out. Nothing bouncy, nothing that loops forever.
- One orchestrated entrance per slide beats five scattered effects.
- **Respect `prefers-reduced-motion`** — gate all non-essential animation behind it.
- Motion never blocks reading: content is legible at rest, animation only adds emphasis.

```css
@media (prefers-reduced-motion: reduce) {
  *,*::before,*::after { animation: none !important; transition: none !important; }
}
```

---

## 9. Data visualization standards (the core of "data-oriented")

This section is where most decks succeed or fail. Hold the line.

### 9.1 Chart-type selection

| Goal | Use | Avoid |
|---|---|---|
| Compare categories | Horizontal bar (sorted) | 3D bars, radar |
| Trend over time | Line (or area for one series) | Many overlapping lines (>4) |
| Part-to-whole | **Stacked bar or just a number**; pie only for 2–3 slices | Pie/donut with 6+ slices |
| Correlation | Scatter | Dual-axis trickery |
| Distribution | Histogram / box | — |
| Single big result | A **number**, not a chart | A one-bar bar chart |

Default to **sorting bars by value**. A sorted bar chart is clearer than almost any pie.

### 9.2 Restyle Chart.js to the design system (mandatory)

Chart.js defaults look generic. Apply a global config:

```js
Chart.defaults.font.family = 'Inter, system-ui, sans-serif';
Chart.defaults.font.size = 13;
Chart.defaults.color = tokens.muted;
Chart.defaults.borderColor = tokens.hairline;
Chart.defaults.plugins.legend.display = false; // prefer DIRECT LABELS over legends
Chart.defaults.plugins.tooltip.backgroundColor = tokens.ink;
Chart.defaults.plugins.tooltip.padding = 10;
Chart.defaults.plugins.tooltip.cornerRadius = 6;
Chart.defaults.datasets.bar.borderRadius = 4;
Chart.defaults.datasets.bar.maxBarThickness = 48;
Chart.defaults.elements.point.radius = 0;       // clean lines; show points on hover
Chart.defaults.elements.line.tension = 0.3;     // gentle smoothing, not wavy
```
Then per chart:
- **Remove chartjunk:** no vertical gridlines, faint horizontal gridlines only (`hairline`), no chart border, no background fill unless an area chart with a low-opacity accent.
- **Direct-label** the end of lines / the key bar instead of a legend whenever feasible.
- **Axis hygiene:** start value axes at 0 for bars (never truncate to exaggerate); concise tick formatting with units (`$1.2M`, `34%`, `12.4k`); label axes only when not obvious.
- **Highlight one series in `accent`**, mute the rest to `muted`/`hairline`. Don't rainbow every series.
- Add a `Source:` line under any chart with external data.

### 9.3 Number formatting (strict, deck-wide consistency)

- **Thousands separators** always (`1,240,000` or `1.24M` — pick one convention per deck and keep it).
- **Consistent decimals** within a metric (don't show 12.4% next to 12.40%).
- **Units attached or in the axis/header**, never ambiguous. Currency symbol or code stated once.
- **Localize on request** (e.g., Indian numbering `₹1,24,000` / lakh-crore if the audience is Indian; otherwise default to international).
- **Deltas** carry sign + direction: `+34%` `▲` in `positive`, `−8%` `▼` in `negative`.
- **Tabular figures** (`tabular-nums`) on every number so columns align.
- Round to the **precision that matters** to the audience — boards want `$4.2M`, not `$4,231,887.34`.

### 9.4 Tables

Financial-report styling: right-aligned numbers, generous row height, header in `muted` uppercase small, hairline under header and above totals, **bold totals**, subtle zebra at most. No heavy borders, no gridlines on every cell. For large tables, consider making rows reveal as fragments or letting the user sort.

### 9.5 ECharts

Only when Chart.js can't do it (sankey, treemap, geo/map, large dense datasets, sunburst). Apply the same tokens (colors, fonts, hairline gridlines, ink tooltips). Keep the visual language identical to Chart.js slides so the deck feels uniform.

---

## 10. Writing & copy

Copy makes a deck feel templated as fast as visuals do.
- **Headlines = conclusions.** (Repeating §5 because it matters most.)
- Plain verbs, sentence case, no filler, no hype adjectives ("revolutionary," "best-in-class," "synergy"). Specific beats clever.
- Active voice. Name things the way the audience says them.
- Bullets: max ~6 words each, parallel structure, no sub-sub-bullets. If a bullet runs two lines, it's a sentence — cut it.
- Every chart gets a one-line **"so what"** insight. Data without interpretation is homework you're handing the audience.
- Footnotes/sources in `muted`, small, bottom-left. Cite real sources; never fabricate a citation.

---

## 11. Print / PDF export (must work)

Decks get emailed. Reveal exports via `?print-pdf` + browser "Print to PDF." Guarantee it:

```css
@media print {
  @page { size: 1280px 720px; margin: 0; }
  .reveal .slides section { page-break-after: always; }
  /* ensure backgrounds/colors print */
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
```
- Test that charts render in print (Chart.js draws to canvas — trigger `resize`/render before print if needed; ECharts needs `renderer:'canvas'`).
- No content clipped at slide edges (respect the safe area).
- Fragments: decide whether the PDF shows the fully-built slide (`pdfSeparateFragments:false`, default) or each build step.
- Tell the user the exact export steps in your delivery summary: open `deck.html?print-pdf`, Ctrl/Cmd-P, "Save as PDF," set margins to None, enable "Background graphics," landscape.

---

## 12. Accessibility & responsiveness (quality floor)

- **Contrast:** text ≥ 4.5:1, large text/UI ≥ 3:1. Check the accent.
- **Keyboard:** all interactive controls focusable with a visible focus ring; don't remove outlines without replacing them.
- **Semantics:** real headings, `alt` on meaningful images, ARIA labels on icon-only buttons, charts get a text summary or `aria-label` describing the takeaway.
- **Reduced motion** honored (§8).
- **Scaling:** Reveal scales the 1280×720 stage to any screen automatically — verify it doesn't overflow on a laptop and is legible projected. The deck is *presented*, so it need not be mobile-perfect, but it shouldn't break on a phone preview.

---

## 13. Anti-patterns — do NOT ship these

- ❌ Reveal's default theme / visible Tailwind-template look (rounded gradient cards, generic blue-violet hero).
- ❌ Emoji as professional iconography. ❌ Clip-art, stock "handshake/lightbulb" images.
- ❌ Pie/donut charts with many slices; 3D charts; truncated y-axes that lie.
- ❌ Rainbow-colored series when one accent + muted would communicate better.
- ❌ Drop shadows everywhere, neon glows, glassmorphism, animated gradients.
- ❌ Title Case Headlines, ALL-CAPS body text, justified body text.
- ❌ Walls of text; >6 bullets; bullets that are full sentences; sub-sub-bullets.
- ❌ Zoom/cube/flip slide transitions; looping/auto-playing animations; parallax for its own sake.
- ❌ Inconsistent number formats, non-tabular figures, missing units.
- ❌ Fabricated data presented as real, or invented sources.
- ❌ Hardcoded hex colors / one-off font sizes that bypass the token system.

---

## 14. Workflow when given a brief

1. **Clarify the essentials** (only if missing and consequential): audience & setting (board / client pitch / internal), narrative goal (the one decision you want), brand colors/fonts/logo, real data vs placeholder, light/dark, offline-needed. Ask at most a few; otherwise proceed and state assumptions.
2. **Outline the narrative first** — list slide headlines (as assertions) so the *argument* is sound before any pixels. Confirm or proceed.
3. **Set tokens** — lock colors, fonts, accent from brand (or defaults) before building.
4. **Build with templates (§7)**, one idea per slide, composing new layouts as needed.
5. **Wire data** — restyle Chart.js (§9.2), format numbers (§9.3), label placeholders.
6. **Add interactivity sparingly** (§8) — fragments on dense slides, animated chart entrances, toggles where they help.
7. **Self-critique pass** against §13 anti-patterns and §15 checklist. Remove one thing. Tighten spacing and number formatting.
8. **Deliver** the single `.html`, plus a short note: assumptions, which numbers are placeholders, how to present (keys), and how to export PDF (§11).

---

## 15. Pre-delivery checklist (run every time)

- [ ] Opens as a single self-contained file; nav, fragments, overview all work.
- [ ] Every content slide headline is an **assertion**, not a topic.
- [ ] One idea per slide; consistent eyebrow / footer / slide number chrome.
- [ ] Colors/fonts/sizes all come from tokens; accent used rarely and meaningfully.
- [ ] Charts restyled (no chartjunk, direct labels, one highlighted series, 0-based bar axes, sources cited).
- [ ] Numbers: tabular figures, consistent decimals/separators, units, signed deltas.
- [ ] Animation restrained, ≤600ms, reduced-motion respected.
- [ ] Contrast AA, keyboard focus visible, charts have text alternatives.
- [ ] Prints to PDF cleanly (one slide/page, backgrounds + charts render, nothing clipped).
- [ ] No anti-patterns from §13. Placeholder data clearly flagged to the user.
- [ ] Took one accessory off — removed the least-necessary element on the busiest slide.

---

## Appendix A — Zero-dependency fallback engine (no Reveal)

Use only when the user demands a single file with **no external libraries at all** (true offline / locked-down environment). Implement a minimal engine:

- Slides are `<section class="slide">`; show one via a CSS class, advance with `keydown` (←/→/Space), click zones, and `hashchange`.
- Scale a fixed 1280×720 stage with a CSS `transform: scale()` computed on resize.
- Implement fragments as `.frag.is-visible` toggled by an index counter.
- Print: same `@media print` rules; each `.slide { page-break-after: always; }`.
- For charts without Chart.js: hand-build SVG (you control every pixel) — bars as `<rect>`, lines as `<polyline>`, all colored from CSS vars. Keep them in the same visual language as §9.

Keep the design system (§6), viz standards (§9), and anti-patterns (§13) **identical** — only the engine changes.

---

## Appendix B — Quick reference snippets

**KPI card:**
```html
<div class="rounded-lg border border-hairline bg-surface p-6">
  <p class="text-[13px] uppercase tracking-wider text-muted">Net revenue retention</p>
  <p class="mt-2 font-display text-6xl font-extrabold text-ink tabular-nums">118%</p>
  <p class="mt-1 text-sm font-medium text-positive tabular-nums">▲ +6 pts YoY</p>
</div>
```

**Slide shell:**
```html
<section data-auto-animate>
  <p class="text-[13px] uppercase tracking-wider text-muted">Financial review</p>
  <h1 class="font-display text-4xl font-bold text-ink leading-tight mt-1">
    Revenue grew 34% on enterprise expansion
  </h1>
  <div class="mt-8 grid grid-cols-12 gap-8 items-center">
    <div class="col-span-8"><canvas id="rev"></canvas></div>
    <aside class="col-span-4 text-body">
      <p class="text-lg"><span class="text-accent font-semibold">Enterprise</span> drove 70% of net new ARR …</p>
    </aside>
  </div>
  <footer class="absolute bottom-8 left-16 right-16 flex justify-between text-xs text-muted">
    <span>Source: Internal finance, FY24</span><span>Confidential</span>
  </footer>
</section>
```

**Chart on slide-activate:**
```js
Reveal.on('slidechanged', e => {
  const c = e.currentSlide.querySelector('canvas');
  if (c && c._chart) c._chart.update();
});
```

---

*End of CLAUDE.md. When in doubt: fewer elements, more whitespace, headlines that argue, numbers that align, one accent. Make it look like a studio built it.*
