Skill: boboy-j/html-ppt-skill (version 1.0.0)

--- name: html-ppt description: > 制作以 HTML 为载体的幻灯片演示文稿（代替传统 PPT/PPTX）。每张幻灯片严格遵循 16:9 比例，使用 CSS scroll-snap 实现翻页，支持键盘/滚轮操作，并可通过浏览器打印导出 PDF。 每当用户提到"做 PPT"、"做幻灯片"、"做演示文稿"、"写 PPT"、"制作 slides"、"deck" 等关键词时，必须触发本 skill，优先以 HTML 形式交付，而非生成 .pptx 文件。 即使用户只说"帮我做个介绍某主题的 PPT"而未指明格式，也应主动采用本 skill 的方案。 --- # HTML PPT Skill 用 HTML + CSS 制作媲美专业设计软件的幻灯片，视觉效果远超传统 PPT 工具。 ## 核心规范（必须遵守） ### 1. 比例与分页 ```css /* 每张幻灯片：宽 = 100vw，高 = 56.25vw（即 9/16）*/ .slide { width: 100vw; height: 56.25vw; overflow: hidden; scroll-snap-align: start; scroll-snap-stop: always; } /* body 开启强制对齐 */ body { scroll-snap-type: y mandatory; overflow-y: scroll; height: 100%; } html { height: 100%; } ``` **原理**：`56.25vw = 9/16 × 100vw`，无论屏幕分辨率如何，每页都精确为 16:9。 ### 2. 打印 / 导出 PDF ```css @media print { html, body { height: auto; overflow: visible; scroll-snap-type: none; } #nav-dots, #nav-arrows { display: none !important; } .slide { width: 297mm; height: 167.0625mm; /* 297 × 9/16 = 167.0625 */ page-break-after: always; break-after: page; scroll-snap-align: none; } } ``` 用户按 **Ctrl+P → 另存为 PDF** 即可导出，每页精确对应一张幻灯片。 ### 3. 导航 JS（标准实现，每次必须包含） ```javascript const slides = Array.from(document.querySelectorAll('.slide')); let current = 0; function goTo(i) { i = Math.max(0, Math.min(slides.length - 1, i)); slides[i].scrollIntoView({ behavior: 'smooth' }); current = i; updateDots(i); } // 键盘支持 document.addEventListener('keydown', e => { if (['ArrowDown','ArrowRight','PageDown'].includes(e.key)) { e.preventDefault(); goTo(current+1); } if (['ArrowUp','ArrowLeft','PageUp'].includes(e.key)) { e.preventDefault(); goTo(current-1); } }); // IntersectionObserver 同步当前页 const io = new IntersectionObserver(entries => { entries.forEach(en => { if (en.isIntersecting) { current = slides.indexOf(en.target); updateDots(current); }}); }, { threshold: 0.6 }); slides.forEach(s => io.observe(s)); ``` --- ## 标准文件结构 每次生成的 HTML 文件必须包含以下部分： ``` <head> Google Fonts 引入（选择与主题匹配的中文字体） <style> 1. CSS 变量（颜色、字体） 2. 核心框架（slide 比例、scroll-snap、body） 3. 导航组件样式（dots、arrows） 4. 通用设计组件（见下方） 5. @media print </style> </head> <body> <nav id="nav-dots">（自动生成）</nav> <div id="nav-arrows">↑ ↓ 按钮</div> <section class="slide" id="slide-1"> ... </section> <section class="slide" id="slide-2"> ... </section> ... <script> 导航逻辑 </script> </body> ``` --- ## 设计规范 详细设计组件库见 `references/design-system.md`。 ### 字体选择原则 - **中文展示字体**：`ZCOOL XiaoWei`（庄重）、`Ma Shan Zheng`（书法）、`Long Cang`（手写） - **中文正文字体**：`Noto Serif SC`（衬线）、`Noto Sans SC`（无衬线） - **英文展示字体**：`Playfair Display`、`Cormorant Garamond`、`Space Mono` - **禁止使用**：Arial、Inter、Roboto、system-ui（太通用，无设计感） ### 颜色主题选择 根据演示主题选择合适的色系，参考 `references/design-system.md` 中的预设主题。 ### 每张幻灯片的尺寸感知 - 字体大小使用 `vw` 单位（如 `3.5vw`），随屏幕等比缩放 - 间距使用 `%` 或 `vw` 单位，避免固定 `px` - 内容区 padding 建议：`4% 6%` --- ## 典型页面类型 | 页面类型 | 适用场景 | 布局要点 | |----------|----------|----------| | 封面页 | 第一页 | 大标题居中或左对齐，背景有视觉冲击力 | | 目录页 | 第二页 | 2×2 或 1×N 卡片网格列举章节 | | 双栏内容页 | 文字+图/列表 | `grid-template-columns: 1fr 1fr` | | 全图页 | 视觉冲击 | 图片铺满，文字叠加半透明遮罩 | | 数据页 | 展示指标 | 大数字 + 进度条 + 说明文字 | | 时间线页 | 历史/流程 | 横向或纵向时间轴 | | 引用页 | 金句/观点 | 超大引号装饰，居中排版 | | 结尾页 | 致谢/Q&A | 简洁有力，附联系方式或行动引导 | --- ## 工作流程 接到 PPT 制作需求时，按以下步骤执行： 1. **理解需求**：主题、受众、页数、风格偏好（科技/商务/学术/文化） 2. **选定主题**：从 `references/design-system.md` 选择或创建配色方案 3. **规划页面**：确定每页类型和内容大纲 4. **逐页编写**：每张 `.slide` 按内容量和页面类型选择合适布局 5. **检查清单**（完成后必须自查）： - [ ] 每页都有 `class="slide"` 和 `id="slide-N"` - [ ] 每页底部有页码 `<span class="slide-num">N / Total</span>` - [ ] body 有 `scroll-snap-type: y mandatory` - [ ] 包含键盘导航 JS - [ ] 包含 `@media print` 样式 - [ ] 所有字体大小用 `vw` 单位（非 `px`） - [ ] 文件输出到 `/mnt/user-data/outputs/` 并调用 `present_files` --- ## 快速参考：CSS 变量模板 ```css :root { /* 根据主题替换以下变量 */ --c-bg: #0D0F14; /* 背景色 */ --c-surface: #151820; /* 卡片背景 */ --c-border: rgba(255,255,255,0.08); --c-accent: #4F8EF7; /* 主强调色 */ --c-accent2: #A78BFA; /* 副强调色 */ --c-text: #F0F2F8; /* 主文字色 */ --c-muted: rgba(240,242,248,0.45); /* 次要文字 */ --f-display: 'ZCOOL XiaoWei', serif; --f-body: 'Noto Sans SC', sans-serif; /* 固定不变 */ --slide-w: 100vw; --slide-h: 56.25vw; } ```

path: README.md
content: # HTML PPT Skill — 用 HTML + CSS 制作专业幻灯片

> **版本**：V1.0.0  
> **语言**：HTML / CSS / JavaScript  
> **核心理念**：用 Web 技术取代传统 PPT/PPTX，制作 16:9 比例、可键盘翻页、可导出 PDF 的专业演示文稿。

---

## 概述

HTML PPT Skill 是一套完整的基于 HTML + CSS 制作幻灯片的工作流方案。与 PowerPoint / Keynote / Canva 等传统工具不同，它利用 **CSS `scroll-snap`** 实现精准的页面切割，以 **16:9 视口比例** 固定每张幻灯片，最终可通过浏览器 **Ctrl+P 导出为 PDF**。

适用场景：
- 技术分享 / 开发者演讲
- 学术报告 / 论文答辩
- 品牌宣传 / 产品路演
- 企业文化 / 历史展示

---

## 特性

| 特性 | 说明 |
|------|------|
| 🎯 **16:9 精确比例** | 每张幻灯片严格 `100vw × 56.25vw`，任何屏幕均等比例显示 |
| ⌨️ **键盘导航** | `↑ ↓ ← → PageUp PageDown` 均可翻页 |
| 🔵 **导航指示器** | 右侧圆点导航 + 底部箭头按钮，自动高亮当前页 |
| 🖨️ **一键导出 PDF** | 浏览器打印 → 另存为 PDF，每页精确对应一张幻灯片 |
| 📱 **响应式** | 所有尺寸使用 `vw` 单位，手机 / 平板 / 投影仪等比缩放 |
| 🎨 **预设主题** | 6 套精心搭配的配色方案（深空暗黑、金墨、自然绿、纯白简约、暖橙、冰蓝） |
| 🧩 **即用组件** | 排版系统、卡片、数据统计、进度条、时间线等开箱即用 |
| ✨ **动画效果** | 入场动画、脉冲光圈、滚动网格等轻量 CSS 动画 |
| 🖼️ **背景装饰** | 网格、光晕、水印、斜线分割、圆点阵列 5 种背景模式 |

---

## 快速开始

### 方式一：从空白模板开始

直接打开 `assets/blank-starter.html`，在 `<!-- ★ 在此开始添加幻灯片 ★ -->` 注释下方复制 `.slide` 块即可。

### 方式二：从设计系统模板开始

参考 `references/design-system.md` 中的布局代码（封面页、双栏页、四格卡片页、数据页、时间线页），复制粘贴后修改内容。

---

## 文件结构

```
V1.0.0/
├── SKILL.md                       # Skill 核心指令（AI 调用入口）
├── assets/
│   └── blank-starter.html         # 空白起始模板（开箱即用）
├── references/
│   └── design-system.md           # 完整设计系统文档
│       ├── 6 套预设颜色主题
│       ├── 通用 CSS 组件（排版 / 卡片 / 统计 / 列表等）
│       ├── 5 种背景装饰模式
│       ├── 5 种布局模板代码
│       ├── 动画效果库
│       └── 导航组件完整代码
└── README.md                      # 本文件
```

---

## 使用指南

### 1. 核心 HTML 结构

```html
<section class="slide" id="slide-1">
  <div class="slide-body">
    <!-- 内容 -->
  </div>
  <span class="slide-num">01 / 10</span>
</section>
```

每张幻灯片必备：
- `class="slide"` — 应用 16:9 尺寸和 scroll-snap 对齐
- `id="slide-N"` — 唯一标识（N 为页码序号）
- `.slide-num` — 底部页码

### 2. 导航系统（自动生效）

- **右侧圆点**：点击跳转对应页面
- **底部箭头**：上 / 下翻页
- **键盘**：`↑ ↓ ← →` 或 `PageUp / PageDown`
- **滚动**：鼠标滚轮 / 触控板逐页滑动
- **IntersectionObserver**：滚动时自动同步高亮当前页

### 3. 导出 PDF

1. 在浏览器中打开 HTML 文件
2. 按 `Ctrl + P` (Windows) 或 `Cmd + P` (Mac)
3. 目标打印机选择「另存为 PDF」
4. 取消勾选「页眉和页脚」
5. 保存 — 每张幻灯片即为一页 PDF

### 4. 编写新幻灯片

SKILL.md 中定义了 8 种典型页面类型：

| 页面类型 | 适用场景 |
|----------|----------|
| 封面页 | 第一页，大标题 + 视觉冲击背景 |
| 目录页 | 第二页，2×2 或 1×N 卡片网格 |
| 双栏内容页 | 文字 + 图片 / 列表 |
| 全图页 | 图片铺满 + 半透明遮罩文字 |
| 数据页 | 大数字 + 进度条 + 指标说明 |
| 时间线页 | 历史 / 流程 / 路线图 |
| 引用页 | 金句 / 观点 / 名人名言 |
| 结尾页 | 致谢 / Q&A / 联系方式 |

---

## 设计系统

详见 `references/design-system.md`，包含：

### 预设颜色主题

| 主题 | 场景 | 主色 |
|------|------|------|
| 🌑 深空暗黑 | 科技 / 互联网 | `#4F8EF7` |
| 🏮 金墨 | 中国文化 / 历史 | `#D4A017` |
| 🌿 自然绿 | 环保 / 农业 / 医疗 | `#34D399` |
| ☁️ 纯白简约 | 学术 / 报告 | `#2563EB` |
| 🔥 暖橙 | 创业 / 品牌 / 活力 | `#F97316` |
| 🧊 冰蓝 | 金融 / 咨询 / 企业 | `#1E40AF` |

### 字体体系

- **中文展示**：`ZCOOL XiaoWei`（庄重）、`Ma Shan Zheng`（书法）、`Long Cang`（手写）
- **中文正文**：`Noto Serif SC`（衬线）、`Noto Sans SC`（无衬线）
- **英文展示**：`Playfair Display`、`Cormorant Garamond`、`Space Mono`
- **禁止使用**：Arial、Inter、Roboto、system-ui（太通用）

### CSS 组件

| 组件 | 类名 | 用途 |
|------|------|------|
| 超大展示标题 | `.title-xl` | 封面页主标题（6.5vw） |
| 页面主标题 | `.title-lg` | 内页大标题（3.8vw） |
| 章节标题 | `.title-md` | 小节标题（2.4vw） |
| 正文 | `.body-text` | 描述文字（1.2vw） |
| 小标签 | `.label` | 标签 / 副标题 |
| 卡片 | `.card` | 内容区块容器 |
| 统计数字 | `.stat-num` | 数据展示（5vw） |
| 分割线 | `.divider` | 装饰分隔 |
| 高亮 | `.hl` / `.hl-2` | 强调文字颜色 |
| 图标圆 | `.icon-circle` | 图标背景容器 |
| 进度条 | `.progress-bar-bg/fill` | 百分比进度 |

### 背景装饰

- **网格背景** — 科技感细线网格
- **光晕装饰 (Glow)** — 模糊彩色光晕
- **大字水印** — 半透明背景文字
- **斜线分割** — 135° 斜线划分
- **圆点阵列** — 规律小圆点背景

---

## 技术原理

### 16:9 比例

```css
.slide {
  width: 100vw;
  height: 56.25vw;  /* 9 ÷ 16 × 100 = 56.25 */
  scroll-snap-align: start;
}
```

`56.25vw = 9/16 × 100vw`，确保在任何分辨率下都精确保持 16:9 比例。

### 翻页机制

使用 CSS `scroll-snap-type: y mandatory` 实现强制逐页对齐，结合 `scrollIntoView({ behavior: 'smooth' })` 实现平滑跳转。

### 打印适配

```css
@media print {
  .slide {
    width: 297mm;           /* A4 横向宽度 */
    height: 167.0625mm;     /* 297 × 9/16 */
    page-break-after: always;
  }
  #nav-dots, #nav-arrows { display: none; }
}
```

打印时自动隐藏导航元素，每张幻灯片精准适配 A4 纸 16:9 区域。

---

## 许可

仅供个人和商业演示使用。Google Fonts 引用的字体遵循各自的开源许可（OFL 等）。

---

*由 HTML PPT Skill V1.0.0 生成 — 用代码重新定义演示文稿*


path: references/design-system.md
content: # HTML PPT Design System

设计组件库与预设主题，供 SKILL.md 引用。

---

## 目录
1. [预设颜色主题](#预设颜色主题)
2. [通用 CSS 组件](#通用-css-组件)
3. [背景装饰模式](#背景装饰模式)
4. [布局模板代码](#布局模板代码)
5. [动画效果库](#动画效果库)

---

## 预设颜色主题

### 🌑 深空暗黑（科技/互联网）
```css
--c-bg: #0D0F14; --c-surface: #151820;
--c-accent: #4F8EF7; --c-accent2: #A78BFA;
--c-text: #F0F2F8; --c-muted: rgba(240,242,248,0.45);
```

### 🏮 金墨（中国文化/历史/政府）
```css
--c-bg: #1A1209; --c-surface: #251A0D;
--c-accent: #D4A017; --c-accent2: #C0392B;
--c-text: #FAF5E8; --c-muted: rgba(250,245,232,0.5);
--f-display: 'ZCOOL XiaoWei', serif;
```

### 🌿 自然绿（环保/农业/医疗）
```css
--c-bg: #0A1A0F; --c-surface: #0F2415;
--c-accent: #34D399; --c-accent2: #6EE7B7;
--c-text: #ECFDF5; --c-muted: rgba(236,253,245,0.5);
```

### ☁️ 纯白简约（学术/报告/通用）
```css
--c-bg: #FFFFFF; --c-surface: #F8F9FA;
--c-border: rgba(0,0,0,0.08);
--c-accent: #2563EB; --c-accent2: #7C3AED;
--c-text: #111827; --c-muted: #6B7280;
```

### 🔥 暖橙（创业/品牌/活力）
```css
--c-bg: #0F0A06; --c-surface: #1A1208;
--c-accent: #F97316; --c-accent2: #FBBF24;
--c-text: #FFF7ED; --c-muted: rgba(255,247,237,0.5);
```

### 🧊 冰蓝（金融/咨询/企业）
```css
--c-bg: #F0F4F8; --c-surface: #FFFFFF;
--c-border: rgba(30,64,175,0.1);
--c-accent: #1E40AF; --c-accent2: #0EA5E9;
--c-text: #0F172A; --c-muted: #475569;
```

---

## 通用 CSS 组件

### 基础排版
```css
/* 超大展示标题 */
.title-xl {
  font-family: var(--f-display);
  font-size: 6.5vw; line-height: 1.1;
  letter-spacing: 0.04em;
}
/* 页面主标题 */
.title-lg {
  font-family: var(--f-serif, var(--f-body));
  font-size: 3.8vw; line-height: 1.25; font-weight: 700;
}
/* 章节标题 */
.title-md {
  font-size: 2.4vw; line-height: 1.3; font-weight: 700;
}
/* 正文 */
.body-text {
  font-size: 1.2vw; line-height: 1.9; color: var(--c-muted); font-weight: 300;
}
/* 小标签 */
.label {
  font-size: 0.85vw; letter-spacing: 0.35em; text-transform: uppercase;
  color: var(--c-accent); font-weight: 500; margin-bottom: 1%;
}
```

### 分割线
```css
.divider {
  width: 5vw; height: 2px;
  background: linear-gradient(90deg, var(--c-accent), transparent);
  margin: 1.5% 0;
}
```

### 卡片
```css
.card {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--c-border);
  border-radius: 4px;
  padding: 2% 2.5%;
  transition: border-color 0.3s;
}
.card:hover { border-color: rgba(79,142,247,0.3); }
/* 顶部强调线变体 */
.card-accent { border-top: 2px solid var(--c-accent); }
```

### 数据统计
```css
.stat-num {
  font-family: var(--f-display);
  font-size: 5vw; color: var(--c-accent); line-height: 1;
}
.stat-label {
  font-size: 0.9vw; color: var(--c-muted);
  letter-spacing: 0.15em; margin-top: 0.3vw;
}
```

### 列表
```css
.bullet-list { list-style: none; display: flex; flex-direction: column; gap: 0.8%; }
.bullet-list li {
  font-size: 1.15vw; color: var(--c-muted);
  padding-left: 1.4vw; position: relative; line-height: 1.7;
}
.bullet-list li::before {
  content: ''; position: absolute; left: 0; top: 0.65vw;
  width: 0.4vw; height: 0.4vw;
  border-radius: 50%; background: var(--c-accent);
}
```

### 进度条
```css
/* 容器 */
.progress-bar-bg {
  height: 0.35vw; background: rgba(255,255,255,0.08); border-radius: 2px;
}
/* 填充：用 style="width:75%" 控制百分比 */
.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--c-accent), var(--c-accent2));
  border-radius: 2px;
}
```

### 图标圆
```css
.icon-circle {
  width: 4vw; height: 4vw; border-radius: 50%;
  background: rgba(79,142,247,0.12);
  border: 1px solid rgba(79,142,247,0.3);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.8vw; flex-shrink: 0;
}
```

### 页码
```css
.slide-num {
  position: absolute; bottom: 2.2%; right: 3%;
  font-size: 0.9vw; color: rgba(255,255,255,0.2);
  letter-spacing: 0.15em; z-index: 10;
}
```

### 高亮文字
```css
.hl        { color: var(--c-accent); }
.hl-2      { color: var(--c-accent2); }
.hl-gold   { color: #F5C842; }
```

---

## 背景装饰模式

### 网格背景
```html
<div style="position:absolute;inset:0;
  background-image:
    linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,0.03) 1px,transparent 1px);
  background-size:4vw 4vw;pointer-events:none;"></div>
```

### 光晕装饰（Glow）
```html
<!-- 蓝色光晕 -->
<div style="position:absolute;width:25vw;height:25vw;
  border-radius:50%;background:var(--c-accent);
  filter:blur(6vw);opacity:0.2;top:-5vw;left:-5vw;pointer-events:none;"></div>
```

### 大字背景水印
```html
<div style="position:absolute;right:4%;top:50%;transform:translateY(-50%);
  font-family:var(--f-display);font-size:18vw;
  color:rgba(79,142,247,0.05);line-height:1;pointer-events:none;">关键词</div>
```

### 斜线装饰分割
```html
<div style="position:absolute;right:0;top:0;bottom:0;width:35%;
  background:linear-gradient(135deg,transparent 50%,rgba(79,142,247,0.06) 50%);
  pointer-events:none;"></div>
```

### 圆点阵列
```html
<div style="position:absolute;inset:0;
  background-image:radial-gradient(rgba(255,255,255,0.08) 1px,transparent 1px);
  background-size:2.5vw 2.5vw;pointer-events:none;"></div>
```

---

## 布局模板代码

### 封面页
```html
<section class="slide" id="slide-1">
  <!-- 背景 -->
  <div class="grid-bg"></div>
  <div class="glow" style="width:30vw;height:30vw;top:-8vw;left:-6vw;background:var(--c-accent);filter:blur(6vw);opacity:0.25;position:absolute;border-radius:50%;pointer-events:none;"></div>

  <div style="position:relative;z-index:2;padding:4% 6%;height:100%;display:flex;flex-direction:column;justify-content:center;gap:1.5%;">
    <p class="label">副标题标签 · 年份</p>
    <h1 class="title-xl">主标题<br><span class="hl">关键词</span></h1>
    <div class="divider"></div>
    <p class="body-text" style="max-width:40vw;">一句话描述演示内容，简洁有力。</p>
  </div>
  <span class="slide-num">01 / N</span>
</section>
```

### 双栏内容页
```html
<section class="slide" id="slide-N">
  <div style="position:relative;z-index:2;padding:4% 6%;height:100%;display:flex;flex-direction:column;justify-content:center;gap:1.5%;">
    <p class="label">章节名</p>
    <h2 class="title-lg">页面标题</h2>
    <div class="divider"></div>

    <div style="display:grid;grid-template-columns:1fr 1fr;gap:3%;flex:1;align-items:center;">
      <div><!-- 左列内容 --></div>
      <div><!-- 右列内容 --></div>
    </div>
  </div>
  <span class="slide-num">N / Total</span>
</section>
```

### 四格卡片页
```html
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1.5% 2%;">
  <div class="card" style="display:flex;align-items:flex-start;gap:1.2vw;">
    <div class="icon-circle">🔍</div>
    <div>
      <p style="font-size:1.3vw;font-weight:500;color:var(--c-text);margin-bottom:0.4vw;">小标题</p>
      <p class="body-text">描述文字。</p>
    </div>
  </div>
  <!-- 复制3次 -->
</div>
```

### 数据统计页
```html
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:2%;">
  <div class="card card-accent" style="text-align:center;">
    <div class="stat-num">99%</div>
    <p class="stat-label">指标说明</p>
  </div>
  <!-- 复制N次 -->
</div>
```

### 时间线页（横向）
```html
<div style="display:flex;align-items:flex-start;gap:0;position:relative;margin-top:3%;">
  <!-- 连接线 -->
  <div style="position:absolute;top:1vw;left:1vw;right:1vw;height:2px;background:linear-gradient(90deg,var(--c-accent),var(--c-accent2));z-index:0;"></div>
  <!-- 节点（重复） -->
  <div style="flex:1;position:relative;z-index:1;text-align:center;padding:0 1%;">
    <div style="width:2vw;height:2vw;border-radius:50%;background:var(--c-accent);border:3px solid var(--c-bg);margin:0 auto 1vw;"></div>
    <p style="font-size:0.9vw;color:var(--c-accent);">年份</p>
    <p style="font-size:1vw;font-weight:600;color:var(--c-text);margin:0.3vw 0;">标题</p>
    <p class="body-text" style="font-size:0.95vw;">描述</p>
  </div>
</div>
```

---

## 动画效果库

### 入场动画（加在 .slide 的直接子元素）
```css
@keyframes fadeUp {
  from { opacity:0; transform:translateY(1.5vw); }
  to   { opacity:1; transform:none; }
}
/* 用法：style="animation: fadeUp 0.8s 0.2s both" */
/* 叠加延迟：每个元素 delay + 0.15s 产生错落感 */
```

### 脉冲光圈
```css
@keyframes pulse-ring {
  0%   { transform:scale(1); opacity:0.6; }
  100% { transform:scale(1.8); opacity:0; }
}
```

### 无限滚动背景网格
```css
@keyframes gridDrift {
  from { transform:translateY(0); }
  to   { transform:translateY(4vw); }
}
/* background-size 与 animation 步长一致 */
```

---

## 导航组件完整代码

```css
/* 右侧导航点 */
#nav-dots {
  position:fixed; right:1.5vw; top:50%; transform:translateY(-50%);
  display:flex; flex-direction:column; gap:8px; z-index:1000;
}
.dot {
  width:6px; height:6px; border-radius:50%;
  background:rgba(255,255,255,0.25); cursor:pointer;
  transition:all 0.3s; border:none; padding:0;
}
.dot.active { background:var(--c-accent); transform:scale(1.4); }

/* 底部箭头 */
#nav-arrows {
  position:fixed; bottom:2.5vw; left:50%; transform:translateX(-50%);
  display:flex; gap:16px; z-index:1000;
}
.arrow-btn {
  width:36px; height:36px; border:1px solid rgba(255,255,255,0.2);
  background:rgba(255,255,255,0.05); backdrop-filter:blur(8px);
  color:rgba(255,255,255,0.6); cursor:pointer; font-size:14px;
  border-radius:50%; transition:all 0.2s;
  display:flex; align-items:center; justify-content:center;
}
.arrow-btn:hover { background:rgba(79,142,247,0.2); border-color:var(--c-accent); color:var(--c-accent); }
```

```javascript
// 完整导航 JS
const slides = Array.from(document.querySelectorAll('.slide'));
const dotsContainer = document.getElementById('nav-dots');

slides.forEach((_, i) => {
  const btn = document.createElement('button');
  btn.className = 'dot' + (i === 0 ? ' active' : '');
  btn.title = `第 ${i+1} 页`;
  btn.addEventListener('click', () => goTo(i));
  dotsContainer.appendChild(btn);
});

const dots = () => Array.from(dotsContainer.querySelectorAll('.dot'));
let current = 0;

function goTo(i) {
  i = Math.max(0, Math.min(slides.length-1, i));
  slides[i].scrollIntoView({ behavior:'smooth' });
  dots().forEach((d,idx) => d.classList.toggle('active', idx===i));
  current = i;
}

document.addEventListener('keydown', e => {
  if (['ArrowDown','ArrowRight','PageDown'].includes(e.key)) { e.preventDefault(); goTo(current+1); }
  if (['ArrowUp','ArrowLeft','PageUp'].includes(e.key))      { e.preventDefault(); goTo(current-1); }
});

document.getElementById('btn-up').addEventListener('click', () => goTo(current-1));
document.getElementById('btn-dn').addEventListener('click', () => goTo(current+1));

new IntersectionObserver(entries => {
  entries.forEach(en => {
    if (en.isIntersecting) {
      current = slides.indexOf(en.target);
      dots().forEach((d,i) => d.classList.toggle('active', i===current));
    }
  });
}, { threshold:0.6 }).observe = (() => {
  const io = new IntersectionObserver(entries => {
    entries.forEach(en => {
      if (en.isIntersecting) {
        current = slides.indexOf(en.target);
        dots().forEach((d,i) => d.classList.toggle('active', i===current));
      }
    });
  }, { threshold:0.6 });
  slides.forEach(s => io.observe(s));
})();
```

path: assets/blank-starter.html
content: <!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>演示标题</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+XiaoWei&display=swap" rel="stylesheet">
<style>
/* ── 全局变量（按需修改）── */
:root {
  --c-bg:      #0D0F14;
  --c-surface: #151820;
  --c-border:  rgba(255,255,255,0.08);
  --c-accent:  #4F8EF7;
  --c-accent2: #A78BFA;
  --c-text:    #F0F2F8;
  --c-muted:   rgba(240,242,248,0.45);
  --f-display: 'ZCOOL XiaoWei', serif;
  --f-body:    'Noto Sans SC', sans-serif;
  --f-serif:   'Noto Serif SC', serif;
}

/* ── 核心框架 ── */
*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
html, body {
  background: var(--c-bg);
  font-family: var(--f-body);
  font-weight: 300;
  color: var(--c-text);
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
  height: 100%;
}
.slide {
  width: 100vw;
  height: 56.25vw;
  position: relative;
  overflow: hidden;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  background: var(--c-bg);
}
.slide-body {
  position: relative; z-index: 2;
  padding: 4% 6%;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.slide-num {
  position:absolute; bottom:2.2%; right:3%;
  font-size:0.9vw; color:rgba(255,255,255,0.2);
  letter-spacing:0.15em; z-index:10;
}

/* ── 排版 ── */
.label     { font-size:0.85vw; letter-spacing:0.35em; text-transform:uppercase; color:var(--c-accent); font-weight:500; margin-bottom:1%; }
.title-xl  { font-family:var(--f-display); font-size:6.5vw; line-height:1.1; letter-spacing:0.04em; }
.title-lg  { font-family:var(--f-serif); font-size:3.8vw; line-height:1.25; font-weight:700; }
.title-md  { font-size:2.4vw; line-height:1.3; font-weight:700; }
.body-text { font-size:1.2vw; line-height:1.9; color:var(--c-muted); }
.divider   { width:5vw; height:2px; background:linear-gradient(90deg,var(--c-accent),transparent); margin:1.5% 0; }
.hl        { color:var(--c-accent); }
.hl-2      { color:var(--c-accent2); }

/* ── 卡片 ── */
.card { background:rgba(255,255,255,0.04); border:1px solid var(--c-border); border-radius:4px; padding:2% 2.5%; }

/* ── 导航 ── */
#nav-dots { position:fixed; right:1.5vw; top:50%; transform:translateY(-50%); display:flex; flex-direction:column; gap:8px; z-index:1000; }
.dot { width:6px; height:6px; border-radius:50%; background:rgba(255,255,255,0.25); cursor:pointer; transition:all 0.3s; border:none; padding:0; }
.dot.active { background:var(--c-accent); transform:scale(1.4); }
#nav-arrows { position:fixed; bottom:2.5vw; left:50%; transform:translateX(-50%); display:flex; gap:16px; z-index:1000; }
.arrow-btn { width:36px; height:36px; border:1px solid rgba(255,255,255,0.2); background:rgba(255,255,255,0.05); backdrop-filter:blur(8px); color:rgba(255,255,255,0.6); cursor:pointer; font-size:14px; border-radius:50%; transition:all 0.2s; display:flex; align-items:center; justify-content:center; }
.arrow-btn:hover { background:rgba(79,142,247,0.2); border-color:var(--c-accent); color:var(--c-accent); }

/* ── 打印 ── */
@media print {
  html, body { height:auto; overflow:visible; scroll-snap-type:none; }
  #nav-dots, #nav-arrows { display:none !important; }
  .slide { width:297mm; height:167.0625mm; page-break-after:always; break-after:page; scroll-snap-align:none; }
}
</style>
</head>
<body>

<nav id="nav-dots"></nav>
<div id="nav-arrows">
  <button class="arrow-btn" id="btn-up">↑</button>
  <button class="arrow-btn" id="btn-dn">↓</button>
</div>

<!-- ★ 在此开始添加幻灯片 ★ -->

<section class="slide" id="slide-1">
  <div class="slide-body" style="justify-content:center;gap:1.5%;">
    <p class="label">标签 · 年份</p>
    <h1 class="title-xl">演示<span class="hl">标题</span></h1>
    <div class="divider"></div>
    <p class="body-text" style="max-width:40vw;">副标题或一句话描述。</p>
  </div>
  <span class="slide-num">01 / 01</span>
</section>

<!-- 复制上方 section 块以新增幻灯片 -->

<script>
const slides = Array.from(document.querySelectorAll('.slide'));
const dotsEl  = document.getElementById('nav-dots');
slides.forEach((_,i)=>{
  const b=document.createElement('button');
  b.className='dot'+(i===0?' active':'');
  b.title=`第${i+1}页`;
  b.addEventListener('click',()=>goTo(i));
  dotsEl.appendChild(b);
});
let cur=0;
const dots=()=>Array.from(dotsEl.querySelectorAll('.dot'));
function goTo(i){
  i=Math.max(0,Math.min(slides.length-1,i));
  slides[i].scrollIntoView({behavior:'smooth'});
  dots().forEach((d,j)=>d.classList.toggle('active',j===i));
  cur=i;
}
document.addEventListener('keydown',e=>{
  if(['ArrowDown','ArrowRight','PageDown'].includes(e.key)){e.preventDefault();goTo(cur+1);}
  if(['ArrowUp','ArrowLeft','PageUp'].includes(e.key)){e.preventDefault();goTo(cur-1);}
});
document.getElementById('btn-up').onclick=()=>goTo(cur-1);
document.getElementById('btn-dn').onclick=()=>goTo(cur+1);
new IntersectionObserver(entries=>{
  entries.forEach(en=>{if(en.isIntersecting){cur=slides.indexOf(en.target);dots().forEach((d,i)=>d.classList.toggle('active',i===cur));}});
},{threshold:0.6}).observe; // placeholder
(()=>{const io=new IntersectionObserver(entries=>{entries.forEach(en=>{if(en.isIntersecting){cur=slides.indexOf(en.target);dots().forEach((d,i)=>d.classList.toggle('active',i===cur));}});},{threshold:0.6});slides.forEach(s=>io.observe(s));})();
</script>
</body>
</html>

Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)