# Pitch Deck Design System

The complete CSS design system for generating professional HTML pitch decks. Every deck generated by this skill MUST use this system — no inline ad-hoc styles.

## Color Philosophy — NO Purple, NO Gradient Backgrounds

**The rules:**
- NEVER default to purple, violet, or any "AI-ish" colors
- NEVER use gradient backgrounds on slides (flat colors only)
- The palette MUST come from the user's brand, or be selected intentionally during the interview
- Use 2-3 colors maximum plus neutrals. One accent for emphasis, not three.
- Let typography and whitespace do the visual work — not color tricks
- Gradients are allowed ONLY for small accents (a progress bar fill, a divider line) — never as slide backgrounds

**Recommended palettes (choose based on product vibe):**

| Palette | Primary | Accent | Background | Best For |
|---------|---------|--------|------------|----------|
| **Navy + White** | `#1a2744` | `#3b82f6` | `#0f1729` | DeFi, infrastructure, enterprise |
| **White + Charcoal** | `#1c1c1e` | `#3b82f6` | `#ffffff` | Clean, any stage (Airbnb approach) |
| **Teal + Ivory** | `#0d9488` | `#f59e0b` | `#0f1d1b` | Consumer crypto, payments |
| **Black + White** | `#ffffff` | `#e2e8f0` | `#0a0a0a` | Premium, bold, hardware |
| **Navy + Orange** | `#1e3a5f` | `#f97316` | `#0c1825` | Consumer apps, marketplaces |
| **Green + Grey** | `#16a34a` | `#64748b` | `#0f1512` | DePIN, climate, sustainability |

**If the user has brand colors:** Use those. Override the CSS variables below.
**If they don't:** Ask during the interview. Pick based on their product type and vibe.

---

## Base HTML Shell

Every deck starts with this shell. Self-contained, zero dependencies, works offline:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{PROJECT_NAME}} — Pitch Deck</title>
  <style>
    /* === DESIGN SYSTEM TOKENS === */
    /* IMPORTANT: Replace these with the user's brand palette or a selected palette above */
    :root {
      /* Brand palette — CUSTOMIZE PER PROJECT */
      --c-bg: #0f1729;
      --c-bg-alt: #131d33;
      --c-bg-card: #182240;
      --c-surface: #1e2a4a;
      --c-border: rgba(255,255,255,0.08);

      --c-primary: #3b82f6;
      --c-primary-dim: rgba(59,130,246,0.12);
      --c-accent: #10b981;
      --c-accent-dim: rgba(16,185,129,0.10);
      --c-danger: #ef4444;
      --c-warning: #f59e0b;

      --c-text: #f1f5f9;
      --c-text-secondary: rgba(241,245,249,0.65);
      --c-text-muted: rgba(241,245,249,0.4);

      /* Typography scale (based on 1920x1080 viewport) */
      --f-hero: 96px;
      --f-h1: 64px;
      --f-h2: 48px;
      --f-h3: 36px;
      --f-body: 28px;
      --f-small: 22px;
      --f-caption: 18px;

      --font-display: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
      --font-mono: 'JetBrains Mono', 'SF Mono', 'Consolas', monospace;

      /* Spacing scale */
      --s-xs: 8px;
      --s-sm: 16px;
      --s-md: 32px;
      --s-lg: 48px;
      --s-xl: 64px;
      --s-2xl: 96px;

      /* Animation */
      --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
      --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
      --duration-enter: 0.6s;
    }

    /* === RESET === */
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    html, body { height: 100%; overflow: hidden; background: var(--c-bg); color: var(--c-text); }

    /* === SLIDE CONTAINER === */
    .deck {
      width: 100vw; height: 100vh;
      position: relative; overflow: hidden;
    }

    .slide {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding: 80px 100px;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.5s var(--ease-out);
      font-family: var(--font-display);
      background: var(--c-bg);
    }

    .slide.active {
      opacity: 1;
      pointer-events: auto;
    }

    /* Entrance animations for active slide children */
    .slide.active .animate-in {
      animation: slideUp var(--duration-enter) var(--ease-out) both;
    }
    .slide.active .animate-in:nth-child(1) { animation-delay: 0s; }
    .slide.active .animate-in:nth-child(2) { animation-delay: 0.08s; }
    .slide.active .animate-in:nth-child(3) { animation-delay: 0.16s; }
    .slide.active .animate-in:nth-child(4) { animation-delay: 0.24s; }
    .slide.active .animate-in:nth-child(5) { animation-delay: 0.32s; }
    .slide.active .animate-in:nth-child(6) { animation-delay: 0.4s; }
    .slide.active .animate-in:nth-child(7) { animation-delay: 0.48s; }
    .slide.active .animate-in:nth-child(8) { animation-delay: 0.56s; }

    @keyframes slideUp {
      from { opacity: 0; transform: translateY(24px); }
      to { opacity: 1; transform: translateY(0); }
    }

    /* === TYPOGRAPHY === */
    .hero { font-size: var(--f-hero); font-weight: 900; letter-spacing: -3px; line-height: 1.05; }
    .h1 { font-size: var(--f-h1); font-weight: 800; letter-spacing: -2px; line-height: 1.1; }
    .h2 { font-size: var(--f-h2); font-weight: 700; letter-spacing: -1px; line-height: 1.2; }
    .h3 { font-size: var(--f-h3); font-weight: 600; line-height: 1.3; }
    .body { font-size: var(--f-body); font-weight: 400; line-height: 1.5; color: var(--c-text-secondary); }
    .small { font-size: var(--f-small); font-weight: 400; line-height: 1.5; color: var(--c-text-secondary); }
    .caption { font-size: var(--f-caption); font-weight: 500; color: var(--c-text-muted); letter-spacing: 2px; text-transform: uppercase; }
    .mono { font-family: var(--font-mono); }

    .text-primary { color: var(--c-primary); }
    .text-accent { color: var(--c-accent); }
    .text-muted { color: var(--c-text-muted); }
    .text-danger { color: var(--c-danger); }

    /* Emphasized text — use primary color, NOT gradient */
    .text-emphasis { color: var(--c-primary); font-weight: 800; }

    /* === LAYOUT UTILITIES === */
    .flex { display: flex; }
    .flex-col { flex-direction: column; }
    .items-center { align-items: center; }
    .justify-center { justify-content: center; }
    .justify-between { justify-content: space-between; }
    .gap-xs { gap: var(--s-xs); }
    .gap-sm { gap: var(--s-sm); }
    .gap-md { gap: var(--s-md); }
    .gap-lg { gap: var(--s-lg); }
    .gap-xl { gap: var(--s-xl); }
    .flex-1 { flex: 1; }
    .w-full { width: 100%; }
    .text-center { text-align: center; }

    .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-lg); }
    .grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--s-md); }
    .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-md); }

    /* === COMPONENTS === */

    /* Card */
    .card {
      background: var(--c-bg-card);
      border: 1px solid var(--c-border);
      border-radius: 16px;
      padding: var(--s-lg);
    }
    .card-glow {
      background: var(--c-bg-card);
      border: 1px solid rgba(153,69,255,0.2);
      border-radius: 16px;
      padding: var(--s-lg);
      box-shadow: 0 0 40px rgba(153,69,255,0.06);
    }

    /* Metric card */
    .metric-card {
      text-align: center;
      padding: var(--s-lg);
    }
    .metric-value {
      font-size: 72px;
      font-weight: 900;
      color: var(--c-accent);
      letter-spacing: -2px;
      line-height: 1;
    }
    .metric-label {
      font-size: var(--f-small);
      color: var(--c-text-muted);
      margin-top: var(--s-xs);
      font-weight: 500;
    }

    /* Badge / tag */
    .badge {
      display: inline-block;
      padding: 6px 16px;
      border-radius: 100px;
      font-size: var(--f-caption);
      font-weight: 600;
      letter-spacing: 1px;
    }
    .badge-primary { background: var(--c-primary-dim); color: var(--c-primary); }
    .badge-accent { background: var(--c-accent-dim); color: var(--c-accent); }
    .badge-outline { border: 1px solid var(--c-border); color: var(--c-text-secondary); }

    /* Divider — flat color, no gradient */
    .divider {
      width: 64px; height: 3px; border-radius: 2px;
      background: var(--c-primary);
      opacity: 0.6;
      margin: var(--s-md) 0;
    }

    /* Progress bar */
    .progress-bar {
      width: 100%; height: 8px; border-radius: 4px;
      background: rgba(255,255,255,0.06);
      overflow: hidden;
    }
    .progress-fill {
      height: 100%; border-radius: 4px;
      background: var(--c-primary);
    }

    /* Bullet list */
    .bullet-list { list-style: none; }
    .bullet-list li {
      padding: var(--s-sm) 0;
      padding-left: var(--s-md);
      position: relative;
      font-size: var(--f-body);
      color: var(--c-text-secondary);
      border-bottom: 1px solid var(--c-border);
    }
    .bullet-list li:last-child { border-bottom: none; }
    .bullet-list li::before {
      content: '';
      position: absolute; left: 0; top: 50%;
      width: 8px; height: 8px; border-radius: 50%;
      background: var(--c-primary);
      transform: translateY(-50%);
    }

    /* Comparison table */
    .comparison-table { width: 100%; border-collapse: collapse; }
    .comparison-table th {
      text-align: left; padding: var(--s-sm) var(--s-md);
      font-size: var(--f-small); color: var(--c-text-muted);
      border-bottom: 1px solid var(--c-border);
      font-weight: 600;
    }
    .comparison-table td {
      padding: var(--s-sm) var(--s-md);
      font-size: var(--f-body);
      border-bottom: 1px solid var(--c-border);
      color: var(--c-text-secondary);
    }
    .comparison-table tr.highlight td {
      color: var(--c-text);
      background: var(--c-primary-dim);
      font-weight: 600;
    }
    .check { color: var(--c-accent); font-weight: 700; }
    .cross { color: var(--c-text-muted); }

    /* Timeline */
    .timeline { position: relative; padding-left: var(--s-lg); }
    .timeline::before {
      content: ''; position: absolute; left: 12px; top: 0; bottom: 0;
      width: 2px; background: var(--c-border);
    }
    .timeline-item { position: relative; padding-bottom: var(--s-lg); }
    .timeline-dot {
      position: absolute; left: -42px; top: 4px;
      width: 12px; height: 12px; border-radius: 50%;
      background: var(--c-primary);
      border: 2px solid var(--c-bg);
    }
    .timeline-item.active .timeline-dot { background: var(--c-accent); box-shadow: 0 0 12px rgba(20,241,149,0.4); }

    /* Quote block */
    .quote-block {
      position: relative;
      padding: var(--s-lg);
      padding-left: var(--s-xl);
      border-left: 3px solid var(--c-primary);
      background: var(--c-bg-card);
      border-radius: 0 12px 12px 0;
    }
    .quote-block::before {
      content: '"'; position: absolute; left: 16px; top: 8px;
      font-size: 64px; color: var(--c-primary); opacity: 0.3;
      font-family: serif; line-height: 1;
    }

    /* === SLIDE BACKGROUNDS — flat colors only, NO gradients === */
    .bg-default { background: var(--c-bg); }
    .bg-alt { background: var(--c-bg-alt); }
    .bg-surface { background: var(--c-surface); }
    /* Use alternating bg-default and bg-alt for visual rhythm between slides */

    /* === NAVIGATION === */
    .nav-bar {
      position: fixed; bottom: 0; left: 0; right: 0;
      display: flex; justify-content: space-between; align-items: center;
      padding: 16px 40px;
      background: linear-gradient(0deg, rgba(10,10,15,0.95) 0%, transparent 100%);
      z-index: 100;
      opacity: 0;
      transition: opacity 0.3s;
    }
    .deck:hover .nav-bar { opacity: 1; }
    .nav-counter {
      font-size: 16px; color: var(--c-text-muted); font-family: var(--font-mono);
    }
    .nav-progress {
      flex: 1; max-width: 200px; height: 3px; border-radius: 2px;
      background: rgba(255,255,255,0.1); margin: 0 24px;
    }
    .nav-progress-fill {
      height: 100%; border-radius: 2px;
      background: var(--c-primary);
      transition: width 0.3s var(--ease-out);
    }
    .nav-btn {
      background: none; border: 1px solid var(--c-border); color: var(--c-text-secondary);
      padding: 8px 16px; border-radius: 8px; cursor: pointer; font-size: 14px;
      font-family: var(--font-display);
    }
    .nav-btn:hover { border-color: var(--c-primary); color: var(--c-text); }

    /* === PRESENTER NOTES === */
    .notes {
      display: none;
      position: fixed; bottom: 60px; left: 40px; right: 40px;
      background: rgba(0,0,0,0.9); border: 1px solid var(--c-border);
      border-radius: 12px; padding: 20px 24px;
      font-size: 16px; color: var(--c-text-secondary); line-height: 1.6;
      z-index: 200; max-height: 200px; overflow-y: auto;
    }
    .notes.visible { display: block; }
    .notes-label {
      font-size: 12px; color: var(--c-text-muted); text-transform: uppercase;
      letter-spacing: 2px; margin-bottom: 8px;
    }

    /* === PRINT === */
    @media print {
      .deck { overflow: visible; }
      .slide {
        position: relative; opacity: 1; pointer-events: auto;
        page-break-after: always; height: 100vh;
        break-inside: avoid;
      }
      .nav-bar, .notes { display: none !important; }
      .animate-in { animation: none !important; opacity: 1 !important; transform: none !important; }
    }
  </style>
</head>
<body>
  <div class="deck" id="deck">
    <!-- SLIDES GO HERE -->

    <!-- Navigation -->
    <div class="nav-bar">
      <button class="nav-btn" onclick="prev()">← Prev</button>
      <span class="nav-counter"><span id="current">1</span> / <span id="total"></span></span>
      <div class="nav-progress"><div class="nav-progress-fill" id="progress"></div></div>
      <button class="nav-btn" onclick="next()">Next →</button>
    </div>
  </div>

  <script>
    let current = 0;
    const slides = document.querySelectorAll('.slide');
    const total = slides.length;
    let notesVisible = false;

    document.getElementById('total').textContent = total;

    function show(i) {
      slides.forEach(s => s.classList.remove('active'));
      current = Math.max(0, Math.min(i, total - 1));
      slides[current].classList.add('active');
      document.getElementById('current').textContent = current + 1;
      document.getElementById('progress').style.width = ((current + 1) / total * 100) + '%';

      // Update notes
      document.querySelectorAll('.notes').forEach(n => n.classList.remove('visible'));
      const note = slides[current].querySelector('.notes');
      if (note && notesVisible) note.classList.add('visible');
    }

    function next() { show(current + 1); }
    function prev() { show(current - 1); }

    document.addEventListener('keydown', (e) => {
      if (e.key === 'ArrowRight' || e.key === ' ') { e.preventDefault(); next(); }
      if (e.key === 'ArrowLeft') { e.preventDefault(); prev(); }
      if (e.key === 'n' || e.key === 'N') {
        notesVisible = !notesVisible;
        document.querySelectorAll('.notes').forEach(n => {
          n.classList.toggle('visible', notesVisible && n.closest('.slide').classList.contains('active'));
        });
      }
    });

    // Click to advance (right half) or go back (left half)
    document.getElementById('deck').addEventListener('click', (e) => {
      if (e.target.closest('.nav-bar') || e.target.closest('.nav-btn')) return;
      if (e.clientX > window.innerWidth / 2) next(); else prev();
    });

    show(0);
  </script>
</body>
</html>
```

---

## Design Rules (Enforced)

1. **One idea per slide** — Never combine two concepts
2. **30pt minimum** — Nothing smaller than `var(--f-body)` (28px). Labels/captions at 18px are the absolute floor.
3. **Max 6 words per bullet** — If it's a sentence, it's too long
4. **Max 6 bullets per slide** — If you need more, split into two slides
5. **Visuals beat text** — Use metric cards, comparison tables, charts, before/after instead of paragraphs
6. **Consistent hierarchy** — Every slide uses the same heading/body/caption structure
7. **Whitespace is a feature** — Don't fill every pixel. Sparse slides feel confident.
8. **Dark theme only** — Projectors in dark rooms. Black backgrounds with bright accents.
9. **No decorative elements** — No random shapes, gradients-for-the-sake-of-gradients, or stock photos
10. **Animate entrance only** — Elements fade up once on slide enter. No continuous animation, no auto-play effects.

---

## Slide Anatomy

Every slide follows this structure:

```
┌──────────────────────────────────────┐
│                                      │
│  [CAPTION — section label]           │  ← Optional: "PROBLEM", "TRACTION", etc.
│                                      │
│  [HEADLINE — one strong line]        │  ← Required: The main point
│                                      │
│  [DIVIDER]                           │  ← Optional: gradient line separator
│                                      │
│  [CONTENT — visual or bullets]       │  ← Required: Supporting evidence
│                                      │
│  [NOTES — presenter speaking notes]  │  ← Hidden by default, press N
│                                      │
└──────────────────────────────────────┘
```

```html
<!-- Slide template -->
<div class="slide bg-glow">
  <span class="caption animate-in">PROBLEM</span>
  <h1 class="h1 animate-in" style="margin-top: 16px;">
    AI agents can't pay each other<br>without a human co-signer.
  </h1>
  <div class="divider animate-in"></div>
  <div class="body animate-in" style="max-width: 800px;">
    Supporting evidence or visual component goes here.
  </div>

  <div class="notes">
    Speaker notes: Explain the manual process, mention 3 specific pain points,
    transition to solution on next slide.
  </div>
</div>
```

---

## Color Usage Guide

| Element | Color | When |
|---------|-------|------|
| Headlines | `var(--c-text)` | Default for all headings |
| Key metric values | `var(--c-accent)` | Numbers that prove traction |
| Emphasis words | `var(--c-primary)` | One word per slide, max. Use `.text-emphasis` |
| Body text | `var(--c-text-secondary)` | All explanatory text |
| Labels, captions | `var(--c-text-muted)` | Section labels, chart labels |
| Positive signals | `var(--c-accent)` | Checkmarks, growth, your product |
| Negative signals | `var(--c-danger)` | Competitor weaknesses, problems |
| Card backgrounds | `var(--c-bg-card)` | Contained content blocks |
| Card with glow | `.card-glow` | Featured/highlighted content |
| Slide backgrounds | `var(--c-bg)` or `var(--c-bg-alt)` | Alternate between slides for rhythm. NEVER use gradients. |

### What NOT to Do
- No purple as a default. Ever.
- No gradient slide backgrounds. Flat colors only.
- No more than 2-3 colors on any single slide.
- No neon accents. Keep colors muted and professional.
- No rainbow palettes. Focused > colorful.
- The design should feel like a consulting firm's deck, not an AI template.
