---
name: leandata-pptx
description: "Create LeanData-branded PowerPoint presentations using PptxGenJS and TypeScript. Use this skill whenever you need to create a LeanData presentation, deck, pitch deck, or slides that follow LeanData's official 2025 brand guidelines. Triggers include: any request for a 'LeanData deck', 'LeanData presentation', 'LeanData slides', branded deck, or when the user mentions creating slides for LeanData-related purposes like sales decks, customer stories, QBRs, team intros, competitive analyses, or deal reviews. Also trigger when user references the LeanData brand template or asks for on-brand slides. This skill produces pixel-accurate reproductions of LeanData's official slide templates."
---

# LeanData Branded PPTX Skill

Creates LeanData-branded presentations using PptxGenJS (TypeScript). All output matches the official 2025 LeanData Presentation Template.

## Quick Start

1. **Brand constants** are inlined below — colors, fonts, dimensions
2. **Slide templates** are inlined below — TypeScript code for every slide type
3. **Download assets** from the URLs below to your working directory
4. **Write your TypeScript** using the templates and constants
5. **Run and QA** per the standard pptx skill

## Setup

```bash
npm install -g pptxgenjs typescript ts-node
```

Download brand assets to your working directory:
```bash
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/ld-icon-green.png
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/ld-icon-dark.png
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/ld-logo-dark.png
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/ld-logo-green.png
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/serpentine-green.png
curl -sO https://leandata-skills.pages.dev/skills/leandata-pptx/assets/serpentine-white.png
```

## Architecture

Every presentation script follows this structure:

```typescript
import PptxGenJS from "pptxgenjs";
import * as fs from "fs";
import * as path from "path";

// 1. Import brand constants (copy from brand-constants.md)
// 2. Create presentation instance
const pres = new PptxGenJS();
pres.layout = "LAYOUT_16x9"; // 10" × 5.625"
pres.author = "LeanData";

// 3. Load logo assets as base64
function loadAsset(filename: string): string {
  const buf = fs.readFileSync(path.join(__dirname, filename));
  return "image/png;base64," + buf.toString("base64");
}

const ASSETS = {
  ldIconGreen: loadAsset("ld-icon-green.png"),
  ldIconDark: loadAsset("ld-icon-dark.png"),
  ldLogoDark: loadAsset("ld-logo-dark.png"),
  ldLogoGreen: loadAsset("ld-logo-green.png"),
  serpentineGreen: loadAsset("serpentine-green.png"),
  serpentineWhite: loadAsset("serpentine-white.png"),
};

// 4. Add slides using template functions from slide-templates.md
// 5. Write file
pres.writeFile({ fileName: "output.pptx" });
```

## Available Slide Types

| Category | Templates | Background |
|----------|-----------|------------|
| **Cover** | Cover (white bg), Cover (green bg), Cover with subtitle (white), Cover with subtitle (green) | White or Green |
| **Section Dividers** | Section divider (dark), Section divider (green bg) | Dark or Green |
| **Agenda** | Agenda (with description), Agenda (with presenter) | Split dark/white |
| **Team** | Team 2-up, Team 3-up, Team 4-up, Team 5-up (dark + photo variants) | Dark |
| **Content** | Simple text, Two-column text, Text with bullets | White or Dark |
| **Split Layout** | Half-page photo right, Half-page photo left | Dark + photo |
| **Quote** | Full-width quote (dark) | Dark |
| **Stats** | 3-stat highlight | Dark |
| **Customer Story** | Customer story with stats | Split white/content |
| **Next Steps** | Next steps / closing | Split dark/white |
| **Thank You** | Thank you / closing | Dark |
| **Blank** | Blank white, Blank dark, Blank green | Various |

## Workflow

1. Read `references/brand-constants.md` for the TypeScript types and color/font constants
2. Read `references/slide-templates.md` for the specific slide functions you need
3. Compose your script, adding slides in order
4. Always include a cover slide and usually a thank-you slide
5. Run the script with `npx ts-node script.ts` or compile and run
6. QA the output using the standard pptx skill QA process

## Critical Rules

- **Font**: Always use `Montserrat` family. Titles are Black/ExtraBold weight, headings are Bold, body is Regular. Since PptxGenJS doesn't distinguish weights by name, use `bold: true` for Bold+ weights and `fontSize` to differentiate.
- **Colors**: Use ONLY the brand palette from `brand-constants.md`. Never use `#` prefix in hex colors.
- **Uppercase**: Primary titles, secondary titles, eyebrow labels, and section labels are ALWAYS UPPERCASE.
- **LD Icon**: Most slides include the green LD icon at bottom-left (0.28", 5.07", 0.37"×0.32"). On dark slides, use green icon. On white slides, use green icon.
- **No accent lines under titles**: This is explicitly banned by the brand guide.
- **Green bottom bar**: Some split-layout slides (Agenda, Next Steps) have a thin green bar at the bottom of the dark panel.

## References

All brand constants and slide templates are inlined below in this file. Assets are hosted at `https://leandata-skills.pages.dev/skills/leandata-pptx/assets/`.
# LeanData Brand Constants (TypeScript)

Copy these constants into every LeanData presentation script.

## Color Palette

```typescript
/** LeanData Brand Colors — NEVER use "#" prefix with PptxGenJS */
const LD = {
  // Primary palette
  GREEN:       "26D07C",  // Lean Green — primary brand color
  ALMOST_BLACK:"2A2A2A",  // Almost Black — dark backgrounds, titles on white
  WHITE:       "FFFFFF",  // White
  ALMOST_WHITE:"F7F7F7",  // Almost White — light backgrounds
  LIGHT_GRAY:  "EDEDED",  // Light gray dividers/borders

  // Grays (for body text, muted elements)
  GRAY_C2:     "C2C2C2",
  GRAY_8F:     "8F8F8F",
  GRAY_5C:     "5C5C5C",
  GRAY_72:     "727272",  // Body text on white slides

  // Data Visualization — Qualitative
  PURPLE:      "8847FF",
  YELLOW:      "F5B700",
  BLUE:        "00A1E4",
  ORANGE:      "E55924",

  // Data Visualization — Divergent (green to purple gradient)
  GREEN_LIGHT: "6EE0A8",
  GREEN_PALE:  "B7EFD3",
  PURPLE_LIGHT:"D7C2FF",
  PURPLE_MED:  "B084FF",
} as const;
```

## Typography

```typescript
/**
 * LeanData uses Montserrat exclusively.
 * PptxGenJS doesn't support font weight variants directly,
 * so we use bold: true and fontSize to create hierarchy.
 *
 * Typography hierarchy from the style guide:
 *   PRIMARY TITLE   — Montserrat Black,     UPPERCASE
 *   SECONDARY TITLE — Montserrat ExtraBold, UPPERCASE
 *   HEADING         — Montserrat Bold,      Mixed case
 *   EYEBROW         — Montserrat Bold,      UPPERCASE, small, green on dark / gray on light
 *   BODY COPY       — Montserrat Regular,   Mixed case
 */
const FONT = {
  FAMILY: "Montserrat",
} as const;
```

## Standard Dimensions (inches)

```typescript
/** Slide: 16:9 = 10" × 5.625" */
const SLIDE = { W: 10, H: 5.625 } as const;

/** Common positioning constants */
const POS = {
  // Margins
  MARGIN_LEFT:  0.54,
  MARGIN_TOP:   0.35,
  MARGIN_RIGHT: 0.54,

  // LD icon — bottom-left on most slides
  LD_ICON: { x: 0.28, y: 5.07, w: 0.37, h: 0.32 },

  // LD icon — bottom-left on dark slides with green bar
  LD_ICON_WITH_BAR: { x: 0.28, y: 4.97, w: 0.37, h: 0.32 },

  // Cover slide positions
  COVER: {
    DATE:   { x: 3.60, y: 0.45, w: 3.32, h: 0.33 },
    TITLE:  { x: 3.60, y: 1.98, w: 6.08, h: 3.31 },
    LOGO:   { x: 8.87, y: 0.35, w: 0.80, h: 0.17 },  // top-right
    SERPENTINE: { x: -0.60, y: -0.20, w: 3.80, h: 5.90 },
  },

  // Cover with subtitle
  COVER_SUB: {
    DATE:     { x: 3.60, y: 0.45, w: 3.32, h: 0.33 },
    TITLE:    { x: 3.60, y: 2.17, w: 6.00, h: 2.28 },
    SUBTITLE: { x: 3.60, y: 4.53, w: 6.00, h: 0.64 },
    LOGO:     { x: 8.87, y: 0.35, w: 0.80, h: 0.17 },
    SERPENTINE: { x: -0.60, y: -0.20, w: 3.80, h: 5.90 },
  },

  // Section divider positions
  SECTION: {
    EYEBROW:  { x: 1.10, y: 1.06, w: 7.81, h: 0.23 },
    TITLE:    { x: 1.10, y: 1.64, w: 7.81, h: 2.34 },
    LD_ICON:  { x: 4.72, y: 4.38, w: 0.56, h: 0.49 },  // centered
  },

  // Content slide (white bg)
  CONTENT: {
    EYEBROW:  { x: 0.60, y: 0.35, w: 3.79, h: 0.19 },
    TITLE:    { x: 0.54, y: 0.64, w: 8.94, h: 3.44 },
    BODY:     { x: 0.61, y: 4.18, w: 4.30, h: 1.17 },
  },

  // Split layout (dark left half)
  SPLIT: {
    DARK_PANEL_W: 5.50,  // width of dark left panel
    EYEBROW:   { x: 0.54, y: 0.35, w: 3.79, h: 0.38 },
    TITLE:     { x: 0.54, y: 0.77, w: 3.86, h: 1.51 },
    SUBTITLE:  { x: 0.54, y: 2.48, w: 3.79, h: 0.38 },
    BODY:      { x: 0.54, y: 3.04, w: 3.79, h: 1.70 },
    PHOTO:     { x: 5.50, y: 0.60, w: 4.08, h: 4.42 },
    GREEN_BAR: { x: 0, y: 5.45, w: 5.50, h: 0.18 },
  },

  // Agenda layout
  AGENDA: {
    LEFT_PANEL_W: 5.08,
    LD_ICON:   { x: 0.54, y: 0.54, w: 0.56, h: 0.49 },
    TITLE:     { x: 0.54, y: 1.20, w: 4.00, h: 1.00 },
    BODY:      { x: 0.54, y: 4.50, w: 4.00, h: 0.60 },
    LIST:      { x: 5.59, y: 1.03, w: 3.79, h: 3.70 },
    GREEN_BAR: { x: 0, y: 5.45, w: 5.08, h: 0.18 },
  },

  // Quote slide
  QUOTE: {
    TEXT:      { x: 0.60, y: 0.60, w: 8.80, h: 3.40 },
    NAME:      { x: 1.85, y: 4.28, w: 5.20, h: 0.30 },
    ROLE:      { x: 1.85, y: 4.64, w: 5.20, h: 0.30 },
    PHOTO:     { x: 0.67, y: 4.13, w: 0.93, h: 0.93 },
    LOGO:      { x: 7.50, y: 4.30, w: 1.80, h: 0.60 },
  },

  // Stats slide
  STATS: {
    EYEBROW:   { x: 0.60, y: 0.35, w: 3.79, h: 0.38 },
    TITLE:     { x: 0.54, y: 0.58, w: 5.96, h: 0.92 },
    // 3 stat columns evenly spaced
    STAT_Y:    2.20,
    STAT_H:    1.20,
    DESC_Y:    3.50,
    SOURCE_Y:  4.10,
  },

  // Team slide
  TEAM: {
    HEADING:   { x: 0, y: 0.60, w: 10, h: 0.40 },
    LOGO:      { x: 3.50, y: 4.80, w: 3.00, h: 0.50 },
    // Circle photo centers computed dynamically based on count
    PHOTO_SIZE: 1.41,  // diameter of photo circles
    PHOTO_Y:   1.60,   // y center of circles
    NAME_OFFSET: 0.15, // below photo circle
  },

  // Thank You slide
  THANKYOU: {
    EYEBROW:   { x: 1.10, y: 1.06, w: 7.81, h: 0.23 },
    TITLE:     { x: 1.10, y: 1.64, w: 7.81, h: 2.34 },
    LD_ICON:   { x: 4.72, y: 4.38, w: 0.56, h: 0.49 },
  },
} as const;
```

## Font Size Reference

```typescript
/** Standard font sizes by role (in points) */
const SIZES = {
  // Cover slides
  COVER_DATE:      11,   // UPPERCASE, bold, charSpacing: 4
  COVER_TITLE:     44,   // Montserrat Black, UPPERCASE

  // Section dividers
  SECTION_EYEBROW: 11,   // UPPERCASE, bold, green
  SECTION_TITLE:   44,   // UPPERCASE, white, bold

  // Content slides
  EYEBROW:         8,    // UPPERCASE, bold, green on dark / gray on white
  TITLE:           32,   // Bold, dark on white / white on dark
  SUBTITLE:        14,   // Bold
  BODY:            12,   // Regular weight
  BODY_SMALL:      10,   // Captions, sources

  // Stat slides
  STAT_NUMBER:     60,   // Green, bold
  STAT_DESC:       14,   // White
  STAT_SOURCE:     10,   // Gray, italic

  // Quote slides
  QUOTE_TEXT:      28,   // White, regular weight
  QUOTE_NAME:      12,   // White, bold
  QUOTE_ROLE:      10,   // Green

  // Team slides
  TEAM_HEADING:    12,   // Green, bold, UPPERCASE
  TEAM_NAME:       14,   // White, bold
  TEAM_ROLE:       11,   // White, regular
  TEAM_EMAIL:      10,   // Green

  // Agenda
  AGENDA_TITLE:    40,   // White, bold, UPPERCASE
  AGENDA_ITEM:     16,   // Dark text, regular
  AGENDA_FOOTER:   10,   // Gray body text

  // Thank You
  THANKYOU_EYEBROW: 11,
  THANKYOU_TITLE:   52,  // White, UPPERCASE
} as const;
```

## Helper: Add LD Icon to Slide

```typescript
/** Adds the green LD icon to bottom-left of a slide */
function addLdIcon(
  slide: PptxGenJS.Slide,
  assets: { ldIconGreen: string; ldIconDark: string },
  variant: "green" | "dark" = "green",
  position = POS.LD_ICON
) {
  slide.addImage({
    data: variant === "green" ? assets.ldIconGreen : assets.ldIconDark,
    x: position.x,
    y: position.y,
    w: position.w,
    h: position.h,
  });
}
```

## Helper: Green Bottom Bar

```typescript
/** Adds the thin green bar at bottom of dark panel (Agenda, Next Steps) */
function addGreenBar(
  slide: PptxGenJS.Slide,
  x: number = 0,
  w: number = 5.08
) {
  slide.addShape("rect", {
    x, y: 5.45, w, h: 0.18,
    fill: { color: LD.GREEN },
  });
}
```

## Important Notes

- **Montserrat availability**: Montserrat must be installed on the machine opening the PPTX for perfect rendering. If not installed, PowerPoint will substitute a similar sans-serif font. The Google Fonts version works. For maximum compatibility, you can specify `fontFace: "Montserrat"` and it will embed the font reference.
- **UPPERCASE is manual**: PptxGenJS does not support text-transform. Always `.toUpperCase()` strings that should be uppercase (titles, eyebrows, section labels).
- **Don't use white text on Lean Green**: The brand guide explicitly prohibits this as it's not accessible.
- **charSpacing**: Use `charSpacing: 4` on eyebrow/date labels for that spaced-out look.
- **Green bullets**: For agenda items, use colored circle shapes, not PptxGenJS bullet feature, to match the green dot style.
# LeanData Slide Templates (TypeScript)

Each function takes a `PptxGenJS` instance, content params, and an `ASSETS` object.
Import the brand constants from `brand-constants.md` before using these.

## Table of Contents

1. [Cover Slides](#1-cover-slides)
2. [Section Dividers](#2-section-dividers)
3. [Agenda / Next Steps](#3-agenda--next-steps)
4. [Team Slides](#4-team-slides)
5. [Simple Text / Content](#5-simple-text--content)
6. [Split Layout](#6-split-layout)
7. [Quote Slides](#7-quote-slides)
8. [Stat Highlights](#8-stat-highlights)
9. [Thank You / Closing](#9-thank-you--closing)
10. [Blank Slides](#10-blank-slides)
11. [Full Example Script](#11-full-example-script)

---

## 1. Cover Slides

### Cover — White Background

```typescript
interface CoverParams {
  date: string;       // e.g. "AUGUST 2025"
  title: string;      // Main title
  subtitle?: string;  // Optional subtitle (up to 2 lines)
}

function addCoverWhite(pres: PptxGenJS, p: CoverParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.WHITE };

  // Serpentine arrow — left side
  slide.addImage({
    data: assets.serpentineGreen,
    x: -0.80, y: -0.30, w: 4.20, h: 6.20,
  });

  // LeanData dark logo — top right
  slide.addImage({
    data: assets.ldLogoDark,
    x: 8.60, y: 0.30, w: 1.10, h: 0.24,
  });

  // Date label
  slide.addText(p.date.toUpperCase(), {
    x: 3.60, y: 0.45, w: 3.32, h: 0.33,
    fontFace: FONT.FAMILY, fontSize: SIZES.COVER_DATE,
    bold: true, color: LD.ALMOST_BLACK,
    charSpacing: 4,
  });

  // Title
  slide.addText(p.title.toUpperCase(), {
    x: 3.60, y: p.subtitle ? 2.17 : 1.98,
    w: 6.08, h: p.subtitle ? 2.28 : 3.31,
    fontFace: FONT.FAMILY, fontSize: SIZES.COVER_TITLE,
    bold: true, color: LD.ALMOST_BLACK,
    valign: "bottom", margin: 0,
  });

  // Subtitle (optional)
  if (p.subtitle) {
    slide.addText(p.subtitle, {
      x: 3.60, y: 4.53, w: 6.00, h: 0.64,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      color: LD.GRAY_5C, valign: "top", margin: 0,
    });
  }
}
```

### Cover — Green Background

```typescript
function addCoverGreen(pres: PptxGenJS, p: CoverParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.GREEN };

  // Serpentine arrow — white variant
  slide.addImage({
    data: assets.serpentineWhite,
    x: -0.80, y: -0.30, w: 4.20, h: 6.20,
  });

  // LeanData dark logo — top right
  slide.addImage({
    data: assets.ldLogoDark,
    x: 8.60, y: 0.30, w: 1.10, h: 0.24,
  });

  // Date label
  slide.addText(p.date.toUpperCase(), {
    x: 3.60, y: 0.45, w: 3.32, h: 0.33,
    fontFace: FONT.FAMILY, fontSize: SIZES.COVER_DATE,
    bold: true, color: LD.ALMOST_BLACK,
    charSpacing: 4,
  });

  // Title — dark text on green
  slide.addText(p.title.toUpperCase(), {
    x: 3.60, y: p.subtitle ? 2.17 : 1.98,
    w: 6.08, h: p.subtitle ? 2.28 : 3.31,
    fontFace: FONT.FAMILY, fontSize: SIZES.COVER_TITLE,
    bold: true, color: LD.ALMOST_BLACK,
    valign: "bottom", margin: 0,
  });

  if (p.subtitle) {
    slide.addText(p.subtitle, {
      x: 3.60, y: 4.53, w: 6.00, h: 0.64,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      color: LD.ALMOST_BLACK, valign: "top", margin: 0,
    });
  }
}
```

---

## 2. Section Dividers

### Section Divider — Dark Background

```typescript
interface SectionParams {
  eyebrow: string;  // e.g. "OVERVIEW"
  title: string;    // Section title
}

function addSectionDark(pres: PptxGenJS, p: SectionParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Eyebrow — green, centered
  slide.addText(p.eyebrow.toUpperCase(), {
    x: 1.10, y: 1.06, w: 7.81, h: 0.23,
    fontFace: FONT.FAMILY, fontSize: SIZES.SECTION_EYEBROW,
    bold: true, color: LD.GREEN,
    align: "center", charSpacing: 4,
  });

  // Title — white, centered, UPPERCASE
  slide.addText(p.title.toUpperCase(), {
    x: 1.10, y: 1.64, w: 7.81, h: 2.34,
    fontFace: FONT.FAMILY, fontSize: SIZES.SECTION_TITLE,
    bold: true, color: LD.WHITE,
    align: "center", valign: "middle", margin: 0,
  });

  // LD icon — centered bottom
  slide.addImage({
    data: assets.ldIconGreen,
    x: 4.72, y: 4.38, w: 0.56, h: 0.49,
  });
}
```

### Section Divider — Green Background

```typescript
function addSectionGreen(pres: PptxGenJS, p: SectionParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.GREEN };

  slide.addText(p.eyebrow.toUpperCase(), {
    x: 1.10, y: 1.06, w: 7.81, h: 0.23,
    fontFace: FONT.FAMILY, fontSize: SIZES.SECTION_EYEBROW,
    bold: true, color: LD.ALMOST_BLACK,
    align: "center", charSpacing: 4,
  });

  slide.addText(p.title.toUpperCase(), {
    x: 1.10, y: 1.64, w: 7.81, h: 2.34,
    fontFace: FONT.FAMILY, fontSize: SIZES.SECTION_TITLE,
    bold: true, color: LD.ALMOST_BLACK,
    align: "center", valign: "middle", margin: 0,
  });

  slide.addImage({
    data: assets.ldIconDark,
    x: 4.72, y: 4.38, w: 0.56, h: 0.49,
  });
}
```

---

## 3. Agenda / Next Steps

### Agenda Slide

```typescript
interface AgendaParams {
  items: Array<{ text: string; isSubItem?: boolean }>;
  footerText?: string;       // Bottom-left description
  presenterName?: string;    // Optional: "PRESENTER NAME"
  presenterTitle?: string;   // Optional: "Presenter title | Company"
}

function addAgenda(pres: PptxGenJS, p: AgendaParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();

  // Dark left panel
  slide.addShape("rect", {
    x: 0, y: 0, w: 5.08, h: 5.625,
    fill: { color: LD.ALMOST_BLACK },
  });

  // Green bottom bar on dark panel
  slide.addShape("rect", {
    x: 0, y: 5.45, w: 5.08, h: 0.18,
    fill: { color: LD.GREEN },
  });

  // LD icon — top-left of dark panel
  slide.addImage({
    data: assets.ldIconGreen,
    x: 0.54, y: 0.54, w: 0.56, h: 0.49,
  });

  // "AGENDA" title
  slide.addText("AGENDA", {
    x: 0.54, y: 1.20, w: 4.00, h: 1.00,
    fontFace: FONT.FAMILY, fontSize: SIZES.AGENDA_TITLE,
    bold: true, color: LD.WHITE, margin: 0,
  });

  // Footer text or presenter info
  if (p.presenterName) {
    slide.addText(p.presenterName.toUpperCase(), {
      x: 0.54, y: 3.80, w: 4.00, h: 0.30,
      fontFace: FONT.FAMILY, fontSize: 12,
      bold: true, color: LD.WHITE, margin: 0,
    });
    if (p.presenterTitle) {
      slide.addText(p.presenterTitle, {
        x: 0.54, y: 4.15, w: 4.00, h: 0.30,
        fontFace: FONT.FAMILY, fontSize: 10,
        color: LD.GRAY_C2, margin: 0,
      });
    }
  } else if (p.footerText) {
    slide.addText(p.footerText, {
      x: 0.54, y: 4.50, w: 4.00, h: 0.60,
      fontFace: FONT.FAMILY, fontSize: SIZES.AGENDA_FOOTER,
      color: LD.GRAY_C2, margin: 0,
    });
  }

  // Agenda items — right panel (white)
  let yPos = 1.03;
  for (const item of p.items) {
    const bulletX = item.isSubItem ? 5.95 : 5.59;
    const textX = item.isSubItem ? 6.35 : 5.99;
    const bulletSize = item.isSubItem ? 0.12 : 0.18;
    const bulletColor = item.isSubItem ? LD.GRAY_C2 : LD.GREEN;
    const textColor = item.isSubItem ? LD.GRAY_5C : LD.ALMOST_BLACK;

    // Green dot bullet
    slide.addShape("ellipse", {
      x: bulletX,
      y: yPos + 0.06,
      w: bulletSize, h: bulletSize,
      fill: { color: bulletColor },
      ...(item.isSubItem ? { line: { color: LD.GRAY_C2, width: 1 }, fill: { color: LD.WHITE } } : {}),
    });

    // Item text
    slide.addText(item.text, {
      x: textX, y: yPos, w: 3.40, h: 0.35,
      fontFace: FONT.FAMILY, fontSize: SIZES.AGENDA_ITEM,
      color: textColor, valign: "middle", margin: 0,
    });

    yPos += item.isSubItem ? 0.40 : 0.50;
  }
}
```

### Next Steps Slide

```typescript
interface NextStepsParams {
  items: string[];
}

function addNextSteps(pres: PptxGenJS, p: NextStepsParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();

  // Dark left panel
  slide.addShape("rect", {
    x: 0, y: 0, w: 5.08, h: 5.625,
    fill: { color: LD.ALMOST_BLACK },
  });

  // Green bottom bar
  slide.addShape("rect", {
    x: 0, y: 5.45, w: 5.08, h: 0.18,
    fill: { color: LD.GREEN },
  });

  // LD icon
  slide.addImage({
    data: assets.ldIconGreen,
    x: 0.54, y: 0.54, w: 0.56, h: 0.49,
  });

  // "NEXT STEPS" title
  slide.addText("NEXT\nSTEPS", {
    x: 0.54, y: 1.20, w: 4.00, h: 2.00,
    fontFace: FONT.FAMILY, fontSize: SIZES.AGENDA_TITLE,
    bold: true, color: LD.WHITE, margin: 0,
  });

  // Items — right side
  let yPos = 1.03;
  for (const item of p.items) {
    slide.addShape("ellipse", {
      x: 5.59, y: yPos + 0.06, w: 0.18, h: 0.18,
      fill: { color: LD.GREEN },
    });
    slide.addText(item, {
      x: 5.99, y: yPos, w: 3.40, h: 0.35,
      fontFace: FONT.FAMILY, fontSize: SIZES.AGENDA_ITEM,
      color: LD.ALMOST_BLACK, valign: "middle", margin: 0,
    });
    yPos += 0.55;
  }
}
```

---

## 4. Team Slides

### Team Slide (Dynamic count: 2-5 members)

```typescript
interface TeamMember {
  name: string;
  title: string;
  email: string;
  photoPath?: string;  // Optional photo file path
}

function addTeamSlide(
  pres: PptxGenJS,
  members: TeamMember[],
  assets: typeof ASSETS,
  heading: string = "MEET YOUR LEANDATA TEAM"
) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Heading — green, centered, UPPERCASE
  slide.addText(heading.toUpperCase(), {
    x: 0, y: 0.60, w: 10, h: 0.40,
    fontFace: FONT.FAMILY, fontSize: SIZES.TEAM_HEADING,
    bold: true, color: LD.GREEN,
    align: "center", charSpacing: 4,
  });

  // Calculate column positions based on member count
  const count = members.length;
  const circleSize = count <= 3 ? 1.41 : count === 4 ? 1.20 : 1.13;
  const spacing = 10 / (count + 1);  // even distribution

  members.forEach((member, i) => {
    const cx = spacing * (i + 1);  // center x

    // Circle outline (photo placeholder)
    if (member.photoPath) {
      slide.addImage({
        path: member.photoPath,
        x: cx - circleSize / 2, y: 1.40,
        w: circleSize, h: circleSize,
        rounding: true,
      });
    } else {
      slide.addShape("ellipse", {
        x: cx - circleSize / 2, y: 1.40,
        w: circleSize, h: circleSize,
        line: { color: LD.GREEN, width: 1.5 },
      });
    }

    // Name — bold white
    const nameY = 1.40 + circleSize + 0.15;
    slide.addText(member.name, {
      x: cx - 1.20, y: nameY, w: 2.40, h: 0.30,
      fontFace: FONT.FAMILY, fontSize: SIZES.TEAM_NAME,
      bold: true, color: LD.WHITE, align: "center", margin: 0,
    });

    // Title — white regular
    slide.addText(member.title, {
      x: cx - 1.20, y: nameY + 0.30, w: 2.40, h: 0.25,
      fontFace: FONT.FAMILY, fontSize: SIZES.TEAM_ROLE,
      color: LD.WHITE, align: "center", margin: 0,
    });

    // Dash separator
    slide.addText("—", {
      x: cx - 1.20, y: nameY + 0.55, w: 2.40, h: 0.20,
      fontFace: FONT.FAMILY, fontSize: 10,
      color: LD.WHITE, align: "center", margin: 0,
    });

    // Email — green
    slide.addText(member.email, {
      x: cx - 1.20, y: nameY + 0.75, w: 2.40, h: 0.25,
      fontFace: FONT.FAMILY, fontSize: SIZES.TEAM_EMAIL,
      color: LD.GREEN, align: "center", margin: 0,
    });
  });

  // LeanData green logo — centered bottom
  slide.addImage({
    data: assets.ldLogoGreen,
    x: 3.50, y: 4.80, w: 3.00, h: 0.50,
    sizing: { type: "contain", w: 3.00, h: 0.50 },
  });
}
```

---

## 5. Simple Text / Content

### Simple Text Slide — White Background

```typescript
interface ContentParams {
  eyebrow?: string;   // e.g. "SECTION • SUBSECTION"
  title: string;
  body?: string;      // Paragraph text
  bullets?: string[]; // Bulleted list
}

function addContentWhite(pres: PptxGenJS, p: ContentParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.WHITE };

  // Eyebrow
  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 0.60, y: 0.35, w: 3.79, h: 0.19,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GRAY_8F,
      charSpacing: 2, margin: 0,
    });
  }

  // Title
  slide.addText(p.title, {
    x: 0.54, y: 0.64, w: 8.94, h: p.body || p.bullets ? 2.00 : 3.44,
    fontFace: FONT.FAMILY, fontSize: SIZES.TITLE,
    bold: true, color: LD.ALMOST_BLACK,
    valign: "top", margin: 0,
  });

  // Body text
  if (p.body) {
    slide.addText(p.body, {
      x: 0.61, y: p.bullets ? 2.80 : 3.80, w: 4.30, h: 1.50,
      fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
      color: LD.GRAY_5C, margin: 0,
    });
  }

  // Bullets
  if (p.bullets) {
    const bulletItems = p.bullets.map((text, i) => ({
      text,
      options: {
        bullet: { color: LD.GREEN } as any,
        breakLine: i < p.bullets!.length - 1,
        color: LD.ALMOST_BLACK,
        fontSize: SIZES.BODY,
      },
    }));
    slide.addText(bulletItems, {
      x: 0.61, y: p.body ? 4.00 : 2.80, w: 8.50, h: 2.20,
      fontFace: FONT.FAMILY, valign: "top", margin: 0,
      paraSpaceAfter: 6,
    });
  }

  // LD icon
  addLdIcon(slide, assets);
}
```

### Simple Text Slide — Dark Background

```typescript
function addContentDark(pres: PptxGenJS, p: ContentParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 0.60, y: 0.35, w: 3.79, h: 0.19,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GREEN,
      charSpacing: 2, margin: 0,
    });
  }

  slide.addText(p.title, {
    x: 0.54, y: 0.64, w: 8.94, h: p.body || p.bullets ? 2.00 : 3.44,
    fontFace: FONT.FAMILY, fontSize: SIZES.TITLE,
    bold: true, color: LD.WHITE,
    valign: "top", margin: 0,
  });

  if (p.body) {
    slide.addText(p.body, {
      x: 0.61, y: 3.80, w: 4.30, h: 1.50,
      fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
      color: LD.GRAY_C2, margin: 0,
    });
  }

  if (p.bullets) {
    const bulletItems = p.bullets.map((text, i) => ({
      text,
      options: {
        bullet: { color: LD.GREEN } as any,
        breakLine: i < p.bullets!.length - 1,
        color: LD.WHITE,
        fontSize: SIZES.BODY,
      },
    }));
    slide.addText(bulletItems, {
      x: 0.61, y: p.body ? 4.00 : 2.80, w: 8.50, h: 2.20,
      fontFace: FONT.FAMILY, valign: "top", margin: 0,
      paraSpaceAfter: 6,
    });
  }

  addLdIcon(slide, assets);
}
```

### Two-Column Content

```typescript
interface TwoColumnParams {
  eyebrow?: string;
  title: string;
  leftSubtitle?: string;
  leftBody: string;
  rightSubtitle?: string;
  rightBody: string;
}

function addTwoColumn(pres: PptxGenJS, p: TwoColumnParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.WHITE };

  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 0.60, y: 0.35, w: 3.79, h: 0.19,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GRAY_8F, charSpacing: 2, margin: 0,
    });
  }

  slide.addText(p.title, {
    x: 0.54, y: 0.64, w: 6.10, h: 0.99,
    fontFace: FONT.FAMILY, fontSize: SIZES.TITLE,
    bold: true, color: LD.ALMOST_BLACK, margin: 0,
  });

  // Left column
  if (p.leftSubtitle) {
    slide.addText(p.leftSubtitle, {
      x: 0.54, y: 1.61, w: 4.33, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      bold: true, color: LD.ALMOST_BLACK, margin: 0,
    });
  }
  slide.addText(p.leftBody, {
    x: 0.54, y: 2.18, w: 4.33, h: 1.21,
    fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
    color: LD.GRAY_5C, margin: 0,
  });

  // Right column
  if (p.rightSubtitle) {
    slide.addText(p.rightSubtitle, {
      x: 5.15, y: 1.61, w: 4.33, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      bold: true, color: LD.ALMOST_BLACK, margin: 0,
    });
  }
  slide.addText(p.rightBody, {
    x: 5.15, y: 2.18, w: 4.33, h: 1.21,
    fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
    color: LD.GRAY_5C, margin: 0,
  });

  addLdIcon(slide, assets);
}
```

---

## 6. Split Layout

### Split — Photo Right

```typescript
interface SplitPhotoParams {
  eyebrow?: string;
  title: string;
  subtitle?: string;
  body?: string;
  photoPath?: string;     // Path to image file
  photoColor?: string;    // Fallback solid color if no photo
}

function addSplitPhotoRight(pres: PptxGenJS, p: SplitPhotoParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Photo or green placeholder on right
  if (p.photoPath) {
    slide.addImage({
      path: p.photoPath,
      x: 5.50, y: 0, w: 4.50, h: 5.625,
      sizing: { type: "cover", w: 4.50, h: 5.625 },
    });
  } else {
    slide.addShape("rect", {
      x: 5.50, y: 0, w: 4.50, h: 5.625,
      fill: { color: p.photoColor || LD.GREEN },
    });
  }

  // Eyebrow
  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 0.54, y: 0.35, w: 3.79, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GREEN, charSpacing: 2, margin: 0,
    });
  }

  // Title
  slide.addText(p.title, {
    x: 0.54, y: 0.77, w: 4.50, h: 1.51,
    fontFace: FONT.FAMILY, fontSize: 28,
    bold: true, color: LD.WHITE, valign: "top", margin: 0,
  });

  // Subtitle
  if (p.subtitle) {
    slide.addText(p.subtitle, {
      x: 0.54, y: 2.48, w: 4.50, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      bold: true, color: LD.WHITE, margin: 0,
    });
  }

  // Body
  if (p.body) {
    slide.addText(p.body, {
      x: 0.54, y: 3.04, w: 4.50, h: 1.70,
      fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
      color: LD.GRAY_C2, margin: 0,
    });
  }

  // LD icon
  addLdIcon(slide, assets);
}
```

### Split — Photo Left

```typescript
function addSplitPhotoLeft(pres: PptxGenJS, p: SplitPhotoParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Photo or placeholder on left
  if (p.photoPath) {
    slide.addImage({
      path: p.photoPath,
      x: 0, y: 0, w: 4.50, h: 5.625,
      sizing: { type: "cover", w: 4.50, h: 5.625 },
    });
  } else {
    slide.addShape("rect", {
      x: 0, y: 0, w: 4.50, h: 5.625,
      fill: { color: p.photoColor || LD.GREEN },
    });
  }

  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 5.57, y: 0.35, w: 3.79, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GREEN, charSpacing: 2, margin: 0,
    });
  }

  slide.addText(p.title, {
    x: 5.57, y: 0.77, w: 3.86, h: 1.51,
    fontFace: FONT.FAMILY, fontSize: 28,
    bold: true, color: LD.WHITE, valign: "top", margin: 0,
  });

  if (p.subtitle) {
    slide.addText(p.subtitle, {
      x: 5.57, y: 2.48, w: 3.79, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.SUBTITLE,
      bold: true, color: LD.WHITE, margin: 0,
    });
  }

  if (p.body) {
    slide.addText(p.body, {
      x: 5.57, y: 3.04, w: 3.79, h: 1.70,
      fontFace: FONT.FAMILY, fontSize: SIZES.BODY,
      color: LD.GRAY_C2, margin: 0,
    });
  }
}
```

---

## 7. Quote Slides

### Quote — Dark Background

```typescript
interface QuoteParams {
  quote: string;
  name: string;
  role: string;
  photoPath?: string;       // Optional speaker photo
  companyLogoPath?: string; // Optional company logo
}

function addQuoteDark(pres: PptxGenJS, p: QuoteParams, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Quote text — uses curly quotes
  const quoteText = `\u201C${p.quote}\u201D`;
  slide.addText(quoteText, {
    x: 0.60, y: 0.60, w: 8.80, h: 3.40,
    fontFace: FONT.FAMILY, fontSize: SIZES.QUOTE_TEXT,
    color: LD.WHITE, valign: "top", margin: 0,
  });

  // Speaker photo (circular)
  if (p.photoPath) {
    slide.addImage({
      path: p.photoPath,
      x: 0.67, y: 4.13, w: 0.93, h: 0.93,
      rounding: true,
    });
  }

  // Speaker name
  slide.addText(p.name, {
    x: p.photoPath ? 1.85 : 0.67, y: 4.28, w: 5.20, h: 0.30,
    fontFace: FONT.FAMILY, fontSize: SIZES.QUOTE_NAME,
    bold: true, color: LD.WHITE, margin: 0,
  });

  // Speaker role
  slide.addText(p.role, {
    x: p.photoPath ? 1.85 : 0.67, y: 4.64, w: 5.20, h: 0.30,
    fontFace: FONT.FAMILY, fontSize: SIZES.QUOTE_ROLE,
    color: LD.GREEN, margin: 0,
  });

  // Company logo
  if (p.companyLogoPath) {
    slide.addImage({
      path: p.companyLogoPath,
      x: 7.50, y: 4.30, w: 1.80, h: 0.60,
      sizing: { type: "contain", w: 1.80, h: 0.60 },
    });
  }

  // LD icon
  addLdIcon(slide, assets);
}
```

---

## 8. Stat Highlights

### 3-Stat Highlight — Dark Background

```typescript
interface StatItem {
  value: string;   // e.g. "25%", "<5min", ">100"
  description: string;
  source?: string;
}

function addStats(
  pres: PptxGenJS,
  p: { eyebrow?: string; title: string; stats: StatItem[] },
  assets: typeof ASSETS
) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Eyebrow
  if (p.eyebrow) {
    slide.addText(p.eyebrow.toUpperCase(), {
      x: 0.60, y: 0.35, w: 3.79, h: 0.38,
      fontFace: FONT.FAMILY, fontSize: SIZES.EYEBROW,
      bold: true, color: LD.GREEN, charSpacing: 2, margin: 0,
    });
  }

  // Title
  slide.addText(p.title, {
    x: 0.54, y: 0.58, w: 5.96, h: 0.92,
    fontFace: FONT.FAMILY, fontSize: 26,
    bold: true, color: LD.WHITE, valign: "top", margin: 0,
  });

  // Stats — evenly spaced columns
  const count = p.stats.length;
  const colW = 9.0 / count;
  const startX = 0.50;

  p.stats.forEach((stat, i) => {
    const x = startX + (i * colW);

    // Big number — green
    slide.addText(stat.value, {
      x, y: 2.20, w: colW, h: 1.20,
      fontFace: FONT.FAMILY, fontSize: SIZES.STAT_NUMBER,
      bold: true, color: LD.GREEN,
      align: "center", valign: "middle", margin: 0,
    });

    // Description — white
    slide.addText(stat.description, {
      x, y: 3.50, w: colW, h: 0.50,
      fontFace: FONT.FAMILY, fontSize: SIZES.STAT_DESC,
      color: LD.WHITE, align: "center", margin: 0,
    });

    // Source — gray italic
    if (stat.source) {
      slide.addText(stat.source, {
        x, y: 4.10, w: colW, h: 0.30,
        fontFace: FONT.FAMILY, fontSize: SIZES.STAT_SOURCE,
        italic: true, color: LD.GRAY_8F,
        align: "center", margin: 0,
      });
    }
  });

  addLdIcon(slide, assets);
}
```

---

## 9. Thank You / Closing

### Thank You Slide

```typescript
function addThankYou(
  pres: PptxGenJS,
  assets: typeof ASSETS,
  eyebrow: string = "INTELLIGENT GO-TO-MARKET ORCHESTRATION"
) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };

  // Eyebrow — green
  slide.addText(eyebrow.toUpperCase(), {
    x: 1.10, y: 1.06, w: 7.81, h: 0.23,
    fontFace: FONT.FAMILY, fontSize: SIZES.THANKYOU_EYEBROW,
    bold: true, color: LD.GREEN,
    align: "center", charSpacing: 4,
  });

  // "THANK YOU"
  slide.addText("THANK YOU", {
    x: 1.10, y: 1.64, w: 7.81, h: 2.34,
    fontFace: FONT.FAMILY, fontSize: SIZES.THANKYOU_TITLE,
    bold: true, color: LD.WHITE,
    align: "center", valign: "middle", margin: 0,
  });

  // LD icon — centered
  slide.addImage({
    data: assets.ldIconGreen,
    x: 4.72, y: 4.38, w: 0.56, h: 0.49,
  });
}
```

---

## 10. Blank Slides

```typescript
function addBlankWhite(pres: PptxGenJS, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.WHITE };
  addLdIcon(slide, assets);
}

function addBlankDark(pres: PptxGenJS, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.ALMOST_BLACK };
  addLdIcon(slide, assets);
}

function addBlankGreen(pres: PptxGenJS, assets: typeof ASSETS) {
  const slide = pres.addSlide();
  slide.background = { color: LD.GREEN };
}
```

---

## 11. Full Example Script

Here is a complete, runnable TypeScript script that demonstrates all slide types:

```typescript
import PptxGenJS from "pptxgenjs";
import * as fs from "fs";
import * as path from "path";

// ============================================================
// BRAND CONSTANTS (from brand-constants.md)
// ============================================================

const LD = {
  GREEN: "26D07C", ALMOST_BLACK: "2A2A2A", WHITE: "FFFFFF",
  ALMOST_WHITE: "F7F7F7", LIGHT_GRAY: "EDEDED",
  GRAY_C2: "C2C2C2", GRAY_8F: "8F8F8F", GRAY_5C: "5C5C5C", GRAY_72: "727272",
  PURPLE: "8847FF", YELLOW: "F5B700", BLUE: "00A1E4", ORANGE: "E55924",
  GREEN_LIGHT: "6EE0A8", GREEN_PALE: "B7EFD3",
  PURPLE_LIGHT: "D7C2FF", PURPLE_MED: "B084FF",
} as const;

const FONT = { FAMILY: "Montserrat" } as const;

const SIZES = {
  COVER_DATE: 11, COVER_TITLE: 44,
  SECTION_EYEBROW: 11, SECTION_TITLE: 44,
  EYEBROW: 8, TITLE: 32, SUBTITLE: 14, BODY: 12, BODY_SMALL: 10,
  STAT_NUMBER: 60, STAT_DESC: 14, STAT_SOURCE: 10,
  QUOTE_TEXT: 28, QUOTE_NAME: 12, QUOTE_ROLE: 10,
  TEAM_HEADING: 12, TEAM_NAME: 14, TEAM_ROLE: 11, TEAM_EMAIL: 10,
  AGENDA_TITLE: 40, AGENDA_ITEM: 16, AGENDA_FOOTER: 10,
  THANKYOU_EYEBROW: 11, THANKYOU_TITLE: 52,
} as const;

// ============================================================
// ASSET LOADING
// ============================================================

function loadAsset(filename: string): string {
  const buf = fs.readFileSync(path.join(__dirname, filename));
  return "image/png;base64," + buf.toString("base64");
}

const ASSETS = {
  ldIconGreen: loadAsset("ld-icon-green.png"),
  ldIconDark: loadAsset("ld-icon-dark.png"),
  ldLogoDark: loadAsset("ld-logo-dark.png"),
  ldLogoGreen: loadAsset("ld-logo-green.png"),
  serpentineGreen: loadAsset("serpentine-green.png"),
  serpentineWhite: loadAsset("serpentine-white.png"),
};

// ============================================================
// HELPERS
// ============================================================

function addLdIcon(
  slide: any, assets: typeof ASSETS,
  variant: "green" | "dark" = "green",
  pos = { x: 0.28, y: 5.07, w: 0.37, h: 0.32 }
) {
  slide.addImage({
    data: variant === "green" ? assets.ldIconGreen : assets.ldIconDark,
    ...pos,
  });
}

// ============================================================
// PASTE THE SLIDE FUNCTIONS FROM ABOVE HERE
// ============================================================

// ... addCoverWhite, addSectionDark, addAgenda, etc.

// ============================================================
// BUILD PRESENTATION
// ============================================================

const pres = new PptxGenJS();
pres.layout = "LAYOUT_16x9";
pres.author = "LeanData";
pres.title = "My LeanData Presentation";

// Add slides...
// addCoverWhite(pres, { date: "MARCH 2026", title: "Q1 Business Review" }, ASSETS);
// addSectionDark(pres, { eyebrow: "OVERVIEW", title: "Company Performance" }, ASSETS);
// ... etc.
// addThankYou(pres, ASSETS);

pres.writeFile({ fileName: "output.pptx" }).then(() => {
  console.log("Done: output.pptx");
});
```

---

## Chart Styling for LeanData

When adding charts, use the brand color palette:

```typescript
// Bar/Column chart with LeanData colors
slide.addChart(pres.charts.BAR, chartData, {
  x: 0.5, y: 1.5, w: 9, h: 3.5,
  barDir: "col",
  chartColors: [LD.GREEN, LD.PURPLE, LD.YELLOW, LD.BLUE, LD.ORANGE],
  chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true },
  catAxisLabelColor: LD.GRAY_5C,
  valAxisLabelColor: LD.GRAY_5C,
  catAxisLabelFontFace: FONT.FAMILY,
  valAxisLabelFontFace: FONT.FAMILY,
  valGridLine: { color: LD.LIGHT_GRAY, size: 0.5 },
  catGridLine: { style: "none" },
  showValue: true,
  dataLabelPosition: "outEnd",
  dataLabelColor: LD.ALMOST_BLACK,
  dataLabelFontFace: FONT.FAMILY,
  showLegend: false,
});

// For highlighting charts (single series, emphasis on one):
// chartColors: [LD.GREEN, LD.LIGHT_GRAY, LD.GRAY_C2, LD.GRAY_8F, LD.GRAY_5C]

// For divergent data:
// chartColors: [LD.GREEN, LD.GREEN_LIGHT, LD.GREEN_PALE, LD.WHITE, LD.PURPLE_LIGHT, LD.PURPLE_MED, LD.PURPLE]
```
