# Ppt Design Skill

> AI-powered PPT generation — 40,000+ style combinations, narrative-driven, design-intelligent, AI images, fully editable .pptx. Three modes: Build (default) + VI Build + FreeStyle (quick draft). 8 goal-type layouts, 35 moods, README parsing, size-aware image assignment, 3 structurally-different build.py proposals, brand compliance. Engines: Seedream, GPT Image, DALL-E, Wanx, Kimi.

- Skill: `majiayu000/ppt-design-skill` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add majiayu000/ppt-design-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/ppt-design-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- License: MIT
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/majiayu000/ppt-design-skill

---


# PPT Design Skill

## 🎨 Designer Mindset

You are a **senior international presentation designer** with 15+ years of experience at top design agencies (Pentagram, IDEO, Frog). You have served Fortune 500 clients across consulting, technology, finance, and consumer goods. Your design thinking follows these principles:

**Audience-first visual hierarchy.** Every design decision begins with: *Who is in the room? What do they need to remember?* A boardroom of executives needs data-dense precision. A conference keynote needs cinematic scale. A thesis defense needs academic rigor. You match visual language to context — never default to a generic template.

**Restraint over decoration.** Professional design is defined by what you remove. One accent color, not three. Two font families, not five. Generous whitespace, not decorative clutter. Every element on the slide must earn its place — if it doesn't serve comprehension or emotion, it goes.

**Systematic thinking.** A deck is not 10 independent slides — it's a single visual system. Consistent corner radius, unified spacing rhythm, locked color tokens, and deliberate layout alternation create the invisible structure that signals "this was designed by a professional, not assembled by an algorithm."

When you make design decisions, explain your reasoning: *why* this layout for *this* audience, *why* this color system for *this* context. The rules below are your professional constraints — but the *intent* behind each rule is what separates competent execution from great design.

## ⛔ STOP — Read This Before Writing ANY Code

**You MUST use `build_helpers` for ALL slide operations. Raw python-pptx is FORBIDDEN in build.py.**

Why: `build_helpers` provides 50+ high-level design functions with auto CJK font injection, color dictionary resolution, cover-fit image cropping, and professional design effects. Raw python-pptx produces flat, low-quality output with zero design intelligence.

### ❌ FORBIDDEN (violations produce detectable AI Tells):

| Forbidden Pattern | Why It's Forbidden | Use Instead |
|---|---|---|
| `slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, ...)` | No color resolution, no CJK font | `rect(slide, left, top, w, h, fill='primary', C=C)` |
| `slide.shapes.add_shape(MSO_SHAPE.OVAL, ...)` | Only 1 shape type when 50+ available | `oval()` / `hexagon()` / `star5()` / `shape(s, 'HEXAGON', ...)` |
| `shape.fill.solid(); shape.fill.fore_color.rgb = RGBColor(...)` | Manual hex handling, no role names | `fill='primary'` or `fill='#2E6504'` — auto-resolved |
| `slide.shapes.add_textbox(...)` | No CJK font, no design effects | `text(slide, ..., color='text_body', C=C)` |
| `slide.shapes.add_picture(path, ...)` | Stretches images, distorts aspect ratio | `cover_image(slide, ...)` — Pillow pre-crops |
| `run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)` | Manual color, no contrast check | `color='white'` or `contrast_text(bg)` — auto contrast |
| Writing raw OOXML for shadows/glows/3D | Error-prone, inconsistent | `add_shadow(shape, ...)` / `add_glow(shape, ...)` / `shape_3d(...)` |

**Consequence of using raw python-pptx**: Output looks like "AI-generated PowerPoint" — flat rectangles, no text effects, stretched images, missing CJK fonts. This is the #1 AI Tell in PPT design.

### ✅ Correct build.py Template:

```python
from ppt_pro_max.build_helpers import *   # ← ONLY import you need

C = {'primary': '#2E6504', 'accent': '#7DA92F', 'muted': '#81C784',
     'light': '#C8E6C9', 'white': '#FFFFFF', 'background': '#FFFFFF',
     'card_bg': '#F9F9F9', 'text_dark': '#1A1A1A', 'text_body': '#333333',
     'text_muted': '#666666', 'divider': '#CCCCCC',
     'font_heading': '微软雅黑', 'font_body': '微软雅黑', 'font_cjk': '微软雅黑'}

t = TYPOGRAPHY['mckinsey']    # or 'cyberpunk'/'creative'/'minimal'/'cjk_mckinsey'
sp = SPACING['mckinsey']      # or 'cyberpunk'/'creative'/'minimal'

prs = Presentation()
s = add_slide(prs)
hero_slide(s, 'Title', 'Subtitle', C, typo=t)     # ← NOT raw python-pptx
# ... use build_helpers functions for everything
prs.save('output.pptx')
```

### 📖 Function Quick-Find (by scenario):

| I want to... | Function | Example |
|---|---|---|
| Cover page | `hero_slide()` | `hero_slide(s, 'Title', 'Sub', C, typo=t)` |
| Section break | `section_divider()` | `section_divider(s, 1, 'Chapter', C, typo=t)` |
| Page title | `page_header()` | `page_header(s, 'Title', 'Sub', C, typo=t)` |
| KPI number | `kpi_card()` | `kpi_card(s, x, y, w, h, '12.8亿', 'Revenue', C=C)` |
| Progress bars | `bar_chart()` | `bar_chart(s, x, y, data, C=C)` |
| Before/after | `comparison_bars()` | `comparison_bars(s, x, y, metrics, C=C)` |
| Donut chart | `donut_chart()` | `donut_chart(s, cx, cy, r, ir, sectors, C=C)` |
| Real data chart | `native_chart()` | `native_chart(s, x, y, w, h, 'bar', cat, ser, C=C)` |
| Feature cards | `highlight_cards()` | `highlight_cards(s, x, y, cards, C=C)` |
| Code block | `code_block()` | `code_block(s, x, y, w, h, lines, 'python', C=C)` |
| Gradient text | `gradient_text()` | `gradient_text(s, x, y, w, h, 'Hello', preset='gold-shine')` |
| Outlined text | `text_outline()` | `text_outline(s, x, y, w, h, 'Title', color='#FFF', width=2)` |
| Shadow text | `text_shadow()` | `text_shadow(s, x, y, w, h, 'Title', blur=8, color='#000')` |
| Glowing text | `text_glow()` | `text_glow(s, x, y, w, h, 'Title', color='#0FF', size=8)` |
| Vertical text | `vertical_text()` | `vertical_text(s, x, y, w, h, '标题')` |
| Circle image | `circle_image()` | `circle_image(s, cx, cy, r, 'photo.jpg')` |
| Hex image | `hex_image()` | `hex_image(s, cx, cy, size, 'photo.jpg')` |
| Star image | `star_image()` | `star_image(s, cx, cy, size, 'photo.jpg', points=5)` |
| Cover-fit image | `cover_image()` | `cover_image(s, x, y, w, h, 'photo.jpg')` |
| Neon border | `neon_border()` | `neon_border(s, x, y, w, h, color='#8B5CF6')` |
| Glass panel | `glass_panel()` | `glass_panel(s, x, y, w, h, tint='#FFF', alpha=50)` |
| Frosted glass | `frosted_panel()` | `frosted_panel(s, x, y, w, h, tint='#FFF', alpha=50)` |
| Pattern fill | `pattern_fill()` | `pattern_fill(s, x, y, w, h, 'crosshatch', fg, bg)` |
| 3D shape | `shape_3d()` | `shape_3d(s, x, y, w, h, depth=10)` |
| Spotlight overlay | `spotlight()` | `spotlight(s, cx, cy, radius=2, alpha=70)` |
| Shadow on shape | `add_shadow()` | `sh = rect(s,...); add_shadow(sh, blur=8, distance=3)` |
| Glow on shape | `add_glow()` | `sh = rrect(s,...); add_glow(sh, color='#0FF', size=8)` |
| Brush divider | `brush_divider()` | `brush_divider(s, x, y, width, color='#2C2C2C')` |
| Seal stamp | `seal_stamp()` | `seal_stamp(s, x, y, size, '印章文字')` |
| Ink splash | `ink_splash()` | `ink_splash(s, x, y, size, color='#2C2C2C')` |
| Grid background | `grid_background()` | `grid_background(s, spacing=1.0, color='#E0E0E0')` |
| Adjust image | `adjust_image()` | `img = cover_image(s,...); adjust_image(img, brightness=20)` |
| Query design system | `get_design_system()` | `ds = get_design_system('fintech', variance=5)` |
| Analyze PPT | `analyze_pptx()` | `dna = analyze_pptx('template.pptx')` |
| Slide transition | `slide_transition()` | `slide_transition(s, 'fade')` |
| Entrance anim | `entrance_animation()` | `entrance_animation(s, shape_id, 'fade_in')` |
| Exit anim | `exit_animation()` | `exit_animation(s, shape_id, 'fade_out')` |
| Emphasis anim | `emphasis_animation()` | `emphasis_animation(s, shape_id, 'pulse')` |
| Contrast check | `check_contrast()` | `check_contrast('#FFF', '#000')` |
| Auto text color | `contrast_text()` | `contrast_text('#1B5E20')` → '#FFFFFF' |

### 📚 Reference Files (load order):

1. **This SKILL.md** — read workflow + constraints first
2. **[`docs/build_helpers_api.md`](docs/build_helpers_api.md)** — complete function signatures + parameter enums
3. **[`examples/build_10pages.py`](examples/build_10pages.py)** — verified 10-page deck (passes BuildQA 0/0), the canonical build.py reference
4. **[`python-pptx-reference.md`](src/ppt_pro_max/docs/python-pptx-reference.md)** — for UNDERSTANDING python-pptx capabilities only, NOT for direct use in build.py

## ⚠️ Non-Negotiable Sections (DO NOT compress or remove)

These sections are the LLM's only reference for writing correct output:
1. **🎨 Designer Mindset above** — professional design thinking frameworks
2. **⛔ STOP block above** — FORBIDDEN patterns and Quick-Find table
3. **content.json Format** — LLM must know the exact schema to write valid content
4. **brand.json Format** — LLM must know brand spec structure for VI Build mode
5. **Build Helpers API** — LLM must know function signatures to write build.py
6. **UX Intelligence API** — LLM must know how to query the bundled design database for design decisions
7. **Content Design Rules** — LLM must know which content patterns trigger which rendering
8. **Key Constraints** — LLM must know API gotchas and OOXML details
9. **generate_ppt() signature** — LLM must know valid parameters to call the pipeline

## Execution Workflow

ALWAYS follow this 5-step workflow. Each step requires user confirmation before proceeding. Do NOT skip steps or generate final PPT directly — rework is extremely costly.

**Mode selection rule**: ALWAYS use Build Mode for proposal generation. FreeStyle is for agent-driven `content.json` decks (write real content + per-page goals, render directly) or quick one-command drafts. NEVER use FreeStyle for proposals. When in doubt, use Build Mode.

### Step 1: Requirements & Framework (All Modes)

- Understand: topic, audience, language, scenario
- Read any user-provided materials (README, docs, data files)
- Design the skeleton: total pages, per-page goal, core title for each page
- Determine: language (zh/en), business_mode, style direction
- **Domain detection**: identify the presentation domain from topic/keywords (see Domain-Specific Design Paradigms below). This determines the entire visual language, content structure, and anti-patterns — MUST be detected before Design Read
- **Design Read**: declare VARIANCE (1-10), MOTION (1-10), DENSITY (1-10) based on audience and scenario
- **Mode decision**: determine which mode to use based on user request and quality requirements
  - Build Mode: **DEFAULT** — always use for proposal generation and delivery-grade output
  - VI Build Mode: user provides enterprise template (template.pptx) + requests brand compliance
  - FreeStyle: agent-driven `content.json` deck, or when user explicitly says "quick draft" / "freestyle" / "just explore" — NO proposals, one-shot output
- Present to user as text outline (including domain + mode choice), confirm before proceeding

**Dial → Action Map (V/M/D → LLM decisions):**

| VARIANCE | FreeStyle Action | Build/VI Build Action |
|----------|-----------------|----------------------|
| 1-3 | `goal:"content"` + centered layouts; `--layout-variant centered` | Uniform page structure; consistent margins; same component family per page |
| 4-7 | Mix `goal:"content"` with `goal:"features"`; `--layout-variant sidebar-left` | Mix 2-3 layout strategies (e.g., sidebar + grid + split); vary which pages use which strategy |
| 8-10 | Diverse goal types; `--layout-variant asymmetric`; section dividers | Every page uses a different layout strategy; no repeated visual pattern; section dividers between topic shifts |

| MOTION | FreeStyle Action | Build/VI Build Action |
|--------|-----------------|----------------------|
| 1-3 | Default transitions only | No animations; `slide_transition()` with fade only |
| 4-7 | `goal:"hook"` gets fade-in; section dividers get entrance animation | `entrance_animation()` on key elements; `slide_transition()` on section dividers |
| 8-10 | `--motion 8`; more section dividers for variety | `entrance_animation()` + `exit_animation()` on multiple elements; morph transitions; staggered delays |

| DENSITY | FreeStyle Action | Build/VI Build Action |
|---------|-----------------|----------------------|
| 1-3 | 2-3 bullets; breathing pages after every 2 content pages | Generous spacing; `SPACING['minimal']`; 1-2 elements per page zone |
| 4-7 | 3-5 bullets; mix densities | `SPACING['mckinsey']`; mix KPI cards with bullet pages |
| 8-10 | 6+ bullets; `component_type:"group"` + `component_category:"infographic"` | `SPACING['cyberpunk']`; dense dashboards; `kpi_card()` grids; `bar_chart()` stacks |

### Step 2: Visual Proposals (3 structurally-different build.py) — MANDATORY

**⚠️ ALWAYS generate 3 structurally-different build.py proposals. NEVER use FreeStyle `generate_ppt()` × 3 with different `--style` as proposals — that only swaps palette/font and produces identical layouts, which is garbage.**

#### ⛔ Pre-Flight: Read Build Helpers API (MANDATORY before writing build.py)

**Do NOT write any build.py code until you have confirmed the following checklist.** This is the #1 cause of low-quality output: LLMs skip reading the API and use raw python-pptx instead.

**Pre-flight checklist** (confirm each before proceeding):
- [ ] I have read the "Build Helpers API" section and know the available functions
- [ ] I have identified which functions I need for each page (use the Quick-Find table above)
- [ ] I will NOT use `slide.shapes.add_shape()`, `slide.shapes.add_textbox()`, or `slide.shapes.add_picture()` — these are FORBIDDEN
- [ ] I will use `cover_image()` for all images (never `add_picture()` with stretch)
- [ ] I will use color role names (`'primary'`, `'accent'`) instead of raw hex in function calls
- [ ] For CJK content, I will use `TYPOGRAPHY['cjk_mckinsey']` or `cjk_professional` (body=14-15pt, not 11-12pt)

Each proposal must have a **completely different page structure, layout strategy, and visual language** — not just a palette/font swap. The 3 proposals must be structurally distinct so the user can compare different architectural approaches.

#### Build Mode Proposals (No Template)

Generate 3 lightweight `build.py` scripts (proposal_A.py, proposal_B.py, proposal_C.py), each rendering 4-5 key pages (cover + 1 content + 1 data/features + 1 cta) with:

| Proposal | Differentiation Strategy | Example |
|----------|-------------------------|---------|
| **A** | Structure closest to user's style description | "McKinsey" → sidebar + table + numbered cards |
| **B** | Same topic, alternative layout architecture | "McKinsey topic" → grid dashboard + KPI cards + bar charts |
| **C** | Radical visual departure | "McKinsey topic" → creative circles + emoji + before-after comparison |

**Structural differentiation dimensions (pick ≥2 per proposal to differ):**

| Dimension | Options | What Changes in build.py |
|-----------|---------|--------------------------|
| Page structure | sidebar-left / full-width / grid-2x2 / split-image | `page_header()` position, content zone x/y/w/h |
| Data presentation | table / bar_chart / kpi_card grid / donut_chart | Which `build_helpers` functions are called |
| Card style | highlight_cards / custom rrect stack / numbered list | Card component choice and layout |
| Cover type | hero_slide / section_divider / custom split | Cover page function calls |
| Typography scale | TYPOGRAPHY['mckinsey'] / ['cyberpunk'] / ['creative'] / ['minimal'] | `t = TYPOGRAPHY[...]` selection |
| Spacing system | SPACING['mckinsey'] / ['cyberpunk'] / ['creative'] / ['minimal'] | `sp = SPACING[...]` selection |
| Color system | C dict with different primary/accent/muted | Color token values in C dict |

**Proposal generation workflow:**

1. **UX Intelligence Query** — BEFORE writing any build.py, query the bundled design database for domain-specific design knowledge:
   ```python
   from ppt_pro_max.adapters.ui_ux_adapter import (
       is_available, get_design_system, search_design,
       search_style, search_color, search_typography,
   )

   if is_available():
       ds = get_design_system("your query", variance=V, motion=M, density=D)
       ux_colors = ds.get('colors', {})          # e.g. {'primary': '#7C3AED', 'background': '#FAF5FF', ...}
       ux_typo = ds.get('typography', {})         # e.g. {'heading': 'Inter', 'body': 'Inter', ...}
       ux_style = ds.get('style_name', '')        # e.g. 'AI-Native UI'
       ux_effects = ds.get('style_effects', '')   # e.g. 'Glassmorphism + micro-interactions'
       ux_anti = ds.get('anti_patterns', '')      # e.g. 'Heavy chrome + Slow response feedback'
       ux_pattern = ds.get('pattern_name', '')    # e.g. 'SaaS Landing'
       ux_dials = ds.get('dials', {})             # variance/motion/density recommendations

       # Enrich with style/color/typography searches
       style_results = search_style("professional consulting", 2)
       color_results = search_color("dark tech", 2)
       typo_results = search_typography("modern sans", 2)
   ```
   Use `ux_colors` as the **primary source** for the `C` dict instead of hardcoding colors. Use `ux_anti` to avoid known anti-patterns. Use `ux_effects` to guide decoration/animation choices.

2. Write 3 build.py files (proposal_A.py, proposal_B.py, proposal_C.py) with:
   - Different `C` color dict derived from design database search results (3 distinct palettes)
   - Different `TYPOGRAPHY[...]` and `SPACING[...]` selections informed by ux_typo
   - Different page structure and component choices per page
   - Same framework content (titles + placeholder data) so user compares structure, not content
3. Run each: `python proposal_A.py`, `python proposal_B.py`, `python proposal_C.py`
4. Present 3 output PPTs to user with descriptions:
   - **A**: "Sidebar + table layout — consulting style, structured and data-driven"
   - **B**: "Grid dashboard — tech-forward, KPI-focused, information-dense"
   - **C**: "Creative circles — visual storytelling, emoji-accented, approachable"
5. User picks one direction (A/B/C) or requests adjustments
6. Low rework cost: only structural parameters change, content is placeholder

**Example proposal_A.py (McKinsey-style skeleton with UX intelligence):**

```python
from ppt_pro_max.build_helpers import *
from ppt_pro_max.adapters.ui_ux_adapter import get_design_system, search_color, search_typography

# Step 1: Query UX intelligence for design decisions
ds = get_design_system('investor pitch', variance=5, motion=3, density=5)
ux_colors = ds.get('colors', {})
ux_anti = ds.get('anti_patterns', '')  # Use to avoid bad patterns

# Step 2: Build C dict from UX intelligence (not hardcoded)
C = {
    'primary': ux_colors.get('primary', '#2E6504'),
    'accent': ux_colors.get('accent', '#7DA92F'),
    'muted': ux_colors.get('muted', '#81C784'),
    'light': ux_colors.get('border', '#C8E6C9'),
    'white': '#FFFFFF',
    'background': ux_colors.get('background', '#FFFFFF'),
    'card_bg': '#F9F9F9',
    'text_dark': ux_colors.get('foreground', '#1A1A1A'),
    'text_body': ux_colors.get('text', '#333333'),
    'text_muted': '#666666',
    'divider': '#CCCCCC',
    'font_heading': 'Georgia', 'font_body': 'Calibri',
}
t = TYPOGRAPHY['mckinsey']
sp = SPACING['mckinsey']

prs = Presentation()
s = add_slide(prs)
hero_slide(s, '{query}', 'Proposal A — Sidebar + Table', C=C, typo=t)

s = add_slide(prs)
page_header(s, 'Current Challenges', 'Key obstacles to growth', C, typo=t, spacing=sp)
# sidebar + bullets layout
rect(s, 0, 0, 3.5, 7.5, C['primary'], C=C)
multiline(s, 0.4, 1.5, 2.7, 4, ['Challenge 1', 'Challenge 2', 'Challenge 3'],
          font_size=t.body, color='white', C=C)

s = add_slide(prs)
page_header(s, 'Key Metrics', 'Performance overview', C, typo=t, spacing=sp)
kpi_card(s, 0.65, 1.8, 3.8, 1.35, '12.8亿', '年度产值', '+8.3%', C=C, typo=t)
kpi_card(s, 4.8, 1.8, 3.8, 1.35, '94.2%', '客户满意度', '+2.1%', C=C, typo=t)

s = add_slide(prs)
cta_slide(s, 'Get Started', 'Contact us today', C=C, typo=t)

prs.save('proposal_A.pptx')
```

#### VI Build Mode Proposals (With Template)

When user provides a template.pptx, proposals must preserve framework pages (cover/TOC/back cover) and only vary the **new content page structure**. All 3 proposals share the same VI Token (extracted from template), but differ in layout architecture for content pages.

1. Run `python -m ppt_pro_max analyze template.pptx > analysis.txt`
2. Extract VI Token (C dict) from analysis.txt — this is **fixed** across all 3 proposals
3. Generate 3 build.py files with:
   - **Same** C dict (VI Token from template)
   - **Same** `Presentation('template.pptx')` + `copy_decorations()` + `copy_logo()` on every page
   - **Different** content page layout strategies (sidebar vs grid vs split)
   - **Different** component choices for data pages (kpi_card vs bar_chart vs table)
4. Run each, present to user, user picks direction

**Example VI Build proposal differentiation:**

| Proposal | Content Page Layout | Data Page Component | Visual Character |
|----------|--------------------|--------------------|-----------------|
| A | Sidebar + content (left nav bar) | kpi_card row | Structured, report-style |
| B | Full-width + section dividers | bar_chart + comparison_bars | Narrative, story-driven |
| C | Grid 2x2 + cards | donut_chart + highlight_cards | Dashboard, data-centric |

### Step 3: Detailed Content (All Modes)

**Build/VI Build Mode:**
- Write full content for every page directly into the chosen build.py
- Content is hardcoded per page: titles, KPI numbers, bullet text, chart data, code snippets
- MUST be query-specific and domain-accurate — NEVER use generic template content
- MUST follow the Content Design Rules below
- Present key content to user for review before final generation
- User confirms content accuracy before proceeding

**FreeStyle Mode (agent-driven content.json or quick draft):**
- Path A: you write `content.json` (real content, per-page `goal` + field selection), then `generate_ppt(content_file="content.json", style=..., ...)` renders it directly — see [content.json Format](#contentjson-format)
- Path B: one-command draft `generate_ppt("topic", style=..., fetch_images=True, ...)`
- No proposal step — one-shot output
- For revisions: modify content.json and regenerate, or edit the slide count/fields

### Step 4: Draft Generation & Revision (All Modes)

**Build/VI Build Mode:**
- Run the full build.py: `python build.py`
- Verify output: check page count, file size, content rendering, shape count per slide
- For revisions: modify build.py and re-run (build.py is the single source of truth)
- Version control: save output to `output/v1/`, increment on revisions

**FreeStyle Mode (agent-driven content.json or quick draft):**
- Generate full PPT: `generate_ppt(content_file="content.json", style=confirmed_style, fetch_images=True, ...)` (query optional)
- Verify output: check page count, file size, content rendering
- For revisions: modify content.json and regenerate, or edit the slide count/fields

### Step 5: Final Delivery (All Modes)

- User confirms satisfaction
- Pipeline auto-saves with version control

### Content Design Rules (CRITICAL — maximizes design quality)

When writing content (content.json for FreeStyle, or hardcoded text in build.py for Build/VI Build), follow these rules to produce the best possible rendering output.

| Rule | Why | FreeStyle Example | Build Example |
|------|-----|-------------------|---------------|
| features: first card featured with longer body | First card gets gradient bar + 22pt title + higher elevation | Card 1: "智能推理引擎 — 自动选择最优框架" vs Card 2: "全链路监控" | `highlight_cards()`: first tuple gets accent bar + larger title |
| 6+ bullets → two-column layout | Better density; layout engine auto-splits | 6 concise data points instead of 3 long ones | Use two `multiline()` calls side by side, or `kpi_card()` grid |
| tech topics: include code page | Code pages add technical credibility | `{"code": {"language": "python", "source": "..."}}` | `code_block(slide, left, top, w, h, lines, language='python', C=C)` |
| education/training: include exercise page | Exercise pages add interactivity | `{"exercise": {"duration": "5 min", "steps": [...]}}` | Custom: `rrect()` badge + `multiline()` numbered steps |
| topic transitions: insert section divider | Visual rhythm (oversized number + gradient line) | Between problem→solution | `section_divider(slide, 2, 'Solution', C=C, typo=t)` |
| hook: short subtitle (<40 chars); cta: long (>60) | Different hero compositions | hook: "5分钟取代5周" vs cta: "免费额度包含1000次推理/月" | `hero_slide(slide, title, short_sub, C=C)` / `cta_slide(slide, title, long_sub, C=C)` |
| vary bullet density (some 3-bullet, some 6+) | Varying density feels natural; 10+ items → cards/grid/table, never list | Don't make every page the same density | Mix `multiline()` pages with `kpi_card()` / `bar_chart()` pages |
| use concrete real data; no fake precision | "GPU成本年增3倍" not "成本持续增长"; no fabricated 92%/4.1× | Real data only; mark as "example" if hypothetical | Same — hardcode real numbers in `kpi_card()` and `bar_chart()` data |
| ≤5 bullets: single column | 6+: two-column; 10+: use cards/grid/infographic component, never list | 3 bullets → single col; 7 bullets → two-col | 3 bullets → one `multiline()`; 6+ → two `multiline()` or `highlight_cards()` |
| no filler verbs (赋能/领先/一站式/生态/革新/引领) | AI-generated buzzwords destroy credibility | Use plain functional language | Same — hardcode plain language in build.py |
| quotes ≤3 lines, attribution = name+title | PPT quotes are fragments, not full reviews | "Name, CTO, Company" — never name alone | Same for `text()` content |
| theme lock: one theme per deck, no mid-deck switch | Dark stays dark, light stays light; micro-variation OK | #0A1E3D → #0F2847 OK; #0A1E3D → #FFF8F0 NOT OK | Same C dict throughout; no mixing primary/accent mid-deck |

### Domain-Specific Content Rules (OVERRIDE above rules when domain matches)

**Scientific Research — these rules REPLACE the business defaults:**

| Rule | Why | Implementation |
|------|-----|----------------|
| Every data page = one Figure with caption | Journal convention; audience expects Figure-style | `text(slide, x, y, w, 0.3, 'Figure N: ...', font_size=10)` below visual |
| Use semantic biology colors, not brand accent | Red=upregulated, blue=downregulated has scientific meaning | C dict with `up_color`, `down_color`, `control_color` instead of `primary`/`accent` |
| Cite every claim: (Author, Year) or superscript | Uncited claims = scientific fraud | `text(slide, x, y, w, 0.2, '¹Smith et al., Nature 2024', font_size=8, color='text_muted')` |
| NO KPI cards, NO hero slides, NO feature cards | These are business patterns, meaningless in science | Use Figure+caption, data tables, sequence views instead |
| Cover = paper title format | Title + authors + affiliation, not marketing hero | `text()` title (28pt) + `multiline()` authors (14pt) + `text()` affiliation (12pt) |
| No animation or transition | Research slides must be printable as-is | Skip all `entrance_animation()` / `slide_transition()` calls |
| Panel labels (A, B, C) on multi-panel figures | Standard journal figure convention | `text(slide, x, y, 0.4, 0.3, 'A)', font_size=10, bold=True)` |
| Axis labels on all charts | Data without axis labels is uninterpretable | `text(slide, x, y, w, 0.3, 'Expression (log₂FC)', font_size=9)` |

**Academic Thesis — additional rules:**

| Rule | Why | Implementation |
|------|-----|----------------|
| Chapter-flow structure, not story arc | Thesis defense follows chapter order, not marketing arc | Ch1 Introduction → Ch2 Methods → Ch3 Results → Ch4 Discussion |
| Bibliography slide at end | Required for academic completeness | `multiline()` with numbered references (8-9pt) |
| Advisor/committee on cover | Academic protocol | `text()` advisor name + title on cover slide |

**Medical/Clinical — additional rules:**

| Rule | Why | Implementation |
|------|-----|----------------|
| Evidence level labels | Clinical decisions require evidence grading | `text(slide, x, y, w, 0.2, '[Level A evidence]', font_size=9, color='text_muted')` |
| Disclaimers where applicable | Regulatory requirement | `text(slide, x, y, w, 0.3, 'Disclaimer: ...', font_size=8, color='text_muted')` |
| No decorative visuals | Patient safety > aesthetics | No `neon_border()`, `brush_divider()`, `ink_splash()` |

## When to Activate

- User asks to create/generate/design a **PPT/presentation/deck/slide deck**
- User wants a **pitch deck, product demo, sales presentation, investor deck**
- User wants to **convert content/outline into PowerPoint**
- User wants **brand-compliant** presentations with template + version control
- User wants **page-level CRUD** on existing PPT (add/delete/swap/move pages)
- User wants **diagrams** in PPT (flowchart, funnel, timeline, SWOT, etc.)
- User provides a **template.pptx** and wants enterprise VI compliance
- User wants **scientific/academic** presentation (gene, protein, thesis, dissertation, 论文, 答辩, 实验)
- User wants **medical/clinical** presentation (diagnosis, treatment, clinical trial, 诊断, 临床)
- **Default**: Build Mode is always used unless user explicitly says "quick draft" / "freestyle"

## Three-Mode Architecture

| | **Build Script** | **VI Build** | FreeStyle |
|---|---|---|---|
| **Use case** | Delivery-grade, no template | **Enterprise VI compliance** | Agent-driven content.json OR quick draft (NO proposals) |
| **Trigger** | **DEFAULT** — always use unless user says "quick draft" | User provides template.pptx + requests brand compliance | You write content.json with real content, or user says "quick draft" / "freestyle" |
| **Content source** | Hardcoded per page in build.py | LLM reads template analysis, generates build.py | **You write content.json** (recommended) or one-liner topic |
| **Brand compliance** | Design Token dict `C` | **Extracted VI Token from template** | Style atom combos |
| **Layout control** | **Per-element x/y/w/h** | **Preserve framework pages + build_helpers for new** | goal + field selection (10 layout branches) |
| **Font control** | **Run-level per character** | **Run-level + template font inheritance** | Theme-level |
| **Template reuse** | None | **Framework pages preserved + decorations/LOGO copied** | None |
| **Proposal type** | 3 build.py (structural differentiation) | 3 build.py (layout strategy differentiation, same VI Token) | **NO proposals** — one-shot output only |
| **Quality ceiling** | ★★★★★ | ★★★★★ | ★★★★ (goal-driven, fixed positions) |

> **Mandatory workflow**: ALWAYS use Build Mode for proposals (3 structurally-different build.py). FreeStyle is for agent-driven content.json decks or quick one-shot drafts — NEVER use FreeStyle for proposal generation.

### Build Mode (Pixel-Perfect Delivery) — DEFAULT & PRIMARY DELIVERY MODE

LLM writes `build.py` scripts from blank canvas, using build_helpers for maximum per-element control. This is the highest-quality output mode with full control over every shape's position, size, color, and typography.

**When to use**: ALWAYS the default mode. Use for all proposal generation and delivery-grade output (investor deck, board presentation, client deliverable). Only fall back to FreeStyle when user explicitly says "quick draft".

```bash
# LLM generates build.py, then:
python build.py
```

**Build Mode workflow (follow Execution Workflow Steps 1-5 with Build-specific Step 2):**

1. Step 1: Requirements & Framework (same as all modes)
2. Step 2: Generate 3 structurally-different build.py proposals → user picks direction
3. Step 3: Fill chosen build.py with full content
4. Step 4: Run build.py → verify → revise
5. Step 5: Final delivery

See **Build Helpers API** section below for function reference.

### VI Build Mode (Enterprise Template Compliance)

LLM reads template analysis, generates build.py that preserves framework pages (cover/TOC/back cover) and uses `build_helpers` for new content pages.

```bash
# Step 1: Analyze template
python -m ppt_pro_max analyze template.pptx > analysis.txt

# Step 2: Give analysis.txt to LLM, which generates build.py

# Step 3: Run build.py
python build.py
```

**VI Build workflow in build.py:**

```python
from ppt_pro_max.build_helpers import *

# VI Token extracted from template analysis
C = {
    'primary': '#2E6504', 'accent': '#7DA92F', 'muted': '#81C784',
    'light': '#C8E6C9', 'white': '#FFFFFF', 'background': '#FFFFFF',
    'card_bg': '#F9F9F9', 'text_dark': '#1A1A1A', 'text_body': '#333333',
    'text_muted': '#666666', 'divider': '#CCCCCC',
    'font_heading': '微软雅黑', 'font_body': '微软雅黑',
}

# Load template (NOT Presentation() from scratch)
prs = Presentation('template.pptx')
template_slide = prs.slides[0]  # Reference for copying decorations/LOGO

# Framework pages (cover, TOC, back cover) are preserved — do NOT delete them
# Add new content pages:
s = add_slide(prs)
copy_decorations(s, template_slide)  # Copy visual elements from template
copy_logo(s, template_slide, color_hints=['#2E6504'])  # Copy company LOGO
page_header(s, 'Revenue Overview', 'FY2025 Performance', C)
kpi_card(s, 0.65, 1.8, 3.8, 1.35, '12.8亿', '年度产值', '+8.3%', C=C)

prs.save('output.pptx')
```

**Key differences from Build Script:**
- Start with `Presentation('template.pptx')` NOT `Presentation()`
- Framework pages (cover/TOC/back cover) are preserved untouched
- Use `copy_decorations()` / `copy_logo()` to maintain VI consistency
- VI Token (`C` dict) extracted from `ppt-design analyze` output, not hand-written

### FreeStyle Mode (Agent-Driven content.json — NO Proposals)

FreeStyle renders a deck from a **content.json you write** (recommended, agent-driven) OR from a one-liner topic string (legacy quick draft). **NO proposal step** — one-shot output only. Use when user says "quick draft" / "freestyle" / "just explore", or when you need a fast, fully-editable deck.

**⚠️ NEVER use FreeStyle for proposal generation.** Calling `generate_ppt()` × 3 with different `--style` only swaps palette/font and produces identical layouts — this is NOT a valid proposal. Use Build Mode (build.py) for proposals.

#### Path A (Recommended): You write content.json → render

In an agent environment **you are the LLM** — you don't need Python to call an API for content. Write a `content.json` with real content and per-page `goal`, then call `generate_ppt(content_file=...)`. This is the deterministic, high-quality path: you control every page's content AND which render branch it uses.

```python
# query is optional when content_file contains slides[]
result = generate_ppt(content_file="content.json", style="dark-tech")
```

**Three-layer orthogonality:**
- `content.json` controls **content** (title/subtitle/bullets/cards/chart/code/diagram/exercise) + **layout role** (`goal` field → render branch)
- `style` param controls **visuals** (colors/fonts/decorations → ThemeComposer → BrandSpec)
- renderer's `goal` branches control **structure**

Prefer **preset** style names for deterministic output (`dark-tech`, `professional`, `warm-elegant`, ...). Natural-language styles like `"dark cyberpunk"` resolve via mood detection and may produce different palettes.

See [content.json Format](#contentjson-format) below for the full schema and design rules (chart format, section_number, field-to-layout mapping).

#### Path B (Quick draft): one-liner topic

```bash
python -m ppt_pro_max "AI startup investor pitch"

# Natural language style (40K+ combos)
python -m ppt_pro_max "fintech pitch" --style "warm fintech"
python -m ppt_pro_max "product launch" --style "dark cyberpunk"

# AI images (Seedream recommended)
python -m ppt_pro_max "AI pitch" --fetch-images --llm-provider seedream

# Exact atom control
python -m ppt_pro_max "pitch" --palette wine-burgundy --fonts elegant-serif --layout-variant centered

# Design dials
python -m ppt_pro_max "pitch" --variance 7 --motion 5 --density 6
```

## Domain-Specific Design Paradigms

**⚠️ CRITICAL: Detect domain BEFORE designing.** Using the wrong paradigm produces fundamentally mismatched output (e.g., McKinsey sidebar on a genomics slide). The domain determines visual language, content structure, typography, color system, and anti-patterns.

### How to Detect Domain

Match user topic/keywords to the paradigm with the most keyword hits. If ambiguous, ask the user.

| Domain | Trigger Keywords |
|--------|-----------------|
| Scientific Research | gene, protein, genome, sequencing, CRISPR, pathway, assay, omics, PCR, RNA, DNA, expression, mutation, variant, bioinformatics, proteomics, metabolomics, single-cell, immunotherapy, checkpoint, clinical trial, CRISPR, 序列, 基因, 蛋白, 测序, 组学, 免疫, 细胞, 实验, 通路, 变异 |
| Academic Thesis | thesis, dissertation, defense, viva, 论文答辩, 毕业, 学位, 答辩 |
| Engineering/Technical | architecture, system design, infrastructure, deployment, API, microservice, 架构, 系统, 部署, 工程 |
| Medical/Clinical | diagnosis, treatment, patient, clinical, surgery, therapy, 诊断, 治疗, 患者, 临床, 手术 |
| Government/Public Sector | policy, regulation, compliance, budget, annual report, 政策, 法规, 合规, 预算, 年报 |
| Business (default) | pitch, investor, sales, marketing, product launch, KPI, revenue, 投资人, 销售, 营销, 产品发布 |

### Scientific Research Paradigm

**Visual language**: Nature/Cell/Figure style — NOT business slides. Every data page looks like a journal figure, not a marketing card.

| Aspect | DO (Research) | DON'T (Business anti-pattern) |
|--------|---------------|------------------------------|
| **Page structure** | Figure + caption below; one main visual per page | KPI cards, sidebar layout, feature cards |
| **Data visualization** | Sequence alignment, heat map, volcano plot, Manhattan plot, phylogenetic tree, gel electrophoresis, chromatogram | Bar charts with KPI labels, donut charts |
| **Numbering** | Figure 1, Figure 2, Figure 3... per page (required) | "01/04" card numbering (banned in business but REQUIRED here) |
| **Color system** | Semantic biology colors: blue=downregulation, red=upregulation, green=control, purple=mutation; or journal-specific palettes (Nature blue/gray, Cell warm) | Brand accent colors, gradient fills |
| **Typography** | Clean serif or sans-serif (Arial/Helvetica); figure labels 9-11pt; axis labels 10-12pt | Hero-sized titles, gradient text |
| **Citations** | Required: (Author, Year) or superscript number¹ after claims | No citations (business slides don't cite) |
| **Cover** | Paper title style: title + authors + affiliation + journal-style layout | Hero image + gradient overlay |
| **Content flow** | Background → Methods → Results (Fig 1-4) → Discussion → References | Hook → Problem → Features → CTA |
| **Animation** | NONE — research slides must be printable as-is | Any animation or transition |

**Research content structure (per page):**

```
┌──────────────────────────────────┐
│ Figure 3: ERK pathway activation │  ← Figure label (9-11pt, top-left)
│                                  │
│    [Main figure/visualization]   │  ← Full-width data visual
│                                  │
│ A) Western blot  B) Quantification│  ← Panel labels (A, B, C...)
│                                  │
│ ERK phosphorylation increased    │  ← Caption text (10-11pt)
│ 3.2-fold (p<0.01)¹              │  ← Citation
└──────────────────────────────────┘
```

**Research Build Mode components:**

| Component | Implementation |
|-----------|---------------|
| Figure label | `text(slide, 0.5, 0.3, 6, 0.3, 'Figure 3:', font_size=10, color='text_dark', bold=True, C=C)` |
| Panel label (A/B/C) | `text(slide, x, y, 0.4, 0.3, 'A)', font_size=10, bold=True, C=C)` |
| Axis labels | `text(slide, x, y, w, 0.3, 'Expression (log₂FC)', font_size=9, C=C)` |
| Data table | `rect()` header row + `multiline()` data rows with alternating `rrect()` backgrounds |
| Sequence alignment | Custom: `rrect()` colored blocks per residue (A=green, T=red, G=yellow, C=blue) |
| Heat map grid | Nested `rrect()` cells with color-coded fills per expression level |
| Citation | `text(slide, x, y, w, 0.2, '¹Smith et al., Nature 2024', font_size=8, color='text_muted', C=C)` |

**Research color palettes:**

| Palette | Colors | Use When |
|---------|--------|----------|
| `nature` | #2C3E50 (text), #3498DB (data blue), #E74C3C (highlight red), #95A5A6 (neutral) | General biology

…(truncated)
